Contents [hide] 下面我們介紹一種文件格式:
一、ELF文件類型通俗點(diǎn)說由匯編器和鏈接器生成的文件都屬于ELF文件。通常我們接觸的ELF文件主要有以下三類:
總之,ELF文件是一種文件格式。但凡是一種格式,總要有一些規(guī)則,下面我們來介紹ELF文件的格式規(guī)則。 二、ELF文件結(jié)構(gòu)一個(gè)典型的ELF文件包括ELF Header、Sections、Section Header Table和Program Header Table。其位置分布如下圖所示: 1. ELF Header每個(gè)ELF文件都存在一個(gè)ELF Header用來描述其結(jié)構(gòu)和組成。ELF Header其實(shí)對(duì)應(yīng)的是一個(gè)結(jié)構(gòu)體,該結(jié)構(gòu)體定義如下: #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 上述結(jié)構(gòu)體的各成員意義如下:
例如,machine的值為 #define EM_X86_64 62 /* AMD x86-64 */ 表示,這個(gè)ELF文件可以運(yùn)行在x86_64的機(jī)器上。 2. Section在ELF文件中,數(shù)據(jù)和代碼分開存放的,這樣可以按照其功能屬性分成一些區(qū)域,比如程序、數(shù)據(jù)、符號(hào)表等。這些分離存放的區(qū)域在ELF文件中反映成
特殊的,
2)對(duì)于可執(zhí)行文件,由于它已經(jīng)全部完成了重定位工作,可以直接加載到內(nèi)存中執(zhí)行,所以它不存在
上述描述的各個(gè)文件中包含的這些section是必須存在的,當(dāng)然除了這些section,每種文件還有一些其他的section用來存放編譯器或者鏈接器所需要的輔助信息,詳情請(qǐng)參考參考閱讀1,在這里就不過多的討論了。 3. Section Header Table上述各個(gè)section的大小和位置等具體信息的存放是由Section Header Table來描述的。Section Header Table是一個(gè)結(jié)構(gòu)體數(shù)組,對(duì)應(yīng)的結(jié)構(gòu)體定義如下: 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基本是按照目標(biāo)文件內(nèi)容的功能來劃分的一些區(qū)域,而根據(jù)其內(nèi)容在內(nèi)存中是否可讀寫等屬性,又可以將不同的section劃分成不同的 在可執(zhí)行文件中,ELF header下面緊接著就是Program Header Table。它描述了各個(gè)segment在ELF文件中的位置以及在程序執(zhí)行過程中系統(tǒng)需要準(zhǔn)備的其他信息。它也是用一個(gè)結(jié)構(gòu)體數(shù)組來表示的。具體代碼如下: 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; 各個(gè)字段的具體含義如下:
三、實(shí)踐為了進(jìn)一步加深對(duì)ELF文件整體結(jié)構(gòu)的理解,我們?nèi)∫粋€(gè)64bit的linux上的可執(zhí)行文件 $ 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) 根據(jù)上述section信息,我們得到:
根據(jù)我們上面的結(jié)論,我們可以得到該ELF文件的組成圖如下:
我們可以計(jì)算出各部分的end_addr上述空白部分,得到: 顯然,各個(gè)section正好和下一個(gè)section首尾相接。然后,通過 四、總結(jié)
|
|