使用目标文件的节头表,可以定位文件的所有节。节头表是 Elf32_Shdr 或 Elf64_Shdr 结构的数组。节头表索引是此数组的下标。ELF 头的 e_shoff 成员表示从文件的起始位置到节头表的字节偏移。e_shnum 成员表示节头表包含的项数。e_shentsize 成员表示每一项的大小(以字节为单位)。
如果节数大于或等于 SHN_LORESERVE (0xff00),则 e_shnum 值为 SHN_UNDEF (0)。节头表的实际项数包含在节头表中索引为 0 的 sh_size 字段中。否则,初始项的 sh_size 成员值为零。
如果上下文中限制了索引大小,则会保留部分节头表索引。例如,符号表项的 st_shndx 成员和 ELF 头的 e_shnum 和 e_shstrndx 成员。在这类上下文中,保留的值不表示目标文件中的实际各节。同样在这类上下文中,转义值表示会在其他位置(较大字段中)找到实际节索引。
表 7–4 ELF 特殊节索引
名称 |
值 |
---|---|
SHN_UNDEF |
0 |
SHN_LORESERVE |
0xff00 |
SHN_LOPROC |
0xff00 |
SHN_BEFORE |
0xff00 |
SHN_AFTER |
0xff01 |
SHN_AMD64_LCOMMON |
0xff02 |
SHN_HIPROC |
0xff1f |
SHN_LOOS |
0xff20 |
SHN_LOSUNW |
0xff3f |
SHN_SUNW_IGNORE |
0xff3f |
SHN_HISUNW |
0xff3f |
SHN_HIOS |
0xff3f |
SHN_ABS |
0xfff1 |
SHN_COMMON |
0xfff2 |
SHN_XINDEX |
0xffff |
SHN_HIRESERVE |
0xffff |
虽然索引 0 保留作为未定义的值,但节头表包含对应于索引 0 的项。即,如果 ELF 头的 e_shnum 成员表示文件在节头表中具有 6 项,则这些节的索引为 0 到 5。初始项的内容会在本节的后面指定。
此节索引用于在可重定位目标文件中提供临时符号定义。保留供 dtrace(1M) 内部使用。
与 SHF_LINK_ORDER 和 SHF_ORDERED 节标志一起用于初始和最终节排序。 请参见表 7–8。
已定义的与此节相关的符号为通用符号,如 FORTRAN COMMON 或未分配的 C 外部变量。这些符号有时称为暂定符号。
所保留索引的范围的上边界。系统保留了 SHN_LORESERVE 和 SHN_HIRESERVE 之间的索引(包括这两个值)。这些值不会引用节头表。节头表不包含对应于所保留索引的项。
节包含目标文件中的所有信息,但 ELF 头、程序头表和节头表除外。此外,目标文件中的各节还满足多个条件:
目标文件中的每一节仅有一个说明该节的节头。可能会有节头存在但节不存在的情况。
每一节在文件中占用可能为空的相邻的一系列字节。
文件中的各节不能重叠。文件中的字节不能位于多个节中。
目标文件可以包含非活动空间。各种头和节可能不会包括目标文件中的每个字节。非活动数据的内容未指定。
节头具有以下结构。 请参见 sys/elf.h。
typedef struct { elf32_Word sh_name; Elf32_Word sh_type; Elf32_Word sh_flags; Elf32_Addr sh_addr; Elf32_Off sh_offset; Elf32_Word sh_size; Elf32_Word sh_link; Elf32_Word sh_info; Elf32_Word sh_addralign; Elf32_Word sh_entsize; } Elf32_Shdr; typedef struct { Elf64_Word sh_name; Elf64_Word sh_type; Elf64_Xword sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; Elf64_Xword sh_size; Elf64_Word sh_link; Elf64_Word sh_info; Elf64_Xword sh_addralign; Elf64_Xword sh_entsize; } Elf64_Shdr;
节的名称。此成员值是节头字符串表的节索引,用于指定以空字符结尾的字符串的位置。表 7–10 中列出了节名及其说明。
用于将节的内容和语义分类。表 7–5 中列出了节类型及其说明。
节可支持用于说明杂项属性的 1 位标志。表 7–8 中列出了标志定义。
如果节显示在进程的内存映像中,则此成员会指定节的第一个字节所在的地址。否则,此成员值为零。
从文件的起始位置到节中第一个字节的字节偏移。对于 SHT_NOBITS 节,此成员表示文件中的概念性偏移,因为该节在文件中不占用任何空间。
节的大小(以字节为单位)。除非节类型为 SHT_NOBITS,否则该节将在文件中占用 sh_size 个字节。SHT_NOBITS 类型的节大小可以不为零,但该节在文件中不占用任何空间。
节头表索引链接,其解释依赖于节类型。表 7–9 说明了相应的值。
额外信息,其解释依赖于节类型。表 7–9 说明了相应的值。
一些节具有地址对齐约束。例如,如果某节包含双字,则系统必须确保整个节双字对齐。在此情况下,sh_addr 的值在以 sh_addralign 的值为模数进行取模时,同余数必须等于 0。当前,仅允许使用 0 和 2 的正整数幂。值 0 和 1 表示节没有对齐约束。
一些节包含固定大小的项的表,如符号表。对于这样的节,此成员会指定每一项的大小(以字节为单位)。如果节不包含固定大小的项的表,则此成员值为零。
节头的 sh_type 成员用于指定节的语义,如下表中所示。
表 7–5 ELF 节类型 sh_type
名称 |
值 |
---|---|
SHT_NULL |
0 |
SHT_PROGBITS |
1 |
SHT_SYMTAB |
2 |
SHT_STRTAB |
3 |
SHT_RELA |
4 |
SHT_HASH |
5 |
SHT_DYNAMIC |
6 |
SHT_NOTE |
7 |
SHT_NOBITS |
8 |
SHT_REL |
9 |
SHT_SHLIB |
10 |
SHT_DYNSYM |
11 |
SHT_INIT_ARRAY |
14 |
SHT_FINI_ARRAY |
15 |
SHT_PREINIT_ARRAY |
16 |
SHT_GROUP |
17 |
SHT_SYMTAB_SHNDX |
18 |
SHT_LOOS |
0x60000000 |
SHT_LOSUNW |
0x6ffffff4 |
SHT_SUNW_dof |
0x6ffffff4 |
SHT_SUNW_cap |
0x6ffffff5 |
SHT_SUNW_SIGNATURE |
0x6ffffff6 |
SHT_SUNW_ANNOTATE |
0x6ffffff7 |
SHT_SUNW_DEBUGSTR |
0x6ffffff8 |
SHT_SUNW_DEBUG |
0x6ffffff9 |
SHT_SUNW_move |
0x6ffffffa |
SHT_SUNW_COMDAT |
0x6ffffffb |
SHT_SUNW_syminfo |
0x6ffffffc |
SHT_SUNW_verdef |
0x6ffffffd |
SHT_SUNW_verneed |
0x6ffffffe |
SHT_SUNW_versym |
0x6fffffff |
SHT_HISUNW |
0x6fffffff |
SHT_HIOS |
0x6fffffff |
SHT_LOPROC |
0x70000000 |
SHT_SPARC_GOTDATA |
0x70000000 |
SHT_AMD64_UNWIND |
0x70000001 |
SHT_HIPROC |
0x7fffffff |
SHT_LOUSER |
0x80000000 |
SHT_HIUSER |
0xffffffff |
标识符号表。通常,SHT_SYMTAB 节会提供用于链接编辑的符号。作为完整的符号表,该表可以包含许多对于动态链接不需要的符号。因此,目标文件还可以包含 SHT_DYNSYM 节,其中包含一组尽可能少的动态链接符号,从而可节省空间。 有关详细信息,请参见符号表节。
标识字符串表。目标文件可以有多个字符串表节。 有关详细信息,请参见字符串表节。
标识包含显式加数的重定位项,如 32 位类的目标文件的 Elf32_Rela 类型。目标文件可以有多个重定位节。 有关详细信息,请参见重定位节。
标识符号散列表。动态链接的目标文件必须包含符号散列表。当前,目标文件只能有一个散列表,但此限制在将来可能会放宽。 有关详细信息,请参见散列表节。
标识动态链接的信息。当前,目标文件只能有一个动态节。 有关详细信息,请参见动态节。
标识以某种方法标记文件的信息。 有关详细信息,请参见注释节。
标识在文件中不占用任何空间,但在其他方面与 SHT_PROGBITS 类似的节。虽然此节不包含任何字节,但 sh_offset 成员包含概念性文件偏移。
标识不包含显式加数的重定位项,如 32 位类的目标文件的 Elf32_Rel 类型。目标文件可以有多个重定位节。 有关详细信息,请参见重定位节。
标识包含指针数组的节,这些指针指向初始化函数。数组中的每个指针都视为不返回任何值的无参数过程。 有关详细信息,请参见初始化和终止节。
标识包含指针数组的节,这些指针指向终止函数。数组中的每个指针都视为不返回任何值的无参数过程。 有关详细信息,请参见初始化和终止节。
标识包含指针数组的节,这些指针指向在其他所有初始化函数之前调用的函数。数组中的每个指针都视为不返回任何值的无参数过程。 有关详细信息,请参见初始化和终止节。
标识节组。节组可标识一组相关的节,这些节必须作为一个单位由链接编辑器进行处理。SHT_GROUP 类型的节只能出现在可重定位目标文件中。 有关详细信息,请参见组节。
标识包含扩展节索引的节,扩展节索引与符号表关联。如果符号表引用的任何节头索引包含转义值 SHN_XINDEX,则需要关联的 SHT_SYMTAB_SHNDX。
SHT_SYMTAB_SHNDX 节是 Elf32_Word 值的数组。此数组包含一项,可与关联的符号表项中的每一项对应。这些值表示针对其定义符号表各项的节头索引。仅当对应符号表项的 st_shndx 字段包含转义值 SHN_XINDEX 时,匹配的 Elf32_Word 才会包含实际节头索引。否则,该项必须为 SHN_UNDEF (0)。
指定硬件和软件的功能要求。 有关详细信息,请参见硬件和软件功能节。
注释节的处理遵循用于处理节的所有缺省规则。仅当注释节位于不可分配的内存中时,才会发生异常。如果未设置节头标志 SHF_ALLOC,则链接编辑器将忽略针对此节的所有不满足要求的重定位而无任何提示。
标识调试信息。使用链接编辑器的 -s 选项,或者在链接编辑之后使用 strip(1),可以将此类型的节从目标文件中删除。
标识用于处理部分初始化的符号的数据。 有关详细信息,请参见移动节。
标识允许将相同数据的多个副本减少为单个副本的节。 有关详细信息,请参见COMDAT 节。
标识其他符号信息。 有关详细信息,请参见Syminfo 表节。
标识此文件定义的细分版本。 有关详细信息,请参见版本定义节。
标识此文件所需的细分依赖性。 有关详细信息,请参见版本依赖性节。
标识用于说明符号与文件提供的版本定义之间关系的表。 有关详细信息,请参见版本符号节。
标识特定于 SPARC 的数据,使用相对于 GOT 的寻址引用这些数据。即,相对于指定给符号 _GLOBAL_OFFSET_TABLE_ 的地址的偏移。对于 64 位 SPARC,此节中的数据必须在链接编辑时绑定到 {+-} 2^32 字节的 GOT 地址中的位置。
指定保留用于应用程序的索引范围的上边界。应用程序可以使用 SHT_LOUSER 和 SHT_HIUSER 之间的节类型,而不会与当前或将来系统定义的节类型产生冲突。
其他节类型的值会保留。如前所述,即使索引 0 (SHN_UNDEF) 标记了未定义的节引用,仍会存在对应于该索引的节头。下表显示了这些值。
表 7–6 ELF 节头表项:索引 0
名称 |
值 |
说明 |
---|---|---|
sh_name |
0 |
无名称 |
sh_type |
SHT_NULL |
非活动 |
sh_flags |
0 |
无标志 |
sh_addr |
0 |
无地址 |
sh_offset |
0 |
无文件偏移 |
sh_size |
0 |
无大小 |
sh_link |
SHN_UNDEF |
无链接信息 |
sh_info |
0 |
无辅助信息 |
sh_addralign |
0 |
无对齐 |
sh_entsize |
0 |
无项 |
如果节或程序头的数目超过 ELF 头数据大小,则节头 0 的各元素可用于定义扩展的 ELF 头属性。下表显示了这些值。
表 7–7 ELF 扩展的节头表项:索引 0
名称 |
值 |
说明 |
---|---|---|
sh_name |
0 |
无名称 |
sh_type |
SHT_NULL |
非活动 |
sh_flags |
0 |
无标志 |
sh_addr |
0 |
无地址 |
sh_offset |
0 |
无文件偏移 |
sh_size |
e_shnum |
节头表中的项数 |
sh_link |
e_shstrndx |
与节名字符串表关联的项的节头索引 |
sh_info |
0 |
无辅助信息 |
sh_addralign |
0 |
无对齐 |
sh_entsize |
0 |
无项 |
节头的 sh_flags 成员包含用于说明节属性的 1 位标志:
表 7–8 ELF 节属性标志
名称 |
值 |
---|---|
SHF_WRITE |
0x1 |
SHF_ALLOC |
0x2 |
SHF_EXECINSTR |
0x4 |
SHF_MERGE |
0x10 |
SHF_STRINGS |
0x20 |
SHF_INFO_LINK |
0x40 |
SHF_LINK_ORDER |
0x80 |
SHF_OS_NONCONFORMING |
0x100 |
SHF_GROUP |
0x200 |
SHF_TLS |
0x400 |
SHF_MASKOS |
0x0ff00000 |
SHF_AMD64_LARGE |
0x10000000 |
SHF_ORDERED |
0x40000000 |
SHF_EXCLUDE |
0x80000000 |
SHF_MASKPROC |
0xf0000000 |
如果在 sh_flags 中设置了标志位,则该节的此属性处于启用状态。否则,此属性处于禁用状态,或者不适用。未定义的属性会保留并设置为零。
标识可以将其中包含的数据合并以消除重复的节。除非还设置了 SHF_STRINGS 标志,否则该节中的数据元素大小一致。每个元素的大小在节头的 sh_entsize 字段中指定。如果还设置了 SHF_STRINGS 标志,则数据元素会包含以空字符结尾的字符串。每个字符的大小在节头的 sh_entsize 字段中指定。
此节可向链接编辑器中添加特殊排序要求。如果此节头的 sh_link 字段引用其他节(链接到的节),则会应用这些要求。如果将此节与输出文件中的其他节合并,则此节将按照与这些其他节相同的相对顺序显示。同样,链接到的节将按照与其合并的节相同的相对顺序显示。
特殊的 sh_link 值 SHN_BEFORE 和 SHN_AFTER(请参见表 7–4)表示,已排序的节将分别位于要排序的集合中其他所有各节之前或之后。如果已排序集合中的多个节包含这些特殊值之一,则会保持输入文件链接行的顺序。
此标志的一个典型用法是生成按地址顺序引用文本或数据节的表。
如果缺少 sh_link 排序信息,则合并到输出文件一个节内的单个输入文件中的各节是相邻的。这些节会与输入文件中的节一样进行相对排序。构成多个输入文件的节按照链接行顺序显示。
此节除了要求标准链接规则之外,还要求特定于操作系统的特殊处理,以避免不正确的行为。如果此节具有 sh_type 值,或者对于这些字段包含特定于操作系统范围的 sh_flags 位,并且链接编辑器无法识别这些值,则包含此节的目标文件会由于出错而被拒绝。
此节是节组的一个成员,可能是唯一的成员。此节必须由 SHT_GROUP 类型的节引用。只能对可重定位目标文件中包含的节设置 SHF_GROUP 标志。 有关详细信息,请参见组节。
此节包含线程局部存储。进程中的每个线程都包含此数据的一个不同实例。 有关详细信息,请参见第 8 章,线程局部存储。
x64 的缺省编译模型仅用于 32 位位移。此位移限制了节的大小,并最终限制段为 2 GB。特定于处理器的 SHF_AMD64_LARGE 属性标志用于标识可包含超过 2 GB 的节。此标志允许链接使用不同代码模型的目标文件。
不包含 SHF_AMD64_LARGE 属性标志的 x64 目标文件节可以由使用小代码模型的目标文件任意引用。包含此标志的节只能由使用较大代码模型的目标文件引用。例如,x64 中间代码模型目标文件可以引用包含属性标志的节和不包含属性标志的节中的数据。但是,x64 小代码模型目标文件只能引用不包含此标志的节中的数据。
此节要求相对于相同类型的其他节进行排序。已排序的节会合并到由 sh_link 项指向的节中。已排序节的 sh_link 项可以指向其本身。
如果已排序节的 sh_info 项在相同输入文件中是有效节,则将基于由 sh_info 项所指向的节的输出文件内的相对排序,对已排序的节进行排序。
特殊的 sh_info 值 SHN_BEFORE 和 SHN_AFTER(请参见表 7–4)表示,已排序的节将分别位于要排序的集合中其他所有各节之前或之后。如果已排序集合中的多个节包含这些特殊值之一,则会保持输入文件链接行的顺序。
如果缺少 sh_info 排序信息,则合并到输出文件一个节内的单个输入文件中的节是相邻的。这些节会与输入文件中的节一样进行相对排序。构成多个输入文件的节按照链接行顺序显示。
此节不包括在可执行文件或共享库的链接编辑的输入中。如果还设置了 SHF_ALLOC 标志,或者存在针对此节的重定位,则会忽略此标志。
根据节类型,节头中的两个成员 sh_link 和 sh_info 会包含特殊信息。
表 7–9 ELF sh_link 和 sh_info 解释
sh_type |
sh_link |
sh_info |
---|---|---|
SHT_DYNAMIC |
关联的字符串表的节头索引。 |
0 |
SHT_HASH |
关联的符号表的节头索引。 |
0 |
SHT_REL SHT_RELA |
关联的符号表的节头索引。 | |
SHT_SYMTAB SHT_DYNSYM |
关联的字符串表的节头索引。 |
比上一个局部符号 STB_LOCAL 的符号表索引大一。 |
SHT_GROUP |
关联的符号表的节头索引。 |
关联的符号表中项的符号表索引。指定的符号表项的名称用于提供节组的签名。 |
SHT_SYMTAB_SHNDX |
关联的符号表的节头索引。 |
0 |
SHT_SUNW_move |
关联的符号表的节头索引。 |
0 |
SHT_SUNW_COMDAT |
0 |
0 |
SHT_SUNW_syminfo |
关联的符号表的节头索引。 |
关联的 .dynamic 节的节头索引。 |
SHT_SUNW_verdef |
关联的字符串表的节头索引。 |
节中版本定义的编号。 |
SHT_SUNW_verneed |
关联的字符串表的节头索引。 |
节中版本依赖性的编号。 |
SHT_SUNW_versym |
关联的符号表的节头索引。 |
0 |