ELF文件格式

发布时间 2024-01-12 15:01:15作者: zxddesk

简介

Linux 内核学习时,需要学习 ELF 文件格式。在 Linux 基金会 - 引用参考文档 中有关于 ELF 文件格式的标准说明。这里翻译一下,当作学习笔记。 原文链接

Tool Interface Standard (TIS)
Executable and Linking Format (ELF)
Specification
Version 1.2

1.2版 ELF 格式规范是工具接口标准委员会(TIS)工作的成果。TIS是一个由微型计算机行业成员组成的协会,旨在实现32位英特尔体系结构操作环境开发工具可见的软件接口标准化。这样的接口包括对象模块格式可执行文件格式以及调试记录信息和格式

该委员会的目标是帮助简化整个微型计算机行业的软件开发过程,目前专注于32位操作环境。为此,委员会制定了一些规范,其中一些是针对可在领先的行业操作系统中移植的文件格式,另一些则描述了32位Windows操作系统的格式。最初作为TIS可移植格式规范1.1版一起分发,现在这些规范被单独分离和分发。

TIS委员会成员包括来自Absoft、Autodesk、Borland International、IBM、Intel、Lahey、Lotus、MetaWare、Microtec Research、Microsoft、Novell、The Santa Cruz Operation和WATCOM International的代表。PharLap软件公司和赛门铁克公司也参与了规范定义工作。 与TIS规范集合中的其他规范一样,该规范基于现有的、经过验证的格式,符合TIS委员会的目标,即采用现有标准,并在必要时扩展现有标准,而不是发明新标准。

关于 ELF: Executable and Linking Format

可执行文件和链接格式最初由UNIX系统实验室(USL)开发并发布,作为应用程序二进制接口(ABI)的一部分。工具接口标准委员会(TIS)选择了不断发展的ELF标准作为一种可移植对象文件格式,适用于各种操作系统的32位英特尔体系结构环境。

ELF标准旨在通过为开发人员提供一组跨多个操作环境扩展的二进制接口定义来简化软件开发。这将减少不同接口实现的数量,从而减少重新编码和重新编译代码的需要。

关于此文档

本文档适用于在各种32位环境操作系统上创建对象或可执行文件的开发人员。为了将ELf扩展到不同的操作系统中,当前的ELf 1.2版本文档已根据操作系统特定信息进行了重组。它分为以下三部分:

  1. ELF,描述了称为ELF的对象文件格式。本书还包含一个附录,其中描述了历史参考资料,并列出了处理器和操作系统的保留名称和单词。
  2. 处理器特定(英特尔架构),传达硬件特定的ELF信息,如英特尔体系结构信息。
  3. 操作系统特定,描述依赖于操作系统的ELF信息,例如System V Release 4信息。本书还包含一个附录,其中描述了ELF信息,这些信息既依赖于操作系统,也依赖于处理器。

目录

[toc]

Executable and Linking Format (ELF)

简介

本章描述了对象文件格式,称为ELF(可执行文件和链接格式)。对象文件主要有三种类型。

  • 可重定位文件(obj) 包含适合与其他对象文件链接以创建可执行文件或共享对象文件的代码和数据。
  • 可执行文件(exe) 包含适合执行的程序。
  • 共享对象文件(so)包含适用于在两个上下文中进行链接的代码和数据。首先,链接编辑器可以将其与其他可重定位和共享的对象文件一起处理,以创建另一个对象文件。其次,动态链接器将其与可执行文件和其他共享对象相结合,以创建进程映像。

对象文件由汇编程序和链接编辑器创建,是用于直接在处理器上执行的程序的二进制表示。需要其他抽象机器的程序被排除在外。 在介绍材料之后,本章将重点介绍文件格式及其与构建程序的关系。第2章还描述了对象文件的各个部分,重点介绍了执行程序所需的信息。

文件格式

对象文件参与程序链接(构建程序)和程序执行(运行程序)。为了方便和高效,对象文件格式提供了文件内容的并行视图,反映了这些活动的不同需求。下图显示了对象文件的组织结构。

ELF Header 位于开头,包含描述文件组织的“路线图”。Section 包含链接视图的大部分对象文件信息:指令、数据、符号表、重新定位信息等。特殊节的描述将在本节后面介绍。第2章还介绍了文件的段和程序执行视图。

