本文主要参考滕启明的《ELF文件格式分析》
开头扔定义。ELF文件,在计算机科学中,是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。它是UNIX系统实验室作为应用程序二进制接口而开发和发布的,也是Linux的主要可执行文件格式。ELF 标准的目的是为软件开发人员提供一组二进制接口定义,这些接口可以延伸到多种操作环境,从而减少重新编码、重新编译程序的需要。接口的内容包括目标模块格式、可执行文件格式以及调试记录信息与格式等。
一般来讲,目标文件有三种类型:
(1)可重定位文件(Relocatable File) 包含适合于与其他目标文件链接来创建可
执行文件或者共享目标文件的代码和数据。
(2)可执行文件(Executable File) 包含适合于执行的一个程序,此文件规定了
exec() 如何创建一个程序的进程映像。
(3)共享目标文件(Shared Object File) 包含可在两种上下文中链接的代码和数
据。首先链接编辑器可以将它和其它可重定位文件和共享目标文件一起处理,
生成另外一个目标文件。其次,动态链接器(Dynamic Linker)可能将它与某
个可执行文件以及其它共享目标一起组合,创建进程映像。
目标文件全部是程序的二进制表示,目的是直接在某种处理器上直接执行。
ELF文件大致组成
ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。实际上,一个文件中不一定包含全部内容,而且它们的位置也未必如同所示这样安排,只有ELF头的位置是固定的,其余各部分的位置、大小等信息由ELF头中的各项值来决定。
ELF Header
格式代码如下:
#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 头部( ELF Header ) ,用来描述整个文件的组织。节区部
分包含链接视图的大量信息:指令、数据、符号表、重定位信息等等。
程序头部表(Program Header Table),如果存在的话,告诉系统如何创建进程映像。
用来构造进程映像的目标文件必须具有程序头部表,可重定位文件不需要这个表。
节区头部表(Section Heade Table)包含了描述文件节区的信息,每个节区在表中
都有一项,每一项给出诸如节区名称、节区大小这类信息。用于链接的目标文件必须包
含节区头部表,其他目标文件可以有,也可以没有这个表。
节区
节区中包含目标文件中的所有信息,除了:ELF 头部、程序头部表格、节区头部
表格。节区满足以下条件:
(1). 目标文件中的每个节区都有对应的节区头部描述它,反过来,有节区头部不意
味着有节区。
(2). 每个节区占用文件中一个连续字节区域(这个区域可能长度为 0)。
(3). 文件中的节区不能重叠,不允许一个字节存在于两个节区中的情况发生。
(4). 目标文件中可能包含非活动空间(INACTIVE SPACE)。这些区域不属于任何
头部和节区,其内容未指定。
节区头部
每个节区头部可以用如下数据结构描述:
字符串表
字符串表节区包含以 NULL(ASCII 码 0)结尾的字符序列,通常称为字符串。ELF
目标文件通常使用字符串来表示符号和节区名称。对字符串的引用通常以字符串在字符
串表中的下标给出。
一般,第一个字节(索引为 0)定义为一个空字符串。类似的,字符串表的最后一
个字节也定义为 NULL,以确保所有的字符串都以 NULL 结尾。索引为 0 的字符串在
不同的上下文中可以表示无名或者名字为 NULL 的字符串。
允许存在空的字符串表节区,其节区头部的 sh_size 成员应该为 0。对空的字符串
表而言,非 0 的索引值是非法的。
符号表
目标文件的符号表中包含用来定位、重定位程序中符号定义和引用的信息。符号表
索引是对此数组的索引。索引 0 表示表中的第一表项,同时也作为未定义符号的索引。
程序加载和动态链接
实现程序加载和动态链接的主要技术有:
程序头部(Program Header):描述与程序执行直接相关的目标文件结构信息。
用来在文件中定位各个段的映像。同时包含其他一些用来为程序创
建进程映像所必需的信息。
程序加载:给定一个目标文件,系统加载该文件到内存中,启动程序执行。
动态链接:系统加载了程序以后,必须通过解析构成进程的目标文件之间的符
号引用,以便完整地构造进程映像。