揭開“目標文件”背後哪些不爲人知的祕密

1. 目標文件概念

     源代碼經過編譯器編譯之後所生成的文件便是目標文件(Windows下的.obj和Linux下的.o)。此時的目標文件還不能執行,因爲因爲還缺失鏈接、裝載等過程,其中某些符號或是地址還沒有被正確尋址調整。它是一種編譯之後的可執行文件格式,即按照可執行文件格式存儲,而在文件的整體結構上面有些差異。從廣義上來看,目標文件和可執行文件的格式其實是一樣的。因此,可以將目標文件和可執行文件看作是同種類型的文件。目標文件如圖1紅色虛線框所示。

在這裏插入圖片描述
                                圖1 可執行文件的創建過程

2. 目標文件格式

     x86平臺至少有四種常用的對象文件格式。這些是OMF,COFF也稱爲PE,ELF和Mach-O格式。a.out格式已經很少使用了。

2.1 OMF文件格式

     OMF代表對象模塊格式。這種格式也稱爲Microsoft 8086可重定位。OMF格式用於16位操作系統(DOS、Windows 3.x和早些時候)。一些編譯器(Borland、Watcom、Symantec、Digital Mars)也對32位Windows使用OMF格式。這種格式最初是爲16位8088微處理器的分段內存模型設計的,在第一臺IBM pc上使用。OMF格式允許地址相對於表示段或段組的任意參考幀的分辨率。參考幀從一個能被16整除的地址開始,可以跨越64千字節。參考幀允許重疊。支持覆蓋(即允許多段代碼共享相同的內存空間)。
     OMF對象文件由一系列記錄組成,其中每個記錄的第一個字節表示記錄中包含的數據類型。任何記錄都不能包含超過1千字節的數據。OMF格式在第一批IBM pc機出現時是爲緊湊而設計的,當時唯一的存儲方式是一個或兩個360 kbytes的軟盤驅動器。OMF格式允許使用幾種不同的方法來壓縮零字節或重複字節,不僅在二進制代碼和數據中如此,在重定位表中也是如此。重複塊可以嵌套到無限深度。這些壓縮特性使OMF文件的解釋變得複雜且容易出錯。壓縮重複重定位信息的方法已經很少使用了,如果曾經使用過的話。一些工具仍然使用數據段中的重複塊。microsoftassembler可以在重複數據中生成重定位,儘管這是不鼓勵的,也不是所有鏈接器都支持。
     OMF標準還指定了靜態庫的格式。OMF庫使用散列表列出庫中所有模塊的公共符號。其他格式使用簡單排序的列表,甚至是一個未排序的列表。使用哈希表要求所有鏈接器和庫管理器使用完全相同的哈希算法。不幸的是,哈希算法的官方定義並不像人們希望的那樣清晰和嚴格。使用哈希表而不是排序列表所獲得的效率提升是微乎其微的,在我看來,這不足以證明複雜性的顯著增加是合理的。

     除了散列表外,OMF庫還可以有一個可選的“擴展字典”。擴展字典指定模塊之間的依賴關係,以方便一次鏈接。擴展字典有兩種不同且不兼容的格式。原始的IBM/Microsoft格式和Borland使用的專有格式。擴展字典很少被使用。

Limitations(限制):
     段字大小:16或32位。可以混合使用。
     段對齊:僅支持1、2、4、16和256或4096。
     最大標識符長度:255個字符。
     最大外部符號:64k。
     最大節數:64 k。
     最大節大小:4 Gbytes。
     庫中的最大模塊數:< 64 k。

     一些舊的鏈接器將庫哈希表的大小限制爲251個塊,每個塊有37個bucket。根據名稱的長度,這將一個庫中的公共符號數量限制在251到9287之間。即使對於允許超過251個塊的鏈接器,哈希表中也存在一些不可預測的限制。

2.2 COFF文件格式

     COFF代表通用對象文件格式。這種格式最初在UNIX系統V中使用,但後來被ELF取代。在Windows中使用了對COFF格式的修改。COFF的Windows版本也稱爲PE(可移植可執行文件)。64位版本稱爲PE32+。相同的格式用於對象文件和可執行文件。windows下使用的COFF格式是微軟對某些其他平臺上使用的COFF格式的改編。
     COFF格式用於Microsoft、Intel和Gnu編譯器在32位和64位Windows中的對象文件。32位Windows的Codeplay編譯器可以使用OMF、COFF或ELF32格式。
     COFF格式使用許多不同的數據結構,這使得它有些複雜。數據結構的定義與現代編譯器的默認對齊規則不一致。
     由於CPU計算相對地址的方式,不同的對象文件格式在實現自相關引用的方式上有所不同。CPU計算相對於指令後的指令指針值的自相關地址,而不是相對於指令代碼中地址字段的位置。從地址字段(重定位源)的位置到CPU使用的參考點的距離是16位代碼中的2、32位代碼中的4和64位代碼中的4、5、6或8。COFF和OMF格式對於這些距離中的每一個都有不同的重定位碼,以便鏈接器可以插入必要的校正。ELF和Mach-O格式沒有對這種差異的固有識別,因此必須將校正作爲顯式加數插入到目標文件中。
     COFF格式允許指定與圖像相關的引用,這在其他平臺上是不可用的。圖像相關引用在32位模式下用於調試信息。32位圖像相關引用在64位模式下用於異常處理信息,通常用於節省空間,否則將需要64位指針。

