参考文献:

Index of /elf/gabi4+

ELF 文件 - CTF Wiki

0x00 ELF简介

ELF (Executable and Linkable Format)文件,也就是在 Linux 中的目标文件,主要有以下三种类型

  • 可重定位文件(Relocatable File),包含由编译器生成的代码以及数据。链接器会将它与其它目标文件链接起来从而创建可执行文件或者共享目标文件。在 Linux 系统中,这种文件的后缀一般为 .o
  • 可执行文件(Executable File),就是我们通常在 Linux 中执行的程序。
  • 共享目标文件(Shared Object File),包含代码和数据,这种文件是我们所称的库文件,一般以 .so 结尾。一般情况下,它有以下两种使用情景:
    • 链接器(Link eDitor, ld)可能会处理它和其它可重定位文件以及共享目标文件,生成另外一个目标文件。
    • 动态链接器(Dynamic Linker)将它与可执行文件以及其它共享目标组合在一起生成进程镜像。

0x01 ELF文件组成

文件组成参考:Object Files

ELF文件由ELF头(ELF Header)、程序头部表(Program Header Table)、节区头部表(Section Header Table)和节区(Sections)组成

除了ELF头以外,其他部分没有严格的顺序,即可以任意更换他们的位置

经典例子如下

0x02 ELF的数据格式

ELF 文件格式支持 8 位 / 32 位体系结构。当然,这种格式是可以扩展的,也可以支持更小的或者更大位数的处理器架构。因此,目标文件会包含一些控制数据,这部分数据表明了目标文件所使用的架构,这也使得它可以被通用的方式来识别和解释。目标文件中的其它数据采用目的处理器的格式进行编码,与在何种机器上创建没有关系。这里其实想表明的意思目标文件可以进行交叉编译,我们可以在 x86 平台生成 arm 平台的可执行代码。

名称 长度 对齐方式 用途
Elf64_Addr 8 8 无符号程序地址
Elf64_Off 8 8 无符号文件偏移
Elf64_Half 2 2 无符号半整型
Elf64_Word 4 4 无符号整型
Elf64_Sword 4 4 有符号整型
Elf64_Xword 8 8 无符号长整形
Elf64_Sxword 8 8 有符号长整型
unsigned char 1 1 无符号小整形

后面将以64位为主进行介绍

0x03 文件头(ELF Header)

参考:ELF Header

类似于PE文件,ELF文件也有一个文件头(ELF Header),头内给出了整个文件的组织情况,以64位文件为例,文件头内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef struct {
unsigned char e_ident[EI_NIDENT];
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry;
Elf64_Off e_phoff;
Elf64_Off e_shoff;
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
} Elf64_Ehdr;

各参数含义如下

e_ident

该变量给出了用于解码和解释文件中与机器无关的数据的方式,不同的下标对应不同的内容

宏名称 下标 目的
EI_MAG0 0 文件标识
EI_MAG1 1 文件标识
EI_MAG2 2 文件标识
EI_MAG3 3 文件标识
EI_CLASS 4 文件类
EI_DATA 5 数据编码
EI_VERSION 6 文件版本
EI_OSABI 7 操作系统/ABI标识
EI_ABIVERSION 8 ABI版本
EI_PAD 9 补齐字节开始处
EI_NIDENT 16 e_ident的大小

EI_MAG0到EI_MAG3

共四字节为魔数,标识该文件为一个ELF目标文件

名称 位置
ELFMAG0 0x7f e_ident[EI_MAG0]
ELFMAG1 ‘E’ e_ident[EI_MAG1]
ELFMAG2 ‘L’ e_ident[EI_MAG2]
ELFMAG3 ‘F’ e_ident[EI_MAG3]

EI_CLASS