program header table(如果存在)告诉系统如何创建进程图像。使用的文件要建立一个进程映像(执行一个程序),必须有一个程序头表;可重新定位的文件不需要。节头表包含描述文件节的信息。表中每个部分都有一个条目;每个条目给出诸如区段名称之类的信息,节大小等等。链接过程中使用的文件必须有节头表;另外对象文件可能有,也可能没有。

Note! 尽管图中显示了ELF标头之后的程序标头表,以及小节之后的小节标头表,但实际文件可能有所不同。此外,截面和分段没有指定的顺序。只有ELF标头在文件中具有固定位置。

数据表达(基本 C 数据结构)

如上所述,对象文件格式支持8位字节和32位的各种处理器架构。然而,它旨在扩展到更大(或更小)的体系结构。因此,对象文件以独立于机器的格式表示一些控制数据,使得可以识别对象文件并以通用的方式解释它们的内容。对象文件中的剩余数据使用目标处理器的编码,而与创建文件的机器无关。

NameSizeAlignmentPurpose
Elf32_Addr 4 4 Unsigned program address
Elf32_Half 2 2 Unsigned medium integer
Elf32_Off 4 4 Unsigned file offset
Elf32_Sword 4 4 Signed large integer
Elf32_Word 4 4 Unsigned large integer
unsigned char 1 1 Unsigned small integer

对象文件格式定义的所有数据结构都遵循相关类的“自然”大小和对齐准则。如果需要,数据结构包含显式填充,以确保4字节对象的4字节对齐,强制结构大小为4的倍数,等等。数据从文件的开头也有适当的对齐方式。因此,例如,包含 Elf32_Addr 成员的结构将在文件内的4字节边界上对齐。出于可移植性的原因,ELF 不使用位字段。

字符表示 (遵循ASCII)

本节描述了默认的ELF字符表示,并定义了用于外部文件的标准字符集,这些文件应该在系统之间可移植。几种外部文件格式用字符表示控制信息。这些单字节字符使用7位ASCII字符集。换句话说,当 ELF 接口文档提到字符常量时,如“/”或“\n”,其数值应遵循7位ASCII准则。对于前面的字符常量,单字节值将分别为47和10。 根据字符编码,0到127范围之外的字符值可能占用一个或多个字节。应用程序可以控制自己的字符集,根据需要为不同的语言使用不同的字符集扩展。尽管TIS一致性并不限制字符集,但它们通常应该遵循一些简单的准则。

  • 介于0和127之间的字符值应与7位ASCII码相对应。也就是说,编码高于127的字符集应该包括7位ASCII码作为子集。
  • 值大于127的多字节字符编码应仅包含值在0到127范围之外的字节。也就是说,每个字符使用一个以上字节的字符集不应在多字节非ASCII字符中“嵌入”类似于7位ASCII字符的字节。
  • 多字节字符应该是自我识别的。例如,这允许在任何一对多字节字符之间插入任何多字节字符,而不改变字符的解释。

这些注意事项与多语言应用程序特别相关。

Note! 对于指定了处理器范围的ELF常量,有一些命名约定。对于特定于处理器的扩展,DT_、PT_等名称包含处理器的名称:例如,DT_M32_SPECIAL。但是,不使用此约定的预先存在的处理器扩展将得到支持。

ELF Header

一些对象文件控制结构可能会增长,因为ELF标头包含它们的实际大小。如果对象文件格式发生变化,程序可能会遇到比预期更大或更小的控制结构。因此,程序可能会忽略“额外”信息。对“丢失”信息的处理取决于上下文,并且将在定义扩展时指定。

#define EI_NIDENT 16
typedef struct {
    unsigned char e_ident[EI_NIDENT];
    Elf32_Half e_type;
    Elf32_Half e_machine;
    Elf32_Word e_version;
    Elf32_Addr e_entry;
    Elf32_Off  e_phoff;
    Elf32_Off  e_shoff;
    Elf32_Word e_flags;
    Elf32_Half e_ehsize;
    Elf32_Half e_phentsize;
    Elf32_Half e_phnum;
    Elf32_Half e_shentsize;
    Elf32_Half e_shnum;
    Elf32_Half e_shstrndx;
} Elf32_Ehdr;

e_ident

  • 初始字节将文件标记为对象文件,并提供独立于机器的数据,用于解码和解释文件的内容。完整的描述出现在下面的 “ELF Identification” 中

e_type

  • 此成员标识对象文件类型。
NameValueMeaning
ET_NONE 0 No file type
ET_REL 1 Relocatable file
ET_EXEC 2 Executable file
ET_DYN 3 Shared object file
ET_CORE 4 Core file
ET_LOPROC 0xff00 Processor-specific
ET_HIPROC 0xffff Processor-specific

