如何让backtrace_symbols调用__wrap_malloc?wrap_malloc拦截问题
问题分析
为什么__wrap_malloc无法拦截backtrace_symbols的malloc调用?核心原因有两个:
- 链接器wrap机制的局限性:
--wrap=malloc是链接阶段的符号替换手段,仅作用于你的代码中对malloc的外部引用,而backtrace_symbols是glibc预编译好的库函数,它内部对malloc的调用已经直接绑定到glibc自身的malloc实现,链接器无法修改库内部的符号引用。 - 动态链接的符号优先级:程序运行时,glibc内部的函数调用会直接使用库内的符号,不会去查找外部的
__wrap_malloc。
解决方案
针对GCC 7.5.0环境,有两种可行的解决方式:
方式一:使用LD_PRELOAD加载自定义动态库
这是最通用的拦截手段,通过动态链接器的预加载机制,让自定义的malloc优先被所有代码(包括glibc内部函数)调用。
- 编写自定义malloc实现文件(比如
mymalloc.c):
#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> // 保存原始的malloc函数指针 static void* (*original_malloc)(size_t) = NULL; // 自定义malloc void* malloc(size_t size) { if (!original_malloc) { original_malloc = dlsym(RTLD_NEXT, "malloc"); if (!original_malloc) { fprintf(stderr, "dlsym error: %s\n", dlerror()); exit(1); } } printf("Intercepted malloc call, size: %zu\n", size); return original_malloc(size); } // 实现free避免链接报错 void free(void* ptr) { static void (*original_free)(void*) = NULL; if (!original_free) { original_free = dlsym(RTLD_NEXT, "free"); if (!original_free) { fprintf(stderr, "dlsym error: %s\n", dlerror()); exit(1); } } original_free(ptr); }
- 编译动态库:
gcc -shared -fPIC -ldl mymalloc.c -o libmymalloc.so
- 运行程序时预加载该库:
LD_PRELOAD=./libmymalloc.so ./your_program
方式二:使用glibc的malloc钩子(仅适用于旧版glibc)
GCC 7.5.0对应的glibc版本(一般为2.23左右)还支持已废弃的__malloc_hook机制,可在程序初始化时替换malloc调用:
- 修改程序代码:
#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <execinfo.h> // 自定义malloc static void* my_malloc(size_t size, const void* caller) { printf("Intercepted malloc via hook, size: %zu\n", size); // 先恢复钩子避免递归调用 __malloc_hook = NULL; void* ptr = malloc(size); // 重新设置钩子 __malloc_hook = my_malloc; return ptr; } // 初始化钩子 static void init_hook() { __malloc_hook = my_malloc; } // 程序启动时自动执行初始化 __attribute__((constructor)) void setup() { init_hook(); } int main() { void* callstack[10]; int frames = backtrace(callstack, 10); char** strs = backtrace_symbols(callstack, frames); // 后续处理 free(strs); return 0; }
- 编译运行:
gcc your_program.c -o your_program -rdynamic ./your_program
注意:__malloc_hook在glibc 2.26之后被正式移除,仅适配你的GCC 7.5.0环境,长期来看推荐使用LD_PRELOAD方式。
内容的提问来源于stack exchange,提问作者刘肃超
相关产品推荐
相关产品推荐