e_ident[EI_CLASS]为e_ident[EI_MAG3]`的下一个字节,标识文件的类型或容量。

名称 意义
ELFCLASSNONE 0 无效类型
ELFCLASS32 1 32 位文件
ELFCLASS64 2 64 位文件

ELF 文件的设计使得它可以在多种字节长度的机器之间移植,而不需要强制规定机器的最长字节长度和最短字节长度。

文件的类定义了对象文件容器本身的数据结构所使用的基本类型。对象文件部分包含的数据可能遵循不同的编程模型。如果是这样,则处理器补充描述了所使用的模型。

EI_DATA

此字节指定了对象文件容器使用的数据结构和对象文件节中包含的数据的编码。目前定义了以下编码。

名称 意义
ELFDATANONE 0 无效数据编码
ELFDATA2LSB 1 小端
ELFDATA2MSB 2 大端

其它值被保留,在未来必要时将被赋予新的编码。

EI_VERSION

给出了ELF头的版本号。目前这个值必须是EV_CURRENT,即之前已经给出的e_version

EI_OSABI

字节e_ident[EI_OSABI]确定该文件所使用的特定于操作系统或应用二进制接口(ABI)的ELF扩展。在其他ELF结构中的某些字段中,有标志和值具有特定于操作系统和/或ABI的含义;这些字段的解释由该字节的值决定。如果对象文件不使用任何扩展,建议将该字节设置为 0。如果该字节的值为64到255,则其含义取决于e_machine头部成员的值。对于某一架构,ABI处理器补充可以在此范围内定义其自己相关的一组值。如果处理器补充未指定一组值,则应使用以下值之一,其中0也可以表示未指定。

名称 含义
ELFOSABI_NONE 0 无扩展或未指定
ELFOSABI_HPUX 1 Hewlett-Packard HP-UX
ELFOSABI_NETBSD 2 NetBSD
ELFOSABI_LINUX 3 Linux
ELFOSABI_SOLARIS 6 Sun Solaris
ELFOSABI_AIX 7 AIX
ELFOSABI_IRIX 8 IRIX
ELFOSABI_FREEBSD 9 FreeBSD
ELFOSABI_TRU64 10 Compaq TRU64 UNIX
ELFOSABI_MODESTO 11 Novell Modesto
ELFOSABI_OPENBSD 12 Open BSD
ELFOSABI_OPENVMS 13 Open VMS
ELFOSABI_NSK 14 Hewlett-Packard Non-Stop Kernel
64-255 特定于架构的值范围

EI_ABIVERSION

字节e_ident[EI_ABIVERSION]用于标识目标对象所面向的ABI版本。此字段用于区分不兼容版本的ABI。此版本号的解释取决于EI_OSABI字段所标识的 ABI。如果处理器补充文件未指定EI_OSABI字段的值,或者对于由EI_OSABI字节的特定值决定的ABI未指定版本值,则EI_ABIVERSION字节的值应使用0;这表示未指定。

EI_PAD

给出了e_ident中未使用字节的开始地址。这些字节被保留并置为0;处理目标文件的程序应该忽略它们。如果之后这些字节被使用,EI_PAD的值就会改变。

e_type

该成员标识目标文件类型

名称 含义
ET_NONE 0 无文件类型
ET_REL 1 可重定位文件
ET_EXEC 2 可执行文件
ET_DYN 3 共享目标文件
ET_CORE 4 核心转储文件
ET_LOPROC 0xff00 处理器指定下限
ET_HIPROC 0xffff 处理器指定上限

虽然核心转储文件的内容没有被详细说明,但ET_CORE还是被保留用于标志此类文件。从ET_LOPROCET_HIPROC(包括边界)被保留用于处理器指定的场景。其它值在未来必要时可被赋予新的目标文件类型。

e_machine

指定了当前文件可以运行的机器架构

名称 含义
EM_NONE 0 无机器类型
EM_M32 1 AT&T WE 32100
EM_SPARC 2 SPARC
EM_386 3 Intel 80386
EM_68K 4 Motorola 68000
EM_88K 5 Motorola 88000
reserved 6 Reserved for future use (was EM_486)
EM_860 7 Intel 80860
EM_MIPS 8 MIPS I Architecture
EM_S370 9 IBM System/370 Processor
EM_MIPS_RS3_LE 10 MIPS RS3000 Little-endian
reserved 11-14 Reserved for future use
EM_PARISC 15 Hewlett-Packard PA-RISC
reserved 16 Reserved for future use
EM_VPP500 17 Fujitsu VPP500
EM_SPARC32PLUS 18 Enhanced instruction set SPARC
EM_960 19 Intel 80960
EM_PPC 20 PowerPC
EM_PPC64 21 64-bit PowerPC
EM_S390 22 IBM System/390 Processor
reserved 23-35 Reserved for future use
EM_V800 36 NEC V800
EM_FR20 37 Fujitsu FR20
EM_RH32 38 TRW RH-32
EM_RCE 39 Motorola RCE
EM_ARM 40 Advanced RISC Machines ARM
EM_ALPHA 41 Digital Alpha
EM_SH 42 Hitachi SH
EM_SPARCV9 43 SPARC Version 9
EM_TRICORE 44 Siemens TriCore embedded processor
EM_ARC 45 Argonaut RISC Core, Argonaut Technologies Inc.
EM_H8_300 46 Hitachi H8/300
EM_H8_300H 47 Hitachi H8/300H
EM_H8S 48 Hitachi H8S
EM_H8_500 49 Hitachi H8/500
EM_IA_64 50 Intel IA-64 processor architecture
EM_MIPS_X 51 Stanford MIPS-X
EM_COLDFIRE 52 Motorola ColdFire
EM_68HC12 53 Motorola M68HC12
EM_MMA 54 Fujitsu MMA Multimedia Accelerator
EM_PCP 55 Siemens PCP
EM_NCPU 56 Sony nCPU embedded RISC processor
EM_NDR1 57 Denso NDR1 microprocessor
EM_STARCORE 58 Motorola Star*Core processor
EM_ME16 59 Toyota ME16 processor
EM_ST100 60 STMicroelectronics ST100 processor
EM_TINYJ 61 Advanced Logic Corp. TinyJ embedded processor family
EM_X86_64 62 AMD x86-64 architecture
EM_PDSP 63 Sony DSP Processor
EM_PDP10 64 Digital Equipment Corp. PDP-10
EM_PDP11 65 Digital Equipment Corp. PDP-11
EM_FX66 66 Siemens FX66 microcontroller
EM_ST9PLUS 67 STMicroelectronics ST9+ 8/16 bit microcontroller
EM_ST7 68 STMicroelectronics ST7 8-bit microcontroller
EM_68HC16 69 Motorola MC68HC16 Microcontroller
EM_68HC11 70 Motorola MC68HC11 Microcontroller
EM_68HC08 71 Motorola MC68HC08 Microcontroller
EM_68HC05 72 Motorola MC68HC05 Microcontroller
EM_SVX 73 Silicon Graphics SVx
EM_ST19 74 STMicroelectronics ST19 8-bit microcontroller
EM_VAX 75 Digital VAX
EM_CRIS 76 Axis Communications 32-bit embedded processor
EM_JAVELIN 77 Infineon Technologies 32-bit embedded processor
EM_FIREPATH 78 Element 14 64-bit DSP Processor
EM_ZSP 79 LSI Logic 16-bit DSP Processor
EM_MMIX 80 Donald Knuth’s educational 64-bit processor
EM_HUANY 81 Harvard University machine-independent object files
EM_PRISM 82 SiTera Prism
EM_AVR 83 Atmel AVR 8-bit microcontroller
EM_FR30 84 Fujitsu FR30
EM_D10V 85 Mitsubishi D10V
EM_D30V 86 Mitsubishi D30V
EM_V850 87 NEC v850
EM_M32R 88 Mitsubishi M32R
EM_MN10300 89 Matsushita MN10300
EM_MN10200 90 Matsushita MN10200
EM_PJ 91 picoJava
EM_OPENRISC 92 OpenRISC 32-bit embedded processor
EM_ARC_A5 93 ARC Cores Tangent-A5
EM_XTENSA 94 Tensilica Xtensa Architecture
EM_VIDEOCORE 95 Alphamosaic VideoCore processor
EM_TMM_GPP 96 Thompson Multimedia General Purpose Processor
EM_NS32K 97 National Semiconductor 32000 series
EM_TPC 98 Tenor Network TPC processor
EM_SNP1K 99 Trebia SNP 1000 processor
EM_ST200 100 STMicroelectronics (www.st.com) ST200 microcontroller

其中EM应该是ELF Machine`的简写。

