前言
作为c的程序员,最常见的就是排查内存泄漏,如果没有被内存泄漏折磨过,说明你写的程序太简单了。本篇文章是本人最近几天突发奇想写的一个小工具,其中参考了大量资料,遇到各种奇葩问题,最后翻墙一一解决,因此决定写个博客总结一下。
说明:下面代码中涉及大量c语言高级知识和linux环境下劫持的知识,仔细研究相信会收获很大,
环境:

第一步、
测试代码:
先来个简单的分配释放内存例子
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= 最后尽量还原一下,以免造成意外错误
运行结果:

记住地址 0x400548和0x400558,下面会转换
第四步、
addr2line工具用法参考:https://www.jianshu.com/p/c2e2b8f8ea0d
地址转换命令:addr2line -f -e 可执行程序 -a 地址

可以看到0x400548对应malloc、0x400558对应free了,行号、文件、函数信息都已经解析出来了。这些信息都已经拿到了,是不是就可以排查内存是否泄漏了呢?后续我准备使用python脚本或者shell脚本解析,敬请期待......
0.0分
1 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复