ELF文件格式
软件版本 | 硬件版本 | 更新内容 |
---|---|---|
ELF64 | arm64 |
1. 概述
ELF文件,也就是Executable and Linking Format.gcc等编译器生成的就是这个类型的文件.存在三种类型的elf文件:
- 可重定位文件relocatable file, 可用于生成可执行文件或者共享库文件的二进制代码和数据,例如**.o**文件
- 可执行文件executable file, 可直接执行的二进制文件
- 共享库文件shared object file, 常见的为**.so**文件,两个作用:
- 用于链接生成新的二进制文件
- 用于动态映射到一个可执行文件中创建新的进程
2. ELF文件组织形式
分两种格式,一种可执行文件,另外一种用于链接的包括.o和.so
一个有效的ELF文件必须满足如下几条:
- 必须存在文件头
- 用于连接的ELF必须包括Section head Table,对于可执行文件这部分可选
- Program Header Table,可执行文件必须包括,用于连接的ELF文件可选
- Section由数据,字符串和可重定位的符号
- 由头,Section header table, Program header table, Sections组成
提示
这里需要注意在linking view中使用的是section,而在executable view中使用是segment,我们写程序时可以通过链接脚本指定当前代码或者数据存放在那个section中,而且只有控制section,而segment是链接器在生成可执行文件时生成的叫segment.
3. ELF文件中使用的数据类型
名子 | 大小 | 对齐方式 | 功能 |
---|---|---|---|
Elf64_Addr | 8 | 8 | 表示程序地址 |
Elf64_Off | 8 | 8 | g表示文件偏移 |
Elf64_Half | 2 | 2 | 表示无符号的中整数 |
Elf64_Word | 4 | 4 | 表示无符号的整数 |
Elf64_Sword | 4 | 4 | 表示有符号的整数 |
Elf64_Xword | 8 | 8 | 表示无符号的大整数 |
Elf64_Sxword | 8 | 8 | 表示有符号的大整数 |
unsigned char | 1 | 1 | 表示无符号的小整数 |
在linux中是如下的定义:
typedef unsigned long long Elf64_Addr;
typedef unsigned short Elf64_Half;
typedef signed short Elf64_SHalf;
typedef unsigned long long Elf64_Off;
typedef signed int Elf64_Sword;
typedef unsigned int Elf64_Word;
typedef unsigned long long Elf64_Xword;
typedef signed long long Elf64_Sxword;
4. ELF文件头
从linux内核中可以找到头部的数据结构如下:
typedef struct elf64_hdr {
unsigned char e_ident[16]; /* ELF "magic number" */
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_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;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
} Elf64_Ehdr;
4.1 ELF头中的e_ident
identification魔数将文件标识为 ELF 目标文件,并提供有关目标文件结构的数据表示的信息。 e_ident是一个数组,在linux内核中使用如下index的访问
/* 这个用于区分32位还是64位,=1 为32位, =2 为64 */
#define EI_CLASS 4
/* 这个字段用于表示大小端,=1 为小端, =2 为大端 */
#define EI_DATA 5
/* 这个字段用于表示版本,目前使用固定的 EV_CURRENT = 1*/
#define EI_VERSION 6
/* 这个字段用于表示操作系统和ABI, 有三种 =0为System V ABI, =1为HP-UX operating system, =2为Standalone (embedded) */
#define EI_OSABI 7
/* 起始填充位 */
#define EI_PAD 8
4.2 ELF头中的e_type
类型如下表:
名子 | 值 | 含义 |
---|---|---|
ET_NONE | 0 | 无文件类型 |
ET_REL | 1 | 可重新定位的文件如.o |
ET_EXEC | 2 | 可执行文件 |
ET_DYN | 3 | 共享库文件 |
ET_CORE | 4 | 核心文件 |
ET_LOOS | 0xFE00 | 特定环境使用 |
ET_HIOS | 0xFEFF | |
ET_LOPROC | 0xFF00 | 特定处理器的使用 |
ET_HIPROC | 0xFFFF |
4.3 ELF头中的e_machine
表示目标处理器架构,如arm64 x86
4.4 ELF头中的e_version
这个和e_ident中版本是一样的
4.5 ELF头中的e_entry
包含程序入口点的虚拟地址。如果没有入口点,则此字段包含零
4.6 ELF头中的e_phoff
包含程序头表的文件偏移量,以字节为单位
4.7 ELF头中的e_shoff
包含节头表的文件偏移量,以字节为单位
4.8 ELF头中的e_flags
包含特定于处理器的标志
4.9 ELF头中的e_ehsize
包含 ELF 标头的大小(以字节为单位)
4.10 ELF头中的e_phentsize
包含程序头表(Program head table)条目的大小(以字节为单位)
4.11 ELF头中的e_phnum
包含程序头表(Program head table)中的条目数
4.12 ELF头中的e_shentsize
每个节头表(section head table)条目的大小(以字节为单位),也就是每个section head 的大小
4.13 ELF头中的e_shnum
节头表(section head table)中的section header条目数
4.14 ELF头中的e_shstrndx
字符串节section header在section header table中的索引
5. SECTIONS节
节是包括除了ELF头,ELF Section header table , ELF Program header table之外的所有东西。
提示
节的内容中没有节的描述信息,它的描述信息都在section header table中对应该的section header中。
6. Section header
在linux中section header的定义如下:
typedef struct elf64_shdr {
Elf64_Word sh_name; /* Section name, index in string tbl */
Elf64_Word sh_type; /* Type of section */
Elf64_Xword sh_flags; /* Miscellaneous section attributes */
Elf64_Addr sh_addr; /* Section virtual addr at execution */
Elf64_Off sh_offset; /* Section file offset */
Elf64_Xword sh_size; /* Size of section in bytes */
Elf64_Word sh_link; /* Index of another section */
Elf64_Word sh_info; /* Additional section information */
Elf64_Xword sh_addralign; /* Section alignment */
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
7. Section header table
是section header的集合,这个表的地址在ELF头中有,是e_shoff这个字段
8. Program header
在linux中Program header的定义如下:
typedef struct elf64_phdr {
Elf64_Word p_type;
Elf64_Word p_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, file & memory */
} Elf64_Phdr;
9. Program header table
是Program header的集合,这个表的地址在ELF头中有,是e_phoff这个字段
10. 特殊的一些Section
10.1 string table section
string table这个节保存了所有的了section的name,也就是说我们可以读取这个段的内容知道,都有那些个section.
提示
欢迎评论、探讨,如果发现错误请指正。转载请注明出处! 探索者