其它值被在未来必要时用于新的机器。此外,特定处理器的ELF名称使用机器名称来进行区分,一般标志会有个前缀EF_ (ELF Flag)。例如,在EM_XYZ机器上名叫 WIDGET 的标志将被称为 EF_XYZ_WIDGET

e_version

标识目标文件的版本。

名称 含义
EV_NONE 0 无效版本
EV_CURRENT 1 当前版本

1表示初始文件格式;未来扩展新的版本的时候 (extensions) 将使用更大的数字。虽然在上面值EV_CURRENT为1,但是为了反映当前版本号,它可能会改变。

e_entry

这一项为系统转交控制权给 ELF 中相应代码的虚拟地址。如果没有相关的入口项,则这一项为 0。

e_phoff

这一项给出程序头部表在文件中的字节偏移(Program Header table OFFset)。如果文件中没有程序头部表,则为 0。

e_shoff

这一项给出节头表在文件中的字节偏移( Section Header table OFFset )。如果文件中没有节头表,则为 0。

e_flags

这一项给出文件中与特定处理器相关的标志,这些标志命名格式为EF_machine_flag

e_ehsize

这一项给出 ELF 文件头部的字节长度(ELF Header Size)。

e_phentsize

这一项给出程序头部表中每个表项的字节长度(Program Header ENTry SIZE)。每个表项的大小相同。

