ELF - Linux手册页
Linux程序员手册 第5部分
更新日期: 2020-04-11
名称
elf-可执行和链接格式(ELF)文件的格式
语法
#include <elf.h>
说明
头文件定义ELF可执行二进制文件的格式。这些文件包括普通可执行文件,可重定位目标文件,核心文件和共享对象。
使用ELF文件格式的可执行文件由ELF头,程序头表或节头表或两者组成。 ELF标头始终位于文件的零偏移处。文件中的程序标题表和节标题表的偏移量在ELF标题中定义。这两个表描述了文件的其余特殊性。
该头文件将上述头文件描述为C结构,并且还包括用于动态节,重定位节和符号表的结构。
Basic types
以下类型用于N位体系结构(N = 32,64,ElfN代表Elf32或Elf64,uintN_t代表uint32_t或uint64_t):
ElfN_Addr Unsigned program address, uintN_t ElfN_Off Unsigned file offset, uintN_t ElfN_Section Unsigned section index, uint16_t ElfN_Versym Unsigned version symbol information, uint16_t Elf_Byte unsigned char ElfN_Half uint16_t ElfN_Sword int32_t ElfN_Word uint32_t ElfN_Sxword int64_t ElfN_Xword uint64_t
(注意:* BSD术语有些不同。在那里,Elf64_Half的大小是Elf32_Half的两倍,而Elf64Quarter用于uint16_t。为避免混淆,在下面将这些类型替换为显式类型。)
文件格式定义的所有数据结构均遵循相关类的"自然"大小和对齐准则。如有必要,数据结构包含显式填充以确保4字节对象的4字节对齐,以将结构大小强制为4的倍数,依此类推。
ELF header (Ehdr)
ELF标头由Elf32_Ehdr或Elf64_Ehdr类型描述:
#define EI_NIDENT 16 typedef struct { unsigned char e_ident[EI_NIDENT]; uint16_t e_type; uint16_t e_machine; uint32_t e_version; ElfN_Addr e_entry; ElfN_Off e_phoff; ElfN_Off e_shoff; uint32_t e_flags; uint16_t e_ehsize; uint16_t e_phentsize; uint16_t e_phnum; uint16_t e_shentsize; uint16_t e_shnum; uint16_t e_shstrndx; } ElfN_Ehdr;
这些字段具有以下含义:
- e_ident
- This array of bytes specifies how to interpret the file,
independent of the processor or the file's remaining contents.
Within this array everything is named by macros, which start with
the prefix
EI_
and may contain values which start with the prefix
ELF.The following macros are defined:
- EI_MAG0
- 幻数的第一个字节。它必须填充ELFMAG0。 (0:0x7f)
- EI_MAG1
- 幻数的第二个字节。它必须填充有ELFMAG1。 (1:aqEaq)
- EI_MAG2
- 幻数的第三个字节。它必须装有ELFMAG2。 (2:aqLaq)
- EI_MAG3
- 幻数的第四个字节。它必须装有ELFMAG3。 (3:aqFaq)
- EI_CLASS
- The fifth byte identifies the architecture for this binary:
- ELFCLASSNONE此类无效。
- ELFCLASS32
- 这定义了32位体系结构。它支持文件和虚拟地址空间最大为4 GB的计算机。
- ELFCLASS64
- 这定义了64位体系结构。
- EI_DATA
- The sixth byte specifies the data encoding of the processor-specific
data in the file.
Currently, these encodings are supported:
- ELFDATANONE未知的数据格式。
- ELFDATA2LSB
- 二进制补码,小尾数。
- ELFDATA2MSB
- 补码,大端。
- EI_VERSION
- 第七个字节是ELF规范的版本号:
- EV_NONE
- 版本无效。
- EV_CURRENT
- 当前版本。
- EI_OSABI
- The eighth byte identifies the operating system
and ABI to which the object is targeted.
Some fields in other ELF structures have flags
and values that have platform-specific meanings;
the interpretation of those fields is determined by the value of this byte.
For example:
- ELFOSABI_NONE与ELFOSABI_SYSV相同
- ELFOSABI_SYSV
- UNIX系统V ABI
- ELFOSABI_HPUX
- HP-UX ABI
- ELFOSABI_NETBSD
- NetBSD ABI
- ELFOSABI_LINUX
- Linux ABI
- ELFOSABI_SOLARIS
- Solaris ABI
- ELFOSABI_IRIX
- 艾力克斯
- ELFOSABI_FREEBSD
- FreeBSD ABI
- ELFOSABI_TRU64
- TRU64 UNIX ABI
- ELFOSABI_ARM
- ARM体系结构ABI
- ELFOSABI_STANDALONE
- 独立(嵌入式)ABI
- EI_ABIVERSION
- 第九个字节标识对象所针对的ABI版本。此字段用于区分ABI的不兼容版本。此版本号的解释取决于EI_OSABI字段标识的ABI。符合此规范的应用程序使用值0。
- EI_PAD
- 开始填充。这些字节被保留并设置为零。读取它们的程序应忽略它们。如果给出当前未使用的字节的含义,EI_PAD的值将在将来更改。
- EI_NIDENT
- e_ident数组的大小。
- e_type
- This member of the structure identifies the object file type:
- ET_NONE未知类型。
- ET_REL
- 可重定位文件。
- ET_EXEC
- 可执行文件。
- ET_DYN
- 共享对象。
- ET_CORE
- 核心文件。
- e_machine
- This member specifies the required architecture for an individual file.
For example:
- EM_NONE未知机器
- EM_M32
- AT&T我们32100
- EM_SPARC
- Sun Microsystems SPARC
- EM_386
- 英特尔80386
- EM_68K
- 摩托罗拉68000
- EM_88K
- 摩托罗拉88000
- EM_860
- 英特尔80860
- EM_MIPS
- MIPS RS3000(仅大端)
- EM_PARISC
- HP / PA
- EM_SPARC32PLUS
- 具有增强指令集的SPARC
- EM_PPC
- PowerPC
- EM_PPC64
- PowerPC 64位
- EM_S390
- IBM S / 390
- EM_ARM
- 先进的RISC机器
- EM_SH
- 瑞萨电子
- EM_SPARCV9
- SPARC v9 64位
- EM_IA_64
- 英特尔安腾
- EM_X86_64
- AMD x86-64
- EM_VAX
- DEC Vax
- e_version
- This member identifies the file version:
- EV_NONE版本无效
- EV_CURRENT
- 当前版本
- e_entry
- 该成员提供系统首先将控制权转移到的虚拟地址,从而开始该过程。如果文件没有关联的入口点,则此成员为零。
- e_phoff
- 该成员保存程序头表的文件偏移量(以字节为单位)。如果文件没有程序头表,则该成员为零。
- e_shoff
- 该成员保存节头表的文件偏移量(以字节为单位)。如果文件没有节头表,则此成员为零。
- e_flags
- 该成员保存与文件关联的特定于处理器的标志。标志名称采用EF_`machine_flag'的形式。当前,尚未定义标志。
- e_ehsize
- 该成员保存ELF标头的大小(以字节为单位)。
- e_phentsize
- 该成员保存文件程序头表中一个条目的大小(以字节为单位)。所有条目的大小均相同。
- e_phnum
- 该成员保存程序头表中的条目数。因此,e_phentsize和e_phnum的乘积给出了表的大小(以字节为单位)。如果文件没有程序头,则e_phnum的值为零。
- If the number of entries in the program header table is
larger than or equal to
PN_XNUM
(0xffff), this member holds
PN_XNUM(0xffff) and the real number of entries in the program header table is held
in the
sh_infomember of the initial entry in section header table.
Otherwise, the
sh_infomember of the initial entry contains the value zero.
- PN_XNUM
- 它定义为0xffff,e_phnum可以具有的最大数字,指定在何处分配程序头的实际数量。
- e_shentsize
- 该成员保存节头的大小(以字节为单位)。节标题是节标题表中的一项;所有条目的大小均相同。
- e_shnum
- 该成员保存节头表中的条目数。因此,e_shentsize和e_shnum的乘积给出了节头表的大小(以字节为单位)。如果文件没有节头表,则e_shnum的值为零。
- 如果节标题表中的条目数大于或等于SHN_LORESERVE(0xff00),则e_shnum保持值为零,节标题表中的实际条目数保留在节标题中初始条目的sh_size成员中表。否则,节标题表中初始条目的sh_size成员的值将为零。
- e_shstrndx
- 该成员保存与节名称字符串表关联的条目的节标题表索引。如果该文件没有节名称字符串表,则此成员保存值SHN_UNDEF。
- 如果节名称字符串表section的索引大于或等于SHN_LORESERVE(0xff00),则该成员保存SHN_XINDEX(0xffff),并且节名称字符串表section的实际索引保存在section的初始条目的sh_link成员中标题表。否则,节标题表中初始条目的sh_link成员包含零值。
Program header (Phdr)
可执行文件或共享对象文件的程序头表是结构数组,每个结构都描述系统为执行程序准备程序所需的段或其他信息。一个目标文件段包含一个或多个节。程序头仅对可执行文件和共享对象文件有意义。文件使用ELF标头的e_phentsize和e_phnum成员指定其自己的程序标头大小。 ELF程序标头由Elf32_Phdr或Elf64_Phdr类型描述,具体取决于体系结构:
typedef struct { uint32_t p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; uint32_t p_filesz; uint32_t p_memsz; uint32_t p_flags; uint32_t p_align; } Elf32_Phdr;
typedef struct { uint32_t p_type; uint32_t p_flags; Elf64_Off p_offset; Elf64_Addr p_vaddr; Elf64_Addr p_paddr; uint64_t p_filesz; uint64_t p_memsz; uint64_t p_align; } Elf64_Phdr;
32位和64位程序头之间的主要区别在于p_flags成员在整个结构中的位置。
- p_type
- This member of the structure indicates what kind of segment this array
element describes or how to interpret the array element's information.
- PT_NULL
- 数组元素未使用,其他成员的值未定义。这样,程序头就可以忽略条目。
- PT_LOAD
- 数组元素指定了一个可加载段,由p_filesz和p_memsz描述。文件中的字节被映射到内存段的开头。如果段的内存大小p_memsz大于文件大小p_filesz,则定义"额外"字节以保留值0并跟随段的初始化区域。文件大小不能大于内存大小。程序头表中的可装入段条目以升序出现,并按p_vaddr成员排序。
- PT_DYNAMIC
- 数组元素指定动态链接信息。
- PT_INTERP
- 数组元素指定以空值结尾的路径名的位置和大小,以用作解释程序。该段类型仅对可执行文件有意义(尽管对于共享对象可能会发生)。但是,它在文件中可能不会出现多次。如果存在,它必须在任何可装入段条目之前。
- PT_NOTE
- 数组元素指定注释的位置(ElfN_Nhdr)。
- PT_SHLIB
- 该段类型是保留的,但是具有未指定的语义。包含此类数组元素的程序不符合ABI。
- PT_PHDR
- 数组元素(如果存在)在文件和程序的内存映像中指定程序头表本身的位置和大小。在文件中,此段类型可能不会出现多次。而且,仅当程序头表是程序的存储映像的一部分时,它才可能发生。如果存在,它必须在任何可装入段条目之前。
- PT_LOPROC, PT_HIPROC
- 包含范围内的值[PT_LOPROC,PT_HIPROC]保留用于特定于处理器的语义。
- PT_GNU_STACK
- GNU扩展,Linux内核使用它通过p_flags成员中设置的标志来控制堆栈的状态。
- p_offset
- 该成员保留该段的第一个字节所在文件的开头的偏移量。
- p_vaddr
- 该成员将虚拟地址(段的第一个字节驻留在内存中)保留在该地址。
- p_paddr
- 在与物理寻址相关的系统上,该成员保留用于网段的物理地址。在BSD下,不使用该成员,并且必须为零。
- p_filesz
- 该成员保存该段的文件映像中的字节数。可能为零。
- p_memsz
- 该成员保存该段的内存映像中的字节数。可能为零。
- p_flags
- This member holds a bit mask of flags relevant to the segment:
- PF_X可执行段。
- PF_W
- 可写段。
- PF_R
- 可读段。
- 文本段通常具有标志PF_X和PF_R。数据段通常具有PF_W和PF_R。
- p_align
- 该成员在内存和文件中保存段与之对齐的值。可装入过程段的p_vaddr和p_offset必须具有一致的值,以页面大小为模。值零和一表示不需要对齐。否则,p_align应该是2的正整数幂,并且p_vaddr应该等于p_offset模p_align。
Section header (Shdr)
使用文件的节头表,可以找到文件的所有节。节标题表是Elf32_Shdr或Elf64_Shdr结构的数组。 ELF标头的e_shoff成员提供从文件开头到节标头表的字节偏移量。 e_shnum保存节头表包含的条目数。 e_shentsize保留每个条目的大小(以字节为单位)。
节标题表索引是此数组的下标。保留了一些节头表索引:初始条目以及SHN_LORESERVE和SHN_HIRESERVE之间的索引。初始条目用于e_phnum,e_shnum和e_shstrndx的ELF扩展;在其他情况下,初始条目中的每个字段都设置为零。对象文件没有这些特殊索引的部分:
- SHN_UNDEF
- 此值标记为未定义,丢失,不相关或其他无意义的节引用。
- SHN_LORESERVE
- 此值指定保留索引范围的下限。
- SHN_LOPROC, SHN_HIPROC
- 保留范围[SHN_LOPROC,SHN_HIPROC]中的较大值保留用于处理器特定的语义。
- SHN_ABS
- 该值指定相应参考的绝对值。例如,相对于段号SHN_ABS定义的符号具有绝对值,并且不受重定位的影响。
- SHN_COMMON
- 相对于本节定义的符号是通用符号,例如FORTRAN COMMON或未分配的C外部变量。
- SHN_HIRESERVE
- 此值指定保留索引范围的上限。系统在SHN_LORESERVE和SHN_HIRESERVE(包括)之间保留索引。节标题表不包含保留索引的条目。
节标题具有以下结构:
typedef struct { uint32_t sh_name; uint32_t sh_type; uint32_t sh_flags; Elf32_Addr sh_addr; Elf32_Off sh_offset; uint32_t sh_size; uint32_t sh_link; uint32_t sh_info; uint32_t sh_addralign; uint32_t sh_entsize; } Elf32_Shdr;
typedef struct { uint32_t sh_name; uint32_t sh_type; uint64_t sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; uint64_t sh_size; uint32_t sh_link; uint32_t sh_info; uint64_t sh_addralign; uint64_t sh_entsize; } Elf64_Shdr;
32位和64位节头之间没有真正的区别。
- sh_name
- 该成员指定节的名称。它的值是到节头字符串表部分的索引,给出了以空终止的字符串的位置。
- sh_type
- This member categorizes the section's contents and semantics.
- SHT_NULL
- 此值将节标题标记为无效。它没有关联的部分。节标题的其他成员具有未定义的值。
- SHT_PROGBITS
- 本节包含由程序定义的信息,其格式和含义仅由程序确定。
- SHT_SYMTAB
- 本节包含一个符号表。通常,SHT_SYMTAB提供用于链接编辑的符号,尽管它也可以用于动态链接。作为完整的符号表,它可能包含许多动态链接不需要的符号。一个目标文件也可以包含一个SHT_DYNSYM节。
- SHT_STRTAB
- 本节包含一个字符串表。一个目标文件可能具有多个字符串表节。
- SHT_RELA
- 本节包含带有显式加数的重定位条目,例如32位类目标文件的Elf32_Rela类型。一个对象可能具有多个重定位部分。
- SHT_HASH
- 本节包含一个符号哈希表。参与动态链接的对象必须包含符号哈希表。一个目标文件可能只有一个哈希表。
- SHT_DYNAMIC
- 本节包含用于动态链接的信息。一个目标文件可能只有一个动态节。
- SHT_NOTE
- 本节包含注释(ElfN_Nhdr)。
- SHT_NOBITS
- 此类型的节在文件中不占空间,但与SHT_PROGBITS相似。尽管本节不包含任何字节,但sh_offset成员包含概念性文件偏移量。
- SHT_REL
- 本节包含没有明显加数的重定位偏移量,例如32位类的目标文件的Elf32_Rel类型。一个目标文件可能具有多个重定位部分。
- SHT_SHLIB
- 本节保留,但具有未指定的语义。
- SHT_DYNSYM
- 本节包含最少的动态链接符号集。一个目标文件也可以包含一个SHT_SYMTAB节。
- SHT_LOPROC, SHT_HIPROC
- 包含范围内的值[SHT_LOPROC,SHT_HIPROC]保留用于特定于处理器的语义。
- SHT_LOUSER
- 此值指定为应用程序保留的索引范围的下限。
- SHT_HIUSER
- 此值指定为应用程序保留的索引范围的上限。应用程序可以使用SHT_LOUSER和SHT_HIUSER之间的节类型,而不会与当前或将来的系统定义的节类型冲突。
- sh_flags
- Sections support one-bit flags that describe miscellaneous attributes.
If a flag bit is set in
sh_flags,
the attribute is
"on"
for the section.
Otherwise, the attribute is
"off"
or does not apply.
Undefined attributes are set to zero.- SHF_WRITE
- 本节包含在流程执行期间应可写的数据。
- SHF_ALLOC
- 此部分在进程执行期间占用内存。某些控制部分不驻留在目标文件的存储映像中。对于那些部分,此属性关闭。
- SHF_EXECINSTR
- 本节包含可执行的机器指令。
- SHF_MASKPROC
- 此掩码中包含的所有位均保留用于特定于处理器的语义。
- sh_addr
- 如果此部分出现在进程的内存映像中,则该成员保存该部分的第一个字节应驻留的地址。否则,成员包含零。
- sh_offset
- 该成员的值保留从文件开头到该节中第一个字节的字节偏移量。一种节类型SHT_NOBITS在文件中不占空间,它的sh_offset成员在文件中定位概念位置。
- sh_size
- 该成员保存节的大小(以字节为单位)。除非节类型为SHT_NOBITS,否则该节在文件中占用sh_size个字节。类型为SHT_NOBITS的节的大小可能为非零,但该文件中没有空间。
- sh_link
- 该成员拥有节头表索引链接,其解释取决于节类型。
- sh_info
- 该成员拥有其他信息,其解释取决于节的类型。
- sh_addralign
- 一些部分具有地址对齐约束。如果部分包含双字,则系统必须确保整个部分的双字对齐。也就是说,sh_addr的值必须与sh_addralign的值取模,然后为零。仅允许零和正整数幂为2。值0或1表示该部分没有对齐约束。
- sh_entsize
- 有些部分包含一个固定大小的条目表,例如符号表。对于这样的部分,该成员以字节为单位给出每个条目的大小。如果该部分不包含固定大小的条目表,则此成员包含零。
各个部分包含程序和控制信息:
- .bss
- 本节包含有助于程序存储映像的未初始化数据。根据定义,当程序开始运行时,系统将数据初始化为零。此部分的类型为SHT_NOBITS。属性类型为SHF_ALLOC和SHF_WRITE。
- .comment
- 本节包含版本控制信息。此部分的类型为SHT_PROGBITS。没有使用属性类型。
- .ctors
- 本节包含指向C ++构造函数的初始化指针。此部分的类型为SHT_PROGBITS。属性类型为SHF_ALLOC和SHF_WRITE。
- .data
- 本节包含有助于程序存储映像的初始化数据。此部分的类型为SHT_PROGBITS。属性类型为SHF_ALLOC和SHF_WRITE。
- .data1
- 本节包含有助于程序存储映像的初始化数据。此部分的类型为SHT_PROGBITS。属性类型为SHF_ALLOC和SHF_WRITE。
- .debug
- 本节包含用于符号调试的信息。内容未指定。此部分的类型为SHT_PROGBITS。没有使用属性类型。
- .dtors
- 本节包含指向C ++析构函数的初始化指针。此部分的类型为SHT_PROGBITS。属性类型为SHF_ALLOC和SHF_WRITE。
- .dynamic
- 本节包含动态链接信息。该部分的属性将包括SHF_ALLOC位。 SHF_WRITE位是否设置是特定于处理器的。此部分的类型为SHT_DYNAMIC。请参阅上面的属性。
- .dynstr
- 本节包含动态链接所需的字符串,最常见的是代表与符号表条目关联的名称的字符串。此部分的类型为SHT_STRTAB。使用的属性类型为SHF_ALLOC。
- .dynsym
- 本节包含动态链接符号表。此部分的类型为SHT_DYNSYM。使用的属性是SHF_ALLOC。
- .fini
- 本节包含有助于处理终止代码的可执行指令。当程序正常退出时,系统将安排执行此部分中的代码。此部分的类型为SHT_PROGBITS。使用的属性是SHF_ALLOC和SHF_EXECINSTR。
- .gnu.version
- 本节包含版本符号表,它是ElfN_Half元素的数组。本部分的类型为SHT_GNU_versym。使用的属性类型为SHF_ALLOC。
- .gnu.version_d
- 本节包含版本符号定义,这是ElfN_Verdef结构的表。此部分的类型为SHT_GNU_verdef。使用的属性类型为SHF_ALLOC。
- .gnu.version_r
- 本节包含版本符号所需的元素,即ElfN_Verneed结构的表。本部分的类型为SHT_GNU_versym。使用的属性类型为SHF_ALLOC。
- .got
- 本节包含全局偏移表。此部分的类型为SHT_PROGBITS。这些属性是特定于处理器的。
- .hash
- 本节包含一个符号哈希表。此部分的类型为SHT_HASH。使用的属性是SHF_ALLOC。
- .init
- 本节包含有助于处理初始化代码的可执行指令。当程序开始运行时,系统会在调用主程序入口点之前执行本节中的代码。此部分的类型为SHT_PROGBITS。使用的属性是SHF_ALLOC和SHF_EXECINSTR。
- .interp
- 本节包含程序解释器的路径名。如果文件具有包含该节的可装入段,则该节的属性将包含SHF_ALLOC位。否则,该位将关闭。此部分的类型为SHT_PROGBITS。
- .line
- 本节包含用于符号调试的行号信息,该信息描述了程序源与机器代码之间的对应关系。内容未指定。此部分的类型为SHT_PROGBITS。没有使用属性类型。
- .note
- 本节包含各种注释。此部分的类型为SHT_NOTE。没有使用属性类型。
- .note.ABI-tag
- 本部分用于声明ELF映像的预期运行时ABI。它可能包括操作系统名称及其运行时版本。此部分的类型为SHT_NOTE。使用的唯一属性是SHF_ALLOC。
- .note.gnu.build-id
- 该部分用于保存唯一标识ELF图像内容的ID。具有相同内部版本ID的不同文件应包含相同的可执行内容。有关更多详细信息,请参见GNU链接程序(ld(1))的--build-id选项。此部分的类型为SHT_NOTE。使用的唯一属性是SHF_ALLOC。
- .note.GNU-stack
- 此部分在Linux目标文件中用于声明堆栈属性。此部分的类型为SHT_PROGBITS。使用的唯一属性是SHF_EXECINSTR。这向GNU链接器指示目标文件需要可执行堆栈。
- .note.openbsd.ident
- OpenBSD本机可执行文件通常包含此部分以标识自身,因此内核在加载文件时可以绕过任何兼容性ELF二进制仿真测试。
- .plt
- 本节包含过程链接表。此部分的类型为SHT_PROGBITS。这些属性是特定于处理器的。
- .relNAME
- 本节包含如下所述的重定位信息。如果文件具有包含重定位的可加载段,则该节的属性将包含SHF_ALLOC位。否则,该位将关闭。按照惯例," NAME"由重定位所适用的部分提供。因此,.text的重定位段通常将具有.rel.text名称。此部分的类型为SHT_REL。
- .relaNAME
- 本节包含如下所述的重定位信息。如果文件具有包含重定位的可加载段,则该节的属性将包含SHF_ALLOC位。否则,该位将关闭。按照惯例," NAME"由重定位所适用的部分提供。因此,.text的重定位节通常将具有.rela.text名称。此部分的类型为SHT_RELA。
- .rodata
- 本节包含通常在过程映像中构成不可写段的只读数据。此部分的类型为SHT_PROGBITS。使用的属性是SHF_ALLOC。
- .rodata1
- 本节包含通常在过程映像中构成不可写段的只读数据。此部分的类型为SHT_PROGBITS。使用的属性是SHF_ALLOC。
- .shstrtab
- 本节包含节名称。此部分的类型为SHT_STRTAB。没有使用属性类型。
- .strtab
- 本节包含字符串,最常见的是代表与符号表条目关联的名称的字符串。如果文件具有包含符号字符串表的可加载段,则该节的属性将包含SHF_ALLOC位。否则,该位将关闭。此部分的类型为SHT_STRTAB。
- .symtab
- 本节包含一个符号表。如果文件具有包含符号表的可加载段,则该节的属性将包含SHF_ALLOC位。否则,该位将关闭。此部分的类型为SHT_SYMTAB。
- .text
- 本节包含程序的"文本"或可执行指令。此部分的类型为SHT_PROGBITS。使用的属性是SHF_ALLOC和SHF_EXECINSTR。
String and symbol tables
字符串表节包含以零结尾的字符序列,通常称为字符串。目标文件使用这些字符串表示符号和节名称。有人将字符串作为字符串表部分的索引。索引为零的第一个字节定义为保存一个空字节(aq \ 0aq)。同样,字符串表的最后一个字节定义为保留一个空字节,以确保所有字符串的终止为空。
目标文件的符号表包含定位和重新定位程序的符号定义和引用所需的信息。符号表索引是该数组的下标。
typedef struct { uint32_t st_name; Elf32_Addr st_value; uint32_t st_size; unsigned char st_info; unsigned char st_other; uint16_t st_shndx; } Elf32_Sym;
typedef struct { uint32_t st_name; unsigned char st_info; unsigned char st_other; uint16_t st_shndx; Elf64_Addr st_value; uint64_t st_size; } Elf64_Sym;
32位和64位版本具有相同的成员,只是顺序不同。
- st_name
- 该成员拥有目标文件符号字符串表的索引,该索引包含符号名称的字符表示。如果该值非零,则表示给出符号名称的字符串表索引。否则,该符号没有名称。
- st_value
- 该成员给出相关符号的值。
- st_size
- 许多符号都有关联的大小。如果符号没有大小或未知大小,则该成员为零。
- st_info
- This member specifies the symbol's type and binding attributes:
- STT_NOTYPE
- 没有定义符号的类型。
- STT_OBJECT
- 该符号与数据对象相关联。
- STT_FUNC
- 该符号与功能或其他可执行代码相关联。
- STT_SECTION
- 该符号与一个节关联。这种类型的符号表条目主要用于重定位,并且通常具有STB_LOCAL绑定。
- STT_FILE
- 按照约定,符号的名称给出与目标文件关联的源文件的名称。文件符号具有STB_LOCAL绑定,其节索引为SHN_ABS,并且在文件的其他STB_LOCAL符号之前(如果存在)。
- STT_LOPROC, STT_HIPROC
- 包含范围内的值[STT_LOPROC,STT_HIPROC]保留用于特定于处理器的语义。
- STB_LOCAL
- 本地符号在包含其定义的目标文件外部不可见。多个文件中可能存在相同名称的本地符号,而不会互相干扰。
- STB_GLOBAL
- 全局符号对所有组合的目标文件可见。一个文件对全局符号的定义将满足另一个文件对同一符号的未定义引用。
- STB_WEAK
- 弱符号类似于全局符号,但是其定义的优先级较低。
- STB_LOPROC, STB_HIPROC
- 包含范围内的值[STB_LOPROC,STB_HIPROC]保留用于特定于处理器的语义。
- There are macros for packing and unpacking the binding and type fields:
- ELF32_ST_BIND(info), ELF64_ST_BIND(info)
- 从st_info值中提取绑定。
- ELF32_ST_TYPE(info), ELF64_ST_TYPE(info)
- 从st_info值中提取类型。
- ELF32_ST_INFO(bind, type), ELF64_ST_INFO(bind, type)
- 将绑定和类型转换为st_info值。
- st_other
- This member defines the symbol visibility.
- STV_DEFAULT默认符号可见性规则。全局和弱符号可用于其他模块;本地模块中的引用可以插入其他模块中的定义。
- STV_INTERNAL
- 特定于处理器的隐藏类。
- STV_HIDDEN
- 符号对其他模块不可用;本地模块中的引用始终解析为本地符号(即,该符号不能被其他模块中的定义插入)。
- STV_PROTECTED
- 符号可用于其他模块,但是本地模块中的引用始终解析为本地符号。
有用于提取可见性类型的宏:
ELF32_ST_VISIBILITY(其他)或ELF64_ST_VISIBILITY(其他)
- st_shndx
- 每个符号表条目都是相对于某个部分"定义的"。该成员保存相关节头表索引。
Relocation entries (Rel & Rela)
重定位是将符号引用与符号定义连接在一起的过程。可重定位文件必须具有描述如何修改其节内容的信息,从而使可执行文件和共享目标文件可以保存进程的程序映像的正确信息。重定位条目是这些数据。
不需要加数的重定位结构:
typedef struct { Elf32_Addr r_offset; uint32_t r_info; } Elf32_Rel;
typedef struct { Elf64_Addr r_offset; uint64_t r_info; } Elf64_Rel;
需要加数的重定位结构:
typedef struct { Elf32_Addr r_offset; uint32_t r_info; int32_t r_addend; } Elf32_Rela;
typedef struct { Elf64_Addr r_offset; uint64_t r_info; int64_t r_addend; } Elf64_Rela;
- r_offset
- 该成员提供了应用重定位操作的位置。对于可重定位文件,该值是从该段的开头到受重定位影响的存储单元的字节偏移量。对于可执行文件或共享对象,该值是受重定位影响的存储单元的虚拟地址。
- r_info
- 该成员既给出了必须进行重定位的符号表索引,也给出了要应用的重定位类型。重定位类型是特定于处理器的。当文本引用重定位条目的重定位类型或符号表索引时,表示将ELF [32 | 64] _R_TYPE或ELF [32 | 64] _R_SYM分别应用于条目的r_info成员的结果。
- r_addend
- 该成员指定用于计算要存储到可重定位字段中的值的常数加数。
Dynamic tags (Dyn)
.dynamic部分包含一系列包含相关动态链接信息的结构。 d_tag成员控制d_un的解释。
typedef struct { Elf32_Sword d_tag; union { Elf32_Word d_val; Elf32_Addr d_ptr; } d_un; } Elf32_Dyn; extern Elf32_Dyn _DYNAMIC[];
typedef struct { Elf64_Sxword d_tag; union { Elf64_Xword d_val; Elf64_Addr d_ptr; } d_un; } Elf64_Dyn; extern Elf64_Dyn _DYNAMIC[];
- d_tag
- This member may have any of the following values:
- DT_NULL
- 标记动态部分的结尾
- DT_NEEDED
- 字符串表到所需库名的偏移量
- DT_PLTRELSZ
- PLT重定位条目的大小(以字节为单位)
- DT_PLTGOT
- PLT和/或GOT的地址
- DT_HASH
- 符号哈希表的地址
- DT_STRTAB
- 字符串表地址
- DT_SYMTAB
- 符号表地址
- DT_RELA
- Rela重定位表的地址
- DT_RELASZ
- Rela重定位表的大小(以字节为单位)
- DT_RELAENT
- Rela重定位表条目的大小(以字节为单位)
- DT_STRSZ
- 字符串表的大小(以字节为单位)
- DT_SYMENT
- 符号表条目的大小(以字节为单位)
- DT_INIT
- 初始化功能的地址
- DT_FINI
- 终止功能的地址
- DT_SONAME
- 字符串表与共享对象名称的偏移量
- DT_RPATH
- 字符串表到库搜索路径的偏移量(不建议使用)
- DT_SYMBOLIC
- 警报链接程序在可执行文件之前搜索该共享对象以查找符号
- DT_REL
- Rel重定位表的地址
- DT_RELSZ
- Rel重定位表的大小(以字节为单位)
- DT_RELENT
- Rel表条目的大小(以字节为单位)
- DT_PLTREL
- PLT引用的重定位条目的类型(相对或相对)
- DT_DEBUG
- 未定义用于调试
- DT_TEXTREL
- 缺少此条目表示没有重定位条目应适用于不可写段
- DT_JMPREL
- 仅与PLT相关联的重定位条目的地址
- DT_BIND_NOW
- 指示动态链接器在将控制权转移到可执行文件之前处理所有重定位
- DT_RUNPATH
- 字符串表到库搜索路径的偏移量
- DT_LOPROC, DT_HIPROC
- 包含范围内的值[DT_LOPROC,DT_HIPROC]保留用于特定于处理器的语义
- d_val
- 该成员表示具有各种解释的整数值。
- d_ptr
- 该成员代表程序虚拟地址。解释这些地址时,应根据原始文件值和内存基址来计算实际地址。文件不包含用于修复这些地址的重定位条目。
- _DYNAMIC
- 包含.dynamic节中所有动态结构的数组。这是由链接器自动填充的。
Notes (Nhdr)
ELF注释允许附加任意信息供系统使用。它们主要由核心文件(ET_CORE的e_type)使用,但是许多项目定义了自己的扩展集。例如,GNU工具链使用ELF注释将信息从链接器传递到C库。
注释部分包含一系列注释(请参见下面的结构定义)。每个音符后跟一个名称字段(其长度在n_namesz中定义),然后是一个描述符字段(其长度在n_descsz中定义),并且其起始地址具有4字节对齐。由于其任意长度,两个字段都未在note结构中定义。
解析两个连续注释的示例应阐明它们在内存中的布局:
void *memory, *name, *desc; Elf64_Nhdr *note, *next_note; /* The buffer is pointing to the start of the section/segment */ note = memory; /* If the name is defined, it follows the note */ name = note->n_namesz == 0 ? NULL : memory + sizeof(*note); /* If the descriptor is defined, it follows the name (with alignment) */ desc = note->n_descsz == 0 ? NULL : memory + sizeof(*note) + ALIGN_UP(note->n_namesz, 4); /* The next note follows both (with alignment) */ next_note = memory + sizeof(*note) + ALIGN_UP(note->n_namesz, 4) + ALIGN_UP(note->n_descsz, 4);
请记住,对n_type的解释取决于n_namesz字段定义的名称空间。如果未设置n_namesz字段(例如,为0),则有两组注释:一组用于核心文件,另一组用于所有其他ELF类型。如果名称空间未知,那么工具通常也将回退到这些注释集。
typedef struct { Elf32_Word n_namesz; Elf32_Word n_descsz; Elf32_Word n_type; } Elf32_Nhdr;
typedef struct { Elf64_Word n_namesz; Elf64_Word n_descsz; Elf64_Word n_type; } Elf64_Nhdr;
- n_namesz
- 名称字段的长度(以字节为单位)。内存中的内容将立即跟随此注释。名称以null终止。例如,如果名称是" GNU",则n_namesz将设置为4。
- n_descsz
- 描述符字段的长度(以字节为单位)。内容将立即跟随内存中的名称字段。
- n_type
- Depending on the value of the name field, this member may have any of the
following values:
- Core files (e_type = ET_CORE)
- Notes used by all core files.
These are highly operating system or architecture specific and often require
close coordination with kernels, C libraries, and debuggers.
These are used when the namespace is the default (i.e.,
n_namesz
will be set to 0), or a fallback when the namespace is unknown.
- NT_PRSTATUS prstatus结构
- NT_FPREGSET
- fpregset结构
- NT_PRPSINFO
- prpsinfo结构
- NT_PRXREG
- prxregset结构
- NT_TASKSTRUCT
- 任务结构
- NT_PLATFORM
- 来自sysinfo(SI_PLATFORM)的字符串
- NT_AUXV
- 辅助数组
- NT_GWINDOWS
- gwindows结构
- NT_ASRS
- asrset结构
- NT_PSTATUS
- 状态结构
- NT_PSINFO
- psinfo结构
- NT_PRCRED
- 预定义结构
- NT_UTSNAME
- utsname结构
- NT_LWPSTATUS
- lwpstatus结构
- NT_LWPSINFO
- lwpinfo结构
- NT_PRFPXREG
- fprxregset结构
- NT_SIGINFO
- siginfo_t(大小可能会随着时间增加)
- NT_FILE
- 包含有关映射文件的信息
- NT_PRXFPREG
- user_fxsr_struct
- NT_PPC_VMX
- PowerPC Altivec / VMX寄存器
- NT_PPC_SPE
- PowerPC SPE / EVR寄存器
- NT_PPC_VSX
- PowerPC VSX寄存器
- NT_386_TLS
- i386 TLS插槽(结构user_desc)
- NT_386_IOPERM
- x86 io权限位图(1 =拒绝)
- NT_X86_XSTATE
- 使用xsave的x86扩展状态
- NT_S390_HIGH_GPRS
- s390上半部分寄存器
- NT_S390_TIMER
- s390计时器寄存器
- NT_S390_TODCMP
- s390时间时钟(TOD)时钟比较器寄存器
- NT_S390_TODPREG
- s390日时钟(TOD)可编程寄存器
- NT_S390_CTRS
- s390控制寄存器
- NT_S390_PREFIX
- s390前缀寄存器
- NT_S390_LAST_BREAK
- s390中断事件地址
- NT_S390_SYSTEM_CALL
- s390系统调用重启数据
- NT_S390_TDB
- s390事务诊断块
- NT_ARM_VFP
- ARM VFP / NEON寄存器
- NT_ARM_TLS
- ARM TLS寄存器
- NT_ARM_HW_BREAK
- ARM硬件断点寄存器
- NT_ARM_HW_WATCH
- ARM硬件观察点寄存器
- NT_ARM_SYSTEM_CALL
- ARM系统电话号码
- n_name = GNU
- Extensions used by the GNU tool chain.
- NT_GNU_ABI_TAG
- 操作系统(OS)ABI信息。 desc字段将是4个字:
- *
- 字0:操作系统描述符(ELF_NOTE_OS_LINUX,ELF_NOTE_OS_GNU等)`
- *
- 词1:ABI的主要版本
- *
- 字2:ABI的次要版本
- *
- 字3:ABI的次要版本
- NT_GNU_HWCAP
- 综合hwcap信息。 desc字段以两个词开头:
- *
- 字0:条目数
- *
- 字1:启用条目的位掩码
- 然后跟随可变长度的条目,一个字节,后跟一个以null结尾的hwcap名称字符串。字节给出了要启用的测试位数(1U
- NT_GNU_BUILD_ID
- 由GNU ld(1)--build-id选项生成的唯一构建ID。 desc由任意数量的非零字节组成。
- NT_GNU_GOLD_VERSION
- desc包含使用的GNU Gold链接器版本。
- Default/unknown namespace (e_type != ET_CORE)
- These are used when the namespace is the default (i.e.,
n_namesz
will be set to 0), or a fallback when the namespace is unknown.
- NT_VERSION某种版本的字符串。
- NT_ARCH
- 建筑信息。
备注
ELF首次出现在System V中。ELF格式是采用的标准。
e_phnum,e_shnum和e_shstrndx的扩展分别是Linux扩展。 Sun,BSD和AMD64也支持它们。有关更多信息,请参见另请参阅。
另外参见
as(1),elfedit(1),gdb(1),ld(1),nm(1),objdump(1),patchelf(1),readelf(1),size(1),字符串(1), strip(1),execve(2),dl_iterate_phdr(3),core(5),ld.so(8)
Hewlett-Packard,Elf-64目标文件格式。
Santa Cruz操作,System V应用程序二进制接口。
UNIX系统实验室,"目标文件",可执行和链接格式(ELF)。
《 Sun Microsystems,链接器和库指南》。
AMD64 ABI草案,系统V应用程序二进制接口AMD64体系结构处理器补充。
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。