链接程序和库指南

使用目标文件的节头表,可以定位文件的所有节。节头表是 Elf32_ShdrElf64_Shdr 结构的数组。节头表索引是此数组的下标。ELF 头的 e_shoff 成员表示从文件的起始位置到节头表的字节偏移。e_shnum 成员表示节头表包含的项数。e_shentsize 成员表示每一项的大小(以字节为单位)。

如果节数大于或等于 SHN_LORESERVE (0xff00),则 e_shnum 值为 SHN_UNDEF (0)。节头表的实际项数包含在节头表中索引为 0sh_size 字段中。否则,初始项的 sh_size 成员值为零。

如果上下文中限制了索引大小,则会保留部分节头表索引。例如,符号表项的 st_shndx 成员和 ELF 头的 e_shnume_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 项,则这些节的索引为 05。初始项的内容会在本节的后面指定。


SHN_UNDEF

未定义、缺少、无关或无意义的节引用。例如,已定义的与节数 SHN_UNDEF 有关的符号即是未定义符号。

SHN_LORESERVE

所保留索引的范围的下边界。

SHN_LOPROC - SHN_HIPROC

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

SHN_LOOS - SHN_HIOS

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

SHN_LOSUNW - SHN_HISUNW

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

SHN_SUNW_IGNORE

此节索引用于在可重定位目标文件中提供临时符号定义。保留供 dtrace(1M) 内部使用。

SHN_BEFORE, SHN_AFTER

SHF_LINK_ORDERSHF_ORDERED 节标志一起用于初始和最终节排序。 请参见表 7–8

SHN_AMD64_LCOMMON

特定于 x64 的通用块标签。此标签与 SHN_COMMON 类似,但用于标识较大的通用块。

SHN_ABS

对应引用的绝对值。例如,已定义的与节数 SHN_ABS 相关的符号具有绝对值,并且不受重定位影响。

SHN_COMMON

已定义的与此节相关的符号为通用符号,如 FORTRAN COMMON 或未分配的 C 外部变量。这些符号有时称为暂定符号。

SHN_XINDEX

转义值,用于表示实际节头索引过大,以致无法放入包含字段。节头索引可在特定于显示节索引的结构的其他位置中找到。

SHN_HIRESERVE

所保留索引的范围的上边界。系统保留了 SHN_LORESERVESHN_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;
sh_name

节的名称。此成员值是节头字符串表的节索引,用于指定以空字符结尾的字符串的位置。表 7–10 中列出了节名及其说明。

sh_type

用于将节的内容和语义分类。表 7–5 中列出了节类型及其说明。

sh_flags

节可支持用于说明杂项属性的 1 位标志。表 7–8 中列出了标志定义。

sh_addr

如果节显示在进程的内存映像中,则此成员会指定节的第一个字节所在的地址。否则,此成员值为零。

sh_offset

从文件的起始位置到节中第一个字节的字节偏移。对于 SHT_NOBITS 节,此成员表示文件中的概念性偏移,因为该节在文件中不占用任何空间。

sh_size

节的大小(以字节为单位)。除非节类型为 SHT_NOBITS,否则该节将在文件中占用 sh_size 个字节。SHT_NOBITS 类型的节大小可以不为零,但该节在文件中不占用任何空间。

sh_link

节头表索引链接,其解释依赖于节类型。表 7–9 说明了相应的值。

sh_info

额外信息,其解释依赖于节类型。表 7–9 说明了相应的值。

sh_addralign

一些节具有地址对齐约束。例如,如果某节包含双字,则系统必须确保整个节双字对齐。在此情况下,sh_addr 的值在以 sh_addralign 的值为模数进行取模时,同余数必须等于 0。当前,仅允许使用 0 和 2 的正整数幂。值 01 表示节没有对齐约束。

sh_entsize

一些节包含固定大小的项的表,如符号表。对于这样的节,此成员会指定每一项的大小(以字节为单位)。如果节不包含固定大小的项的表,则此成员值为零。

节头的 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_NULL

将节头标识为非活动。此节头没有关联的节。节头的其他成员具有未定义的值。

SHT_PROGBITS

标识由程序定义的信息,这些信息的格式和含义仅由程序确定。

SHT_SYMTABSHT_DYNSYM

标识符号表。通常,SHT_SYMTAB 节会提供用于链接编辑的符号。作为完整的符号表,该表可以包含许多对于动态链接不需要的符号。因此,目标文件还可以包含 SHT_DYNSYM 节,其中包含一组尽可能少的动态链接符号,从而可节省空间。 有关详细信息,请参见符号表节

SHT_STRTABSHT_DYNSTR

标识字符串表。目标文件可以有多个字符串表节。 有关详细信息,请参见字符串表节

SHT_RELA

标识包含显式加数的重定位项,如 32 位类的目标文件的 Elf32_Rela 类型。目标文件可以有多个重定位节。 有关详细信息,请参见重定位节