e_phnum

这一项给出程序头部表的项数(Program Header entry NUMber)。因此,e_phnume_phentsize的乘积即为程序头部表的字节长度。如果文件中没有程序头部表,则该项值为 0。

e_shentsize

这一项给出节头的字节长度(Section Header ENTry SIZE)。一个节头是节头表中的一项;节头表中所有项占据的空间大小相同。

e_shnum

这一项给出节头表中的项数(Section Header NUMber)。因此,e_shnume_shentsize的乘积即为节头表的字节长度。如果文件中没有节头表,则该项值为0。

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

e_shstrndx

这一项给出节头表中与节名字符串表相关的表项的索引值(Section Header table InDeX related with section name STRing table)。如果文件中没有节名字符串表,则该项值为SHN_UNDEF

如果节名字符串表的节索引大于或等于SHN_LORESERVE (0xff00),则该成员的值为SHN_XINDEX (0xffff),并且节名字符串表的实际索引包含在索引 0 的段头的sh_link字段中。(否则,初始条目的sh_link成员的值为 0。)

0x04 程序头部表(Program Header Table)

参考:Program Header

Program Header Table是一个结构体数组,每一个元素的类型是Elf64_Phdr,每个结构描述了一个段(segment)或者其它系统在准备程序执行时所需要的信息,一个段(segment)包含一个或多个节(section)。其中,ELF 头中的e_phentsizee_phnum指定了该数组每个元素的大小以及元素个数。一个目标文件的段包含一个或者多个节。程序的头部只有对于可执行文件和共享目标文件有意义。

可以说,Program Header Table就是专门为ELF文件运行时中的段所准备的。

Elf64_phdr数据结构如下

1
2
3
4
5
6
7
8
9
10
typedef struct {
Elf64_Word p_type;
Elf64_Word p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
Elf64_Xword p_filesz;
Elf64_Xword p_memsz;
Elf64_Xword p_align;
} Elf64_Phdr;

字段说明如下:

p_type

该字段为段的类型,或者表明了该结构的相关信息。该字段取值如下:

