《程式設計師的自我修養》第三章學習筆記

2021-09-20 01:20:57 字數 4737 閱讀 5183

1,

編譯器編譯源**生成的檔案叫做目標檔案。

從結構上說,是編譯後的可執行檔案,只不過還沒有經過鏈結

3.1目標檔案的格式

1,可執行檔案的格式:windows下的pe  和linux下的elf

2,從廣義上說,目標檔案與可執行檔案的格式幾乎是一樣的,所以廣義上可以將目標檔案與可執行檔案看成是一種型別的檔案。

3,可執行檔案,動態鏈結庫,靜態鏈結庫都按照可執行檔案格式儲存(windows下是pe-coff格式,linux下是elf格式)。

4,linux下命令:$: file   ***   顯示出對應檔案的型別

目標檔案是什麼樣的

1,目標檔案包含的內容:編譯後的機器指令**、資料,還有鏈結時要的一些資訊(比如符號表、除錯資訊、字串等)。

1,  一般目標檔案把上述資訊按不同的屬性,以節(section)的形式儲存。有時也叫段(segment)

2,  **段常見的名字有「.code」  「.text」,編譯後的機器指令就放在**段,

資料段:一般名字都是「.data」,已初始化全域性變數和區域性靜態變數資料放這

3,elf檔案的開頭是乙個」檔案頭」,它描述了整個檔案的檔案屬性(是否可讀可寫可執行,是靜態鏈結還是動態鏈結及入口位址)、目標硬體、目標作業系統等資訊。

4,  檔案頭還有乙個段表(section table)。描述檔案各個段的陣列(各個段在檔案中的偏移和屬性)。

5,  關於bss段:未初始化的全域性變數和靜態區域性變數一般放在乙個」.bss」段的地方。

它只是為未初始化的全域性變數和靜態區域性變數預留位置而已,並沒有內容,在檔案中不佔空間。

6,  總體來說:程式源**被編譯後主要分成兩種段:程式指令(**段),程式資料(資料段,bss段)。

3.3挖掘******section.o

1,objdump 檢視各種目標檔案的結構和內容,objdump –h main.o  -h 表示把elf檔案的各個段的基本資訊打出來

readelf 專門針對elf檔案格式的解析器

size 可以用來檢視elf檔案的**段、資料段和bss段的長度size main.o

3.3.1**段

1,objdump 的引數–s 將所有的段的內容以十六進製制的方式列印出來

-d 將所有包含指令的段反彙編比如objdump  –s  –d  main.o

-h 把關鍵的段顯示了出來,忽略了輔助性段

3.3.2資料段和唯讀資料段

1,「.data」 :儲存的是已初始化全域性變數和區域性靜態變數

2,,」rodata」:存放的是唯讀資料,一般是程式中的唯讀變數(如用const修飾的)和字串常量。

3.3.3 bss段

1,存放的是未初始化的全域性變數和靜態區域性變數。不佔磁碟空間

3.3.4 其他段

還可以自定義段gcc提供的擴充套件機制

3.4 elf檔案結構描述

3.4.1 檔案頭

1,檢視readelf –h main.o

2,elf檔案中定義了:elf魔數、檔案機器位元組長度、資料儲存方式、版本、執行平台、abi版本、

elf重定位型別、硬體平台、硬體平台版本、入口位址、程式頭入口和長度、段表的位置和長度及段的數量等。

3,elf魔數:檔案頭最開始的4個位元組是所有elf都必須相同的標識碼。又稱為魔數。

魔數用來確認檔案型別,作業系統在載入可執行檔案的時候會確認魔數是否正確,若不正確則拒絕載入。

4,elf檔案型別:分為可重定位、可執行、共享目標檔案、核心轉儲檔案

3.4.2 段表(除了檔案頭以外最重要的結構)

1,描述了elf各個段的資訊(比如每個段的段名、段的長度、在檔案中的偏移,讀寫許可權及其他屬性)。

2,編譯器、鏈結器和裝載器都是靠段表來定位和訪問各個段的屬性的。

3,readelf –s main.o 顯示真正的段表結構

4,上述結果是乙個以「elf32_shdr」 結構體為元素的陣列。

3.4.3 重定位表

1,乙個叫」rel.text」的段,型別是」sht_rel」,就是重定位表

2,鏈結器在處理目標檔案時,需要對目標檔案中的某些部位進行重定位(即**段和資料段中那些對絕對位址的引用的位置)。

3,這些重定位資訊都記錄在elf檔案的重定位表裡。對於每個需要重定位的**段或資料段,都會有乙個相應的重定位表。

3.4.3 字串表

1,把elf檔案中用到的字串(段名、變數名等)集中起來存放到乙個表中。然後使用字串在表中的偏移來引用字串。這個表就是字串表。

2,一般字串表在elf檔案中也以段的形式儲存。常見的段名有」.strtab」,」.shstrtab」

3,」.strtab」:字串表:儲存普通的字串

4,」.shstrtab」:段表字串表:儲存段表中用到的字串,最常見的就是段名。

3.5鏈結的介面——符號

