Linux程序編譯執行原理之二:gcc編譯出的elf文件分析

本系列導航:

Linux程序編譯執行原理之一:預處理-編譯-彙編-鏈接過程分析

Linux程序編譯執行原理之二:gcc編譯出的elf文件分析



使用gcc編譯出的可執行程序是啥樣的呢?使用編輯器打開只會看到一堆亂碼^-^ 它又爲何能夠執行,如何執行的呢?今天我們以上一篇文章中編譯出來的elf文件爲例,來一起了解一下這其中的緣由。

 

Elf格式與bin格式的區別

首先來對比一下另一種二進制文件格式bin

1,  bin文件是raw binary文件,其中只有機器碼

2,  elf文件除了含有機器碼之外還有其它信息,如:段加載地址,運行入口地址,數據段等

3,  運行bin文件只需要將bin文件起始地址賦值pc指針即可

4,  Elf程序需要專門的elf loader將其中的代碼段、數據段解析加載到內存中指定的位置(此處使用的是4GB虛擬地址哦),再跳轉到elf header指定的入口地址開始執行。

 

 

Linux下編譯出來的程序是elf格式的,ELF全稱Executable and Linkable Format,可執行鏈接格式。ELF文件(目標文件)格式主要三種:

可重定向文件:文件保存着代碼和適當的數據,用來和其他的目標文件一起來創建一個可執行文件或者是一個共享目標文件。(目標文件或者靜態庫文件,即linux通常後綴爲.a和.o的文件)

可執行文件:文件保存着一個用來執行的程序。(例如bash,gcc等)

共享目標文件:共享庫。文件保存着代碼和合適的數據,用來被下連接編輯器和動態鏈接器鏈接。(linux下後綴爲.so的文件。)

(ps:windows下的可執行文件格式是不是elf呢?以後有機會研究一下)


ELF文件組成:



1,ELF文件由4部分組成

分別是ELF頭(ELF header)、程序頭表(Program header table)、節(Section)和節頭表(Section header table)。實際上,一個文件中不一定包含全部內容,而且他們的位置也未必如同所示這樣安排,只有ELF頭的位置是固定的,其餘各部分的位置、大小等信息由ELF頭中的各項值來決定。

下面這3部分簡單分佈情況,上面這條橫條可以看成ELF文件從頭到尾。對於ELF頭,節區表,節區都對應分佈在文件裏面,通過偏移來表示其對應在文件的位置。


2、ELF頭對應字段的意義

簡單用下圖來說明,其他字段可以對應解析



3、節區相關信息



4sh_info,sh_link段

對於節區經常使用的兩個信息字段sh_info,sh_link對應字段意義



5、常見section

對於一個ELF目標文件,通常都會有以下幾個節區,可以通readelf –S test


編譯出的elf文件中的各種section

.text段是代碼段。它用來放程序代碼(code)。它通常是隻讀的

.data段是數據段。它用來存放初始化了的(initailized)全局變量(global)和初始化了的靜態變量(static)。它是可讀可寫的。

.bss段是全局變量數據段。它用來存放未初始化的(uninitailized)全局變量(global)和未初始化的靜態變量(static)。它也是可讀可寫的。bss是英文BlockStarted by Symbol的縮寫。之所以把bss跟data分開來,是因爲系統會爲這些bss段的變量的初值清零。

.constdata段是常量數據段。它用來存放常量(const)。它也是隻讀的。


符號表:對應於.symtab,它保存着目標文件中所有的符號信息 
字符串表:.strtab,保存字符竄信息。信息組織規則



對應符號信息:


6、重定位

上面列出的信息中,沒有包含重定位信息段,因爲test.o是一個簡單的目標文件,就定義了一個函數,所有沒有涉及重定位,其實在 絕大部門目標文件中,都存在這個重定位信息段。若一個目標文件引用了其他目標文件的符號,就會生成重定位信息段,方便在連接的 
時候進行。重定位項信息如下:


7、對於一個ELF文件,重定位過程可以簡單表示成下面過程