LD_PRELOAD只为malloc工作,不是免费的 [英] LD_PRELOAD only working for malloc, not free
问题描述
我试图插入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,则应该使用 malloc钩子挂钩内存分配功能。 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工作,不是免费的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!