目標檔案裡面到底有什麼 2 ?

2021-07-23 08:47:59 字數 2926 閱讀 4010

真正了不起的程式設計師對自己的程式的每乙個位元組都瞭如指掌!

前面對於目標檔案只是做了概念上的闡述,如果不徹底深入目標檔案的具體細節,這樣的分析就是泛泛而談沒有意義,也沒有深入的理解。就象知道tcp/ip協議是基於包的結構,但是從來沒有看到過包的結構是什麼樣的(說得好像就是我),包的頭部有哪些內容?目標位址和源位址是怎樣存放的?如果不能細緻且深入的去了解,就會步入乙個誤區:很多問題其實在表面上看似很簡單,實際深入內部會發現很多鮮為人知的秘密,或者發現以前自己認為理所當然的東西居然是錯誤的!!!我需要做的,就是改變這個現狀!

/*

*******section.c

* *linux:

* gcc -c ******section.c

* *windows:

* cl ******section.c /c /za

*/int printf(const char* format, ...);

int global_init_var = 84;

int global_uninit_var;

void func1(int i)

int main(void)

利用gcc對原始檔進行編譯可以得到目標檔案:

$ gcc -c ******section.c
檢視目標檔案中的內容如下:

**段

將所有段的內容以十六進製制的形式列印,並對所有包含指令的段進行反彙編,得到以下結果:

「contents of section  .text」就是.text的資料以十六進製制方式列印出來的內容,總共0x5b位元組,跟前面我們了解到的".text"段中的長度相一致。最左面一列指的是偏移量,中間四列指的是十六進製制內容,最後一列是該段的ascii碼形式。

對照下面反彙編的結果,我們可以很明顯的看到,.text段裡所包含的正是******section.c裡面兩個函式func1()和main()函式的指令。

資料段與唯讀資料段

.data段儲存的是那些已經初始化了的全域性靜態變數或區域性靜態變數。前面的******section.c**中一共有兩個這樣變數,分別是global_init_var和static_var。這兩個變數每乙個都是4個位元組,總共八個位元組,所以「.data」這個段的大小為8個位元組。

「.rodata」中只存放唯讀資料。本例中存放的就是字串常量,剛好是4個位元組。單獨設立「.rodata」段有很多好處,不管是在語義上支援了c++的const關鍵字,而且作業系統自載入時可以將「.rodata」段的屬性對映為唯讀,這樣對於這個段的任何修改操作都會作為非法操作處理,大大保證了程式的安全性。

bss段

.bss段存放的是未初始化的全域性變數和區域性靜態變數。如示例**中,global_uninit_var和static_var就是被存放在.bss段,其實更準確的說法是,.bss段為他們預留了空間。

其他段

除了.data、.text、.bss這3個最常用的段之外,elf檔案也有可能包含其他的段,用來儲存與程式相關的其他資訊。具體如下表所示:

其實,通過上面的******section.o例項,我們已經基本了解到了elf檔案的輪廓,下面我們可以正式地看一下elf的檔案總體結構。如下圖所示:

elf目標檔案格式的最前部是elf檔案頭(file header),它包含了描述整個檔案的基本屬性,比如elf檔案版本、目標機器型號、程式入口位址等。緊接著是elf檔案各個段。其中,elf檔案中與段有關的重要結構就是段表(section header table),該錶描述了elf檔案中語段有關的所有段的資訊,比如每個段的段名、段的長度、在檔案中的偏移、讀寫許可權以及其他屬性。本處,僅想詳細討論一下符號表的作用,以為他和程式的鏈結有著很大的關聯。

連線的介面——符號

鏈結過程的本質就是要把多個不同的目標檔案之間相互關聯到一起。為了使不同目標檔案之間能夠在相互粘合,這些目標檔案之間必須有固定的規則才可以。在鏈結中,目標檔案之間相互拼接實際上是目標檔案位址間的相互引用,即對函式以及變數的位址進行引用。比如目標檔案b要用到目標檔案a中的函式「foo」,那麼我們就成目標檔案a定義了函式「foo」,稱目標檔案b引用了目標檔案a中的函式「foo」。在鏈結中,我們將函式以及變數都通稱為符號,函式名或者變數名就是符號名。

我們可以將符號看作是鏈結中的黏合劑,整個連線過程正是基於符號才能正常地完成。鏈結過程中很重要的一環就是符號的管理,每乙個目標檔案都會有乙個相應的符號表,這個表裡面記載著目標檔案中所有要用的到的符號,每乙個定義的符號有乙個對應的值,叫做符號值。對於變數以及函式而言,符號值就是他們的位址。除了函式和變數之外,也會存在其他幾種不常用的符號,如下面所示:

點git檔案到底有什麼

git commit editmsg 儲存最新的commit message config 倉庫的配置檔案 description 倉庫的描述資訊,主要給gitweb使用 head 指向當前分支 hooks 存放一些shell指令碼,可以設定特定的git命令後觸發相應的指令碼 index 二進位制暫...

介面到底有什麼用

我們定義乙個介面 public inte ce ibark 再定義乙個類,繼承於ibark,並且必需實現其中的bark 方法 public class dog ibark public void bark 然後,宣告dog的乙個例項,並呼叫bark 方法 dog 旺財 new dog 旺財.bark...

學歷到底有什麼用

每年都會有不少想考研又在猶豫的學弟學妹問我,考研有用嗎?我也跟不少高學歷的朋友聊過,這個 學歷 到底有什麼用。乙個有趣的現象是,一般上了研的,都喜歡自嘲說,學歷啊 名校啊什麼的,都是浮雲。或者大呼後悔,說想到又 浪費 了自己幾年的光陰,很是悔不當初。問起當年考研的原因,多半是興趣所致,或是覺得自己的...