问题描述
我试图插入malloc / free / calloc / realloc等与一些插件通过LD_PRELOAD。在我的小测试中,只有 malloc 似乎插入,即使检测到 free (见输出) p>
我希望输出包含一行NANO:free(x) - 但是这行没有了。
给定
// compile with:gcc test.cc
#include< stdio.h>
#include< stdlib.h>
int main(int argc,char * argv []){
void * p = malloc(123);
printf(HOST p =%p\\\
,p);
free(p);
}
和
// compile with:g ++ -O2 -Wall -fPIC -ldl -o libnano.so -shared main.cc
#include< stdio.h>
#include< dlfcn.h>
typedef void *(* MallocFunc)(size_t size);
typedef void(* FreeFunc)(void *);
//原函数
static MallocFunc real_malloc = NULL;
static FreeFunc real_free = NULL;
static void __nano_init(void){
//覆盖原函数
real_malloc =(MallocFunc)dlsym(RTLD_NEXT,malloc);
if(NULL == real_malloc){
fprintf(stderr,dlsym中的错误:%s\\\
,dlerror());
} else {
fprintf(stderr,NANO:malloc()replaced @%p\\\
,real_malloc);
}
real_free =(FreeFunc)dlsym(RTLD_NEXT,free);
if(NULL == real_free){
fprintf(stderr,dlsym中的错误:%s\\\
,dlerror());
} else {
fprintf(stderr,NANO:free()replaced @%p\\\
,real_free);
}
}
//替换函数
void * malloc(size_t size){
if(real_malloc == NULL)__nano_init();
void * p = NULL;
fprintf(stderr,NANO:malloc(%lu)=,size);
p = real_malloc(size);
fprintf(stderr,%p \\\
,p);
return p;
}
void free(void * ptr){
if(real_free == NULL)__nano_init();
fprintf(stderr,NANO:free(%p)\\\
,ptr)
real_free(ptr);
return;
}
实际输出是:
$ b b
%./a.out
NANO:malloc()replace @ 0x3b36274dc0
NANO:free()replace @ 0x3b36272870
NANO:malloc (123)= 0x601010
HOST p = 0x601010
你正在编译一个C ++;这意味着(默认情况下)函数被名称压缩以适应C ++ ABI。不幸的是,您尝试加入的函数不是名称受损,因此您最终会遇到错误的(不存在的)函数。
修复是要么a)在 externC{} 块中定义您的包装器或a)确保包括函数的头 - 如 #include< cstdlib> 。这将引入 malloc 和免费的声明和 externC$
原因 malloc 可能是因为< stdio.h> 或< dlfcn.h> 拉入 malloc ,但不是 免费。因此, malloc 未解决,但免费已损坏。
另请注意:如果您使用glibc,则应该使用挂钩内存分配功能。 glibc做一些很奇怪的东西与符号版本化,否则可能会干扰你的钩子。如何使用它的一个例子是在文档链接 - 不要忘记 externC s如果你使用C ++,尽管!
I'm trying to interpose malloc/free/calloc/realloc etc with some interposers via LD_PRELOAD. In my small test, only malloc seems to be interposed, even though free is detected (see output).
I'd expect the output to contain a line "NANO: free(x)" - but this line is missing.
Given
// compile with: gcc test.cc #include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]) { void* p = malloc(123); printf("HOST p=%p\n", p); free(p); }
And
// compile with: g++ -O2 -Wall -fPIC -ldl -o libnano.so -shared main.cc #include <stdio.h> #include <dlfcn.h> typedef void *(*MallocFunc)(size_t size); typedef void (*FreeFunc)(void*); // Original functions static MallocFunc real_malloc = NULL; static FreeFunc real_free = NULL; static void __nano_init(void) { // Override original functions real_malloc = (MallocFunc)dlsym(RTLD_NEXT, "malloc"); if (NULL == real_malloc) { fprintf(stderr, "Error in `dlsym`: %s\n", dlerror()); } else { fprintf(stderr, "NANO: malloc() replaced @%p\n", real_malloc); } real_free = (FreeFunc)dlsym(RTLD_NEXT, "free"); if (NULL == real_free) { fprintf(stderr, "Error in `dlsym`: %s\n", dlerror()); } else { fprintf(stderr, "NANO: free() replaced @%p\n", real_free); } } // replacement functions void *malloc(size_t size) { if(real_malloc==NULL) __nano_init(); void *p = NULL; fprintf(stderr, "NANO: malloc(%lu) = ", size); p = real_malloc(size); fprintf(stderr, "%p\n", p); return p; } void free(void* ptr) { if(real_free==NULL) __nano_init(); fprintf(stderr, "NANO: free(%p)\n", ptr); real_free(ptr); return; }
The actual output is:
% ./a.out NANO: malloc() replaced @0x3b36274dc0 NANO: free() replaced @0x3b36272870 NANO: malloc(123) = 0x601010 HOST p=0x601010
You are compiling a C++; this means that (by default) functions are name-mangled to fit the C++ ABI. Unfortunately, the functions you are trying to hook are not name-mangled, so you end up hooking the wrong (nonexistent) function.
The fix is to either a) define your wrappers in a extern "C" { } block or a) make sure you include the header for the function - as in #include <cstdlib>. This will pull in declarations for malloc and free with an extern "C" wrapper, telling the compiler not to name-mangle.
The reason malloc works is probably because <stdio.h> or <dlfcn.h> pulls in a declaration for malloc but not free. Thus, malloc is unmangled, but free is mangled.
Also note: If you're using glibc, you should be using malloc hooks to hook memory allocation functions. glibc does some pretty weird stuff with symbol versioning that may interfere with your hooks otherwise. An example of how to use it is in the documentation linked - don't forget extern "C"s if you're using C++, though!
这篇关于LD_PRELOAD只为malloc工作,不是免费的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!