-symbolic 和 -shared GCC 标志之间有啥区别?

Posted

技术标签:

【中文标题】-symbolic 和 -shared GCC 标志之间有啥区别?【英文标题】:What's the difference between the -symbolic and -shared GCC flags?-symbolic 和 -shared GCC 标志之间有什么区别? 【发布时间】:2009-10-19 14:15:46 【问题描述】:

从文档的描述来看,它们似乎做了同样的事情,除了“并非所有系统”都支持共享和“只有部分系统”支持符号(不清楚这些系统是否是同一组系统):

-共享 生成一个共享对象,然后可以将其与其他对象链接到 形成一个可执行文件。并非所有系统 支持这个选项。对于可预测的 结果,您还必须指定 相同的一组选项用于 生成代码(-fpic、-fPIC 或模型 子选项)当你指定这个 选项1]

-象征性的 构建共享对象时绑定对全局符号的引用。警告 关于任何未解决的参考 (除非被链接编辑器覆盖 选项 -Xlinker -z -Xlinker defs)。 只有少数系统支持这个 选项。

我怀疑区别在于“生成一个共享对象,然后可以将其与其他对象链接以形成可执行文件”部分,但这听起来像是任何库都适用的东西。这是否意味着生成的共享对象也可以静态链接?

【问题讨论】:

【参考方案1】:

总结:-symbolic 防止内部共享对象函数插入

与共享对象的链接允许一个称为符号插入的功能。这个想法是您可以“插入”全局符号的新定义,以便调用它而不是“常规”定义。

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

默认情况下,共享对象中的任何非静态函数都是全局符号。因此,可以插入共享对象中的任何函数。考虑一个共享对象具有函数 high_level() 和 low_level() 并且 high_level() 调用 low_level() 作为其实现的一部分并且 high_level() 和 low_level() 都不是静态函数的场景。

可以插入 low_level() 以便 high_level() 从不同的共享对象调用 low_level()。

这就是 -symbolic 的用武之地。在创建共享对象时,链接器将看到 low_level() 与 high_level() 在同一个共享对象中定义,并绑定调用以使其无法插入。这样,您就知道从共享对象中的一个函数对同一共享对象中的另一个函数的任何调用都不会被插入。

【讨论】:

难道像 valgrind(也许还有 gprof?)这样的工具不是通过插入来工作的吗?如果我进行 -symbolic 构建,它们会不起作用吗? Valgrind 仍应作为 -symbolic 工作,仅防止内部共享对象插入,不影响共享对象间插入。也就是说,真正重要的是符号绑定的符号是否是 Valgrind 想要插入的符号。 万一有人再次遇到这种情况:这样做的一个重要后果是外部变量不再跨共享库边界工作。

以上是关于-symbolic 和 -shared GCC 标志之间有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

不可见的 GCC 优化标志?

打造一款基于notepad++的C代码开发环境

手把手教你在Keil MDK中使用GCC编译器工具链

在c语言中声明时按索引分配数组

SEGGER编译器会是一个新的“Clang”吗?

升级版 | C和汇编互相调用及规则