尽管未指定核心文件内容,但保留类型ET_core来标记文件类型。从ET_LOPROC到ET_HIPROC(包括在内)的值保留用于处理器特定的语义。其他值是保留的,并将根据需要分配给新的对象文件类型。

e_machine

  • 此成员的值指定单个文件所需的体系结构。
NameValueMeaning
ET_NONE 0 No machine
EM_M32 1 AT&T WE 32100
EM_SPARC 2 SPARC
EM_386 3 Intel Architecture
EM_68K 4 Motorola 68000
EM_88K 5 Motorola 88000
EM_860 7 Intel 80860
EM_MIPS 8 MIPS RS3000 Big-Endian
EM_MIPS_RS4_BE 10 MIPS RS4000 Big-Endian
RESERVED 11-16 Reserved for future use

其他值将被保留,并将根据需要分配给新机器。处理器特定的ELF名称使用机器名称来区分它们。例如,下面提到的标志使用前缀EF_;XYZ机器的名为WIDGET的标志将被称为EF_XYZ_WIDGET。

e_version

  • This member identifies the object file version.
NameValueMeaning
EV_NONE 0 Invalid versionn
EV_CURRENT 1 Current version

值1表示原始文件格式;扩展将创建具有更高数字的新版本。EV_CURRENT的值,尽管上面给出为1,但将根据需要进行更改,以反映当前版本号。

e_entry

  • 该成员给出系统首先将控制权转移到的虚拟地址,从而启动该过程。如果该文件没有关联的入口点,则该成员将保持零。

e_phoff

  • 此成员保存程序头表的文件偏移量(以字节为单位)。如果该文件没有程序头表,则该成员保持零。

e_shoff

  • 此成员保存节头表的文件偏移量(以字节为单位)。如果文件没有节头表,则此成员将保持零。

e_flags

  • 此成员持有与文件相关联的处理器特定标志。标志名称的格式为 EF_machine_Flag

e_ehsize

  • This member holds the ELF header's size in bytes.

e_phentsize

  • 该成员保存文件的 program header table 中一个条目的字节大小;所有条目的大小都相同。

e_phnum

  • 此成员保存程序头表中的条目数。因此,e_phentsizee_phnum 的乘积给出了表的字节大小。如果一个文件没有程序头表,e_phnum将保持值为零。

e_shentsize

  • This member holds a section header's size in bytes. A section header is one entry in the section header table; all entries are the same size.

e_shnum

  • This member holds the number of entries in the section header table. Thus the product of e_shentsize and e_shnum gives the section header table's size in bytes. If a file has no section header table, e_shnum holds the value zero.

e_shstrndx

  • 此成员保存与节名称字符串表关联的条目的节头表索引。如果文件没有节名字符串表,则此成员将保留值SHN_UNDEF。有关更多信息,请参阅下面的“Sections”和“String Table”。

ELF Identification

如上所述,ELF提供了一个对象文件框架来支持多个处理器、多个数据编码和多类机器。为了支持这个对象文件族,文件的初始字节指定如何解释文件,与进行查询的处理器无关,也与文件的剩余内容无关。 ELF header(和对象文件)的初始字节对应于 e_ident 成员。

NameValueMeaning
EI_MAG0 0 File identification
EI_MAG1 1 File identification
EI_MAG2 2 File identification
EI_MAG3 3 File identification
EI_CLASS 4 File class
EI_DATA 5 Data encoding
EI_VERSION 6 File version
EI_PAD 7 Start of padding bytes
EI_NIDENT 16 Size of e_ident[]

这些索引访问包含以下值的字节。

EI_MAG0到EI_MAG3

  • 文件的前4个字节包含一个“magic number”,将文件标识为ELF对象文件。
NameValueMeaning
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]标识文件的类或容量。
NameValueMeaning
ELFCLASSNONE 0 Invalid class
ELFCLASS32 1 32-bit objects
ELFCLASS64 2 64-bit objects

文件格式设计为可在各种尺寸的机器之间移植,而不会将最大机器的尺寸强加给最小机器。ELFCLASS32类支持具有高达4GB的文件和虚拟地址空间的机器;它使用上面定义的基本类型。 ELFCLASS64类是不完整的,它指的是64位体系结构。它在这里的外观显示了对象文件可能发生的变化。其他类将根据需要进行定义,对象文件数据具有不同的基本类型和大小。

