2010-06-15 204 views
42

在C或C++編譯的各個階段,我知道生成了一個目標文件(即any_name.o文件)。這個.o文件中包含什麼?我無法打開它,因爲它是一個二進制文件。目標文件包含什麼內容?

有人能幫我嗎?目標文件的內容主要依賴於我們在Unix上使用的編譯器嗎?

+1

有一大堆* nix工具用於查看目標文件內部:以nm開頭,http://unixhelp.ed.ac.uk/CGI/man-cgi?nm – 2010-06-15 13:48:25

回答

45

對象文件可以包含一堆東西:基本上它的部分或全部下表中:

  • 符號名
  • 編譯代碼
  • 恆定的數據,例如。字符串
  • 導入 - 編譯代碼引用的哪些符號(通過鏈接器得到修復)
  • 導出 - 目標文件可用於OTHER對象文件的哪些符號。

鏈接器通過匹配所有導入和導出,修改編譯後的代碼,將一堆目標文件轉換爲可執行文件,以便調用正確的函數。

3

對於這樣的事情使用file命令。這是一個在現代Linux系統上的ELF目標文件。例如。如果編譯爲32位x86。

ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped 

相反,動態鏈接的可執行文件看起來像:

ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped 

要查看標題,包括部分的名稱,你可以使用:

objdump -x any_name.o 

要拆卸:

objdump -d any_name.o 
3

對象文件是編譯後的源文件。

這意味着它是機器代碼,它依賴於目標平臺(如果您真的想在Windows上編譯Unix的話)以及使用的編譯器。不同的編譯器會從同一個源文件中產生不同的機器碼。

1

該文件包含必須通過linker運行,以生成可執行的二進制數據。它本質上是一堆帶有命名部分的機器代碼指令(與您的功能相對應)。維基百科的「Object File」的文章:

在計算機科學中,目標文件是 的機器 代碼分離, 命名序列的有組織的收集[來源請求]。每個序列, 或對象,通常包含 指令主機到 完成一些任務,可能是 伴隨着相關的數據和 元數據(例如重定位 信息,棧展開 信息,評論,節目 符號,調試或分析 信息)。鏈接器通常是 ,用於通過組合對象 文件的部分來生成可執行文件或 庫。

7

有幾種標準格式(Unix上的COFF,ELF),基本上它們是用於可執行文件但缺少某些信息的相同格式的變體。這些缺少的信息將在鏈接時完成。

對象的文件格式基本上包含相同的信息:

  • 所得編譯的二進制代碼(對目標處理器)
  • 通過的那部分程序使用的靜態數據(如恆定字符串等)。您可以更好地區分BSS(導出數據)和文本(不會被程序修改的數據)。但是這對於編譯器和鏈接器來說非常重要。請注意,與二進制代碼一樣,數據也依賴於目標(大端,小端,32位,64位)。由程序的這部分導出的符號的
  • 表(主要是功能入口點)由程序

當對象將被鏈接的代碼的部分組合在一起的這部分使用的外部碼元的

  • 表指的是外部符號將被實際值取代(當然,這仍然過於簡化,在運行程序時加載時會完成最後一部分,但這就是想法)。

    目標文件還可能包含更多符號信息,這些信息對於解析導入和導出(對調試有用)是嚴格必需的。該信息可以使用strip命令刪除。

  • 1

    在GNU編譯環境中,您可以使用objdump在可執行文件和目標文件中查看。

    正如您所看到的,該對象只包含編譯文件中聲明/引用的函數的代碼(該文件僅包含帶有scanf調用和printf調用的主函數)。

    $ objdump -t scanf_sample.o 
    
    scanf_sample.o:  file format pe-i386 
    
    SYMBOL TABLE: 
    [ 0](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x00000000 scanf_sample.c 
    File 
    [ 2](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _main 
    [ 3](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .text 
    AUX scnlen 0x91 nreloc 9 nlnno 0 
    [ 5](sec 2)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .data 
    AUX scnlen 0x0 nreloc 0 nlnno 0 
    [ 7](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .bss 
    AUX scnlen 0x0 nreloc 0 nlnno 0 
    [ 9](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .rdata 
    AUX scnlen 0x54 nreloc 0 nlnno 0 
    [ 11](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x00000000 ___main 
    AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0 
    [ 13](sec 0)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __alloca 
    [ 14](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _memset 
    [ 15](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _scanf 
    [ 16](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _printf 
    

    如果你在一個可執行使用objdump的,你可以看到很多更功能(除了那些對象內部發現的)。這證明目標文件只包含源文件中定義的函數並引用其他函數。這些引用將在鏈接階段解決。

    閱讀更多關於linkingcompilationobjects

    +0

    我在Windows下使用了MinGW for the上面的示例 - 它在* nix下工作相同 – INS 2010-06-15 14:11:32

    3

    首先,二進制文件可以打開!不要害怕它,你只需要正確的工具!作爲二進制數據,文本編輯器當然不是正確的工具;一個正確的工具可能是一個十六進制編輯器,或者像emacs這樣的高級編輯器,或者是一種工具,它不是簡單地以其「十六進制」表示方式「輸出」字節,而是讓您獨自解釋數據,知道特定的格式和「在某種程度上解釋「數據」(例如,GIMP將PNG文件解釋爲圖像並顯示它,PNG分析器將「分解」PNG部分內的數據,顯示特定字節中的標誌,等等)。

    就你而言,一般的答案是,目標文件包含你的編譯代碼(和數據),加上鍊接器所需的所有額外信息,最終還有更多。

    這些信息如何「組織」,在某些情況下「最終更多」是什麼,它取決於具體的對象格式。一些上市的可能性,一些維基百科鏈接thisthisthisthis ...

    每一種可能的工具來分析的內容;例如readelf爲ELF,objdump爲幾種格式(嘗試objdump -i)取決於它如何編譯。

    相關問題