LD_PRELOAD只为malloc工作,不是免费的 [英] LD_PRELOAD only working for malloc, not free

查看:341
本文介绍了LD_PRELOAD只为malloc工作,不是免费的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图插入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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