EI_DATA

  • e_ident[EI_DATA] 指定对象文件中处理器特定数据的数据编码。当前定义了以下编码。
NameValueMeaning
ELFDATANONE 0 Invalid data encoding
ELFDATA2LSB 1 See below
ELFDATA2MSB 2 See below

下面显示了有关这些编码的更多信息。其他值是保留的,并将根据需要分配给新的编码。

EI_VERSION

  • 字节 e_ident[EI_VERSION] 指定ELF标头版本号。目前,这个值必须是 EV_CURRENT,正如上面对 e_version 所解释的那样。

EI_PAD

  • 此值标记e_ident中未使用的字节的开始。这些字节被保留并设置为零;读取对象文件的程序应该忽略它们。如果当前未使用的字节被赋予意义,那么EI_PAD的值将来会发生变化。
    文件的数据编码指定如何解释文件中的基本对象。如上所述,class ELFCLASS32 文件使用占用1、2和4个字节的对象。在定义的编码下,对象的表示方式如下所示。字节号显示在左上角。编码 ELFDATA2LSB 指定2的补码值,最低有效字节占据最低地址。


编码 ELFDATA2MSB 指定2的补码值,最高有效字节占据最低地址。

 

Sections

对象文件的节头表可以定位文件的所有节。节头表是如下所述的 Elf32_Shdr 结构的阵列。节头表索引是此数组中的一个下标。ELF头的 e_shoff 成员给出了从文件开头到节头表的字节偏移量;e_shnum 告诉节标题表包含多少条目;e_shentsize 以字节为单位给出每个条目的大小。 Some section header table indexes are reserved; an object file will not have sections for these special indexes.

Special Section Indexes

NameValue
SHN_UNDEF 0
SHN_LORESERVE 0xff00
SHN_LOPROC 0xff00
SHN_HIPROC 0xff1f
SHN_ABS 0xfff1
SHN_COMMON 0xfff2
SHN_HIRESERVE 0xffff

SHN_UNDEF

  • 此值标记未定义、缺失、不相关或其他无意义的节引用。例如,相对于截面编号SHN_UNDEF“定义的”符号是未定义的符号。
Note! 尽管索引0被保留为未定义的值,但节头表包含索引0的一个条目。也就是说,如果ELF头的e_shnum成员表示一个文件在节头表中有6个条目,那么它们的索引为0到5。本节稍后将指定初始条目的内容。

SHN_LORESERVE - 此值指定保留索引范围的下限。

SHN_LOPROC - SHN_HIPROC - 此包含范围内的值是为处理器特定的语义保留的。

SHN_ABS - 此值指定相应引用的绝对值。例如,相对于截面编号 SHN_ABS 定义的符号具有绝对值,不受重新定位的影响。

SHN_COMMON - 相对于本节定义的符号是常见符号,如FORTRAN common或未分配的C外部变量。

SHN_HIRESERVE - 此值指定保留索引范围的上限。系统在 SHN_LORESERVESHN_HIRESERVE 之间保留索引,包括索引;这些值不引用节头表。

节包含对象文件中的所有信息,ELF头、程序头表和节头表除外。此外,对象文件的部分满足几个条件。 - 对象文件中的每个节都有一个节头来描述它。可能存在没有节的节头。 - 每个节在一个文件中占据一个连续的(可能是空的)字节序列 - 文件中的节不能重叠。文件中没有任何字节位于多个节中。 - 对象文件可能具有非活动空间(空白区,填充区)。不同的头和节可能不会“覆盖”对象文件中的每个字节。未指定非活动数据的内容。

A section header has the following structure.

Section Header

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;

sh_name - 此成员指定节的名称。它的值是节头字符串表节的索引[参见下面的“字符串表”],给出以 null 结尾的字符串的位置。

sh_type - 此成员对节的内容和语义进行分类。节类型及其描述如下所示。

sh_flags - 节支持用于描述杂项属性的1位标志。标志定义如下所示。

sh_addr - 如果该节将出现在进程的内存映像中,则该成员将给出该节的第一个字节应驻留的地址。否则,该成员包含0。

sh_offset - 该成员的值给出了从文件开头到节中第一个字节的字节偏移量。下面描述的一种节类型 SHT_NOBITS 在文件中不占用空间,其 sh_offset 成员定位文件中的概念位置。

sh_size - 此成员以字节为单位提供节的大小。除非节类型为SHT_NOBITS,否则该节在文件中占用 sh_size 字节。SHT_NOBITS类型的节可能具有非零大小,但它在文件中不占用空间。

