首页 > 其他分享 >ELF 文件

ELF 文件

时间:2023-03-12 16:44:39浏览次数:48  
标签:文件 ident EI 字节 ELF ELF32

ELF 文件

本部分内容来源于 ELF 1.2 标准,内容经过一定的修改与整理,主要参考文献如下

  1. ELF 文件格式分析,北京大学,滕启明
  2. ELF-摧毁圣诞

简介

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

  • 可重定位文件(Relocatable File),包含由编译器生成的代码以及数据。链接器会将它与其它目标文件链接起来从而创建可执行文件或者共享目标文件。在 Linux 系统中,这种文件的后缀一般为 .o
  • 可执行文件(Executable File),就是我们通常在 Linux 中执行的程序。

  • 共享目标文件(Shared Object File),包含代码和数据,这种文件是我们所称的库文件,一般以 .so 结尾。一般情况下,它有以下两种使用情景

  • 链接器(Link eDitor, ld)可能会处理它和其它可重定位文件以及共享目标文件,生成另外一个目标文件。
  • 动态链接器(Dynamic Linker)将它与可执行文件以及其它共享目标组合在一起生成进程镜像。

关于Link eDitor的命名,https://en.wikipedia.org/wiki/GNU_linker

目标文件由汇编器和链接器创建,是文本程序的二进制形式,可以直接在处理器上运行。那些需要虚拟机才能够执行的程序(Java)不属于这一范围。

这里我们主要关注于 ELF 的文件格式。

文件格式

目标文件既会参与程序链接又会参与程序执行。出于方便性和效率考虑,根据过程的不同,目标文件格式提供了其内容的两种并行视图,如下

首先,我们来关注一下链接视图

文件开始处是 ELF 头部( ELF Header),它给出了整个文件的组织情况。

如果程序头部表(Program Header Table)存在的话,它会告诉系统如何创建进程。用于生成进程的目标文件必须具有程序头部表,但是重定位文件不需要这个表。

节区部分包含在链接视图中要使用的大部分信息:指令、数据、符号表、重定位信息等等。

节区头部表(Section Header Table)包含了描述文件节区的信息,每个节区在表中都有一个表项,会给出节区名称、节区大小等信息。用于链接的目标文件必须有节区头部表,其它目标文件则无所谓,可以有,也可以没有。

这里给出一个关于链接视图比较形象的展示

对于执行视图来说,其主要的不同点在于没有了section,而有了多个segment。其实这里的 segment 大都是来源于链接视图中的 section。

注意:

尽管图中是按照 ELF 头,程序头部表,节区,节区头部表的顺序排列的。但实际上除了 ELF 头部表以外,其它部分都没有严格的的顺序。

数据形式

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

目标文件中的所有数据结构都遵从“自然”大小和对齐规则。如下

名称 长度 对齐方式 用途
Elf32_Addr 4 4 无符号程序地址
Elf32_Half 2 2 无符号半整型
Elf32_Off 4 4 无符号文件偏移
Elf32_Sword 4 4 有符号大整型
Elf32_Word 4 4 无符号大整型
unsigned char 1 1 无符号小整型

如果必要,数据结构可以包含显式地补齐来确保 4 字节对象按 4 字节对齐,强制数据结构的大小是 4 的整数倍等等。数据同样适用是对齐的。因此,包含一个 Elf32_Addr 类型成员的结构体会在文件中的 4 字节边界处对齐。

为了具有可移植性,ELF 文件不使用位域。

字符表示

待。

注:在下面的介绍中,我们以 32 位为主进行介绍。

ELF Header

ELF Header 描述了 ELF 文件的概要信息,利用这个数据结构可以索引到 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 开头的,它们应该都是 ELF 的缩写。每个成员具体的说明如下。

e_ident

正如之前所说,ELF 提供了一个目标文件框架,以便于支持多种处理器,多种编码格式的机器。该变量给出了用于解码和解释文件中与机器无关的数据的方式。这个数组对于不同的下标的含义如下

宏名称 下标 目的
EI_MAG0 0 文件标识
EI_MAG1 1 文件标识
EI_MAG2 2 文件标识
EI_MAG3 3 文件标识
EI_CLASS 4 文件类
EI_DATA 5 数据编码
EI_VERSION 6 文件版本
EI_PAD 7 补齐字节开始处

其中,

e_ident[EI_MAG0]e_ident[EI_MAG3],即文件的头4个字节,被称作“魔数”,标识该文件是一个ELF目标文件。至于开头为什么是0x7f,并没有仔细去查过

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

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

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

ELF 文件的设计使得它可以在多种字节长度的机器之间移植,而不需要强制规定机器的最长字节长度和最短字节长度。ELFCLASS32类型支持文件大小和虚拟地址空间上限为 4GB 的机器;它使用上述定义中的基本类型。

ELFCLASS64 类型用于 64 位架构。

e_ident[EI_DATA]字节给出了目标文件中的特定处理器数据的编码方式。下面是目前已定义的编码:

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

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

文件数据编码方式表明了文件内容的解析方式。正如之前所述,ELFCLASS32类型文件使用了具有1,2 和 4 字节的变量类型。对于已定义的不同的编码方式,其表示如下所示,其中字节号在左上角。

ELFDATA2LSB编码使用补码,最低有效位(Least Significant Byte)占用最低地址。

ELFDATA2MSB编码使用补码,最高有效位(Most Significant Byte)占用最低地址。

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

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

e_type

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
EM_860 7 Intel 80860
EM_MIPS 8 MIPS RS3000

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

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

e_version

标识目标文件的版本。

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

标签:文件,ident,EI,字节,ELF,ELF32
From: https://www.cnblogs.com/liert/p/17208450.html

相关文章