Limitations(限制):
     段字大小:32或64位。
     最大分段數:32k。
     最大文件大小:4 Gbytes。
     最大節大小:4 Gbytes。
     每節最大移位:64 k。
     最大庫大小:4 Gbytes。
     

2.3 ELF文件格式

     ELF代表可執行和可鏈接的格式。這種格式已經取代了Linux和BSD中的舊格式,如a.out和COFF。運行在Linux和BSD下的Gnu工具通常接受其他幾種格式,不包括Windows下使用的格式。在Windows下運行的Gnu工具接受COFF和ELF格式。
     ELF格式的設計是靈活的和可擴展的。所有數據結構的大小都是顯式指定的,因此可以在不失去向後兼容性的情況下進行擴展。這使得ELF格式比其他格式更加清晰和健壯。

Limitations(限制):
     段字大小:32或64位。
     最大分段數:64 k
     最大文件大小:32位爲4 GB,64位爲264字節。
     最大節大小:32位爲4 GB,64位爲264字節。
     最大字符串表大小:4 GB。
     最大符號數:32位16m,64位4g。
     最大庫大小:4 GB。

2.4 Mach-o文件格式

     Mach-O代表Mach對象。這種格式在Mac操作系統和較舊的Mach操作系統中用於對象文件和可執行文件。以下描述僅適用於基於Intel的Mac OS X(Darwin)系統。
     Mach-O對象文件只有一個段記錄,它由幾個段記錄組成。Mach-O可執行文件有幾個段記錄。
     Mach-O格式允許在任意部分指定相對於任意參考點的地址。這種尋址方法用於與位置無關的代碼,它在其他目標文件格式中不可用。
     32位Mac OS X的Gnu編譯器默認使用獨立於位置的代碼和延遲綁定,這使得代碼執行效率降低。位置無關代碼僅適用於Mac OS X中的共享對象(動態鏈接庫)。
     本地符號僅在32位Mach-O文件中由其地址引用,其中COFF和ELF格式具有用於本地符號的符號表條目。

Limitations(限制):
     分段名稱長度:16個字符。
     最大文件大小:4 GB。
     最大節大小:位置索引爲16 M。代碼,4 GB表示32位,264字節表示64位。
     最大節數:16 M。
     最大符號數:16 M。
     最大庫大小:4 GB。

3. ELF文件格式分析

3.1 ELF文件格式概述

     ELF,即可執行與可鏈接格式 (英語:Executable and Linkable Format,縮寫爲ELF),常被稱爲ELF格式,在計算機科學中,是一種用於可執行文件、目標文件、共享庫和核心轉儲的標準文件格式。1999年,被86open項目選爲x86架構上的類Unix操作系統的二進制文件格式標準,用來取代COFF。ELF 的最大特點在於它有比較廣泛的適用性,通用的二進制接口定義使之可以平滑地移植到多種不同的操作環境上。這樣,不需要爲每一種操作系統都定義一套不同的接口,因此減少了軟件的重複編碼與編譯,加強了軟件的可移植性。ELF 文件格式規範由 TIS(Tool Interface Standards – 工具接口標準)委員會制定,TIS 委員會是一個微型計算機工業的聯合組織,它致力於爲 32 位操作系統下的開發工具提供標準化的軟件接口。這種接口包括目標標誌格式、可執行文件格式,以及調試信息的格式。

ELF文件類型 說明 實例
可重定位文件 這類文件包含了代碼和數據,可以被用來鏈接成可執行文件或目標文件,靜態鏈接庫可以歸納爲這一類 Linux下的.o文件;Windows下的.obj
可執行文件 這類文件包含了可以直接執行的程序,它的代碼是ELF可執行文件,一般都沒有擴展名 Linux下的/bin/bash文件;Windwos下的.exe文件
共享目標文件 這類文件包含了代碼和數據,動態鏈接器可以將幾個這種共享目標文件與可執行文件結合,作爲進程映像的一部分來運行 Linux下的.so;Windows下的.dll
核心轉存文件 當進程意外終止時候,系統可以將該進程的地址空間的內容及終止時的一些其他信息轉存儲到核心轉存文件 Linux下的core dump

                                圖2 採用ELF文件格式的文件列表
     備註:此圖來自書籍《程序員的自我修養》,P57的表3-1.

     ELF規範中把ELF文件統稱爲“目標文件(Object file)”,這與我們平時的理解上面有點不太相同。一般我們把通過編譯+彙編,但是沒有鏈接過程中所生成的文件(Linux上面爲.o,Windows下的.obj)稱爲目標文件;但是在ELF規範中,所有符合ELF格式規範的文件都統稱呼爲ELF文件,也稱呼爲目標文件。

3.2

     
     
     
     
     
     
     







5. 參考

1. 《程序員的自我修養》
2. 《嵌入式計算系統設計原理》
3. 《嵌入式操作系統預定義宏》
4. 《維基百科》
5. 《https://paper.seebug.org/papers/Archive/refs/elf/Understanding_ELF.pdf》

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