升级到最新的 glibc 后,我注意到 malloc_hooks 已被弃用,因此我尝试使用 --wrap 符号用用户定义的函数覆盖某些 glibc 函数。例如,我使用 --wrap=malloc 来使用自定义的wrapp_malloc 覆盖 glibc malloc 函数。
我的代码中对 malloc 的直接调用被正确重定向到wrap_malloc。然而,当调用像 fopen() 这样的 glibc 函数时,它会在内部调用 malloc,内部 malloc 调用不会被我的 wrap_malloc 覆盖。
有人对如何解决此问题并确保内部 malloc 调用(例如,来自 fopen() 的调用)被我的自定义函数覆盖有建议吗?任何见解将不胜感激!
我尝试使用 LD_PRELOAD 选项,但它似乎不起作用,因为我的应用程序是静态构建的
对于完全静态链接,您最好的(可能也是唯一的)选择是用替代实现替换整个
libc.a(malloc.o)
。
请注意,您必须替换
malloc.o
中的所有符号,否则您的链接将因多重定义的符号而失败。
例如,在 Fedora 40 上,以下“有效”:
#include <stdio.h>
#include <string.h>
static char buf[10000] __attribute__((aligned(16)));
static char *mptr = &buf[0];
void *malloc(size_t sz)
{
char *r = mptr;
mptr += (sz + 0xF) & ~0xF;
fprintf(stderr, "malloc(%zu) -> %p\n", sz, r);
return r;
}
void free(void *p)
{
fprintf(stderr, "free(%p)\n", p);
}
void *calloc(size_t nelem, size_t sz)
{
void *r = malloc(nelem * sz);
fprintf(stderr, "calloc(%zu, %zu) -> %p\n", nelem, sz, r);
return r;
}
void *realloc(void *p, size_t sz)
{
char *r = malloc(sz);
memcpy(r, p, sz);
fprintf(stderr, "realloc(%p, %zu) -> %p\n", p, sz, r);
return r;
}
int main(int argc, char *argv[])
{
if (argc < 2) return 0;
fprintf(stderr, " fopen(%s)\n", argv[1]);
FILE *fp = fopen(argv[1], "w");
fprintf(stderr, " fopen(%s) -> %p\n", argv[1], fp);
if (fp == NULL) return 1;
fprintf(stderr, " fclose(%p)\n", fp);
fclose(fp);
fprintf(stderr, " main returns\n");
return 0;
}
gcc -Wall -Wextra -static t.c && ./a.out foo.txt
malloc(6) -> 0x49d1b0
malloc(1241) -> 0x49d1c0
calloc(1241, 1) -> 0x49d1c0
malloc(24) -> 0x49d6a0
malloc(160) -> 0x49d6c0
malloc(160) -> 0x49d760
malloc(256) -> 0x49d800
malloc(256) -> 0x49d900
fopen(foo.txt)
malloc(472) -> 0x49da00
fopen(foo.txt) -> 0x49da00
fclose(0x49da00)
free(0x49da00)
main returns
free(0x49d900)
free(0x49d800)
在上面您可以清楚地看到
malloc
被从 fopen
调用,而 free
被从 fclose
调用。