“-symbolic”和“-shared” GCC标志有什么区别?

9
根据文档的描述,它们似乎做着相同的事情,只是“不是所有系统”都支持共享,“只有一些系统”支持符号(不清楚这些系统是否是同一组系统):
-shared 生成一个共享对象,可以与其他对象链接以形成可执行文件。并非所有系统都支持此选项。为了获得可预测的结果,您必须在指定此选项时同时指定用于生成代码的相同选项(-fpic、-fPIC或模型子选项)。
-symbolic 在构建共享对象时绑定对全局符号的引用。警告任何未解决的引用(除非被链接编辑器选项-Xlinker -z -Xlinker defs覆盖)。只有少数系统支持此选项。
我怀疑区别在于“生成一个共享对象,可以与其他对象链接以形成可执行文件”的部分,但这听起来像任何库都是正确的。这是否意味着生成的共享对象也可以静态链接?
1个回答

8

概述:-symbolic可以防止共享对象函数内部的相互干扰。

与共享对象链接允许使用符号重定位功能。这意味着您可以“插入”全局符号的新定义,以便调用它而不是“常规”定义。

一个经典的例子是malloc()。在最常见的情况下,malloc()在libc中定义。但是,您可以通过加载定义该符号的库来插入自己的malloc版本,然后加载libc(大多数运行时链接器允许您使用LD_PRELOAD指定要在可执行文件之前加载的库)。

默认情况下,共享对象中的任何非静态函数都是全局符号。因此,共享对象中的任何函数都可以进行重定位。考虑这样一种情况:共享对象具有高级别函数和低级别函数,并且高级别函数作为其实现的一部分调用低级别函数,而高级别函数和低级别函数都不是静态函数。

可以插入低级别函数,以便高级别函数调用来自不同共享对象的低级别函数。

-symbolic就是为了解决这个问题。创建共享对象时,链接器将看到低级别函数在与高级别函数相同的共享对象中定义,并绑定调用,使其无法进行重定位。这样,您就知道从共享对象中的一个函数调用到同一共享对象中的另一个函数永远不会被重定位。


像valgrind(也许包括gprof)这样的工具不是通过插入来工作的吗?如果我进行符号化构建,它们不会工作吗? - Joseph Garvin
Valgrind 应该仍然可以工作,因为“-symbolic” 仅防止共享对象内部的重定向,不影响共享对象之间的重定向。也就是说,真正重要的是已经被符号绑定的符号是否是 Valgrind 想要进行重定向的符号。 - R Samuel Klatchko
1
如果有人再次发现这个问题:其中一个重要的后果是,在共享库边界上不再能够使用“extern”变量。 - Joseph Garvin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接