使用gold vs ld链接器时使用的glibc/pthreads中的不同符号

前端之家收集整理的这篇文章主要介绍了使用gold vs ld链接器时使用的glibc/pthreads中的不同符号前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我有一个简单的测试程序调用pthread_cond_broadcast.

与ld链接链接时,显示

情况1:

$nm ld-test  | grep cond_broadcast
U pthread_cond_broadcast@@GLIBC_2.3.2

当与黄金链接链接时,它显示

案例2:

 $nm gold-test  | grep cond_broadcast
 U pthread_cond_broadcast

pthread / libc包含几个带有不同版本符号的pthread_cond_broadcast符号,可能是因为ABI已被更改.

$nm  /lib64/libc.so.6  |grep cond_broadca
00000036b84f7d30 t __pthread_cond_broadcast
00000036b85278f0 t __pthread_cond_broadcast_2_0
00000036b84f7d30 T pthread_cond_broadcast@@GLIBC_2.3.2
00000036b85278f0 T pthread_cond_broadcast@GLIBC_2.2.5
$nm  /lib64/libpthread.so.0  |grep cond_broadcast
00000036b880bee0 t __pthread_cond_broadcast
00000036b880c250 t __pthread_cond_broadcast_2_0
00000036b880bee0 T pthread_cond_broadcast@@GLIBC_2.3.2
00000036b880c250 T pthread_cond_broadcast@GLIBC_2.2.5

所以问题是:

>为什么黄金和旧/普通ld之间的行为不同.
>当二进制文件链接到无版本的pthread_cond_broadcast符号时,在案例2中运行时使用了哪个pthread_cond_broadcast符号. pthread_cond_broadcast的最新实现?最老的 ?

这是使用gcc 4.9.2和binutils 2.24中的gold / ld链接器(作为Red Hat的devtoolset-3的一部分.)

最佳答案
首先澄清一下:ELF文件通常有两个符号表.包含所有内部符号的“胖”或“完整”符号(通常位于SHT_SYMTAB类型的.symtab部分中),并且只有包含运行时详细信息的“slim”部分(通常位于名为.dynsym的部分中)输入SHT_DYNSYM). nm只解析第一个,因此它通常不是运行时行为的良好指标.你想使用readelf -s,然后查看.dynsym表来查看运行时真正重要的内容.

(1)我不知道为什么调试符号表在使用黄金时不包含完整的符号版本控制.对我来说似乎是个错误.

(2)一旦查看运行时符号表,您的答案就会自动出现:将使用pthread_cond_broadcast@GLIBC_2.3.2.

(2a)关于将从哪个库加载的库,这完全取决于ELF的链接方式和运行时环境.让我们忽略所有的可能性并专注于常见的:如果你与-lpthread链接,那么将使用libpthread.so中的版本.如果你没有,那么将使用libc.so中的版本.

(2b)为什么单个库有多个版本(例如libc.so有pthread_cond_broadcast @@ GLIBC_2.2.5和pthread_cond_broadcast @@ GLIBC_2.3.2)?你正确地猜到它是为了向后兼容.在过去的某个时刻,ABI已被更改,因此他们不是破坏所有现有应用程序,而是更新了版本.所有与旧glibc版本链接的程序都将使用旧符号版本,而新程序将使用新符号.作为一个策略问题,glibc将最新的符号版本公开为默认版本,因此当您使用pthread_cond_broadcast时,您将与pthread_cond_broadcast @@ GLIBC_2.3.2链接.这纯粹是大多数人都使用的约定……虽然技术上可以将它们中的任何一个暴露为默认版本.

(2c)为什么符号存在于libc.so& libpthread.so?这允许库支持多线程环境,不会在单线程环境中受到惩罚,或者不必编写两个不同的库,例如:一个名为libfoo.so,另一个名为libfoo_thread.so. libc.so中的符号是虚拟符号 – 它们总是返回“成功”.因此,如果您的主程序不是多线程的,则libfoo.so中的所有调用都将被删除.但如果您的主程序是多线程的(即链接到-lpthread),则符号将是透明的&自动路由到libpthread.so并且libfoo.so中的所有调用都将DTRT(即抓取互斥锁/等…).

原文链接:https://www.f2er.com/linux/440970.html

猜你在找的Linux相关文章