Linux ELF文件格式

1. ELF header結構體
主要定義了文件的類型,程序頭表位置,大小和個數,節頭表位置,大小和個數
typedef struct {
               unsigned char e_ident[EI_NIDENT];/*ELF Majic*/
               uint16_t      e_type;/*文件類型(ET_REL,ET_EXEC,ET_DYN)*/
               uint16_t      e_machine;/*CPU體系(ARM ,X86,MIPS),表示程序在哪種cpu執行*/
               uint32_t      e_version;
               ElfN_Addr     e_entry;/* 程序的入口點*/
               ElfN_Off      e_phoff;/*程序頭表的offset */
               ElfN_Off      e_shoff;/*節頭表的offset */
               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;/*字符串節表在節表頭table中的index */
           } ElfN_Ehdr;

2.常見的ELF程序類型
ET_REL :可重定向文件
ET_EXEC:可執行文件
ET_DYN : 共享文件

3.程序頭(Program header)
可執行文件或者共享文件的program header table描述了系統執行一個程序所需要的段(segment)或者其它信息。
目標文件的一個段(segment)包含一個或者多個section。Program header只對可執行文件和共享目標文件有意義,
對於程序的鏈接沒有任何意義。一個program header table包含多個program header,定義如下:

typedef struct {
               uint32_t   p_type;/*segment類型(PT_LOAD,PT_DYNAMIC,PT_GNU_STACK) */
               uint32_t   p_flags;/*segment 屬性PF_X,PF_R,PF_W*/
               Elf64_Off  p_offset;/*這個segment相對文件的偏移 */
               Elf64_Addr p_vaddr;/*這個segment在運行時的虛擬地址 */
               Elf64_Addr p_paddr;/* 物理地址,暫時沒用*/
               uint64_t   p_filesz;/*這個segment的大小 */
               uint64_t   p_memsz;/*這個segment加載到內存後的大小 */
               uint64_t   p_align;/*對齊相關*/
           } Elf64_Phdr;

4.segment類型和flags說明
PT_LOAD :這個段是可裝載的(程序運行時,把這個segment加載到內存)
PT_DYNAMIC:動態鏈接相關的segment
PT_INTERP  :制定動態鏈接庫的全路徑
PF_X: segment具有執行權限
PF_R: segment是隻讀的
PF_W: segment是可寫的.
代碼段具有:PF_X, PF_W
數據段具有:PF_X,PF_W,PF_R

5.readelf常用指令
readelf -h  binary_file /*顯示文件頭信息 */
readelf -l  binary_file /*顯示程序頭信息 */
readelf -S  binary_file /*顯示段表頭信息 */
readelf -s  binary_file /*顯示.symtab內容 */
readelf -n  binary_file /*顯示文件的Note信息 */
readelf -x  section_name /*以16進制顯示段表內容 */
readelf -p  section_name /*以字符串顯示段表內容 */

6. objdump常用指令
objdump -d binary_file /*把代碼段反彙編 */
objdump -d -Mintel binary_file /*以intel彙編格式來反彙編代碼,默認是AT&T格式 */

7.段表(section header table)
目標文件的section header table可以定位所有的section,段表實際上是一個數組

           typedef struct {
               uint32_t   sh_name;/* section name在string section 中的Index*/
               uint32_t   sh_type;/*section類型,常見類型SHT_PROGBITS,SHT_REL,SHT_SYMTAB,SHT_STRTAB,SHT_DYNSYM */
               uint64_t   sh_flags;/*section訪問權限,SHF_WRITE,SHF_ALLOC,SHF_EXECINSTR */
               Elf64_Addr sh_addr;/*section在內存中的地址. */
               Elf64_Off  sh_offset;/*section在文件中的偏移 */
               uint64_t   sh_size;/*section的大小 */
               uint32_t   sh_link;/*section依賴其他section的index,比如.symtab依賴.strtab,sh_link的值就是.strtab的index */
               uint32_t   sh_info;/*額外信息,.symtab會用到 */
               uint64_t   sh_addralign;/*對齊相關 */
               uint64_t   sh_entsize;/*有些section包含額外的信息 */
           } Elf64_Shdr;

8. section 的sh_name解析
    1.先根據file header找到section header table的位置
    2.根據file header中的e_shstrndx,在段表中找到字符串section ".strtab"
    3.根據sh_name的值從".strtab"找到對應的字符串.從而得出section name

9. 常見的section
可以用readelf -S binary_file查看所有的段
.bss :爲初始化的全局變量
.text :代碼段
.data :數據段
.rodata:只讀數據段
.strtab :包含所有符號的名字

.shstrtab:包含所有section name
.symtab :包含文件所有的符號表(函數名,文件名,全局變量名等等)
.rel/.rela: 可重定向相關
.dymtab/.dymstr :動態鏈接相關

10. symbol/section/segment的關係
symbol被定義在各種section中。而section最終又被包含到segment中.
一個segment可以包含多個section

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章