原文出自 : 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 |
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索引. |
程序头为一结构数组,每个元素描述执行文件的一个可载入段.
元素结构如下(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的条目大小,如符号表. |
一些典型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 |
包含符号表. |
重定位信息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 |
加到符号上的常数,用于计算放在重定位域的值. |
符号表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) 不分配, 外部变量 |
串表sections( .strtab和.shstrtab) 包含符号表中符号名和section名.名都以null结束. 这些符号通过偏移指向[point into]串表. 串表的第一字节总是零, 其后所有串顺序存放.