ELF基本結構

《程序員的自我修養——鏈接、裝載與庫》讀書筆記

        編譯器編譯源代碼後產生的文件叫做目標文件。它們經過鏈接後可以形成庫文件或者可執行文件。主流平臺的可執行文件格式主要有Windows下的PE(Portable Executable)和Linux下的ELF(Executable Linkable Format),他們都是COFF(Common File Format)的變種。ELF文件標準裏面把系統採用ELF格式的文件歸爲四類:可重定位文件(Relocatable File),可執行文件(Executable File),共享目標文件(Shared Object File)和核心轉儲文件(Core Dump File)。

1. 總體結構

        可重定位文件(如靜態鏈接庫,Linux的.o,Windows的.obj)包含了代碼和數據,可以被用來鏈接生成可執行文件或共享目標文件。可執行文件(如Linux的/bin/bash,Windows的.exe)包含了可以直接執行的程序。共享目標文件(如Linux的.so,Windows的.dll)包含了代碼和數據,鏈接器可以使用這種文件跟其他的可重定位文件和共享目標文件鏈接,產生新的目標文件;也可以將幾個這種共享目標文件與可執行文件結合,作爲進程映像的一部分來運行。當進程意外終止時,系統可以將該進程的地址空間的內容及終止時的一些其它信息轉儲到核心轉儲文件(Linux下的core dump)。

        目標文件中的信息按照屬性的不同,以節(Section)的形式存儲。一般一個ELF文件中包含了代碼節(.code或.text)、數據節(.data)、只讀數據節(.rodata)、未初始化數據節(.bss)、註釋信息節(.comment)和堆棧提示節(.note.GNU-stack)等。一個ELF文件的基本結構如下圖所示:


ELF結構
圖1 ELF結構

        位於文件最前部的是ELF文件頭(ELF Header),他描述了整個文件的基本屬性,包括節表(Section Table)在文件中的偏移。而節表中包含了所有節的信息,比如每個節的節名、節的長度、在文件中的偏移、讀寫權限及節的其它屬性。

2. .bss節

        對於程序中的數據來說,.rodata節中存放着只讀數據,如程序中的只讀變量和字符串常量,.data節中存儲着已初始化的全局變量和局部靜態變量,.bss節中存儲着未初始化的全局變量和局部靜態變量。由於未初始化的全局變量和局部靜態變量的默認值爲0,爲它們在.data節中分配空間並且存放數據0是沒有意義的,而在程序運行中它們的確要佔內存空間,所以可執行文件只是在節表中記錄了它們的大小,爲它們預留了位置,記爲.bss節。它並沒有內容,在文件中也不佔據空間。(BSS原是彙編器FAP的僞指令,用於定義符號並且爲該符號預留給定數量的未初始化空間。)值得注意的是,有些編譯器會將未初始化全局變量存放在目標文件的.bss節,有些則不存放,只是預留一個未定義的全局符號,等到最終鏈接成可執行文件時再在.bss節分配空間,這又和程序的鏈接過程有關。

3. 字符串表

        ELF文件中用到了許多字符串,比如段名、變量名。由於它們的長度不定,難以用固定的結構表示,常見做法是把它們集中起來存放到一個表,然後用它們在表中的偏移來引用它們。如,.strtab節爲字符串表(String Table),用來保存普通的字符串,.shstrtab節爲節表字符串表(Section Header String Table),用來保存節表中用到的字符串,比如節名。

4. 符號表

        在鏈接中,函數和變量被統稱爲符號(Symbol),函數名或變量名就是符號名(Symbol Name)。每個目標文件都會有一個符號表(Symbol Table),這個表裏面記錄了目標文件中所用到的所有符號。每個定義的符號有一個對應的值,叫符號值(Symbol Value),對於函數和變量來說,符號值就是它們的地址。符號表中的符號可以分爲一下幾類:

  • 定義在本目標文件中的全局符號
  • 本目標文件中引用的,沒有定義在本目標文件中全局符號,這一般叫做外部符號(External Symbol)
  • 節名,它的值就是該節的起始地址
  • 局部符號,這類符號只在編譯單元內部可見,這些符號對於鏈接過程沒有作用
  • 行號信息,即目標文件指令與源代碼中代碼行的對應關係

5. 重定位表

        鏈接器在處理目標文件時,需要對目標文件中代碼節和數據節中,那些對絕對位置的引用的位置進行重定位。這些重定位信息都記錄在ELF文件的重定位表(Relocation Table)中,對於每一個需要重定位的代碼節或者數據節,都有一個相應的重定位表。

6. 總結

        這裏描述的只是ELF文件的基本結構,當考慮到靜態鏈接,動態鏈接和裝載的過程時,還需要涉及到很多內容,暫且不表。

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