sh_link - 此成员拥有一个节头表索引链接,其解释取决于节类型。下表描述了这些值。

sh_info - 此成员包含额外的信息,其解释取决于节类型。下表描述了这些值。

sh_addralign - 某些部分具有地址对齐约束。例如,如果一个节包含一个双字,则系统必须确保整个节的双字对齐。也就是说,sh_addr的值必须与0一致,以sh_addralin的值为模。目前,只允许0和2的正整数幂。值0和1表示该截面没有对齐约束。

sh_entsize - 有些部分包含固定大小的条目表,例如符号表。对于这样的部分,该成员给出每个条目的大小(以字节为单位)。如果节中没有固定大小的条目表,则该成员包含0。

A section header's sh_type member specifies the section's semantics.

Section Types, sh_type

NameValue
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_LOPROC 0x70000000
SHT_HIPROC 0x7fffffff
SHT_LOUSER 0x80000000
SHT_HIUSER 0xffffffff

SHT_NULL - 此值将节标头标记为不活动;它没有关联的部分。节标头的其他成员具有未定义的值。

SHT_PROGBITS - 该部分保存由程序定义的信息,其格式和含义仅由程序决定。

SHT_SYMTAB SHT_DYNSYM - These sections hold a symbol table.

SHT_STRTAB - The section holds a string table.

SHT_RELA - The section holds relocation entries with explicit addends,例如用于32位类对象文件的类型Elf32_La。一个对象文件可能有多个重新定位部分。有关详细信息,请参阅下面的“搬迁”。

SHT_HASH - The section holds a symbol hash table.

SHT_DYNAMIC - The section holds information for dynamic linking.

SHT_NOTE - This section holds information that marks the file in some way

SHT_NOBITS - 此类型的节在文件中不占用空间,但在其他方面类似于SHT_PROGPITS。尽管此部分不包含字节,但sh_offset成员包含概念文件偏移量。

SHT_REL - The section holds relocation entries without explicit addends, such as type Elf32_Rel for the 32-bit class of object files. An object file may have multiple relocation sections. See "Relocation'' below for details. 该部分保存没有显式加数的重定位条目,例如用于32位类对象文件的类型Elf32_rl。一个对象文件可能有多个重新定位部分。有关详细信息,请参阅下面的“搬迁”。

SHT_SHLIB - This section type is reserved but has unspecified semantics.

SHT_LOPROC - SHT_HIPROC - Values in this inclusive range are reserved for processor-specific semantics. 此包含范围内的值是为处理器特定的语义保留的。

SHT_LOUSER - This value specifies the lower bound of the range of indexes reserved for application programs.

SHT_HIUSER - This value specifies the upper bound of the range of indexes reserved for application programs. Section types between SHT_LOUSER and SHT_HIUSER may be used by the application, without conflicting with current or future system-defined section types.

Section Header Table Entry: Index 0

保留其他节类型值。如前所述,索引0的节头(SHN_UNDEF)存在,即使索引标记了未定义的节引用。此条目包含以下内容。

NameValueMeaning
sh_name 0 No name
sh_type SHT_NULL Inactive
sh_flags 0 No flags
sh_addr 0 No address
sh_offset 0 No file offset
sh_size 0 No size
sh_link SHN_UNDEF No link information
sh_info 0 No auxiliary information
sh_addralign 0 No alignment
sh_entsize 0 No entries

Section Attribute Flags, sh_flags

区段标头的sh_flags成员持有描述区段属性的1位标志。定义值如下所示;保留其他值。

NameValue
SHF_WRITE 0x1
SHF_ALLOC 0x2
SHF_EXECINSTR 0x4
SHF_MASKPROC 0xf0000000

如果在sh_flags中设置了标志位,则该节的属性为“on”。否则,该属性为“off”或不适用。未定义的属性将设置为零。

SHF_WRITE - The section contains data that should be writable during process execution.

SHF_ALLOC - 该部分在进程执行期间占用内存。一些控制部分不存在于对象文件的存储器映像中;对于那些部分,该属性处于禁用状态。

SHF_EXECINSTR - The section contains executable machine instructions.

SHF_MASKPROC - All bits included in this mask are reserved for processor-specific semantics.

sh_link and sh_info Interpretation

Two members in the section header, sh_link and sh_info, hold special information, depending on section type.

