【问题标题】:It is possible to force an executable to use an user defined 'malloc'?可以强制可执行文件使用用户定义的“malloc”吗?
【发布时间】:2016-12-25 14:43:22
【问题描述】:

我想了解内存跟踪器和泄漏检测器是如何工作的,所以我有了这个想法,我有一个可执行文件,我想在执行时强制它使用我自己的内存分配函数而不是通常的系统函数 (" malloc"、"realloc"...)。

我自己的函数存储在库(静态或共享)或只是一个目标文件(“.o”)中,想想类似的东西:

void *my_own_malloc(unsigned long size) {
     printf("allocate: %lu\n", size);
     return malloc(size);
}

PS:我不用改可执行源代码(我没有源代码)

PS2:我想在所有不同的平台(Windows、OS X 和 Linux...)上做到这一点

【问题讨论】:

  • @Lolrapa 这里的问题是注入函数必须有一些名称为'malloc',但在注入函数内部有一个对系统“malloc”的调用,这可能会产生无限递归函数?!

标签: c debugging memory-management compilation linker


【解决方案1】:

我不了解其他平台,但在 GNU/Linux 上,您可以使用 LD_PRELOAD 环境变量预加载一个小型内存跟踪库,其中定义了您自己的 mallocfree

您自己的malloc 可能希望使用真正的malloc 函数分配内存,因此这里可能存在递归问题。要解决此问题,dlsym 函数可以使用 RTLD_NEXT 参数来获取指向下一个(即“真实”)malloc 函数的指针。

对此的一个非常小的测试可能如下所示:

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

void *malloc(size_t size)
{
    static void *(*real_malloc)(size_t size) = 0;

    if (!real_malloc)
        real_malloc = dlsym(RTLD_NEXT, "malloc");

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

void free(void *ptr)
{
    static void (*real_free)(void *ptr) = 0;
    if (!real_free)
        real_free = dlsym(RTLD_NEXT, "free");

    real_free(ptr);
    fprintf(stderr, "free(%p)\n", ptr);
}

如果我们称这个文件为fakemalloc.c,可以用命令编译成fakemalloc.so共享对象

gcc -fPIC -shared -Wl,-soname,fakemalloc.so -o fakemalloc.so fakemalloc.c -ldl

作为测试,要查看在调用 ls 命令时发生了哪些 mallocfree 调用,您需要执行

LD_PRELOAD=/path/to/fakemalloc.so ls

编辑:正如评论中提到的,在 glibc-systems 上,您可以通过使用函数 __libc_malloc__libc_free 来避免使用 RTLD_NEXT 方法。这将产生以下代码:

#include <stdio.h>

void *__libc_malloc(size_t size);
void *__libc_free(void *ptr);

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

void free(void *ptr)
{
    __libc_free(ptr);
    fprintf(stderr, "free(%p)\n", ptr);
}

【讨论】:

  • 非常感谢您! LD_PRELOAD是所有需要的,构建步骤也很有用。 DYLD_INSERT_LIBRARIES 可能是 OS X 中的等价物。
  • 在基于 glibc 的系统上,您还可以通过在替换 malloc 例程中调用 __libc_malloc 来调用系统 malloc(不需要 RTLD_NEXT 技巧)
  • 可能会在可能未定义的行为之前打印消息,例如调用 free() 并刷新结果,如果它还没有被换行符(当 stderr 是一个真实文件时?)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-02
  • 1970-01-01
  • 2016-01-25
  • 1970-01-01
相关资源
最近更新 更多