Linux[ELF]: ELF文件結(jié)構(gòu)簡單梳理

Linux[ELF]: ELF文件結(jié)構(gòu)簡單梳理

一.編譯過程-ELF文件生成

在這里插入圖片描述

二.ELF的文件概述

2.1 4種ELF文件類型

ELF文件類型 說明 實(shí)例
Relocatable File 包含例代碼和數(shù)據(jù),可以被鏈接成可執(zhí)行文件或共享目標(biāo)文件 Linux下的.o文件
Executable File 包含可以直接執(zhí)行的程序,ELF可執(zhí)行文件,一般沒有擴(kuò)展名 /bin/bash文件
Shared Object File 包含代碼和數(shù)據(jù),和其他目標(biāo)文件鏈接成新的目標(biāo)文件,和可執(zhí)行文件鏈接作為進(jìn)程映像的一部分來允許 Linux下的.so文件
Core Dump File 進(jìn)程意外終止時(shí)可以產(chǎn)生的文件,存儲(chǔ)著該進(jìn)程的內(nèi)存空間中的內(nèi)容等信息 Linux下的core dump

2.2 ELF文件簡單結(jié)構(gòu)

在這里插入圖片描述

兩種視圖:


在這里插入圖片描述

三.ELF重要的結(jié)構(gòu)

3.1 文件結(jié)構(gòu)詳細(xì)學(xué)習(xí):

ELF文件格式解析: https://blog.csdn.net/dddxxxx/article/details/80347610

3.2 詳細(xì)結(jié)構(gòu)整理:

在這里插入圖片描述

3.3 注意點(diǎn):

  1. 除了 ELF 頭部表以外,其他節(jié)區(qū)和段都沒有規(guī)定的順序
  2. 目標(biāo)文件中的每個(gè)節(jié)區(qū)都有對(duì)應(yīng)的節(jié)區(qū)頭部描述它,反過來,有節(jié)區(qū)頭部不意味著有節(jié)區(qū)
  3. 每個(gè)節(jié)區(qū)占用文件中一個(gè)連續(xù)字節(jié)區(qū)域(這個(gè)區(qū)域可能長度為 0)。
  4. 文件中的節(jié)區(qū)不能重疊,不允許一個(gè)字節(jié)存在于兩個(gè)節(jié)區(qū)中的情況發(fā)生。
  5. 目標(biāo)文件中可能包含非活動(dòng)空間(INACTIVE SPACE)。這些區(qū)域不屬于任何頭部和節(jié)區(qū),其內(nèi)容未指定。
  6. 以“.”開頭的節(jié)區(qū)名稱是系統(tǒng)保留的。應(yīng)用程序可以使用沒有前綴的節(jié)區(qū)名稱,以避免與系統(tǒng)節(jié)區(qū)沖突。
  7. 目標(biāo)文件中也可以包含多個(gè)名字相同的節(jié)區(qū)。
  8. Section和Segment的區(qū)別和聯(lián)系
    可執(zhí)行文件中,一個(gè)program header描述的內(nèi)容稱為一個(gè)段(segment)。Segment包含一個(gè)或者多個(gè)section
  9. 可執(zhí)行程序中的幾個(gè)段:
名稱 內(nèi)容
代碼段 可執(zhí)行代碼、字符串常量
數(shù)據(jù)段 已初始化全局變量、已初始化全局靜態(tài)變量、局部靜態(tài)變量、常量數(shù)據(jù)
BSS段 未初始化全局變量,未初始化全局靜態(tài)變量
而當(dāng)程序被加載到內(nèi)存單元時(shí),則需要另外兩個(gè)域:堆域和棧域
局部變量、函數(shù)參數(shù)
動(dòng)態(tài)內(nèi)存分配

3.4 section類型:

