当有多个定义时,函数何时在 GLIBC 中获取 .plt 条目?

When do functions get .plt entries in GLIBC when there are multiple definitions?

一些函数在 GLIBC 库中定义了两次。例如,考虑 _dl_signal_exception:

$ readelf -s libc-2.31.so | grep _dl_signal_exception
   103: 0000000000138130    77 FUNC    GLOBAL DEFAULT   14 _dl_signal_exception@@GLIBC_PRIVATE
$ readelf -s ld-2.31.so | grep _dl_signal_exception
     2: 000000000001a8b0    73 FUNC    GLOBAL DEFAULT   12 _dl_signal_exception@@GLIBC_PRIVATE

ld.so 中的其他函数调用 _dl_signal_exception,因此 _dl_signal_exception 得到一个 .plt 条目,该条目在运行时将实际解析为 libc.so_dl_signal_exception。据我了解,共享库(在 Linux 上)将间接调用函数(除非是静态的)以支持符号插入。

但是libc.so中的其他函数调用了_dl_signal_exception,但是libc.so中没有.plt这个函数的入口。

所以我有两个问题:

  1. 为什么 ld.so 可以从 libc.so 获取它时定义 _dl_signal_exception
  2. 为什么我们在 libc.so 中看不到 _dl_signal_exception.plt 条目?

Why does ld.so define _dl_signal_exception when it can just get it from libc.so?

ld.sospecial -- 它是内核在映射主要可执行文件和 ld.so 之后将控制转移到的目标(路径是硬编码到主要可执行文件的 PT_INTERP 段)。

尚无其他库 -- ld.so 的工作是加载所有其他库。

所以ld.so必须完全独立,不能依赖任何其他库(包括libc.so)。因此,ld.so 有自己的(小)malloclibc 的其他部分需要 openmmap 文件等。

Why don't we see a .plt entry for _dl_signal_exception in libc.so?

许多 libc.so 调用被认为是内部实现细节,并绕过了 .plt。这是在 GLIBC 源代码中使用 internal_call 宏实现的。

例如,fopen(可能)使用 mmap 的事实是内部实现细节,从 fopenmmap 的调用隐藏在中间。