前言
作为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分
3 人评分
输出九九乘法表 (C语言代码)浏览:584 |
2006年春浙江省计算机等级考试二级C 编程题(2) (C语言代码)浏览:507 |
奖学金 (C++代码)浏览:2057 |
P1002 (C语言代码)浏览:1021 |
最小公倍数 (C语言代码)浏览:898 |
C语言程序设计教程(第三版)课后习题1.5 (C语言代码)浏览:644 |
C语言程序设计教程(第三版)课后习题11.8 (C语言代码)浏览:911 |
众数问题 (C语言代码)浏览:912 |
C语言考试练习题_保留字母 (C语言代码)浏览:743 |
C语言程序设计教程(第三版)课后习题5.4 (C语言代码)浏览:823 |