![ELF 符号可见性级别之间有什么区别?](https://linux22.com/image/11842/ELF%20%E7%AC%A6%E5%8F%B7%E5%8F%AF%E8%A7%81%E6%80%A7%E7%BA%A7%E5%88%AB%E4%B9%8B%E9%97%B4%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%EF%BC%9F.png)
您还可以选择控制符号的 ELF 可见性。只需添加可见性关键字之一:
default
、internal
、hidden
或protected
。当然是默认default
的。
这些是在哪里定义的?以及如何ld
使用它们?我懂了C++ 中经常提到的访问级别包括受保护的,民众, 和 私人的,但不知道ELF指的是不是这个?
我的用例是 C 和汇编,因此如果您能让这与这两种语言和链接器相关,那就加分了。
答案1
看来从NASM来源这些似乎与文档相对应甲骨文《链接器和库指南》,这些似乎对应于STV_DEFAULT
、STV_INTERNAL
、STV_HIDDEN
和STV_PROTECTED
。
甲骨文是这样说的:
STV_DEFAULT
具有该属性的符号的可见性STV_DEFAULT
由符号的绑定类型指定。也就是说,全局符号和弱符号在其定义组件、可执行文件或共享对象之外是可见的。局部符号被隐藏。全局符号和弱符号也可以被抢占,也就是说,它们可以被另一个组件中的同名定义插入。
STV_PROTECTED
如果当前组件中定义的符号在其他组件中可见但不能被抢占,则该符号受到保护。定义组件内对此类符号的任何引用都必须解析为该组件中的定义,即使另一个组件中存在按默认规则插入的定义。具有绑定的符号STB_LOCAL
将不具有STV_PROTECTED
可见性。
STV_HIDDEN
如果当前组件中定义的符号的名称对其他组件不可见,则该符号将被隐藏。这样的符号必然受到保护。该属性用于控制组件的外部接口。如果将其地址传递到外部,则由此类符号命名的对象仍可以从另一个组件引用。
STB_LOCAL
当可重定位对象包含在可执行文件或共享对象中时,链接编辑器将删除可重定位对象中包含的隐藏符号或将其转换为绑定。
STV_INTERNAL
该可见性属性当前已被保留。
至于对C和Assembly的影响,Oracle 文档继续说
在链接编辑期间,任何可见性属性都不会影响可执行文件或共享库中符号的解析。这种分辨率由绑定类型控制。一旦链接编辑器选择了其分辨率,这些属性就会提出两个要求。这两个要求都基于以下事实:链接的代码中的引用可能已被优化以利用属性。
首先,当应用于符号引用时,所有非默认可见性属性都意味着必须在当前可执行文件或共享对象中提供满足该引用的定义。如果这种类型的符号引用在所链接的组件内没有定义,则该引用必须具有
STB_WEAK
绑定并解析为零。其次,如果对名称的任何引用或定义是具有非默认可见性属性的符号,则必须将可见性属性传播到链接对象中的解析符号。如果为符号的不同引用或定义指定了不同的可见性属性,则必须将最具约束力的可见性属性传播到链接对象中的解析符号。属性按从最小约束到最大约束的顺序排列为
STV_PROTECTED
、STV_HIDDEN
和STV_INTERNAL
。
也可以看看