ELF文件分析
背景
????????一個程序要想運行,首先要加載到內存中,程序的pc指針指向內存中的代碼,代碼在執行的時候會使用內存中的數據。所以ELF文件主要包含代碼和數據。
數據可以分為兩類:
什么是動態數據?,動態數據程序運行過程中產生,在堆或者棧上分配內存。而靜態數據則不然,靜態數據在代碼編譯完成后,就應該確定使用的地址和空間。
靜態數據又分為兩種,只讀數據和可讀寫數據。
????????一個庫要想被其他程序調用,還要約定一種方式,使調用者可以找到被調用者的函數地址,所以運行程序還要保存動態鏈接相關的信息。另外程序還要告知連接器,如何將代碼和數據加載到內存中,這就是程序的加載信息。ELF文件格式是類unix系統中常見的程序和庫的文件格式,所以ELF要包含上述信息(代碼,數據,加載信息和鏈接信息)。ELF怎么來組這這些信息呢,下面是ELF的數據格式圖。
程序的信息都保存在section(節)中,文件通過section header table(節頭表)來描述每個節的信息,這些信息包括如下幾項:
- Name:節的名稱。
- Type:節的類型。
- Addr:節映射到虛擬空間的位置(這個信息一般不用)。
- Off :節在ELF文件中的偏移。
- Size:節的大小。
- ES Flg Lk Inf Al。
不同類型的節有不同的作用。
程序的加載信息則保存在program header table(程序段表)中,ELF被加載到內存中后用segment(段)表示,段的描述信息:
- Type: 段類型。
- Offset: 段對應的ELF文件偏移(也就是說該段用于映射ELF文件的偏移地址)。
- VirtAddr: 段在虛擬內存中的偏移地址(注意:在PIC模式下段不一定被加載到該地址,可能會與該地址有個偏移)。
- PhysAddr:段被加載到的物理地址(在mmu系統下不使用該地址)。
- FileSiz:該段映射的文件大小。從offset—>(offset + FileSiz) 映射到內存的VirtAddr—>(VirtAddr + FileSiz)
- MemSiz: 該段占用的內存大小(MemSiz >= FileSiz)。
- Flg: 讀寫權限,該段在內存中是否具有讀寫執行權限。
- Align:段的對齊要求。
程序的鏈接信息也保存在section(節)中,關于鏈接信息我們可以分為兩部分,一部分為庫導出的函數/變量,另一部分則是庫依賴的其他庫的函數/變量。對于描述導出的函數/變量是比較容易的,因為庫自身知道函數/變量的名稱和要加載到的內存位置,這部分信息(名字和地址)保存在類型為DYNSYM的節中。 對于要導入的函數/變量,在類型為RELA/REL的節中保存了引用其他庫的函數/變量在符號表中的索引,符號表中則保存該函數/變量的名稱,在類型為DYNAMIC的節中保存了程序依賴的庫名稱,鏈接器在鏈接的時候會去依賴的庫中根據函數/變量的名稱去尋找該函數/變量被加載到內存的位置,將找到的函數/變量地址寫入到類型為PROGBITS(一般名稱為.got的節) 節對應的位置,之后再使用函數/變量就直接從got表中獲取地址即可。
ELF文件的映射及詳解
ELF的加載主要的依據為程序頭表,程序頭表中每一項描述的段(segment)的信息,一個段可能包含多個section(節)。
我們以上圖中的程序頭表的段信息來舉例:
-
PHDR:程序頭的作用主要用于加載的驗證。
-
LOAD: load類型的頭主要指導連接器如何分配內存和如何把elf映射到內存中,以及內存的權限。
-
DYNMIC: 這個頭描述了動態鏈接信息被加載到內存的位置。也就是圖中.dynmic在內存中的位置。
對于上圖兩個LOAD段是比較重要的,第一個LOAD段對應ELF從頭部到.rodata節結尾的部分,這部分被加載到內存后,設置權限為可讀和可執行的。上圖是arm gcc編譯出來的elf程序,這部分其實有些內容是不需要執行權限的,說明arm gcc控制還是比較粗獷的。
第二個LOAD段對應ELF文件從.data.rel.ro.local節開頭到.bss節結尾的部分,這部分被加載到內存后,設置權限為開讀和可寫的。為什么右邊內存中的讀寫區域會大于左邊文件的區域呢,是因為.bss段只保存了全局為初始化數據(這些變量默認初值為0)需要的空間,而沒有在文件中分配該空間,所以LOAD段會為這部分空間分配內存,填充內容為0。
另外ELF的節頭表和一些節是不需要加載到內存的。
動態鏈接
關于動態鏈接需要知道如下幾點即可:
關于鏈接腳本
EFL_load圖中描述的是gcc連接器默認的鏈接腳本生成的ELF文件,節的名稱都是gcc定義的。所以我們只要能滿足elf連接器的要求,elf的節名稱組織方式完全可以自己定義,也就是鏈接腳本的作用,我們甚至可以自己寫加載器。
總結
- 上一篇: 正在播放2020Me比较特别的我_【一点
- 下一篇: 微信支付开发:开通微信免充值代金券和开通