关于C#:libc.so和ld

您所在的位置:网站首页 enb是什么格式 关于C#:libc.so和ld

关于C#:libc.so和ld

2023-03-13 11:17| 来源: 网络整理| 查看: 265

一些序言

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

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

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

我在x86_64 linux框中使用gcc对其进行编译,并使用gdb进行一些调试:

12345678910111213141516$ 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           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显示以下内容:

1234567891011121314$ 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清楚地显示了其他含义(两个不同的地址)。为什么 是吗?

gdb在键入break malloc时实际上在两个不同的地址处中断,但在键入info symbol malloc时仅在ld.so中显示符号的信息。为什么会这样?

尽管我在malloc处中断,并且libc.so定义了自己的malloc符号(如nm所示),但gdb在符号__GI___libc_malloc处中断。为什么会这样?

相关讨论 如果确实复制了malloc,那么为什么它不显示在符号中也不中断呢? @Constantius自言自语:malloc是在libc.so和ld-linux.so中复制的,但对于ld-linux.so则是一个弱符号,因此它们都应解析为相同的地址。另外,据我了解,动态加载程序的符号解析表是全局的,每个符号仅解析一个地址(如果我输入错了,请更正我)。 我的意思是ld中的malloc是否具有主体(该函数在此处定义)? @Constantius好的,现在我明白了你的意思,谢谢。是的,很可能它确实具有主体,并且无论最终符号解析度是什么,gdb都会显示该主体。这部分地回答了一些问题,但不是全部,也不是全部:)。

我怀疑GDB会将断点放在它可以找到的所有malloc符号上,可以说"以防万一"。 GDB使用其内部符号表,而不使用动态加载器。这样,如果有调试符号,它可能会在未导出的符号上中断。命令反馈仅列出一个地址,可能在匹配过多的情况下减少噪声。它仍然提到" 2个位置",因此您可以使用info breakpoints自己检查它。 我的猜测是info symbol实现者只是没有预见到这种情况,因此它只打印第一个匹配项 __GI___libc_malloc是libc.so内部malloc的内部,实际实现的名称。由于您还可以获取源代码行信息"at malloc.c:2910",因此我猜测它来自调试符号,而不是来自ELF的symtab。同样,一个位置可以有多个名称(请参见符号列表中的__libc_malloc),因此GDB仅选择一个。

BTW,在加载libc.so时,ld.so \\的GOT中的malloc \\指针确实被libc \\的malloc地址代替(最初它指向内部实现)。因此,当到达进程入口点时,您确实会为两个地址获得相同的地址,并且不再使用ld.so \\的malloc。

相关讨论 明白了感谢您的详细解释。我认为让我感到困惑的是(我猜也可能会发生在其他人身上)是,在gdb选择一种可能的符号(例如"信息符号"和"打印")的情况下,它不会t选择全局一个(即ELF加载器的符号表中的一个)。可以将其视为错误吗? @fons本身可能不是一个" bug",但它可能可以改进。我不确定GDB当前是否完全考虑到符号可见性。我认为发送至GDB邮件列表的电子邮件可能有助于清除问题。

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

相关讨论 是的,我知道ld.so是动态链接器,但是它也是一个使用动态库隐式加载到任何二进制文件的内存空间中的库。顺便说一句,您没有回答我问的三个问题中的任何一个。 不,ld.so不是库,它是静态链接的可执行文件,读取ld.so(8)。实际上,这种格式是用于(现在已经过时)a.out格式的,而今天,动态链接器是用于ELF的ld-linux.so。对于其他问题,我不了解glibc符号魔术的复杂性。 不,这是一个共享库,只需readelf -h /lib64/ld-linux-x86-64.so.2 | grep Type即可,它也可以作为可执行文件。顺便说一句,该手册页(至少在我的发行版中)没有引用,否则引用。 另外,除了我提出的3个问题之外,ld.so(或ld-linux.so)是否合格为库的事实。 为了进一步参考,ld.so是一个自包含的共享库,它碰巧有一个_start符号(这就是为什么它也可用作可执行文件)的原因,但毕竟是共享库。 它是一个共享库,并成为可执行文件以帮助调试。您可以通过尝试将其作为常规可执行文件运行来看到它。 @vonbrand停止引用它,而确实引用了另有说明的文件。如果愿意,您还可以挖掘它的源代码,并发现它具有显式检查,是按常规程序运行还是由内核作为共享库加载。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3