ELF文件格式说明

ELF文件类型

ELF文件主要分为三种类型:

  • 可重定位文件(Relocatable File)包含适合于与其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据。
  • 可执行文件(Executable File) 包含适合于执行的一个程序,此文件规定了exec() 如何创建一个程序的进程映像。
  • 共享目标文件(Shared Object File) 包含可在两种上下文中链接的代码和数据。首先链接编辑器可以将它和其它可重定位文件和共享目标文件一起处理,生成另外一个目标文件。其次,动态链接器(Dynamic Linker)可能将它与某个可执行文件以及其它共享目标一起组合,创建进程映像。

ELF文件的数据表示

ELF文件头结构及相关常数被定义在”/usr/include/elf.h”里。ELF目标文件中的所有数据结构都遵从自然大小和对齐规则。如果必要,数据结构可以包含显式的补齐,例如为了确保4字节对象按4字节边界对齐。数据对齐同样适用于文件内部。下面为ELF中常用的数据格式:

名称 大小 对齐 描述
Elf32_Addr 4 4 无符号程序地址
Elf32_Half 2 2 无符号短整型
Elf32_Off 4 4 无符号偏移地址
Elf32_Sword 4 4 有符号整型
Elf32_Word 4 4 有符号整型

ELF除了32位版还有64位版本,数据类型的名称和大小也相应地变化(Elf64_Addr…)。

链接视图和执行视图

目标文件既要参与程序链接又要参与程序执行。出于方便性和效率考虑,目标文件格式提供了两种并行视图,分别反映了这些活动的不同需求。

exec_view

这两个视图并不冲突,在执行视图中的”Segment”是由链接视图中的多个权限和性质相仿的”Section”组成的。

文件开始处是一个ELF头部(ELF Header),用来描述整个文件的组织。ELF的文件头定义了ELF魔数、文件机器字节长度、数据存储方式、版本、运行平台、ABI版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址、程序头入口和长度、段表的位置和长度及段的数量等信息。

程序头部表(Program Header Table),主要用来保存”Segment”的信息。可重位文件由于不需要被装载,因此没有这个表,而ELF可执行文件和共享库文件则有。

段表(Section Header Table),保存各个段的基本属性,包括每个段的段名、段的长度、在文件中的偏移、读写权限、段的链接信息等等。

ELF Header 部分

下面是使用readelf来查看一个ELF文件的文件头信息:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                                          ELF32
  Data:                                           2's complement, little endian
  Version:                                      1 (current)
  OS/ABI:                                       UNIX - System V
  ABI Version:                                0
  Type:                                          REL (Relocatable file)
  Machine:                                     Intel 80386
  Version:                                      0x1
  Entry point address:                     0x0
  Start of program headers:           0 (bytes into file)
  Start of section headers:              264 (bytes into file)
  Flags:                                          0x0
  Size of this header:                      52 (bytes)
  Size of program headers:            0 (bytes)
  Number of program headers:      0
  Size of section headers:               40 (bytes)
  Number of section headers:         11
  Section header string table index: 8

文件头对应一个Elf32_Ehdr的结构如下(如上面的输出信息是一一对应的):

#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;

ELF Header中各个字段说明如下:

成员 说明
e_ident ELF文件标识。

  • 前4个字节为ELF魔数,分别是0x7F、0×45、0x4c、0×46,第一个字节对应ASCII字符里面的DEL控制符,后面3个字节就是ELF这3个字母的ASCII码。
  • 第5个字节标识ELF文件类别。0为无效文件,1为32位ELF文件,2为64位ELF文件。
  • 第6个字节标识字节序。0为无效格式,1为小端格式,2为大端格式。
  • 第7个字节为ELF主版本号,一般是1。
  • 后面的9个字节ELF标准没有定义,一般填0。
e_type 目标文件类型:

名称 取值 含义
ET_NONE 0 未知目标文件格式
ET_REL 1 可重定位文件
ET_EXEC 2 可执行文件
ET_DYN 3 共享目标文件
ET_CORE 4 Core 文件(转储格式)
ET_LOPROC 0xff00 特定处理器文件
ET_HIPROC 0xffff 特定处理器文件

ET_LOPROC 和 ET_HIPROC 之间的取值用来标识与处理器相关的文件格式。

e_machine ELF文件的CPU平台属性:

名称 取值 含义
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_68K 5 Motorola 68000
EM_860 7 Intel 80860
EM_MIPS 8 MIPS RS3000

其它值都是保留的。特定处理器的ELF名称会使用机器名来进行区分。

e_version ELF文件版本号,一般为常数1

名称 取值 含义
EV_NONE 0 非法版本
EV_CURRENT 1 当前版本
e_entry 程序入口的虚拟地址,操作系统在加载完该程序后从这个地址开始执行进程的指令。可重定位文件一般没有入口地址,则这个值为0。
e_phofff 程序头表(Program Header Table)在文件中的偏移量(以字节计算)。如果没有程序头表,可以为0。
e_shoff 段表在文件中的偏移量(以字节计算)
e_flags ELF标志位,用来标识一些ELF文件平台相关的属性。相关常量的格式一般为EF_machine_flag,machine为平台,flag为标志。
e_ehsize ELF文件头本身的大小。
e_phentsize 程序头表的表项大小。
e_phnum 程序头表的表项数目,可以为0。
e_shentsize 段表的表项大小。
e_shnum 段表的表项数目,可以为0。
e_shstrndx 段表字符串所在的段在段表中的下标。也就是段表字符串表的位置,可以从段表中用索引获取。

本来很有冲动想将其它的一些段的格式说明也记录下来,但发现这样太费时间了,而且wp的编辑器有点让我抓狂。其实主要也就参考了《程序员的自我修养》这本书和《ELF文件格式分析》这份PDF文件。

This entry was posted in Operating System. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>