gpt4 book ai didi

c - glibc 已弃用的 __malloc_hook 功能的替代方案

转载 作者:太空狗 更新时间:2023-10-29 16:21:43 57 4
gpt4 key购买 nike

我正在为 C 编写一个内存分析器,为此我正在通过 malloc_hooks 拦截对 mallocreallocfree 函数的调用。不幸的是,由于它们在多线程环境中的不良行为,这些已被弃用。我找不到描述实现相同目标的替代最佳实践解决方案的文档,有人可以启发我吗?

我读过一个简单的#define malloc(s) malloc_hook(s) 就可以解决这个问题,但这不适用于我想要的系统设置,因为它太侵入原始代码库,适合在分析/跟踪工具中使用。必须手动更改原始应用程序代码对于任何像样的分析器来说都是一个 killer 。最理想的是,我正在寻找的解决方案应该仅通过链接到一个可选的共享库来启用或禁用。例如,我当前的设置使用用 __attribute__ ((constructor)) 声明的函数来安装拦截 malloc Hook 。

谢谢

最佳答案

在尝试了一些事情之后,我终于弄清楚了如何做到这一点。

首先,在glibc中,malloc被定义为弱符号,这意味着它可以被应用程序或共享库覆盖。因此,不一定需要 LD_PRELOAD。相反,我在共享库中实现了以下功能:

void*
malloc (size_t size)
{
[ ... ]
}

它由应用程序而不是 glibcmalloc 调用。

现在,要等同于 __malloc_hook 的功能,仍然缺少一些东西。

1.) 来电地址

除了malloc的原始参数外,glibc__malloc_hook还提供了调用函数的地址,其实就是malloc 将返回的返回地址。为了达到同样的目的,我们可以使用 gcc 中提供的 __builtin_return_address 函数。我没有研究其他编译器,因为无论如何我都仅限于 gcc,但是如果你碰巧知道如何以可移植的方式做这样的事情,请给我留言 :)

我们的 malloc 函数现在看起来像这样:

void*
malloc (size_t size)
{
void *caller = __builtin_return_address(0);
[ ... ]
}

2.) 从你的钩子(Hook)中访问glibc的malloc

由于我的应用程序仅限于 glibc,所以我选择使用 __libc_malloc 来访问原始的 malloc 实现。或者,可以使用 dlsym(RTLD_NEXT, "malloc"),但可能存在的缺陷是此函数在其第一次调用时使用了 calloc,可能导致无限循环到段错误。

完整的 malloc 钩子(Hook)

我完整的 Hook 函数现在看起来像这样:

extern void *__libc_malloc(size_t size);

int malloc_hook_active = 0;

void*
malloc (size_t size)
{
void *caller = __builtin_return_address(0);
if (malloc_hook_active)
return my_malloc_hook(size, caller);
return __libc_malloc(size);
}

my_malloc_hook 看起来像这样:

void*
my_malloc_hook (size_t size, void *caller)
{
void *result;

// deactivate hooks for logging
malloc_hook_active = 0;

result = malloc(size);

// do logging
[ ... ]

// reactivate hooks
malloc_hook_active = 1;

return result;
}

当然,callocreallocfree 的钩子(Hook)工作方式类似。

动态和静态链接

有了这些功能,动态链接就可以开箱即用。链接包含 malloc 钩子(Hook)实现的 .so 文件将导致应用程序对 malloc 的所有调用以及所有库调用都将通过我的钩子(Hook)进行路由。静态链接是有问题的。我还没有完全理解它,但在静态链接中,malloc 不是一个弱符号,导致链接时出现多重定义错误。

如果您出于任何原因需要静态链接,例如通过调试符号将 3rd 方库中的函数地址转换为代码行,那么您可以静态链接这些 3rd 方库,同时仍然动态链接 malloc Hook ,避免多重定义问题.我还没有找到更好的解决方法,如果您知道,请随时给我留言。

这是一个简短的例子:

gcc -o test test.c -lmalloc_hook_library -Wl,-Bstatic -l3rdparty -Wl,-Bdynamic

3rdparty 将被静态链接,而 malloc_hook_library 将被动态链接,导致预期的行为和 3rdparty 中的函数地址到可通过 test 中的调试符号进行翻译。很整洁,对吧?

结论

上述技术描述了一种未被弃用的、与 __malloc_hook 几乎等效的方法,但有一些平均限制:

__builtin_caller_address 仅适用于 gcc

__libc_malloc 仅适用于 glibc

dlsym(RTLD_NEXT, [...])glibc 中的 GNU 扩展

链接器标志 -Wl,-Bstatic-Wl,-Bdynamic 特定于 GNU binutils。

换句话说,这个解决方案是完全不可移植的,如果要将 hooks 库移植到非 GNU 操作系统,则必须添加替代解决方案。

关于c - glibc 已弃用的 __malloc_hook 功能的替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17803456/

57 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com