原文出自 : http://blog.chinaunix.net/uid-8473611-id-3184556.html
1.1.1 整体结构
ELF对象格式用于目标文件(.o扩展名)和执行文件. 有些信息只出现在目标文件或执行文件中.
ELF文件由下列部件构成. ELF header必须放在文件的开始;其他部件可以随便排放(ELF header给出了其他部件的偏移量).
ELF文件构件:
Section | 描述 |
ELF header | 一般信息. |
Program header table | 执行文件信息;只出现在执行文件中. |
Section data | Section的实际数据;一些section有特殊的含义, 例如: symbol table和string table. |
Section headers | 不同ELF section信息; 每个section一个. |
典型ELF文件结构:
ELF Header |
Program Header Table |
Section 1 Data …… Section n Data |
Section Header Table |
1.1.2 ELF头[ELF Header]
ELF头包含目标文件的一般信息;具有如下结构(from elf.h):
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_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;
};
ELF头域描述:
域 | 描述 |
e_ident | 16字节串: 4字节标识: '_ELF' 1字节class: 32位对象->1 1字节数据编码: litte-endian->1,big-endian->2 1字节版本: 当前版本->1 9字节零填充 |
e_type | 文件类型: 可重定位->1,可执行->2 |
e_machine | 目标体系结构: MC68000&ColdFire->4 |
e_version | 目标文件版本: 设定为1. |
e_entry | 程序入口地址. |
e_phoff | Program Header Table的文件偏移. |
e_shoff | Section Header Table的文件偏移. |
e_flags | 未使用. |
e_ehsize | ELF头大小. |
e_phentsize | Program Header Table中每条目的大小. |
e_phnum | Program Header Table中条目个数. |
e_shentsize | Section Header Table中每条目的大小. |
e_shnum | Section Header Table中条目个数. |
e_shstrndx | 包含Section名串表的条目的Section Header索引. |
1.1.3 程序头[Program Header]
程序头为一结构数组,每个元素描述执行文件的一个可载入段.
元素结构如下(from elf.h):
typedef struct {
Elf32_Word p_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;
ELF程序头域描述:
域 | 描述 |
p_type | 段类型;linker只使用PT_LOAD(1). |
p_offset | 段raw数据的文件偏移. |
p_vaddr | 载入时段在内存中的驻留地址. |
p_paddr | 未使用. |
p_filesz | 段在文件中的大小;可以为0. |
p_memsz | 段在内存中的大小;可以为0. |
p_flags | 包含如下标志组合的Bit mask: PF_X (1) Execute PF_W (2) Write PF_R (4) Read |
p_align | 段在内存&文件中的对齐方式. |
1.1.4 Section Headers
ELF文件中的每个section的都有激励[incitation]头; Section个数由ELF Header中的e_shnum 域指明. Section headers结构如下(from elf.h):
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;
ELF section header域描述:
域 | 描述 |
sh_name | 指明section名;可作为section header string表的索引. |
sh_type | Section类型: SHT_NULL(0) inactive header SHT_PROGBITS(1) 程序定义的数据或代码 SHT_SYMTAB(2) 符号表 SHT_STRTAB(3) 串表 SHT_RELA(4) 重定位条目 SHT_NOBITS(8) 未初始化数据 SHT_COMDAT(12) 似SHT_PROGBITS |
sh_flags | 如下标志组合: SHF_WRITE(1) 包含可写数据 SHF_ALLOC(2) 包含分配数据 SHF_EXECINSTR(4) 包含可执行指令 |
sh_addr | 若section将载入内存, section的地址. |
sh_offset | Section的raw数据的文件偏移;注意SHT_NOBIT section没有raw数据,它将由操作系统初始化. |
Sh_size | Section大小; 即使SHT_NOBITS section未占任何文件空间,也可能非零. |
sh_link | 连接到其他section头的索引. SHT_COMDAT,SHT_NOBITS,SHT_PROGBITS, SHT_RELA 符号表; SHT_SYMTAB 串表. |
sh_info | 包含如下信息: SHT_RELA 重定位应用到该section SHT_SYMTAB 第一个非本地符号索引 |
sh_addralign | 对齐要求. |
sh_entsize | 包含固定大小条目的section的条目大小,如符号表. |
1.1.5 Special Sections
一些典型section的名和内容解释如下表所示:
名称 | 内容 |
.text | 机器指令, 常值数据和常值串. |
.data | 初始化数据. |
.sdata | 小初始化数据. |
.bss | 未初始化变量. |
.sbss | 小未初始化变量. |
.comment | Comments from #ident directives in C. |
.init | Main()函数之前执行的代码. |
.fini | 程序执行完成后执行的代码. |
.eini | .fini代码的最后指令;.init,.fini和eini section应以序放入内存. |
.debug | DWARF格式的符号调试信息. |
.line | 符号调试的行号信息. |
.relaname | Section name的重定位信息. |
.shstrtab | Section名. |
.strtab | 串表for符号表中的符号. |
.symtab | 包含符号表. |
1.1.6 重定位信息[Relocation Information]
重定位信息section包含关于非确定引用[unresolved references]的信息.因为编译器[compilers]和汇编器[assemblers]不知道符号将分配的绝对内存地址,和别的文件的符号定义;所以对符号的每个引用都将创建一个重定位条目. 该条目指向地址(where the reference is being made), 和指向包含被引用符号的符号表. 连接器[linker]给所有符号分配地址之后, 将使用重定位信息添入正确的地址. 执行文件没有重定位section.
例如: 汇编表示符号加上偏移:
move.l var+16,d0
偏移量存储在r_addend域,这样,符号真实地址加上该地址域将产生一个正确的引用.
重定位条目有如下结构(from elf.h):
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
Elf32_Sword r_addend;
} Elf32_Rel;
ELF重定位条目的域描述:
域 | 描述 |
r_offset | Area在当前section的相对地址(to be patched with正确地址). |
r_info >> 8 | r_info的高24位是符号表的索引; 指向描述在r_offset引用的符号的条目. |
r_info & 255 | 低8位是重定位类型,用来描述寻址模式[绝对|相对,大小]. |
r_addend | 加到符号上的常数,用于计算放在重定位域的值. |
1.1.7 符号表
符号表section .symtab为一数组,数组元素包含关于被ELF文件引用的符号的信息.
符号表条目有如下结构(from elf.h):
typedef struct {
ELF32_Word st_name;
ELF32_Addr st_value;
ELF32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half sth_shndx;
} Elf32_Sym;
ELF符号表域说明:
域 | 描述 |
st_name | 符号串表索引. 串表用于保存符号名. |
st_value | 符号值: 符号的section索引为SHN_COMMON:符号对齐要求. 重定位文件:离section起始位置的偏移. 执行文件:符号的地址. |
st_size | 对象大小. |
st_info >> 4 | 高4位定义符号的绑定[binding ]: STB_LOCAL (0) symbol is local to the file STB_GLOBAL (1) symbol is visible to all object files STB_WEAK (2) symbol is global with lower precedence |
st_info & 15 | 低4位定义符号的类型: STT_NOTYPE (0) 无类型 STT_OBJECT (1) 数据对象(变量) STT_FUNC (2) 函数 STT_SECTION (3) section名 STT_FILE (4) 文件名 |
st_other | 未使用. |
st_shndx | 定义符号sectiond的索引.特殊的section数包括: SHN_UNDEF (0x0000) 未定义section SHN_ABS (0xfff1) 绝对, 不可重定位符号 SHN_COMMON (0xfff2) 不分配, 外部变量 |
1.1.8 串表
串表sections( .strtab和.shstrtab) 包含符号表中符号名和section名.名都以null结束. 这些符号通过偏移指向[point into]串表. 串表的第一字节总是零, 其后所有串顺序存放.
最后 由于春运快到了,给大家安利一个抢火车票的小程序心到抢票,微信扫码关注点击立即抢票即可
个人亲测效率很高,大家也可以加他们官方微信 xdticket 咨询。