lvxuzhou


私信TA

用户名:lvxuzhou

访问量:106753

签 名:

lvxuzhou

等  级
排  名 47
经  验 12168
参赛次数 0
文章发表 56
年  龄 0
在职情况 学生
学  校 西安
专  业

  自我简介:

    前言

     作为c的程序员,最常见的就是排查内存泄漏,如果没有被内存泄漏折磨过,说明你写的程序太简单了。本篇文章是本人最近几天突发奇想写的一个小工具,其中参考了大量资料,遇到各种奇葩问题,最后翻墙一一解决,因此决定写个博客总结一下。

     说明:下面代码中涉及大量c语言高级知识和linux环境下劫持的知识,仔细研究相信会收获很大,

    环境:

    微信图片_20210922225910.png

第一步、

测试代码:

先来个简单的分配释放内存例子

helloworld.c 

#include <stdio.h>
#include <stdlib.h>
void fun(void)
{
  void *p = malloc(10); //分配内存
  free(p);    //释放内存
}
int main(void)
{
  fun();
  return 0;
}

第二步、

劫持代码:

hack_malloc.c

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
static void *(*mymalloc)(size_t) = NULL;
static void (*myfree)(void *) = NULL;
static void __attribute__((constructor)) init(void)
{
    mymalloc = dlsym(RTLD_NEXT, "malloc");
    myfree = dlsym(RTLD_NEXT, "free");
    if (!mymalloc)
    {
        fprintf(stderr, "unable to get malloc symbol!\n");
        exit(1);
    }
    if (!myfree)
    {
        fprintf(stderr, "unable to get free symbol!\n");
        exit(1);
    }
    fprintf(stderr, "libhack_malloc.so  successfully wrapped!\n");
}
void *malloc(size_t size)
{
    const void *caller_addr = __builtin_return_address(0);
    fprintf(stderr, "malloc_addr %p size=%lu\n", caller_addr - 1, size);
    return mymalloc(size);
}
void free(void *ptr)
{
    const void *caller_addr = __builtin_return_address(0);
    fprintf(stderr, "free_addr %p\n", caller_addr - 1);
    myfree(ptr);
}

知识点一、

    __attribute__((constructor))的作用 参考:https://blog.csdn.net/sun172270102/article/details/88227519

知识点二、

    1、gcc默认不支持__builtin_return_address(LEVEL)的参数为非0。好像只支持参数为0。
    2、__builtin_return_address(0)的含义是,得到当前函数返回地址,即此函数被别的函数调用,然后此函数执行完毕后,返回,所谓返回地址就是那时候的地址。
    3、__builtin_return_address(1)的含义是,得到当前函数的调用者的返回地址。注意是调用者的返回地址,而不是函数起始地址。

知识点三、

    dlsym(RTLD_NEXT, "malloc"); 的作用参考:https://blog.csdn.net/Cxinsect/article/details/100761916

注意点:

    1、#define _GNU_SOURCE 不能省略

    2、只能使用fprintf 不能使用printf,因为printf内部会调用malloc导致死循环

第三步、

测试脚本:

gcc hack_malloc.c -o libhack_malloc.so -fPIC -shared -ldl -g3
gcc   helloworld.c   -o helloworld  -g3   -no-pie
export LD_PRELOAD=/root/damo/libhack_malloc.so
./helloworld
export LD_PRELOAD=

注意点:

    1、-no-pie不能省略

    2、LD_PRELOAD= 最后尽量还原一下,以免造成意外错误

运行结果:

QQ图片20211011003921.png

记住地址 0x400548和0x400558,下面会转换

第四步、

addr2line工具用法参考:https://www.jianshu.com/p/c2e2b8f8ea0d

地址转换命令:addr2line -f -e 可执行程序 -a 地址

QQ图片20211011010450.png

    可以看到0x400548对应malloc、0x400558对应free了,行号、文件、函数信息都已经解析出来了。这些信息都已经拿到了,是不是就可以排查内存是否泄漏了呢?后续我准备使用python脚本或者shell脚本解析,敬请期待......

 

0.0分

3 人评分

新上线《蓝桥杯辅导》课程,近五年的蓝桥杯省赛与国赛真题都有,从读题开始理解题意、梳理思路、实现代码再提交评测全过程,可有效提升获奖比例甚至进国赛!课程介绍、试听请猛击这里

  评论区

  • «
  • »