![为什么有些 libc 符号具有 WEAK 绑定,而另一些则具有 GLOBAL 绑定?](https://linux22.com/image/141364/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%9C%89%E4%BA%9B%20libc%20%E7%AC%A6%E5%8F%B7%E5%85%B7%E6%9C%89%20WEAK%20%E7%BB%91%E5%AE%9A%EF%BC%8C%E8%80%8C%E5%8F%A6%E4%B8%80%E4%BA%9B%E5%88%99%E5%85%B7%E6%9C%89%20GLOBAL%20%E7%BB%91%E5%AE%9A%EF%BC%9F.png)
为什么 libc 中的不同符号使用不同的绑定声明,
1510 0x0003d200 0xf7d55200 WEAK FUNC 55 system
454 0x00067b40 0xf7d7fb40 WEAK FUNC 474 puts
147 0x000303d0 0xf7d483d0 GLOBAL FUNC 33 exit
从readelf -s /lib/i386-linux-gnu/libc-2.27.so
,
1510: 0003d200 55 FUNC WEAK DEFAULT 13 system@@GLIBC_2.0
454: 00067b40 474 FUNC WEAK DEFAULT 13 puts@@GLIBC_2.0
147: 000303d0 33 FUNC GLOBAL DEFAULT 13 exit@@GLIBC_2.0
从这个问题,好像作者的libc有一个LOCAL
退出?
不同 libc 绑定级别背后的韵律或原因是什么?
答案1
glibc 中的弱符号即使在静态链接下也允许覆盖。
全球退出是一个强烈的象征。附加定义不会解析,并且会引发链接错误。
因此,您可能能够提供自己的puts
,并且除非第二个定义puts
很强大,否则puts
将选择具有最大内存占用(大小)的。
为什么是最大尺寸?好吧,GCC 需要一些鉴别器,并且大多数 glibc 的结构使得公共符号几乎普遍别名为私有符号,这意味着大小相当小(跳跃)。这意味着,如果您提供自己的 实现puts
,除非您以完全相同的方式将其构造为别名,否则您的实现的可能性更大。对于puts
别名指向__IO_puts
.
这是标准库提供标准库调用实现的机制和允许您覆盖它们。
答案2
问题的答案什么从技术角度来看正在发生的是Edwin 提到的原因的实现细节(符号别名)。但更重要的是,它之所以存在,是因为它是偶然的,而且它适合打补丁。
15:14 < azanella> EvanCarroll,它是一个实现细节,
exit
不在内部使用,因此不需要定义带有别名的内部符号[...],system
并且puts
都由带有别名的不同符号实现[ ...] 但这是一个很好的问题,我相信对于exit
这种情况,glibc 并不是真正专注于静态链接,并且没有人提出任何试图在静态链接中覆盖它的问题
来自 2018 年 10 月 31 日 irc.freenode.net 上的 #glibc