名称
PT_NULL 0
PT_LOAD 1
PT_DYNAMIC 2
PT_INTERP 3
PT_NOTE 4
PT_SHLIB 5
PT_PHDR 6
PT_TLS 7
PT_LOOS 0x60000000
PT_HIOS 0x6fffffff
PT_LOPROC 0x70000000
PT_HIPROC 0x7fffffff

各值含义如下:

PT_NULL

表明段未使用,其结构中其他成员都是未定义的。

PT_LOAD

此类型段为一个可加载的段,大小由p_fileszp_memsz描述。文件中的字节被映射到相应内存段开始处。如果p_memsz大于p_filesz,“剩余” 的字节都要被置为 0。p_filesz不能大于p_memsz。可加载的段在程序头部中按照p_vaddr的升序排列。

PT_DYNAMIC

此类型段给出动态链接信息,具体参考Dynamic Section

PT_INTERP

此类型段给出了一个以 NULL 结尾的字符串的位置和长度,该字符串将被当作解释器调用。这种段类型仅对可执行文件有意义(也可能出现在共享目标文件中)。此外,这种段在一个文件中最多出现一次。而且这种类型的段存在的话,它必须在所有可加载段项的前面。更多信息参考Program Interpreter

PT_NOTE

此类型段给出附加信息的位置和大小。更多信息参考Program Header

PT_SHLIB

该段类型被保留,不过语义未指定。而且,包含这种类型的段的程序不符合 ABI 标准。

PT_PHDR

该段类型的数组元素如果存在的话,则给出了程序头部表自身的大小和位置,既包括在文件中也包括在内存中的信息。此类型的段在文件中最多出现一次。此外,只有程序头部表是程序的内存映像的一部分时,它才会出现。如果此类型段存在,则必须在所有可加载段项目的前面。更多信息参考Program Interpreter

PT_TLS

数组元素指定线程局部存储模板。实现不需要支持此程序表条目。更多信息参考Thread-Local Storage

PT_LOOS到PT_HIOS

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

PT_LOPROC到PT_HIPROC

在此包含范围内的值保留用于处理器特定的语义。如果有具体的含义说明,处理器补充文档将对此进行解释。

p_flags

被系统加载到内存中的程序至少有一个可加载的段。当系统为可加载的段创建内存镜像时,它会按照 p_flags 将段设置为对应的权限。可能的段权限位有

名称 含义
PF_X 0x1 可执行
PF_W 0x2 可写
PF_R 0x4 可读
PF_MASKOS 0x0ff00000 未定义
PF_MASKPROC 0xf0000000 未定义

其中,PF_MASKOS掩码中包含的所有位保留用于操作系统特定语义。PF_MASKPROC掩码中包含的所有位保留用于处理器特定语义。如果指定了含义,处理器补充说明将进行解释。

如果一个权限位被设置为 0,这种类型的段是不可访问的。实际的内存权限取决于相应的内存管理单元,不同的系统可能操作方式不一样。尽管所有的权限组合都是可以的,但是系统一般会授予比请求更多的权限。在任何情况下,除非明确说明,一个段不会有写权限。下面给出了所有的可能组合。

Flags Value Exact Allowable
none 0 All access denied All access denied
PF_X 1 Execute only Read, execute
PF_W 2 Write only Read, write, execute
PF_W+PF_X 3 Write, execute Read, write, execute
PF_R 4 Read only Read, execute
PF_R+PF_X 5 Read, execute Read, execute
PF_R+PF_W 6 Read, write Read, write, execute
PF_R+PF_W+PF_X 7 Read, write, execute Read, write, execute

例如,一般来说,代码段一般具有读和执行权限,但是不会有写权限。数据段一般具有写,读,以及执行权限。

p_offset

该字段给出了从文件开始到该段开头的第一个字节的偏移。

p_vaddr

该字段给出了该段第一个字节在内存中的虚拟地址。

p_paddr

该字段仅用于物理地址寻址相关的系统中, 由于 “System V” 忽略了应用程序的物理寻址,可执行文件和共享目标文件的该项内容并未被限定。

p_filesz

该字段给出了文件镜像中该段的大小,可能为 0。

p_memsz

