ELF文件格式

1、简介

可执行与可链接格式(Executable and Linkable Format,ELF),常被称为ELF格式,是一种用于可执行文件、目标代码、共享库和核心转储的标准文件格式

ELF文件有三种:

  1. 可重定向文件(.o文件):包含基础代码和数据,但它的代码及数据都没有指定绝对地址,因此它适合与其他目标文件链接来创建可执行文件或者共享目标文件。
  2. 可执行文件(.out):包含代码和数据,是可以直接运行的程序。其代码和数据都有固定的地址(或相对于基址的偏移),系统可根据这些地址信息把程序加载到内存执行。
  3. 共享目标文件(.so):也称动态库文件,包含了代码和数据,这些数据是在链接时被链接器(ld)和运行时动态链接器(ld.so.l、libc.so.l、ld-linux.so.l)使用的。

2、ELF文件基本格式

ELF文件有一定格式,从文件格式上来说,分别从编译阶段的链接视角和程序的执行视角去分析

从程序执行视角来看就是Linux加载器加载的各种Segment的集合。根据各种节的权限来分段,段就是相同权限的节的合并

从链接角度来看就是各种节section

ELF文件主要由四个部分组成1、ELF头(ELF header),2、程序头表(Program header),3、节(Section),4、节头表

ELF文件头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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;
1
2

typedef uint16_t Elf32_Half
1
typedef uint32_t Elf32_Word
1
typedef uint32_t Elf32_Addr
1
2

typedef uint32_t Elf32_Off

e_ident作为开头主要用装一些标示信息,固定值来判断ELF文件的合法性,其开头4个字节固定为0x7f, ELF三个字符。(7f 45 4c 46)

e_type是用来标志文件类型的比如有1.可重定位文件,2.可执行文件,3.共享目标文件。

e_machine来用标志运行文件的机器类型,

e_version表示文件的版本

e_entry 程序的入口的虚拟地址,作为执行文件可以作为执行向量地址

e_phoff 表示程序表头相对于文件头的偏移量

e_shoff 表示节头表相对于文件头的编移量

e_flags 与文件相关的,特定处理器的标志

e_ehsize 表示ELF头部的大小(单位字节)

e_phentsize 表示每个程序头表条目大小(单位字节)

e_phnum 表示有多少个程序头条目

e_shentsize 表示每个节头表的条目大小

e_shnum 表示有多少个节头表条目

e_shstrndx 包含节名称的字符串,作为一个符号表

程序头表

程序头表用来描述一个段在文件的位置,大小以及它被放进内存后所在的位置和大小

1
2
3
4
5
6
7
8
9
10
typedef struct {
Elf32_Wordp _type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
}Elf32_Phdr;

p_type 表示程序头描述的段类型

p_offset 表示段的第一字节相对文件头的偏移

p_vaddr 物理地址

p_filesz 段在文件中的长度

p_memsz 段在内存中的长度

p_flags 与段相关的标志

p_align 根据此项值来确定段在文件及内存中如何对齐

节头表

节头表包含文件中各个节的条目,每个节的条目对应了该节的类型,定义了节的大小,以及在二进制文件内部的编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
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表示节区名称

sh_type表示节区类型

sh_flags表示节的类型是否是可执行节,内容是否可以修改

sh_addr表示节区在第一个字节应处的位置

sh_offset表示节区第一个字节相对文件头的偏移

sh_size表示节区的大小(单位字节)

sh_link表示节区头部表索引链接

sh_info表示节区的附加信息

sh_addralign用于地址对齐

sh_entsize表示符号表相关