sh_typesh_linksh_info
SHT_DYNAMIC The section header index of the string table used by entries in the section. 0
SHT_HASH The section header index of the symbol table to which the hash table applies. 0
SHT_REL
SHT_RELA
The section header index of the associated symbol table. The section header index of the section to which the relocation applies.
SHT_SYMTAB
SHT_DYNSYM
This information is operating system specific. This information is operating system specific.
other SHN_UNDEF 0

Special Sections

ELF中的各个部分都是预定义的,并保存程序和控制信息。这些部分由操作系统使用,并且对于不同的操作系统具有不同的类型和属性。

可执行文件是通过链接过程从单个对象文件和库创建的。链接器解析不同对象文件之间的引用(包括子例程和数据引用),调整对象文件中的绝对引用,并重新定位指令。第2章中描述的链接和加载过程需要在对象文件中定义的信息,并将这些信息存储在特定的部分中,如.dynamic。

每个操作系统都支持一组链接模型,这些模型分为两类:

Static: 静态绑定一组对象文件、系统库和库档案,解析引用,并创建一个完全自包含的可执行文件。

Dynamic: 一组对象文件、库、系统共享资源和其他共享库链接在一起以创建可执行文件。加载此可执行文件时,必须使系统中的其他共享资源和动态库可用,程序才能成功运行。

在操作系统使用的链接模型中描述了用于在执行时解析动态链接的可执行文件的引用的通用方法,并且该链接模型的实际实现将包含处理器特定组件。

Special Sections

还有一些部分支持调试,如.debug和.line,以及程序控制,包括.bss、.data、.data1、.rodata和.rodata1。

NameTypeAttributes
.bss SHT_NOBITS SHF_ALLOC+SHF_WRITE
.comment SHT_PROGBITS none
.data SHT_PROGBITS SHF_ALLOC + SHF_WRITE
.data1 SHT_PROGBITS SHF_ALLOC + SHF_WRITE
.debug SHT_PROGBITS none
.dynamic SHT_DYNAMIC see below
.hash SHT_HASH SHF_ALLOC
.line SHT_PROGBITS none
.note SHT_NOTE none
.rodata SHT_PROGBITS SHF_ALLOC
.rodata1 SHT_PROGBITS SHF_ALLOC
.shstrtab SHT_STRTAB none
.strtab SHT_STRTAB see below
.symtab SHT_SYMTAB see below
.text SHT_PROGBITS SHF_ALLOC + SHF_EXECINSTR

.bss - 此部分保存对程序内存映像有贡献的未初始化数据。根据定义,当程序开始运行时,系统会用零初始化数据。节不占用文件空间,如节类型 SHT_NOBITS 所示。

comment - This section holds version control information.

.data .data1 - These sections hold initialized data that contribute to the program's memory image.

.debug - This section holds information for symbolic debugging. The contents are unspecified. All section names with the prefix .debug are reserved for future use.

.dynamic - This section holds dynamic linking information and has attributes such as SHF_ALLOC and SHF_WRITE. Whether the SHF_WRITE bit is set is determined by the operating system and processor.

.hash - This section holds a symbol hash table.

.line - This section holds line number information for symbolic debugging, which describes the correspondence between the source program and the machine code. The contents are unspecified.

.note - This section holds information in the format that is described in the "Note Section'' in Chapter 2.

rodata rodata1 - These sections hold read-only data that typically contribute to a non-writable segment in the process image. See "Program Header'' in Chapter 2 for more information.

shstrtab - This section holds section names.

.strtab - 本节保存字符串,最常见的是表示与符号表条目相关联的名称的字符串。如果文件具有包含符号字符串表的可加载段,则该段的属性将包括SHF_ALLOC位;否则,该位将关闭。

.symtab - This section holds a symbol table, as "Symbol Table'' in this chapter describes. If a file has a loadable segment that includes the symbol table, the section's attributes will include the SHF_ALLOC bit; otherwise, that bit will be off.

.text - This section holds the "text" or executable instructions, of a program.

带有句点(.)前缀的节名称是为系统保留的,但如果这些节的现有含义令人满意,则应用程序可以使用这些节。应用程序可以使用不带前缀的名称,以避免与系统部分发生冲突。对象文件格式允许定义不在上面列表中的部分。一个对象文件可能有多个具有相同名称的节。

String Table

本节介绍默认字符串表。字符串表部分包含以null结尾的字符序列,通常称为字符串。对象文件使用这些字符串来表示符号和截面名称。其中一个引用字符串作为字符串表部分的索引。第一个字节是索引零,它被定义为包含一个空字符。同样,字符串表的最后一个字节被定义为包含一个null字符,从而确保所有字符串的null终止。索引为零的字符串不指定名称或指定空名称,具体取决于上下文。允许使用空字符串表部分;其节头的shsize成员将包含零。非零索引对于空字符串表无效。