SHT_HASH

标识符号散列表。动态链接的目标文件必须包含符号散列表。当前,目标文件只能有一个散列表,但此限制在将来可能会放宽。 有关详细信息,请参见散列表节

SHT_DYNAMIC

标识动态链接的信息。当前,目标文件只能有一个动态节。 有关详细信息,请参见动态节

SHT_NOTE

标识以某种方法标记文件的信息。 有关详细信息,请参见注释节

SHT_NOBITS

标识在文件中不占用任何空间,但在其他方面与 SHT_PROGBITS 类似的节。虽然此节不包含任何字节,但 sh_offset 成员包含概念性文件偏移。

SHT_REL

标识不包含显式加数的重定位项,如 32 位类的目标文件的 Elf32_Rel 类型。目标文件可以有多个重定位节。 有关详细信息,请参见重定位节

SHT_SHLIB

标识具有未指定的语义的保留节。包含此类型的节的程序不符合 ABI。

SHT_INIT_ARRAY

标识包含指针数组的节,这些指针指向初始化函数。数组中的每个指针都视为不返回任何值的无参数过程。 有关详细信息,请参见初始化和终止节

SHT_FINI_ARRAY

标识包含指针数组的节,这些指针指向终止函数。数组中的每个指针都视为不返回任何值的无参数过程。 有关详细信息,请参见初始化和终止节

SHT_PREINIT_ARRAY

标识包含指针数组的节,这些指针指向在其他所有初始化函数之前调用的函数。数组中的每个指针都视为不返回任何值的无参数过程。 有关详细信息,请参见初始化和终止节

SHT_GROUP

标识节组。节组可标识一组相关的节,这些节必须作为一个单位由链接编辑器进行处理。SHT_GROUP 类型的节只能出现在可重定位目标文件中。 有关详细信息,请参见组节

SHT_SYMTAB_SHNDX

标识包含扩展节索引的节,扩展节索引与符号表关联。如果符号表引用的任何节头索引包含转义值 SHN_XINDEX,则需要关联的 SHT_SYMTAB_SHNDX

SHT_SYMTAB_SHNDX 节是 Elf32_Word 值的数组。此数组包含一项,可与关联的符号表项中的每一项对应。这些值表示针对其定义符号表各项的节头索引。仅当对应符号表项的 st_shndx 字段包含转义值 SHN_XINDEX 时,匹配的 Elf32_Word 才会包含实际节头索引。否则,该项必须为 SHN_UNDEF (0)。

SHT_LOOSSHT_HIOS

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

SHT_LOSUNWSHT_HISUNW

此范围内包含的值保留用于 Solaris 语义。

SHT_SUNW_cap

指定硬件和软件的功能要求。 有关详细信息,请参见硬件和软件功能节

SHT_SUNW_SIGNATURE

标识模块验证签名。

SHT_SUNW_ANNOTATE

注释节的处理遵循用于处理节的所有缺省规则。仅当注释节位于不可分配的内存中时,才会发生异常。如果未设置节头标志 SHF_ALLOC,则链接编辑器将忽略针对此节的所有不满足要求的重定位而无任何提示。

SHT_SUNW_DEBUGSTRSHT_SUNW_DEBUG

标识调试信息。使用链接编辑器的 -s 选项,或者在链接编辑之后使用 strip(1),可以将此类型的节从目标文件中删除。

SHT_SUNW_move

标识用于处理部分初始化的符号的数据。 有关详细信息,请参见移动节

SHT_SUNW_COMDAT

标识允许将相同数据的多个副本减少为单个副本的节。 有关详细信息,请参见COMDAT 节

SHT_SUNW_syminfo

标识其他符号信息。 有关详细信息,请参见Syminfo 表节

SHT_SUNW_verdef

标识此文件定义的细分版本。 有关详细信息,请参见版本定义节

SHT_SUNW_verneed

标识此文件所需的细分依赖性。 有关详细信息,请参见版本依赖性节

SHT_SUNW_versym

标识用于说明符号与文件提供的版本定义之间关系的表。 有关详细信息,请参见版本符号节

SHT_LOPROCSHT_HIPROC

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

SHT_SPARC_GOTDATA

标识特定于 SPARC 的数据,使用相对于 GOT 的寻址引用这些数据。即,相对于指定给符号 _GLOBAL_OFFSET_TABLE_ 的地址的偏移。对于 64 位 SPARC,此节中的数据必须在链接编辑时绑定到 {+-} 2^32 字节的 GOT 地址中的位置。

SHT_AMD64_UNWIND

标识特定于 x64 的数据,其中包含对应于栈展开的展开函数表的各项。

SHT_LOUSER

指定保留用于应用程序的索引范围的下边界。

SHT_HIUSER

指定保留用于应用程序的索引范围的上边界。应用程序可以使用 SHT_LOUSERSHT_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_WRITE

标识在进程执行过程中应可写的节。

SHF_ALLOC

