ELF - Linux手册页

时间:2019-08-20 18:01:48  来源:igfitidea点击:

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_info

member of the initial entry in section header table.
Otherwise, the
sh_info

member 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/