区段标头的sh_name成员将索引保存到区段标头字符串表区段中,由ELF标头的e_shstrndx成员指定。下图显示了一个包含25个字节的字符串表以及与各种索引相关联的字符串。

String Table

String Table Indexes

IndexString
0 none
1 name.
7 Variable
11 able
16 able
24 null string

As the example shows, a string table index may refer to any byte in the section. A string may appear more than once; references to substrings may exist; and a single string may be referenced multiple times. Unreferenced strings also are allowed.

如示例所示,字符串表索引可以引用该部分中的任何字节。字符串可能出现多次;可能存在对子字符串的引用;并且单个字符串可以被多次引用。也允许使用未引用的字符串。

Symbol Table

对象文件的符号表包含定位和重新定位程序的符号定义和引用所需的信息。符号表索引是这个数组的下标。索引0既指定表中的第一个条目,又用作未定义的符号索引。本节稍后将指定初始条目的内容。

NameValue
STN_UNDEF 0

A symbol table entry has the following format.

Symbol Table Entry

typedef struct {
    Elf32_Word st_name;
    Elf32_Addr st_value;
    Elf32_Word st_size;
    unsigned char st_info;
    unsigned char st_other;
    Elf32_Half st_shndx;
} Elf32_Sym;

st_name - This member holds an index into the object file's symbol string table, which holds the character representations of the symbol names.

st_value - 此成员提供关联符号的值。根据上下文的不同,这可能是一个绝对值、一个地址等等;详细信息如下。

st_size - Many symbols have associated sizes. For example, a data object's size is the number of bytes contained in the object. This member holds 0 if the symbol has no size or an unknown size.

st_info - This member specifies the symbol's type and binding attributes. A list of the values and meanings appears below. The following code shows how to manipulate the values.

#define ELF32_ST_BIND(i) ((i)>>4) #define ELF32_ST_TYPE(i) ((i)&0xf) #define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))

st_other - This member currently holds 0 and has no defined meaning.

st_shndx - Every symbol table entry is "defined'' in relation to some section; this member holds the relevant section header table index. As Figure 1-7 and the related text describe, some section indexes indicate special meanings.

Symbol Binding, ELF32_ST_BIND 符号的绑定决定了链接的可见性和行为。

NameValue
STB_LOCAL 0
STB_GLOBAL 1
STB_WEAK 2
STB_LOPROC 13
STB_HIPROC 15

STB_LOCAL - 局部符号在包含其定义的对象文件之外不可见。相同名称的本地符号可以存在于多个文件中,而不会相互干扰。

STB_GLOBAL - 全局符号对正在组合的所有对象文件都可见。一个文件对全局符号的定义将满足另一个文件对未定义的同一全局符号的引用。

STB_WEAK - 弱符号类似于全局符号,但它们的定义具有较低的优先级。

STB_LOPROC STB_HIPROC - 此包含范围内的值是为处理器特定的语义保留的。

Symbol Types, ELF32_ST_TYPE

在每个符号表中,具有STB_LOCAL绑定的所有符号都位于弱符号和全局符号之前。符号的类型为关联实体提供了一般分类。 |Name |Value| |:-|:-| |STT_NOTYPE |0| |STT_OBJECT |1| |STT_FUNC |2| |STT_SECTION |3| |STT_FILE |4| |STT_LOPROC |13| |STT_HIPROC |15|

STT_NOTYPE - The symbol's type is not specified.

STT_OBJECT - The symbol is associated with a data object, such as a variable, an array, and so on.

STT_FUNC - The symbol is associated with a function or other executable code.

STT_SECTION - The symbol is associated with a section. Symbol table entries of this type exist primarily for relocation and normally have STB_LOCAL binding.

STT_LOPROC - STT_HIPROC - Values in this inclusive range are reserved for processor-specific semantics. If a symbol's value refers to a specific location within a section, its section index member, st_shndx, holds an index into the section header table. As the section moves during relocation, the symbol's value changes as well, and references to the symbol continue to "point'' to the same location in the program. Some special section index values give other semantics.

STT_FILE - A file symbol has STB_LOCAL binding, its section index is SHN_ABS, and it precedes the other STB_LOCAL symbols for the file, if it is present.

ELF对象文件中的符号向链接器和加载程序传递特定信息。有关系统中使用的实际链接模型的描述,请参阅操作系统部分。

