为什么libc.so符号表中没有main_arena,而glibc2.23的malloc.c中有一个?

时间:2016-06-22 07:03:16

标签: linux malloc glibc libc

我正在研究glibc的堆。

libc.so中没有main_arena符号,即使我尝试使用pwntool转储它。但是,当我调试测试程序时,我可以打印main_arena结构。

gdb-peda$ p main_arena
$1 = {
    mutex = 0x0, 
    flags = 0x0, 
    fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 
    top = 0x0, 
    last_remainder = 0x0, 
    bins = {0x0 <repeats 254 times>}, 
    binmap = {0x0, 0x0, 0x0, 0x0}, 
    next = 0x7ffff7dd1b20 <main_arena>, 
    next_free = 0x0, 
    attached_threads = 0x1, 
    system_mem = 0x0, 
    max_system_mem = 0x0
}

此外,当我用-m32编译测试程序时,也找不到main_arena。

2 个答案:

答案 0 :(得分:2)

main_arena是本地符号,特别是不会导出。导出符号列表通过glibc源代码树中的Version文件控制。根据设计,这是为了防止人们无法链接glibc内部使用的随机符号(以便不像POSIX和其他标准那样污染命名空间)。

gdb可以找到它,因为您有可用的调试符号... C lib未被剥离,或者您在/usr/lib/debug/中有拆分调试符号,gdb正在查找这些符号。当你启动gdb时,它会告诉你像Reading symbols from /usr/lib/debug/xxxxx

这样的东西

能够链接符号的唯一方法是从源重建glibc并修改导出列表。

或者,你可以在你的应用程序中编写一些代码来表现得像gdb。即,打开调试文件,处理其中的ELF / DWARF信息,使用活动加载的库信息应用重定位(请参阅dl_iterate_phdr),然后直接开始戳内存。

如果这工作太多,那么hackery解决方案可能针对您自己的进程fork() + popen() gdb,并以批处理模式运行它以转储符号信息。

char *cmd;
FILE *fp;

asprintf(&cmd, "gdb -q -p %i -batch -ex 'p &main_arena'", getpid());
fp = popen(cmd, "r");
// parse the output of |fp| here looking for the address.

free(cmd);
fclose(fp);

答案 1 :(得分:0)

剥离了libc.so.6。 它的调试版本不是。 这就是为什么readelf没有显示main_arena的原因。

我仍然想知道gdb如何知道符号名称,即使文件被剥离了。