目標檔案格式

2021-10-06 03:05:37 字數 1731 閱讀 1796

在linux 0.12 系統中, gnu gcc 或gas 編譯輸出的目標模組檔案和鏈結程式生成的可執行檔案都使用了unix傳統的a.out格式。這是一種被稱為彙編與鏈結輸出(assembly & linker editor output) 的目標檔案格式。對於具有記憶體分頁機制的系統來說,這是一種簡單有效的目標檔案格式。a.out 格式檔案由乙個檔案頭和隨後的**區(text section, 也稱為正文段)已初始化資料區(data section, 也稱為資料段),重定位資訊區。符號表以及符號名字串構成,

a.out 格式7個區的基本定義和用途是:

執行頭部分(exec header). 執行檔案頭部分。該部分中含有一些引數(exec 結構), 是有關目標檔案的整體結構資訊。例如**和資料區的長度,未初始化資料區的長度。對應源程式檔名以及目標檔案建立時間等。核心使用這些引數把執行檔案載入到記憶體中並執行,而鏈結程式使用這些引數將一些模組檔案組合成乙個可執行檔案。這是目標檔案唯一必要的組成部分。

**區(text segment). 由編譯器或彙編器生成的二進位制指令**和資料資訊,這部分含有已經初始化過的資料,總是被載入到可讀完蛋的記憶體中。

**重定位部分(text relocation). 這部分含有供鏈結程式使用的記錄資料。在組合目標檔案時用於定位**段中的指標或位址。當鏈結程式需要改變目標**的位址時,就需要修正和維護這些地方。

資料重定位部分(symbol table). 這部分同樣含有供鏈結程式使用的記錄資料。這些記錄資料儲存著模組檔案中定義的全域性符號以及霜從其他模組檔案中輸入的符號,或者由鏈結器定義的符號,用於在模組檔案之間對命名的變數和函式時行交叉引用。

字串表部分(string table).該部分含有與符號名相對應的字串, 供除錯程式除錯目標**,與鏈結過程無關。這些資訊可包含源程式**和行號,區域性符號以及資料描述資訊等。

對於乙個指定的目標檔案並非一定會包含所有以上資訊。下面對其中幾個重要的區域或部分進行說明。

1 執行頭部分

目標檔案的檔案頭含有乙個長度為32b 的exec 資料結構,通常稱為檔案頭結構或執行頭結構。其定義如下所示。有關a.out結構的詳細資訊請參見include/a.out.h 檔案後的介紹。

struct exec
根據a.out 檔案中頭部結構magic 數字段的值,可以把a.out格式的檔案分成幾種型別。對於執行檔案,使用了zmagic 型別的a.out 格式,它指明檔案為需求分頁處理(demand-paging), 即需求載入load on demand) 的可執行檔案。其魔數是0x10b.  主要區別在於它們對各個部分儲存分配方式上。雖然該結構的總長度只有32b, 但是對於乙個zmagic 型別的執行檔案來說,其檔案開始部分卻需要專門留出1kb的空間給頭結構使用。除被頭結構占用的32b以外,其餘部分均為0. 從1024位元組之後才開始放置程式的正文段和資料段等資訊。而對於乙個omagic型別的.o 模組檔案來說,檔案開始部分的32位元組頭結構後面緊接著就執行區和資料區。

執行頭結構中的a_text和a_data欄位分別指明後面唯讀的**段和可讀資料段的位元組長度。a_bss 字段指明核心在載入目標檔案時資料段後面未初化資料區域(bss段)的長度。由於linux 在分配記憶體時會自動對記憶體對齊清零,因此bss段不需要被包括在模組檔案或執行檔案中。

a_entry欄位指定了程式從**開始執行的位址,而a_syms, a_trsize 和a_drsize 欄位則分別說明資料段後符號表,**和資料段重定位資訊的大小。對於可執行檔案來說並不需要符號表和定位資訊。因此除非鏈結程式為了除錯目的而包括了符號資訊,執行檔案中的這幾個字段通常為0.

目標檔案格式

unix 最早的可執行檔案格式為a.out格式,它的設計非常的簡單,以至於後來共享庫這個概念出現的時候,a.out格式就變得捉襟見肘 於是人們設計了coff格式來解決這個問題,coff是由unix system v release 3首先提出並使用的格式規範,後來微軟公司基於coff格式,制定了pe...

目標檔案格式

程式從原始碼編譯為目標 的時候,這個目標檔案的格式是怎麼樣的?elf目標檔案有 段,資料段和bss段。elf目標檔案的標頭檔案,段表,重定位表,字串表,符號表,除錯表。無論是可執行檔案,目標檔案或庫,它們實際上都是一樣基於段的檔案或是基於這種檔案的集合。程式的源 經過編譯後,按照 和資料分別存放到相...

Linux鏈結 目標檔案格式

將各種 段和資料段收集組合成為乙個單一檔案的過程。鏈結器的出現使得構建大型軟體系統成為可能,因為它使得各個模組可以單獨完成編譯。當需要改進模組時,單獨的修改相應的模組並編譯,通過鏈結器重新鏈結生成新版本的軟體系統。sum.cpp中定義乙個函式int sum int a,int b main.cpp中...