标识在进程执行过程中占用内存的节。一些控制节不位于目标文件的内存映像中。对于这些节,此属性处于禁用状态。

SHF_EXECINSTR

标识包含可执行计算机指令的节。

SHF_MERGE

标识可以将其中包含的数据合并以消除重复的节。除非还设置了 SHF_STRINGS 标志,否则该节中的数据元素大小一致。每个元素的大小在节头的 sh_entsize 字段中指定。如果还设置了 SHF_STRINGS 标志,则数据元素会包含以空字符结尾的字符串。每个字符的大小在节头的 sh_entsize 字段中指定。

SHF_STRINGS

标识包含以空字符结尾的字符串的节。每个字符的大小在节头的 sh_entsize 字段中指定。

SHF_INFO_LINK

此节头的 sh_info 字段包含节头表索引。

SHF_LINK_ORDER

此节可向链接编辑器中添加特殊排序要求。如果此节头的 sh_link 字段引用其他节(链接到的节),则会应用这些要求。如果将此节与输出文件中的其他节合并,则此节将按照与这些其他节相同的相对顺序显示。同样,链接到的节将按照与其合并的节相同的相对顺序显示。

特殊的 sh_linkSHN_BEFORESHN_AFTER(请参见表 7–4)表示,已排序的节将分别位于要排序的集合中其他所有各节之前或之后。如果已排序集合中的多个节包含这些特殊值之一,则会保持输入文件链接行的顺序。

此标志的一个典型用法是生成按地址顺序引用文本或数据节的表。

如果缺少 sh_link 排序信息,则合并到输出文件一个节内的单个输入文件中的各节是相邻的。这些节会与输入文件中的节一样进行相对排序。构成多个输入文件的节按照链接行顺序显示。

SHF_OS_NONCONFORMING

此节除了要求标准链接规则之外,还要求特定于操作系统的特殊处理,以避免不正确的行为。如果此节具有 sh_type 值,或者对于这些字段包含特定于操作系统范围的 sh_flags 位,并且链接编辑器无法识别这些值,则包含此节的目标文件会由于出错而被拒绝。

SHF_GROUP

此节是节组的一个成员,可能是唯一的成员。此节必须由 SHT_GROUP 类型的节引用。只能对可重定位目标文件中包含的节设置 SHF_GROUP 标志。 有关详细信息,请参见组节

SHF_TLS

此节包含线程局部存储。进程中的每个线程都包含此数据的一个不同实例。 有关详细信息,请参见第 8 章,线程局部存储

SHF_MASKOS

此掩码中包括的所有位都保留用于特定于操作系统的语义。

SHF_AMD64_LARGE

x64 的缺省编译模型仅用于 32 位位移。此位移限制了节的大小,并最终限制段为 2 GB。特定于处理器的 SHF_AMD64_LARGE 属性标志用于标识可包含超过 2 GB 的节。此标志允许链接使用不同代码模型的目标文件。

不包含 SHF_AMD64_LARGE 属性标志的 x64 目标文件节可以由使用小代码模型的目标文件任意引用。包含此标志的节只能由使用较大代码模型的目标文件引用。例如,x64 中间代码模型目标文件可以引用包含属性标志的节和不包含属性标志的节中的数据。但是,x64 小代码模型目标文件只能引用不包含此标志的节中的数据。

SHF_ORDERED

此节要求相对于相同类型的其他节进行排序。已排序的节会合并到由 sh_link 项指向的节中。已排序节的 sh_link 项可以指向其本身。

如果已排序节的 sh_info 项在相同输入文件中是有效节,则将基于由 sh_info 项所指向的节的输出文件内的相对排序,对已排序的节进行排序。

特殊的 sh_infoSHN_BEFORESHN_AFTER(请参见表 7–4)表示,已排序的节将分别位于要排序的集合中其他所有各节之前或之后。如果已排序集合中的多个节包含这些特殊值之一,则会保持输入文件链接行的顺序。

如果缺少 sh_info 排序信息,则合并到输出文件一个节内的单个输入文件中的节是相邻的。这些节会与输入文件中的节一样进行相对排序。构成多个输入文件的节按照链接行顺序显示。

SHF_EXCLUDE

此节不包括在可执行文件或共享库的链接编辑的输入中。如果还设置了 SHF_ALLOC 标志,或者存在针对此节的重定位,则会忽略此标志。

SHF_MASKPROC

此掩码中包括的所有位都保留用于特定于处理器的语义。

根据节类型,节头中的两个成员 sh_linksh_info 会包含特殊信息。

表 7–9 ELF sh_linksh_info 解释

sh_type

sh_link

sh_info

SHT_DYNAMIC

关联的字符串表的节头索引。 

0

SHT_HASH

关联的符号表的节头索引。 

0

SHT_REL

SHT_RELA

关联的符号表的节头索引。 

应用重定位的节的节头索引。 另请参见表 7–10重定位节

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