链接程序和库指南

符号表节

目标文件的符号表包含定位和重定位程序的符号定义和符号引用所需的信息。符号表索引是此数组的下标。索引 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;
st_name

目标文件的符号字符串表的索引,其中包含符号名称的字符表示形式。如果该值为非零,则表示指定符号名称的字符串表索引。否则,符号表项没有名称。

st_value

关联符号的值。根据上下文,该值可以是绝对值或地址。 请参见符号值

st_size

许多符号具有关联大小。例如,数据目标文件的大小是目标文件中包含的字节数。如果符号没有大小或大小未知,则此成员值为零。

st_info

符号的类型和绑定属性。表 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))
st_other

符号的可见性。表 7–20 中显示了值和含义的列表。以下代码说明了如何处理 32 位目标文件和 64 位目标文件的值。其他位设置为零,并且未定义任何含义。

#define ELF32_ST_VISIBILITY(o)       ((o)&0x3)

#define ELF64_ST_VISIBILITY(o)       ((o)&0x3)
st_shndx

所定义的每一个符号表项都与某节有关。此成员包含相关节头表索引。部分节索引会表示特殊含义。 请参见表 7–4

如果此成员包含 SHN_XINDEX,则实际节头索引会过大而无法放入此字段中。实际值包含在 SHT_SYMTAB_SHNDX 类型的关联节中。

根据符号的 st_info 字段确定的符号绑定可确定链接可见性和行为。

表 7–18 ELF 符号绑定:ELF32_ST_BINDELF64_ST_BIND

名称 

值 

STB_LOCAL

0

STB_GLOBAL

1

STB_WEAK

2

STB_LOOS

10

STB_HIOS

12

STB_LOPROC

13

STB_HIPROC

15

STB_LOCAL

局部符号。这些符号在包含其定义的目标文件的外部不可见。名称相同的局部符号可存在于多个文件中而不会相互干扰。

STB_GLOBAL

全局符号。这些符号对于合并的所有目标文件都可见。一个文件的全局符号定义满足另一个文件对相同全局符号的未定义引用。

STB_WEAK

弱符号。这些符号与全局符号类似,但其定义具有较低的优先级。

STB_LOOSSTB_HIOS

此范围内包含的值保留用于特定于操作系统的语义。

STB_LOPROCSTB_HIPROC

此范围内包含的值保留用于特定于处理器的语义。

全局符号和弱符号在以下两个主要方面不同:


注 –

弱符号主要适用于系统软件。建议不要在应用程序中使用弱符号。


在每个符号表中,具有 STB_LOCAL 绑定的所有符号都优先于弱符号和全局符号。如中所述,符号表节的 sh_info 节头成员包含第一个非局部符号的符号表索引。

根据符号的 st_info 字段确定的符号类型用于对关联实体进行一般分类。

表 7–19 ELF 符号类型:ELF32_ST_TYPEELF64_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

STT_NOTYPE

未指定符号类型。

STT_OBJECT

此符号与变量、数组等数据目标文件关联。

STT_FUNC

此符号与函数或其他可执行代码关联。

STT_SECTION

此符号与节关联。此类型的符号表各项主要用于重定位,并且通常具有 STB_LOCAL 绑定。

STT_FILE

通常,符号的名称会指定与目标文件关联的源文件的名称。文件符号具有 STB_LOCAL 绑定和节索引 SHN_ABS。此符号(如果存在)位于文件的其他 STB_LOCAL 符号前面。

符号索引为 1 的 SHT_SYMTAB 是表示目标文件的 STT_FILE 符号。通常,此符号后跟文件的 STT_SECTION 符号。这些节符号又后跟已降为局部符号的任何全局符号。

STT_COMMON

此符号标记未初始化的通用块。此符号的处理与对 STT_OBJECT 的处理完全相同。

STT_TLS

此符号指定线程局部存储实体。定义后,此符号可为符号指明指定的偏移,而不是实际地址。

线程局部存储重定位只能引用 STT_TLS 类型的符号。从可分配节中引用 STT_TLS 类型的符号只能通过使用特殊线程局部存储重定位来实现。 有关详细信息,请参见第 8 章,线程局部存储。从非可分配节中引用 STT_TLS 类型的符号没有此限制。

STT_LOOSSTT_HIOS

此范围内包含的值保留用于特定于操作系统的语义。

STT_LOPROCSTT_HIPROC

此范围内包含的值保留用于特定于处理器的语义。

符号的可见性根据其 st_other 字段确定。此可见性可以在可重定位目标文件中指定。此可见性定义了在符号成为可执行文件或共享库的一部分后访问该符号的方式。

表 7–20 ELF 符号可见性

名称 

值 

STV_DEFAULT

0

STV_INTERNAL

1

STV_HIDDEN

2

STV_PROTECTED

3

STV_DEFAULT

具有 STV_DEFAULT 属性的符号的可见性与符号的绑定类型指定的可见性相同。全局符号和弱符号在其定义组件(可执行文件或共享库)外部可见。局部符号处于隐藏状态。另外,还可以替换全局符号和弱符号。可以在另一个组件中通过定义相同的名称插入这些符号。

STV_PROTECTED

如果当前组件中定义的符号在其他组件中可见,但不能被替换,则该符号会处于受保护状态。定义组件中对这类符号的任何引用都必须解析为该组件中的定义。即使在另一个组件中存在按缺省规则插入的符号定义,也必须进行此解析。具有 STB_LOCAL 绑定的符号将没有 STV_PROTECTED 可见性。

STV_HIDDEN

如果当前组件中定义的符号的名称对于其他组件不可见,则该符号处于隐藏状态。必须对这类符号进行保护。此属性用于控制组件的外部接口。由这样的符号命名的目标文件仍可以在另一个组件中引用(如果将目标文件的地址传到外部)。

如果可执行文件或共享库中包括可重定位目标文件,则该目标文件中包含的隐藏符号将会删除或转换为使用 STB_LOCAL 绑定。

STV_INTERNAL

此可见性属性当前被保留。

在链接编辑过程中,可见性属性不会影响可执行文件或共享库中符号的解析。这样的解析由绑定类型控制。一旦链接编辑器选定了其解析,这些属性即会强加两种要求。两种要求都基于以下事实,即所链接的代码中的引用可能已优化,从而可利用这些属性。

如果符号的值指向节中的特定位置,则符号的节索引成员 st_shndx 会包含节头表的索引。节在重定位过程中移动时,符号的值也会更改。符号的引用仍然指向程序中的相同位置。一些特殊节索引值会具有其他语义:

SHN_ABS

此符号具有不会由于重定位而发生更改的绝对值。

SHN_COMMONSHN_AMD64_LCOMMON

此符号标记尚未分配的通用块。与节的 sh_addralign 成员类似,符号的值也会指定对齐约束。链接编辑器在值为 st_value 的倍数的地址位置为符号分配存储空间。符号的大小会指明所需的字节数。

SHN_UNDEF

此节表索引表示未定义符号。链接编辑器将此目标文件与用于定义所表示的符号的另一目标文件合并时,此文件中对该符号的引用将与该定义绑定。

如之前所述,索引 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 成员的解释稍有不同。

尽管符号表值对于不同的目标文件具有类似含义,但通过适当的程序可以有效地访问数据。

寄存器符号

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

如果缺少特定全局寄存器的项,则意味着目标文件根本没有使用特定全局寄存器。