libc.so和ld-linux.so中的重复内存管理符号

时间:2013-02-14 02:49:27

标签: c linux linker gdb glibc

一些序言

似乎malloc,calloc,realloc和free都在ld-linux.solibc.so中复制。据我了解,这是由动态加载程序完成的,在加载ld-linux.so之前在libc.so内处理内存管理并使其内存管理功能可用。但是,我对这些重复的符号有一些疑问:

这是一个非常简单的C程序,调用malloc并退出:

#include <stdlib.h>

int main()
{
  void *p = malloc(8);
  return 0;
}

我在x86_64 linux框中用gcc编译它并用gdb进行一些调试:

$ gcc -g -o main main.c
$ gdb ./main
(gdb) start
Temporary breakpoint 1 at 0x4004f8
Starting program: main 

Temporary breakpoint 1, 0x00000000004004f8 in main ()
(gdb) info symbol malloc
malloc in section .text of /lib64/ld-linux-x86-64.so.2
(gdb) b malloc
Breakpoint 2 at 0x7ffff7df0930: malloc. (2 locations)
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   <MULTIPLE>         
2.1                         y     0x00007ffff7df0930 in malloc at dl-minimal.c:95
2.2                         y     0x00007ffff7a9f9d0 in __GI___libc_malloc at malloc.c:2910
libc.so和ld.so中的

nm显示以下内容:

$ nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep malloc
00000000000829d0 T __libc_malloc
00000000003b6700 V __malloc_hook
00000000003b8b00 V __malloc_initialize_hook
00000000000829d0 T malloc
0000000000082db0 W malloc_get_state
00000000000847c0 T malloc_info
0000000000082480 W malloc_set_state
00000000000844f0 W malloc_stats
0000000000084160 W malloc_trim
00000000000844b0 W malloc_usable_size

$ nm -D /lib64/ld-linux-x86-64.so.2 | grep malloc
0000000000016930 W malloc

问题

  1. malloclibc.sold-linux.so中被复制,但在ld-linux.so的情况下,它是一个弱符号,所以他们都应该解析为相同的地址。另外,据我所知,动态加载器的符号解析表是全局的,每个符号只解析一个地址(如果我错了,请纠正我)。

    但是,gdb清楚地显示了其他信息(两个不同的地址)。为什么 那是吗?

  2. 在键入break malloc时,gdb在两个不同的地址有效中断,但在键入info symbol malloc时仅显示ld.so中符号的信息。那是为什么?

  3. 虽然我在malloc打破并且libc.so定义了自己的malloc符号(如nm所示),但gdb在符号__GI___libc_malloc处中断。那是为什么?

2 个答案:

答案 0 :(得分:2)

  1. 我怀疑GDB只是在它可以找到的所有malloc个符号上放置断点,“以防万一”可以这么说。 GDB使用其内部符号表,而不是动态加载器。这样,如果您有调试符号,它可以在非导出符号上中断。命令反馈仅列出一个地址,可能在匹配太多时减少噪声。它仍然提到“2个位置”,因此您可以使用info breakpoints自行检查。
  2. 我的猜测是info symbol实施者只是没有预见到这种情况所以只打印第一场比赛
  3. __GI___libc_malloc是libc.so中malloc的内部实际实现的名称。由于您还获得了源代码行信息"at malloc.c:2910",我猜测它来自调试符号,而不是来自ELF的symtab。同样,一个位置可以有许多名称(请参阅符号列表中的__libc_malloc),因此GDB只选择一个。
  4. 顺便说一句,当libc.so被加载时,ld.so的GOT中的malloc指针确实被libc的malloc地址取代(最初它指向内部实现)。因此,当到达进程入口点时,您确实获得了相同的地址,并且不再使用ld.so的malloc

答案 1 :(得分:-1)

ld.so不是库,它是动态链接器(通过在程序启动时将可执行文件与共享库链接起来,隐式调用以在内存中创建可运行映像)。