目标文件的符号表包含定位和重定位程序的符号定义和符号引用所需的信息。符号表索引是此数组的下标。索引 0 指定表中的第一项并用作未定义的符号索引。 请参见表 7–21。
符号表项具有以下格式。 请参见 sys/elf.h。
typedef struct { Elf32_Word st_name; Elf32_Addr st_value; Elf32_Word st_size; unsigned char st_info; unsigned char st_other; Elf32_Half st_shndx; } Elf32_Sym; typedef struct { Elf64_Word st_name; unsigned char st_info; unsigned char st_other; Elf64_Half st_shndx; Elf64_Addr st_value; Elf64_Xword st_size; } Elf64_Sym;
目标文件的符号字符串表的索引,其中包含符号名称的字符表示形式。如果该值为非零,则表示指定符号名称的字符串表索引。否则,符号表项没有名称。
关联符号的值。根据上下文,该值可以是绝对值或地址。 请参见符号值。
许多符号具有关联大小。例如,数据目标文件的大小是目标文件中包含的字节数。如果符号没有大小或大小未知,则此成员值为零。
符号的类型和绑定属性。表 7–18 中显示了值和含义的列表。以下代码说明了如何处理这些值。 请参见 sys/elf.h。
#define ELF32_ST_BIND(info) ((info) >> 4) #define ELF32_ST_TYPE(info) ((info) & 0xf) #define ELF32_ST_INFO(bind, type) (((bind)<<4)+((type)&0xf)) #define ELF64_ST_BIND(info) ((info) >> 4) #define ELF64_ST_TYPE(info) ((info) & 0xf) #define ELF64_ST_INFO(bind, type) (((bind)<<4)+((type)&0xf))
符号的可见性。表 7–20 中显示了值和含义的列表。以下代码说明了如何处理 32 位目标文件和 64 位目标文件的值。其他位设置为零,并且未定义任何含义。
#define ELF32_ST_VISIBILITY(o) ((o)&0x3) #define ELF64_ST_VISIBILITY(o) ((o)&0x3)
所定义的每一个符号表项都与某节有关。此成员包含相关节头表索引。部分节索引会表示特殊含义。 请参见表 7–4。
如果此成员包含 SHN_XINDEX,则实际节头索引会过大而无法放入此字段中。实际值包含在 SHT_SYMTAB_SHNDX 类型的关联节中。
根据符号的 st_info 字段确定的符号绑定可确定链接可见性和行为。
表 7–18 ELF 符号绑定:ELF32_ST_BIND 和 ELF64_ST_BIND
名称 |
值 |
---|---|
STB_LOCAL |
0 |
STB_GLOBAL |
1 |
STB_WEAK |
2 |
STB_LOOS |
10 |
STB_HIOS |
12 |
STB_LOPROC |
13 |
STB_HIPROC |
15 |
此范围内包含的值保留用于特定于操作系统的语义。
此范围内包含的值保留用于特定于处理器的语义。
链接编辑器合并多个可重定位目标文件时,不允许多次定义相同名称的 STB_GLOBAL 符号。但是,如果存在已定义的全局符号,则出现相同名称的弱符号不会导致错误。链接编辑器会接受全局定义,并忽略弱定义。
同样,如果存在通用符号,则出现相同名称的弱符号也不会导致错误。链接编辑器将使用通用定义,并忽略弱定义。通用符号具有包含 SHN_COMMON 的 st_shndx 字段。 请参见符号解析。
链接编辑器搜索归档库时,将会提取包含未定义全局符号或暂定全局符号的定义的归档成员。此成员的定义可以是全局符号或弱符号。
缺省情况下,链接编辑器不会提取归档成员来解析未定义的弱符号。未解析的弱符号的值为零。使用 -z weakextract 可覆盖此缺省行为。使用此选项,弱引用可提取归档成员。
弱符号主要适用于系统软件。建议不要在应用程序中使用弱符号。
在每个符号表中,具有 STB_LOCAL 绑定的所有符号都优先于弱符号和全局符号。如节中所述,符号表节的 sh_info 节头成员包含第一个非局部符号的符号表索引。
根据符号的 st_info 字段确定的符号类型用于对关联实体进行一般分类。
表 7–19 ELF 符号类型:ELF32_ST_TYPE 和 ELF64_ST_TYPE
名称 |
值 |
---|---|
STT_NOTYPE |
0 |
STT_OBJECT |
1 |
STT_FUNC |
2 |
STT_SECTION |
3 |
STT_FILE |
4 |
STT_COMMON |
5 |
STT_TLS |
6 |
STT_LOOS |
10 |
STT_HIOS |
12 |
STT_LOPROC |
13 |
STT_SPARC_REGISTER |
13 |
STT_HIPROC |
15 |
未指定符号类型。
此符号与变量、数组等数据目标文件关联。
此符号与函数或其他可执行代码关联。
此符号与节关联。此类型的符号表各项主要用于重定位,并且通常具有 STB_LOCAL 绑定。
通常,符号的名称会指定与目标文件关联的源文件的名称。文件符号具有 STB_LOCAL 绑定和节索引 SHN_ABS。此符号(如果存在)位于文件的其他 STB_LOCAL 符号前面。
符号索引为 1 的 SHT_SYMTAB 是表示目标文件的 STT_FILE 符号。通常,此符号后跟文件的 STT_SECTION 符号。这些节符号又后跟已降为局部符号的任何全局符号。
此符号标记未初始化的通用块。此符号的处理与对 STT_OBJECT 的处理完全相同。
此符号指定线程局部存储实体。定义后,此符号可为符号指明指定的偏移,而不是实际地址。
线程局部存储重定位只能引用 STT_TLS 类型的符号。从可分配节中引用 STT_TLS 类型的符号只能通过使用特殊线程局部存储重定位来实现。 有关详细信息,请参见第 8 章,线程局部存储。从非可分配节中引用 STT_TLS 类型的符号没有此限制。
此范围内包含的值保留用于特定于操作系统的语义。
此范围内包含的值保留用于特定于处理器的语义。
符号的可见性根据其 st_other 字段确定。此可见性可以在可重定位目标文件中指定。此可见性定义了在符号成为可执行文件或共享库的一部分后访问该符号的方式。
表 7–20 ELF 符号可见性
名称 |
值 |
---|---|
STV_DEFAULT |
0 |
STV_INTERNAL |
1 |
STV_HIDDEN |
2 |
STV_PROTECTED |
3 |
具有 STV_DEFAULT 属性的符号的可见性与符号的绑定类型指定的可见性相同。全局符号和弱符号在其定义组件(可执行文件或共享库)外部可见。局部符号处于隐藏状态。另外,还可以替换全局符号和弱符号。可以在另一个组件中通过定义相同的名称插入这些符号。
如果当前组件中定义的符号在其他组件中可见,但不能被替换,则该符号会处于受保护状态。定义组件中对这类符号的任何引用都必须解析为该组件中的定义。即使在另一个组件中存在按缺省规则插入的符号定义,也必须进行此解析。具有 STB_LOCAL 绑定的符号将没有 STV_PROTECTED 可见性。
如果当前组件中定义的符号的名称对于其他组件不可见,则该符号处于隐藏状态。必须对这类符号进行保护。此属性用于控制组件的外部接口。由这样的符号命名的目标文件仍可以在另一个组件中引用(如果将目标文件的地址传到外部)。
如果可执行文件或共享库中包括可重定位目标文件,则该目标文件中包含的隐藏符号将会删除或转换为使用 STB_LOCAL 绑定。
此可见性属性当前被保留。
在链接编辑过程中,可见性属性不会影响可执行文件或共享库中符号的解析。这样的解析由绑定类型控制。一旦链接编辑器选定了其解析,这些属性即会强加两种要求。两种要求都基于以下事实,即所链接的代码中的引用可能已优化,从而可利用这些属性。
所有非缺省可见性属性在应用于符号引用时都表示,在链接的目标文件中必须提供满足该引用的定义。如果在链接的目标文件中没有定义此类型的符号引用,则该引用必须具有 STB_WEAK 绑定。在此情况下,引用将解析为零。
如果任何名称的引用或定义是具有非缺省可见性属性的符号,则该可见性属性将传播给链接的目标文件中的解析符号。如果针对符号的不同实例指定不同的可见性属性,则最具约束的可见性属性将传播给链接的目标文件中的解析符号。这些属性按最低到最高约束进行排序,依次为 STV_PROTECTED、STV_HIDDEN 和 STV_INTERNAL。
如果符号的值指向节中的特定位置,则符号的节索引成员 st_shndx 会包含节头表的索引。节在重定位过程中移动时,符号的值也会更改。符号的引用仍然指向程序中的相同位置。一些特殊节索引值会具有其他语义:
此符号标记尚未分配的通用块。与节的 sh_addralign 成员类似,符号的值也会指定对齐约束。链接编辑器在值为 st_value 的倍数的地址位置为符号分配存储空间。符号的大小会指明所需的字节数。
此节表索引表示未定义符号。链接编辑器将此目标文件与用于定义所表示的符号的另一目标文件合并时,此文件中对该符号的引用将与该定义绑定。
如之前所述,索引 0 (STN_UNDEF) 的符号表项会保留。此项具有下表中列出的值。
表 7–21 ELF 符号表项:索引 0
名称 |
值 |
说明 |
---|---|---|
st_name |
0 |
无名称 |
st_value |
0 |
零值 |
st_size |
0 |
无大小 |
st_info |
0 |
无类型,本地绑定 |
st_other |
0 |
|
st_shndx |
SHN_UNDEF |
无节 |
不同目标文件类型的符号表的各项对于 st_value 成员的解释稍有不同。
在可重定位文件中,st_value 包含所定义符号的节偏移。st_value 表示从 st_shndx 所标识的节的起始位置的偏移。
在可执行文件和共享库文件中,st_value 包含虚拟地址。为使这些文件的符号更适用于运行时链接程序,节偏移(文件解释)会替换为与节数无关的虚拟地址(内存解释)。
尽管符号表值对于不同的目标文件具有类似含义,但通过适当的程序可以有效地访问数据。
SPARC 体系结构支持用于初始化全局寄存器的寄存器符号。下表中列出了寄存器符号的符号表项包含的各项。
表 7–22 SPARC: ELF 符号表项:寄存器符号
字段 |
含义 |
---|---|
st_name |
符号名称的字符串表的索引;若其值为 0 则代表临时寄存器。 |
st_value |
寄存器编号。有关整数寄存器赋值的信息,请参见 ABI 手册。 |
st_size |
未使用 (0)。 |
st_info |
绑定通常为 STB_GLOBAL,类型必须是 STT_SPARC_REGISTER。 |
st_other |
未使用 (0)。 |
st_shndx |
如果该目标文件初始化此寄存器符号,则为 SHN_ABS,否则为 SHN_UNDEF。 |
下表中列出了为 SPARC 定义的寄存器值。
表 7–23 SPARC: ELF 寄存器编号
名称 |
值 |
含义 |
---|---|---|
STO_SPARC_REGISTER_G2 |
0x2 |
%g2 |
STO_SPARC_REGISTER_G3 |
0x3 |
%g3 |
如果缺少特定全局寄存器的项,则意味着目标文件根本没有使用特定全局寄存器。