Contents [hide] 下面我们介绍一种文件格式:
一、ELF文件类型通俗点说由汇编器和链接器生成的文件都属于ELF文件。通常我们接触的ELF文件主要有以下三类:
总之,ELF文件是一种文件格式。但凡是一种格式,总要有一些规则,下面我们来介绍ELF文件的格式规则。 二、ELF文件结构一个典型的ELF文件包括ELF Header、Sections、Section Header Table和Program Header Table。其位置分布如下图所示: 1. ELF Header每个ELF文件都存在一个ELF Header用来描述其结构和组成。ELF Header其实对应的是一个结构体,该结构体定义如下: #define EI_NIDENT 16 typedef struct { unsigned char e_ident[EI_NIDENT]; uint16_t e_type; uint16_t e_machine; uint32_t e_version; ElfN_Addr e_entry; ElfN_Off e_phoff; ElfN_Off e_shoff; uint32_t e_flags; uint16_t e_ehsize; uint16_t e_phentsize; uint16_t e_phnum; uint16_t e_shentsize; uint16_t e_shnum; uint16_t e_shstrndx; } ElfN_Ehdr; 其中 ElfN_Addr Unsigned program address, uintN_tElfN_Off Unsigned file offset, uintN_t 上述结构体的各成员意义如下:
例如,machine的值为 #define EM_X86_64 62 /* AMD x86-64 */ 表示,这个ELF文件可以运行在x86_64的机器上。 2. Section在ELF文件中,数据和代码分开存放的,这样可以按照其功能属性分成一些区域,比如程序、数据、符号表等。这些分离存放的区域在ELF文件中反映成
特殊的,
2)对于可执行文件,由于它已经全部完成了重定位工作,可以直接加载到内存中执行,所以它不存在
上述描述的各个文件中包含的这些section是必须存在的,当然除了这些section,每种文件还有一些其他的section用来存放编译器或者链接器所需要的辅助信息,详情请参考参考阅读1,在这里就不过多的讨论了。 3. Section Header Table上述各个section的大小和位置等具体信息的存放是由Section Header Table来描述的。Section Header Table是一个结构体数组,对应的结构体定义如下: typedef struct { uint32_t sh_name; uint32_t sh_type; uint64_t sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; uint64_t sh_size; uint32_t sh_link; uint32_t sh_info; uint64_t sh_addralign; uint64_t sh_entsize;} Elf64_Shdr; 其中各成员的意义如下:
4. Program Header Table前面讲过了,section基本是按照目标文件内容的功能来划分的一些区域,而根据其内容在内存中是否可读写等属性,又可以将不同的section划分成不同的 在可执行文件中,ELF header下面紧接着就是Program Header Table。它描述了各个segment在ELF文件中的位置以及在程序执行过程中系统需要准备的其他信息。它也是用一个结构体数组来表示的。具体代码如下: typedef uint64_t Elf64_Addr;typedef uint64_t Elf64_Off;typedef uint32_t Elf64_Word;typedef uint64_t Elf64_Xword;typedef struct { Elf64_Word p_type; // 4 Elf64_Word p_flags; // 4 Elf64_Off p_offset; // 8 Elf64_Addr p_vaddr; // 8 Elf64_Addr p_paddr; // 8 Elf64_Xword p_filesz; // 8 Elf64_Xword p_memsz; // 8 Elf64_Xword p_align; // 8} Elf64_Phdr; 各个字段的具体含义如下:
三、实践为了进一步加深对ELF文件整体结构的理解,我们取一个64bit的linux上的可执行文件 $ readelf -h helloELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x400430 Start of program headers: 64 (bytes into file) Start of section headers: 6616 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 9 Size of section headers: 64 (bytes) Number of section headers: 31 Section header string table index: 28 从ELF Header中我们得到如下信息:
其次,使用 $ readelf -S helloThere are 31 section headers, starting at offset 0x19d8:Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 0000000000400238 00000238 000000000000001c 0000000000000000 A 0 0 1 [ 2] .note.ABI-tag NOTE 0000000000400254 00000254 0000000000000020 0000000000000000 A 0 0 4 [ 3] .note.gnu.build-i NOTE 0000000000400274 00000274 0000000000000024 0000000000000000 A 0 0 4 ... snip ... [27] .comment PROGBITS 0000000000000000 00001038 0000000000000035 0000000000000001 MS 0 0 1 [28] .shstrtab STRTAB 0000000000000000 000018cc 000000000000010c 0000000000000000 0 0 1 [29] .symtab SYMTAB 0000000000000000 00001070 0000000000000648 0000000000000018 30 47 8 [30] .strtab STRTAB 0000000000000000 000016b8 0000000000000214 0000000000000000 0 0 1Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), l (large) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) 根据上述section信息,我们得到:
根据我们上面的结论,我们可以得到该ELF文件的组成图如下:
我们可以计算出各部分的end_addr上述空白部分,得到: 显然,各个section正好和下一个section首尾相接。然后,通过 四、总结
|
|
来自: xiaofenglib > 《收藏》