名稱 類型 屬性 含義
.bss SHT_NOBITS SHF_ALLOC SHF_WRITE 包含將出現(xiàn)在程序的內(nèi)存映像中的為初始化數(shù)據(jù)。根據(jù)定義,當(dāng)程序開始執(zhí)行,系統(tǒng)將把這些數(shù)據(jù)初始化為 0。此節(jié)區(qū)不占用文件空間。
.data SHT_PROGBITS (無) 包含版本控制信息。
.data1 SHT_PROGBITS SHF_ALLOC SHF_WRITE 這些節(jié)區(qū)包含初始化了的數(shù)據(jù),將出現(xiàn)在程序的內(nèi)存映像中。
.debug SHT_PROGBITS (無) 此節(jié)區(qū)包含用于符號(hào)調(diào)試的信息。
.dynamic SHT_DYNAMIC 此節(jié)區(qū)包含動(dòng)態(tài)鏈接信息。節(jié)區(qū)的屬性將包含 SHF_ALLOC 位。是否 SHF_WRITE 位被設(shè)置取決于處理器。
.dynstr SHT_STRTAB SHF_ALLOC 此節(jié)區(qū)包含用于動(dòng)態(tài)鏈接的字符串,大多數(shù)情況下這些字符串代表了與符號(hào)表項(xiàng)相關(guān)的名稱。
.dynsym SHT_DYNSYM SHF_ALLOC 此節(jié)區(qū)包含了動(dòng)態(tài)鏈接符號(hào)表。
.fini SHT_PROGBITS SHF_ALLOCSHF_EXECINSTR 此節(jié)區(qū)包含了可執(zhí)行的指令,是進(jìn)程終止代碼的一部分。程序正常退出時(shí),系統(tǒng)將安排執(zhí)行這里的代碼。
.got SHT_PROGBITS 此節(jié)區(qū)包含全局偏移表。
.hash SHT_HASH SHF_ALLOC 此節(jié)區(qū)包含了一個(gè)符號(hào)哈希表.
.init SHT_PROGBITS SHF_ALLOCSHF_EXECINSTR 此節(jié)區(qū)包含了可執(zhí)行指令,是進(jìn)程初始化代碼的一部分。當(dāng)程序開始執(zhí)行時(shí),系統(tǒng)要在SHF_EXECINSTR 開始調(diào)用主程序入口之前(通常指 C 語言的 main 函數(shù))執(zhí)行這些代碼。
.interp SHT_PROGBITS 此節(jié)區(qū)包含程序解釋器的路徑名。如果程序包含一個(gè)可加載的段,段中包含此節(jié)區(qū),那么節(jié)區(qū)的屬性將包含 SHF_ALLOC 位,否則該位為 0。
.line SHT_PROGBITS 此節(jié)區(qū)包含符號(hào)調(diào)試的行號(hào)信息,其中描述了源程序與機(jī)器指令之間的對(duì)應(yīng)關(guān)系。其內(nèi)容是未定義的。
.note SHT_NOTE 此節(jié)區(qū)中包含注釋信息,有獨(dú)立的格式。
.plt SHT_PROGBITS 此節(jié)區(qū)包含過程鏈接表(procedure linkage table)。
.relname SHT_REL 這些節(jié)區(qū)中包含了重定位信息。如果文件中包含可加載的段,段中有重定位內(nèi)容,節(jié)區(qū)的屬性將包含 SHF_ALLOC 位,否則該位 置 0。傳統(tǒng)上 name 根據(jù)重定位所適用的節(jié)區(qū)給定。例如 .text 節(jié)區(qū)的重定位節(jié)區(qū)名字將是:.rel.text 或者 .rela.text。
.rela name SHT_RELA
.rodata SHT_PROGBITS SHF_ALLOC 這些節(jié)區(qū)包含只讀數(shù)據(jù),這些數(shù)據(jù)通常參與進(jìn)程映像的不可寫段。
.rodata1 SHT_PROGBITS SHF_ALLOC
.shstrtab SHT_STRTAB 此節(jié)區(qū)包含節(jié)區(qū)名稱。
.strtab SHT_STRTAB 此節(jié)區(qū)包含字符串,通常是代表與符號(hào)表項(xiàng)相關(guān)的名稱。如果文件擁有一個(gè)可加載的段,段中包含符號(hào)串表,節(jié)區(qū)的屬性將包含 SHF_ALLOC 位,否則該位為 0。
.symtab SHT_SYMTAB 此節(jié)區(qū)包含一個(gè)符號(hào)表。如果文件中包含一個(gè)可加載的段,并且該段中包含符號(hào)表,那么節(jié)區(qū)的屬性中包含SHF_ALLOC 位,否則該位置為 0。
.text SHT_PROGBITS 此節(jié)區(qū)包含程序的可執(zhí)行指令。

3.5 segment類型:

