LD_PRELOAD 仅适用于 malloc,不适用于 free

发布于 2024-12-10 18:03:26 字数 1833 浏览 0 评论 0原文

我正在尝试通过 LD_PRELOAD 使用一些插入器插入 malloc/free/calloc/realloc 等。在我的小测试中,即使检测到 free (请参阅输出),似乎也只插入了 malloc

我希望输出包含一行“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\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;
}

实际输出是:

% ./a.out
NANO: malloc() replaced @0x3b36274dc0
NANO: free() replaced @0x3b36272870
NANO: malloc(123) = 0x601010
HOST p=0x601010

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

葬シ愛 2024-12-17 18:03:26

你正在编译一个C++;这意味着(默认情况下)函数会被名称修改以适应 C++ ABI。不幸的是,您尝试挂钩的函数没有名称损坏,因此您最终会挂钩错误的(不存在的)函数。

解决方法是 a) 在 extern "C" { } 块中定义包装器,或者 a) 确保包含函数的标头 - 如 #include中所示。这将使用 extern "C" 包装器引入 mallocfree 声明,告诉编译器不要进行名称修改。

malloc 起作用的原因可能是因为 引入了 malloc 的声明 但不是 免费。因此,malloc 未损坏,但 free 已损坏。

另请注意:如果您使用 glibc,则应该使用 malloc hooks 挂钩内存分配函数。 glibc 在符号版本控制方面做了一些非常奇怪的事情,否则可能会干扰你的钩子。如何使用它的示例位于链接的文档中 - 不过,如果您使用的是 C++,请不要忘记 extern "C"

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文