ELF文件格式

关于ELF

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

  ELF文件格式在链接和程序的运行阶段的格式不同。链接阶段每个.o文件都是一个独立的ELF文件,为了效率和便利性将他们的节合并为段才能生成对应的可执行文件。
一个ELF文件包含的内容有:ELF文件头,程序头表,节头表和节。

数据类型和大小

32bit的ELF文件

类型 大小
unsigned char 1
Elf32_Addr 4
Elf32_Half 2
Elf32_Off 4
Elf32_SWord 4
Elf32_Word 4

64位的ELF文件

类型 大小
unsigned char 1
Elf32_Addr 8
Elf32_Half 2
Elf32_Off 8
Elf32_Xword 8
Elf32_Word 4

ELF 文件头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#define EI_NIDENT	16

typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf64_Half e_type; /* Object file type */
Elf64_Half e_machine; /* Architecture */
Elf64_Word e_version; /* Object file version */
Elf64_Addr e_entry; /* Entry point virtual address */
Elf64_Off e_phoff; /* Program header table file offset */
Elf64_Off e_shoff; /* Section header table file offset */
Elf64_Word e_flags; /* Processor-specific flags */
Elf64_Half e_ehsize; /* ELF header size in bytes */
Elf64_Half e_phentsize; /* Program header table entry size */
Elf64_Half e_phnum; /* Program header table entry count */
Elf64_Half e_shentsize; /* Section header table entry size */
Elf64_Half e_shnum; /* Section header table entry count */
Elf64_Half e_shstrndx; /* Section header string table index */
} Elf64_Ehdr;

需要注意的几个字段:

  • e_entry: 可执行程序入口点地址
  • e_phoff: 程序头表偏移地址
  • e_shoff: 节头表偏移地址
  • e_ehsize: ELF头部的大小
  • e_phentsize: 程序头表中每个条目的大小
  • e_phnum: 程序头表中的条目数量。
  • e_shentsize: 节头表中每个条目的大小
  • e_shnum: 节头表中的条目数量
  • e_shstrndx: 节头字符串表索引

程序头表

1
2
3
4
5
6
7
8
9
10
11
typedef struct
{
Elf64_Word p_type; /* Segment type */
Elf64_Word p_flags; /* Segment flags */
Elf64_Off p_offset; /* Segment file offset */
Elf64_Addr p_vaddr; /* Segment virtual address */
Elf64_Addr p_paddr; /* Segment physical address */
Elf64_Xword p_filesz; /* Segment size in file */
Elf64_Xword p_memsz; /* Segment size in memory */
Elf64_Xword p_align; /* Segment alignment */
} Elf64_Phdr;
  • p_offset: 段相对于文件的偏移地址
  • p_vaddr: 段在内存中的虚拟地址
  • p_paddr: 段的物理地址
  • p_filesz: 段在文件中所占的大小
  • p_memsz: 段在内存中所占的大小
  • p_align: 对齐长度

节头表

1
2
3
4
5
6
7
8
9
10
11
12
typedef struct {
Elf64_Word sh_name;
Elf64_Word sh_type;
Elf64_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf64_Xword sh_size;
Elf64_Word sh_link;
Elf64_Word sh_info;
Elf64_Xword sh_addralign;
Elf64_Xword sh_entsize;
} Elf64_Shdr;
  • sh_name: 节名称,是节区头字符串表节区中(Section Header String Table Section)的索引,因此该字段实际是一个数值。在字符串表中的具体内容是以 NULL 结尾的字符串。
  • sh_type: 节类型
  • sh_addr: 节在内存中的地址
  • sh_offset: 节在文件中的偏移
  • sh_size: 节的大小
  • sh_addralign: 节的地址对齐长度