程序段類型 取值 說明
PT_NULL 0 此數(shù)組元素未用。結(jié)構(gòu)中其他成員都是未定義的。
PT_LOAD 1 此數(shù)組元素給出一個(gè)可加載的段,段的大小由 p_filesz 和 p_memsz描述。文件中的字節(jié)被映射到內(nèi)存段開始處。如果 p_memsz 大于p_filesz,“剩余”的字節(jié)要清零。p_filesz 不能大于 p_memsz??杉虞d的段在程序頭部表格中根據(jù) p_vaddr 成員按升序排列。
PT_DYNAMIC 2 數(shù)組元素給出動(dòng)態(tài)鏈接信息。Dynamic Segment 是很重要的一個(gè)程序頭,里面存儲(chǔ)著函數(shù)名、使用過的動(dòng)態(tài)庫名、重定位表、函數(shù)代碼偏移等重要信息,不過不是直接記錄,而是通過一定的方法查詢得到,這個(gè)查詢過程是elf設(shè)計(jì)中巧妙且關(guān)鍵的核心所在。
PT_INTERP 3 該記錄的是鏈接器linker的路徑.數(shù)組元素給出一個(gè) NULL 結(jié)尾的字符串的位置和長度,該字符串將被當(dāng)作解釋器調(diào)用。這種段類型僅對(duì)與可執(zhí)行文件有意義(盡管也可能在共享目標(biāo)文件上發(fā)生)。在一個(gè)文件中不能出現(xiàn)一次以上。如果存在這種類型的段,它必須在所有可加載段項(xiàng)目的前面。
PT_NOTE 4 此數(shù)組元素給出附加信息的位置和大小。
PT_SHLIB 5 此段類型被保留,不過語義未指定。包含這種類型的段的程序與 ABI 不符。
PT_PHDR 6 此類型的數(shù)組元素如果存在,則給出了程序頭部表自身的大小和位置,既包括在文件中也包括在內(nèi)存中的信息。此類型的段在文件中不能出現(xiàn)一次以上。并且只有程序頭部表是程序的內(nèi)存映像的一部分時(shí)才起作用。如果存在此類型段,則必須在所有可加載段項(xiàng)目的前面。
PT_LOPROC 0x70000000 此范圍的類型保留給處理器專用語義。
PT_HIPROC 0x7ffffffff

四. 舉個(gè)例子

  1. Cpp代碼:
//abc.cpp
#include<iostream>
using namespace std;

int main(){
        int sum=0,value=0;
        while(cin>>value){
                sum+=value;
          cout<<"sum:"<<sum;
        }
        return 0;
}
  1. g++ abc.cpp生成.out文件,file看一下是ELF文件類型:


    在這里插入圖片描述
  2. 使用readelf命令簡單查看該a.out這個(gè)elf文件的program header,可以看出一個(gè)segment對(duì)應(yīng)著多個(gè)section,readelf加參數(shù)可以查看更多其他信息:


    在這里插入圖片描述

    當(dāng)ELF文件被加載到內(nèi)存之后,系統(tǒng)會(huì)將多個(gè)具有相同權(quán)限的section合并到一個(gè)segment。
    操作系統(tǒng)往往以頁為基本單位來管理內(nèi)存分配,一般頁的大小位4KB。同時(shí),內(nèi)存的權(quán)限管理的粒度也是以頁為單位,頁內(nèi)的內(nèi)存是具有同樣的權(quán)限,并且操作系統(tǒng)對(duì)內(nèi)存的管理往往追求高效和高利用率這樣的目標(biāo)。
    ELF文件在被映射時(shí),是以系統(tǒng)的頁長度位單位的,那么每個(gè)section在映射時(shí)的長度都是系統(tǒng)頁長度的整數(shù)倍,如果section的長度不是其整數(shù)倍,則導(dǎo)致多余部分也將占用一個(gè)頁。
    而我們從上面的例子中知道,一個(gè)ELF文件具有很多section,那么會(huì)導(dǎo)致內(nèi)存浪費(fèi)。將sections映射到segment可以減少頁面內(nèi)部的碎片,節(jié)省了空間,顯著提高內(nèi)存利用率。

詳細(xì)參考:

Linux ELF文件格式分析 https://blog.csdn.net/xj178926426/article/details/72825630
程序或-內(nèi)存區(qū)域分配(五個(gè)段)--終于搞明白了:https://blog.csdn.net/love_gaohz/article/details/41310597
C程序內(nèi)存區(qū)域分配(5個(gè)段作用): http://www.cnblogs.com/bigbigtree/archive/2012/11/23/2784137.html
學(xué)習(xí)資料:
specific 中英文版及 Learning Linux Binary Analysis 英文版百度云盤下載:
鏈接: https://pan.baidu.com/s/1vt5clx862dqmelYP8PWyLA 提取碼: amgs

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容