c - 使用 LD_PRELOAD 机制覆盖 'malloc'

标签 c malloc dynamic-linking

我正在尝试编写一个简单的共享库,用于记录对 stderr 的 malloc 调用(如果您愿意的话,是一种“mtrace”)。

但是,这是行不通的。 这是我的做法:

/* mtrace.c */
#include <dlfcn.h>
#include <stdio.h>

static void* (*real_malloc)(size_t);

void *malloc(size_t size)
{
    void *p = NULL;
    fprintf(stderr, "malloc(%d) = ", size);
    p = real_malloc(size);
    fprintf(stderr, "%p\n", p);
    return p;
}

static void __mtrace_init(void) __attribute__((constructor));
static void __mtrace_init(void)
{
    void *handle = NULL;
    handle = dlopen("libc.so.6", RTLD_LAZY);
    if (NULL == handle) {
        fprintf(stderr, "Error in `dlopen`: %s\n", dlerror());
        return;
    }
    real_malloc = dlsym(handle, "malloc");
    if (NULL == real_malloc) {
        fprintf(stderr, "Error in `dlsym`: %s\n", dlerror());
        return;
    }
}

我编译它:

gcc -shared -fPIC -o mtrace.so mtrace.c

然后当我尝试执行 ls 时:

$ LD_PRELOAD=./mtrace.so ls
malloc(352) = Segmentation fault

现在,我怀疑 dlopen 需要 malloc,并且当我在共享库中重新定义它时,它使用该版本和仍未分配的 real_malloc

问题是……我该如何让它发挥作用?

附言很抱歉标签太少,我找不到合适的标签,而且我仍然没有足够的声誉来创建新标签。

最佳答案

我总是这样做:

#define _GNU_SOURCE

#include <stdio.h>
#include <dlfcn.h>

static void* (*real_malloc)(size_t)=NULL;

static void mtrace_init(void)
{
    real_malloc = dlsym(RTLD_NEXT, "malloc");
    if (NULL == real_malloc) {
        fprintf(stderr, "Error in `dlsym`: %s\n", dlerror());
    }
}

void *malloc(size_t size)
{
    if(real_malloc==NULL) {
        mtrace_init();
    }

    void *p = NULL;
    fprintf(stderr, "malloc(%d) = ", size);
    p = real_malloc(size);
    fprintf(stderr, "%p\n", p);
    return p;
}

不要使用构造函数,只需在第一次调用 malloc 时进行初始化。使用 RTLD_NEXT 来避免 dlopen。你也可以试试 malloc hooks .请注意,所有这些都是 GNU 扩展,可能无法在其他地方使用。

关于c - 使用 LD_PRELOAD 机制覆盖 'malloc',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57897343/

相关文章:

macos - 如何让 LLDB 打印共享库在内存中的位置?

c - C中静态函数的优先级

c - malloc 上的段错误

c - 从堆栈和堆中获取二维数组的函数

c - 数组的地址与数组[0]的地址 - C语言

c++ - 编写 makefile 来构建动态库

linux - 加载共享库时出错 : librun. 所以

c - C 中的越界地址/指针

有人可以改进我的堆数据结构代码吗?

c - 如何使用 fread 从文件中读取特定数据?