似乎malloc,calloc,realloc和free都在ld-linux.so
和libc.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
malloc
在libc.so
和ld-linux.so
中被复制,但在ld-linux.so
的情况下,它是一个弱符号,所以他们都应该解析为相同的地址。另外,据我所知,动态加载器的符号解析表是全局的,每个符号只解析一个地址(如果我错了,请纠正我)。
但是,gdb清楚地显示了其他信息(两个不同的地址)。为什么 那是吗?
在键入break malloc
时,gdb在两个不同的地址有效中断,但在键入info symbol malloc
时仅显示ld.so中符号的信息。那是为什么?
虽然我在malloc打破并且libc.so
定义了自己的malloc
符号(如nm所示),但gdb在符号__GI___libc_malloc
处中断。那是为什么?
答案 0 :(得分:2)
malloc
个符号上放置断点,“以防万一”可以这么说。 GDB使用其内部符号表,而不是动态加载器。这样,如果您有调试符号,它可以在非导出符号上中断。命令反馈仅列出一个地址,可能在匹配太多时减少噪声。它仍然提到“2个位置”,因此您可以使用info breakpoints
自行检查。info symbol
实施者只是没有预见到这种情况所以只打印第一场比赛__GI___libc_malloc
是libc.so中malloc
的内部实际实现的名称。由于您还获得了源代码行信息"at malloc.c:2910"
,我猜测它来自调试符号,而不是来自ELF的symtab。同样,一个位置可以有许多名称(请参阅符号列表中的__libc_malloc
),因此GDB只选择一个。顺便说一句,当libc.so被加载时,ld.so的GOT中的malloc
指针确实被libc的malloc
地址取代(最初它指向内部实现)。因此,当到达进程入口点时,您确实获得了相同的地址,并且不再使用ld.so的malloc
。
答案 1 :(得分:-1)
ld.so
不是库,它是动态链接器(通过在程序启动时将可执行文件与共享库链接起来,隐式调用以在内存中创建可运行映像)。