fon*_*ons 6 c linux linker gdb glibc
似乎 malloc、calloc、realloc 和 free 都在ld-linux.soand 中复制了libc.so。据我了解,这是由动态加载器完成的,用于在加载ld-linux.so之前处理内存管理libc.so并使其内存管理功能可用。但是,我对那些重复的符号有一些疑问:
这是一个非常简单的 C 程序调用 malloc 并退出:
#include <stdlib.h>
int main()
{
void *p = malloc(8);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在 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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
malloc被复制在libc.soandld-linux.so但在ld-linux.so它的情况下是一个弱符号,所以它们都应该解析到相同的地址。此外,据我所知,动态加载器的符号解析表是全局的,每个符号只解析一个地址(如果我错了,请纠正我)。
但是,gdb 清楚地表明并非如此(两个不同的地址)。这是为什么?
gdb 在键入时有效地在两个不同的地址中断,break malloc但在键入时仅显示 ld.so 中的符号信息info symbol malloc。这是为什么?
尽管我在 malloc 处中断并libc.so定义了malloc它自己的符号(如 nm 所示),但 gdb 在符号处中断__GI___libc_malloc。这是为什么?
malloc,可以这么说,“以防万一”。GDB 使用其内部符号表,而不是动态加载器的符号表。这样,如果您有调试符号,它可以在非导出符号上中断。命令反馈仅列出一个地址,可能是为了在匹配太多的情况下减少噪音。它仍然提到“2 个位置”,因此您可以使用 自行检查info breakpoints。info symbol实施者只是没有预见到这种情况,所以它只打印第一个匹配项__GI___libc_mallocmalloc是libc.so 内部实际实现的名称。由于您还获得了源行信息"at malloc.c:2910",我猜测它来自调试符号而不是来自 ELF 的符号表。同样,一个位置可以有多个名称(请参见__libc_malloc符号列表),因此 GDB 仅选择一个。顺便说一句,当 libc.so 加载时malloc,ld.so 的 GOT 中的 ' 指针确实会被 libc 的malloc地址替换(最初它指向内部实现)。因此,当到达进程入口点时,您确实会获得相同的地址,并且malloc不再使用ld.so。
| 归档时间: |
|
| 查看次数: |
1221 次 |
| 最近记录: |