1,鏈結過程的本質就是要把多個不同的目標檔案之間相互粘滯到一起。

2,為了使不同目標檔案之間能夠相互粘合,這寫目標檔案必須要有固定的規則才行。

4,在鏈結中,我們將函式和變數統稱為符號(symbol),函式名或變數名就是符號名(symbol name)。

5,每乙個目標檔案都會有乙個相應的符號表(symbol table),記錄著目標檔案中所用到的所有的符號。

6,每個定義的符號有乙個對應的值叫做符號值(symbol value)。對於變數或函式來說,符號值就是它們的位址。

8,  符號的分類:(1)和(2)比較需要關注

(1)       定義在本目標檔案的全域性符號,可被其他目標檔案引用。

(2)       在本目標檔案中引用的全域性符號,在別的目標檔案中定義。一般叫做外部符號(external symbol)。

(3)       段名,這種符號往往由編譯器產生,它的值就是該段的起始位址。

(4)       區域性符號,這類符號只在編譯單元內部可見,

(5)       行號資訊,即目標檔案指令與源**中**行的對應關係,是可選的。

3.5.1 elf符號表結構

1,elf檔案中的符號表往往是檔案中的乙個段,y一般叫做「.symtab」。是乙個elf32_sym的陣列,陣列中每個元素對應乙個符號。

2,結構體定義如下

3.5.2 特殊符號

1,ld鏈結器產生可執行檔案時,會給我們定義很多符號(沒有在自己的程式中定義),但是可以直接宣告並且引用它,我們稱之為特殊符號。

3.5.3 符號修飾與函式簽名

1,c++增加了命名空間(namespace)的方法來解決多模組之間的符號衝突問題。

2,c++符號修飾

(1)       函式簽名:包含了乙個函式的資訊(函式名、引數型別、所在的類和命名空間和其他資訊)。函式簽名用於識別不同的函式。

3.5.4 extern」c」

1,c++為了與c相容,在符號的管理上,c++有乙個用來宣告或定義乙個c的符號extern」c」的關鍵字用法。

2,可以讓c++的名稱修飾機制不作用。

3.5.5 弱符號與強符號

1,多個目標檔案含有相同名字的全域性符號的定義,在鏈結時將會出現符號重複定義的錯誤。

2,編譯器預設函式和初始化了的全域性變數為強符號,未初始化的全域性變數為弱符號。

3,強弱符號都是針對定義來說的,不是針對符號的引用。假如extern int ext; ext不是強符號也不是弱符號,因為它是乙個外部變數的引用。

4,鏈結器按下面規則處理與選擇被多次定義的全域性符號。

(1)       不允許強符號被多次定義,否則報錯。

(2)       若乙個符號在某個目標檔案中是強符號,在其他檔案中都是弱符號,那麼選擇強符號。

(3)       若乙個符號早所有的目標檔案中都是若符號,那麼選擇其中占用空間最大的那乙個。

5,弱引用與強引用:

弱引用:假如鏈結時沒找到該符號的定義,鏈結器不會報錯,預設其為0或是乙個特殊值。

6,gcc中可以通過「__attribute__((weakref))」這個擴充套件關鍵字來宣告乙個外部函式為弱引用p93

用法:__attribute__((weakref)) void foo();  這樣就說明foo為弱符號。

7,弱符號和弱引用對庫來說非常有用,比如庫中定義的弱符號可以被使用者定義的強符號所覆蓋。

8,補充:linux中支援多執行緒時需要在編譯時加上–lpthread 選項,比如gcc test.c -lpthread

3.6除錯資訊

1,在gcc編譯時加上–g 引數就會在產生的目標檔案裡面加上除錯資訊。目標檔案會多些debug段。

2,假設有個目標檔案test,linux下可以用」strip」 命令來去除除錯資訊,用法:$ strip test

3.7本章小結

參考《程式設計師的自我修養》

elf檔案分析 程式設計師的自我修養第三章學習

今天學習程式設計師的自我修養第三章學習對其中的一些內容提取。elf檔案 linux 作業系統二進位制檔案統一管理的格式檔案,對其分析對於理解編譯和鏈結 整合大型系統,修復 bug很有幫助。源程式都會通過編譯 鏈結成可執行檔案,可執行檔案的elf 檔案格式是固定,下面看如下圖 這個就是c語言 與 el...

程式設計師的自我修養第三章筆記(目標檔案有什麼)

目標檔案主要分為檔案頭 段 資料段 bss 段等等。objdump 工具可以分析目標檔案,包括 d 反彙編 s 顯示為16進製制的形式等等。一般情況下 會被放到 text 段,而全域性變數和靜態變數會被放到 data 和 bss 段。readelf 可以檢視 elf 檔案的檔案頭。elf檔案的結構可...

程式設計師的自我修養筆記三

目標檔案裡有什麼 3.1目標檔案的格式 windows中動態鏈結庫.dll linux中是.so windows中靜態鏈結庫.lib linux中是.a 可執行檔案在windows下按照pe coff格式儲存,linux下按照elf格式儲存 elf檔案分類 3.2目標檔案是什麼樣的 目標檔案中不僅有...