SHN_ABS - 符号的绝对值不会因为重新定位而更改。

SHN_COMMON - The symbol labels a common block that has not yet been allocated. The symbol's value gives alignment constraints, similar to a section's sh_addralign member. That is, the link editor will allocate the storage for the symbol at an address that is a multiple of st_value. The symbol's size tells how many bytes are required. 该符号标记尚未分配的公共块。符号的值提供对齐约束,类似于截面的sh_addralign成员。也就是说,链接编辑器将为st_value的倍数地址处的符号分配存储。符号的大小告诉需要多少字节。

SHN_UNDEF - This section table index means the symbol is undefined. When the link editor combines this object file with another that defines the indicated symbol, this file's references to the symbol will be linked to the actual definition.

Symbol Table Entry: Index 0

如上所述,索引0的符号表条目(STN_UNDEF)被保留;它包含以下内容。

NameValueNote
st_name 0 No name
st_value 0 Zero value
st_size 0 No size
st_info 0 No type, local binding
st_other 0  
st_shndx SHN_UNDEF No section

Symbol Values

不同对象文件类型的符号表条目对 st_value 成员的解释略有不同。 - In relocatable files, st_value holds alignment constraints for a symbol whose section index is SHN_COMMON. - In relocatable files, st_value holds a section offset for a defined symbol. That is, st_value is an offset from the beginning of the section that st_shndx identifies. - In executable and shared object files, st_value holds a virtual address. To make these files' symbols more useful for the dynamic linker, the section offset (file interpretation) gives way to a virtual address (memory interpretation) for which the section number is irrelevant.

尽管符号表值对于不同的对象文件具有相似的含义,但这些数据允许适当的程序进行有效的访问。

Relocation

重新定位是将符号引用与符号定义连接起来的过程。例如,当程序调用函数时,相关的调用指令必须在执行时将控制权转移到正确的目标地址。换言之,可重定位文件必须具有描述如何修改其部分内容的信息,从而允许可执行和共享对象文件保存进程程序映像的正确信息。搬迁条目就是这些数据。

Relocation Entries

typedef struct {
    Elf32_Addr r_offset;
    Elf32_Word r_info;
} Elf32_Rel;

typedef struct {
    Elf32_Addr r_offset;
    Elf32_Word r_info;
    Elf32_Sword r_addend;
} Elf32_Rela;

r_offset - 此成员提供应用重新定位操作的位置。对于可重定位文件,该值是从节的开头到受重定位影响的存储单元的字节偏移量。对于可执行文件或共享对象,该值是受重新定位影响的存储单元的虚拟地址。

r_info - 此成员提供必须进行重新定位的符号表索引和要应用的重新定位类型。例如,调用指令的重定位条目将保存被调用函数的符号表索引。如果索引是STN_UNDEF,即未定义的符号索引,则重定位使用0作为“符号值”。重定位类型是特定于处理器的;对其行为的描述出现在处理器补充中。当处理器补充中的文本指的是重定位条目的重定位类型或符号表索引时,这意味着将ELF32_R_type或ELF32_R-SYM分别应用于条目的R_info成员的结果。

#define ELF32_R_SYM(i) ((i)>>8)
#define ELF32_R_TYPE(i) ((unsigned char)(i))
#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t))

r_addend - 此成员指定一个常量加数,用于计算要存储到可重定位字段中的值。

如上所示,只有Elf32_La条目包含显式加数。Elf32_rl类型的条目在要修改的位置中存储一个隐式加数。根据处理器体系结构的不同,一种或另一种形式可能是必要的或更方便的。因此,特定机器的实现可以专门使用一种形式,也可以根据上下文使用任意一种形式。

重定位部分引用另外两个部分:符号表和要修改的部分。节头的sh_info和sh_link成员(如上文“Sections”中所述)指定了这些关系。不同对象文件的重新定位条目对r_offset成员的解释略有不同。

  • 在可重定位文件中,r_offset保存一个节偏移量。也就是说,重定位部分本身描述了如何修改文件中的另一个部分;重新定位偏移指定第二部分内的存储单元。
  • 在可执行文件和共享对象文件中,r_offset保存一个虚拟地址。为了使这些文件的重定位条目对动态链接器更有用,部分偏移(文件解释)让位给了虚拟地址(内存解释)。

尽管对于不同的对象文件,r_offset的解释会发生变化,以允许相关程序进行有效访问,但重新定位类型的含义保持不变。