【发布时间】:2020-08-31 15:36:42
【问题描述】:
虽然我可以编写合理的 C 代码,但我的专长主要是 Java,所以如果这个问题没有意义,我深表歉意。
我正在编写一些代码来帮助我进行堆分析。我通过使用 LLVM 进行检测来做到这一点。我正在寻找的是一种从自身内部访问进程的堆元数据的方法。这样的事情可能吗?我知道有关堆的信息存储在许多malloc_state 结构中(例如main_arena)。如果我可以访问main_arena,我可以开始枚举不同的竞技场、堆、垃圾箱等。据我了解,这些变量都是静态定义的,因此无法访问。
但是有什么方法可以获取这些信息吗?例如,我可以使用/proc/$pid/mem 以某种方式泄露信息吗?
一旦我有了这些信息,我想基本上得到关于所有不同空闲列表的信息。因此,对于每种 bin 类型中的每个 bin,我想要 bin 中的块数及其大小。对于快速、小型和 tcache 箱,我知道我只需要索引来确定大小。我已经研究了这些结构是如何实现的以及如何遍历它们。所以我所需要的就是访问这些内部结构。
我查看了malloc_info,这是我的后备方案,但我也想获得有关tcache 的信息,我认为malloc_info 中不包含这些信息。
我考虑过的一个选项是构建一个自定义版本的 glibc,以非静态方式声明 malloc_struct 变量。但据我所知,构建自己的自定义 glibc 并不是很简单,因为您必须构建整个工具链。我正在使用clang,所以我必须根据我的自定义glibc从源代码构建LLVM(至少这是我通过研究这种方法所理解的)。
【问题讨论】:
-
你应该拉取
glibc的源代码。在malloc子目录下,您可以检查所有源代码。特别是,查看hooks.c,有一个公共[非静态]函数:void *__malloc_get_state(void),它将来自各种子结构的很多信息序列化为struct malloc_save_state指针[即alloc'在内部编辑——因此,必须被释放]。由于有一个恢复:__malloc_set_state,我假设给定的结构有 everything 人们可能关心的(例如主竞技场、fastbins、binmap、bins,...)。glibc也有各种钩子函数。 -
我相信你可以得到你想要[和/或需要]的东西,用上面和其他的钩子。我以前使用过这些钩子,我认为它们比尝试使用
/proc/self/mem[它只是映射原始内存——不太有用] 有用得多。 如果您需要查找未导出的内容,您可能会更幸运地解析readelf libc.so输出或使用ELF [或bfd] 库来查找符号和与公共符号的地址(例如malloc)组合/重定位以找到正确的地址。如果您需要.so负载的基地址,您可以解析/proc/self/maps -
@CraigEstey 不幸的是,
malloc_{get,set}_state在很久以前在 glibc 2.25 中被删除了。见here。 -
@MarcoBonelli 当然……它们很有用。我在fedora
fc29在家里,glibc 2.28,但我在看一个更旧的(fc22glibc 源)。刚刚拉到fc29,是的,它已经消失了。它对调试很有用,但看起来它是为emacs[per cmets] 实现某种 hack。尽管如此,ELF 还是将main_arena作为本地符号,因此可以通过 maps/bfd 获取它的地址并从 glibc 源中抓取必要的struct定义以拼凑一些东西。
标签: c malloc heap-memory glibc libc