该字段给出了内存镜像中该段的大小,可能为 0。

p_align

可加载的程序的段的p_vaddr以及p_offset的大小必须是page的整数倍。该成员给出了段在文件以及内存中的对齐方式。如果该值为0或1的话,表示不需要对齐。除此之外,p_align应该是2的整数指数次方,并且p_vaddrp_offset在模p_align`的意义下,应该相等。

0x05 节区头部表(Section Header Table)

该结构用于定位ELF文件中的每个节区的具体位置(一般放在ELF文件末尾)。

首先,ELF头中的e_shoff项给出了从文件开头到节头表位置的字节偏移。e_shnum告诉了我们节头表包含的项数;e_shentsize给出了每一项的字节大小。

其次,节头表是一个数组,每个数组的元素的类型是ELF64_Shdr,每一个元素都描述了一个节区的概要内容。

1
2
3
4
5
6
7
8
9
10
11
12
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 节名称,是节区头字符串表节区中(Section Header String Table Section)的索引,因此该字段实际是一个数值。在字符串表中的具体内容是以NULL结尾的字符串。
sh_type 根据节的内容和语义进行分类,具体的类型下面会介绍。
sh_flags 每一比特代表不同的标志,描述节是否可写,可执行,需要分配内存等属性。
sh_addr 如果节区将出现在进程的内存映像中,此成员给出节区的第一个字节应该在进程镜像中的位置。否则,此字段为 0。
sh_offset 给出节区的第一个字节与文件开始处之间的偏移。SHT_NOBITS类型的节区不占用文件的空间,因此其sh_offset成员给出的是概念性的偏移。
sh_size 此成员给出节区的字节大小。除非节区的类型是SHT_NOBITS,否则该节占用文件中的sh_size字节。类型为SHT_NOBITS的节区长度可能非零,不过却不占用文件中的空间。
sh_link 此成员给出节区头部表索引链接,其具体的解释依赖于节区类型。
sh_info 此成员给出附加信息,其解释依赖于节区类型。
sh_addralign 某些节区的地址需要对齐。例如,如果一个节区有一个doubleword类型的变量,那么系统必须保证整个节区按双字对齐。也就是说,sh_addr % sh_addralign=0。目前它仅允许为0,以及2的正整数幂数。0和1表示没有对齐约束。
sh_entsize 某些节区中存在具有固定大小的表项的表,如符号表。对于这类节区,该成员给出每个表项的字节大小。反之,此成员取值为0。

除了一般的下标外,节头表中还有一些特殊的下标,具体参考Special Section Indexes

名称 含义
SHN_UNDEF 0 标志未定义的,丢失的,不相关的或者其它没有意义的节引用。例如,与节号 SHN_UNDEF 相关的 “定义” 的符号就是一个未定义符号。注:虽然 0 号索引被保留用于未定义值,节头表仍然包含索引 0 的项。也就是说,如果 ELF 头的 e_shnum 为 6,那么索引应该为 0~5。更加详细的内容在后面会说明。
SHN_LORESERVE 0xff00 保留索引值范围的下界。
SHN_LOPROC 0xff00 处理器相关的下界
SHN_HIPROC 0xff1f 处理器相关的上界
SHN_ABS 0xfff1 相关引用的绝对值。例如与节号 SHN_ABS 相关的符号拥有绝对值,它们不受重定位的影响
SHN_COMMON 0xfff2 这一节区相定义的符号是通用符号,例如 FORTRAN COMMON,C 语言中未分配的外部变量。
SHN_HIRESERVE 0xffff 保留索引值范围的上界。

其中,当节区头部表的下标为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 无表项

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

在某些上下文中,节头表索引被保留,例如符号表项的st_shndx成员和ELF头的e_shnume_shstrndx成员。在这些上下文中,保留的值并不代表目标文件中的实际节。此外,在这些上下文中,转义值表示实际节索引在其他地方找到,位于更大的字段中。

部分节头表项成员的具体含义如下:

sh_name

此成员指定对应节表的名称。其值是对字符串节表内容的索引,指示出一个不以NULL为结尾的字符串的位置

关于字符串节表可以参考String Table

sh_type

该成员对部分的内容和语义进行分类。目前由下列可选范围(其中SHT是Section Header Table的简写)

名称 取值 说明
SHT_NULL 0 该类型节区是非活动的,这种类型的节头中的其它成员取值无意义。
SHT_PROGBITS 1 该类型节区包含程序定义的信息,它的格式和含义都由程序来决定。
SHT_SYMTAB 2 该类型节区包含一个符号表(SYMbol TABle)。目前目标文件对每种类型的节区都只 能包含一个,不过这个限制将来可能发生变化。 一般,SHT_SYMTAB 节区提供用于链接编辑(指 ld 而言) 的符号,尽管也可用来实现动态链接。
SHT_STRTAB 3 该类型节区包含字符串表( STRing TABle )。
SHT_RELA 4 该类型节区包含显式指定位数的重定位项( RELocation entry with Addends ),例如,32 位目标文件中的 Elf32_Rela 类型。此外,目标文件可能拥有多个重定位节区。
SHT_HASH 5 该类型节区包含符号哈希表( HASH table )。
SHT_DYNAMIC 6 该类型节区包含动态链接的信息( DYNAMIC linking )。
SHT_NOTE 7 该类型节区包含以某种方式标记文件的信息(NOTE)。
SHT_NOBITS 8 该类型节区不占用文件的空间,其它方面和 SHT_PROGBITS 相似。尽管该类型节区不包含任何字节,其对应的节头成员 sh_offset 中还是会包含概念性的文件偏移。
SHT_REL 9 该类型节区包含重定位表项(RELocation entry without Addends),不过并没有指定位数。例如,32 位目标文件中的 Elf32_rel 类型。目标文件中可以拥有多个重定位节区。
SHT_SHLIB 10 该类型此节区被保留,不过其语义尚未被定义。
SHT_DYNSYM 11 作为一个完整的符号表,它可能包含很多对动态链接而言不必 要的符号。因此,目标文件也可以包含一个 SHT_DYNSYM 节区,其中保存动态链接符号的一个最小集合,以节省空间。
SHT_LOPROC 0X70000000 此值指定保留给处理器专用语义的下界( LOw PROCessor-specific semantics )。
SHT_HIPROC OX7FFFFFFF 此值指定保留给处理器专用语义的上界( HIgh PROCessor-specific semantics )。
SHT_LOUSER 0X80000000 此值指定保留给应用程序的索引下界。
SHT_HIUSER 0X8FFFFFFF 此值指定保留给应用程序的索引上界。

sh_flags

节头中sh_flags字段的每一个比特位都可以给出其相应的标记信息,其定义了对应的节区的内容是否可以被修改、被执行等信息。如果一个标志位被设置,则该位取值为1,未定义的位都为0。目前已定义值如下,其他值保留。

名称 说明
SHF_WRITE 0x1 这种节包含了进程运行过程中可以被写的数据。
SHF_ALLOC 0x2 这种节在进程运行时占用内存。对于不占用目标文件的内存镜像空间的某些控制节,该属性处于关闭状态 (off)。
SHF_EXECINSTR 0x4 这种节包含可执行的机器指令(EXECutable INSTRuction)。
SHF_MASKPROC 0xf0000000 所有在这个掩码中的比特位用于特定处理器语义。

当节区类型的不同的时候,sh_linksh_info也会具有不同的含义。

sh_type sh_link sh_info
SHT_DYNAMIC 节区中使用的字符串表的节头索引 0
SHT_HASH 此哈希表所使用的符号表的节头索引 0
SHT_REL/SHT_RELA 与符号表相关的节头索引 重定位应用到的节的节头索引
SHT_SYMTAB/SHT_DYNSYM 操作系统特定信息,Linux 中的 ELF 文件中该项指向符号表中符号所对应的字符串节区在 Section Header Table 中的偏移。 操作系统特定信息
other SHN_UNDEF 0