"-fno-semantic-interposition"与"-fvisibility=p

How, exactly, is `-fno-semantic-interposition` different than `-fvisibility=protected`?

本文关键字:quot -fno-semantic-interposition -fvisibility      更新时间:2023-10-16

From https://gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/Optimize-Options.html#index-fsemantic-interposition

-语义插入

某些对象格式(如 ELF(允许通过动态链接器插入符号。这意味着对于从 DSO 导出的符号,编译器无法执行过程间传播、内联和其他优化,以预期相关函数或变量可能会更改。虽然此功能很有用,例如,通过调试实现重写内存分配函数,但在代码质量方面却很昂贵。使用 -fno-semantic-interposition,编译器假定如果函数发生插入,则覆盖函数将具有完全相同的语义(和副作用(。同样,如果变量发生插入,则变量的构造函数将是相同的。该标志对显式内联声明的函数(其中永远不允许插入更改语义(和显式声明弱的符号无效。

从 https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-visibility-function-attribute

保护

受保护的可见性与默认可见性类似,不同之处在于它指示定义模块中的引用绑定到该模块中的定义。也就是说,声明的实体不能被另一个模块覆盖。

这听起来完全一样。

除了将任何明确标记为default的功能更改为protected-fno-semantic-interposition之外,是否有任何真正的区别?

这个问题很难回答,因为目前-fsemantic-interposition实际上不起作用。 在此示例中,

int a;
int
f1 (int a)
{
return a;
}
int
f2 (void)
{
return f1 (a) - a;
}

即使使用-O2 -fsemantic-interposition(以及-O2 -fno-semantic-interposition,如果选项的含义在文档中颠倒(,f2的主体也会有效地优化为return 0;(。 我提交了一个错误。

可能的意图是-fsemantic-interposition将禁用此类优化,以便您最终调用f1显式计算结果。

ELF 符号可见性与此无关,主要是因为它仅适用于动态链接。 链接编辑器仍然可以在静态链接时插入符号(例如,使用-z muldefs选项(,因此编译器应该真正提供一种在不更改符号属性的情况下启用插入的方法(因此除了__attribute__ ((weak))之外的其他内容(。

-fno-semantic-interposition应该是关于代码生成的。-fvisibility=protected是关于符号属性的。protected可见性出现在-fsemantic-interposition之前,正如 Ulrich Drepper 的 How to Write Shared Library 中所解释的那样,这是一个你不应该使用的可见性属性。

通用 ELF ABI 定义了另一种可见性模式:受保护。在 此方案对同一对象中定义的符号的引用是 总是在当地满意。但这些符号在外面仍然可用 DSO。这听起来像是通过以下方式优化 DSO 的理想机制 避免使用导出的符号(请参阅第 2.2.7 节(,但事实并非如此。 处理对受保护符号的引用甚至比 正常查找。问题是ISO C标准中的一个要求。 该标准要求函数指针指向相同的 功能,可以比较平等。违反此规则将违反 快速、简单地实施受保护的 能见度。假设一个应用程序引用了 pro- 在 DSO 中执行的功能。同样在DSO中是另一个 引用所述函数的函数。中的指针 应用程序指向函数的 PLT 条目 在应用程序的 PLT 中。如果受保护的符号查找 将简单地返回内部函数的地址 DSO地址会有所不同。 在没有此要求的编程环境中 在函数指针上使用受保护的可见性 将是有用和快速的。但由于通常只有 系统上动态链接器的一个实现 TEM 和这个实现必须处理 C 程序 同样,强烈建议不要使用受保护的。

如果您希望库引用自己的全局变量而没有插入的可能性(并且由于避免了 PLT 而使函数的速度更快(,首选方法是使用隐藏别名定义符号并在内部使用隐藏别名。