COFF 格式比 a.out 格式要復(fù)雜一些,最重要的是包含一個(gè)節(jié)段表(section table),因此除了 .text,.data,和 .bss 區(qū)段以外,還可以包含其它的區(qū)段。另外也多了一個(gè)可選的頭部,不同的操作系統(tǒng)可一對(duì)此頭部做特定的定義。
COFF 文件格式如下:
File Header(文件頭部) |
文件頭部的數(shù)據(jù)結(jié)構(gòu):
struct filehdr |
COFF 文件頭部中魔數(shù)與其它兩種格式的意義不太一樣,它是表示針對(duì)的機(jī)器類型,例如 0x014c 相對(duì)于 I386 平臺(tái),而 0x268 相對(duì)于 Motorola 68000系列等。當(dāng) COFF 文件為可執(zhí)行文件時(shí),字段 f_flags 的值為 F_EXEC(0X00002),同時(shí)也表示此文件沒(méi)有未解析的符號(hào),換句話說(shuō),也就是重定位在連接時(shí)就已經(jīng)完成。由此也可以看出,原始的 COFF 格式不支持動(dòng)態(tài)連接。為了解決這個(gè)問(wèn)題以及增加一些新的特性,一些操作系統(tǒng)對(duì) COFF 格式進(jìn)行了擴(kuò)展。Microsoft 設(shè)計(jì)了名為 PE(Portable Executable)的文件格式,主要擴(kuò)展是在 COFF 文件頭部之上增加了一些專用頭部,具體細(xì)節(jié)請(qǐng)參閱參考資料 18,某些 UNIX 系統(tǒng)也對(duì) COFF 格式進(jìn)行了擴(kuò)展,如 XCOFF(extended common object file format)格式,支持動(dòng)態(tài)連接,請(qǐng)參閱參考資料 5。
緊接文件頭部的是可選頭部,COFF 文件格式規(guī)范中規(guī)定可選頭部的長(zhǎng)度可以為 0,但在 LINUX 系統(tǒng)下可選頭部是必須存在的。下面是 LINUX 下可選頭部的數(shù)據(jù)結(jié)構(gòu):
typedef struct |
字段 magic 為 0413 時(shí)表示 COFF 文件是可執(zhí)行的,注意到可選頭部中顯式定義了程序進(jìn)入點(diǎn),標(biāo)準(zhǔn)的 COFF 文件沒(méi)有明確的定義程序進(jìn)入點(diǎn)的值,通常是從 .text 節(jié)開(kāi)始執(zhí)行,但這種設(shè)計(jì)并不好。
前面我們提到,COFF 格式比 a.out 格式多了一個(gè)節(jié)段表,一個(gè)節(jié)頭條目描述一個(gè)節(jié)數(shù)據(jù)的細(xì)節(jié),因此 COFF 格式能包含更多的節(jié),或者說(shuō)可以根據(jù)實(shí)際需要,增加特定的節(jié),具體表現(xiàn)在 COFF 格式本身的定義以及稍早提及的 COFF 格式擴(kuò)展。我個(gè)人認(rèn)為,節(jié)段表的出現(xiàn)可能是 COFF 格式相對(duì) a.out 格式最大的進(jìn)步。下面我們將簡(jiǎn)單描述 COFF 文件中節(jié)的數(shù)據(jù)結(jié)構(gòu),因?yàn)楣?jié)的意義更多體現(xiàn)在程序的編譯和連接上,所以本文不對(duì)其做更多的描述。此外,ELF 格式和 COFF格式對(duì)節(jié)的定義非常相似,在隨后的 ELF 格式分析中,我們將省略相關(guān)討論。
struct COFF_scnhdr |
有一點(diǎn)需要注意:LINUX系統(tǒng)中頭文件coff.h中對(duì)字段s_paddr的注釋是"physical address",但似乎應(yīng)該理解為"節(jié)被加載到內(nèi)存中所占用的空間長(zhǎng)度"。字段s_flags標(biāo)記該節(jié)的類型,如文本段、數(shù)據(jù)段、BSS段等。在 COFF的節(jié)中也出現(xiàn)了行信息,行信息描述了二進(jìn)制代碼與源代碼的行號(hào)之間的對(duì)映關(guān)系,在調(diào)試時(shí)很有用。
ELF文件格式分析
ELF 文件有三種類型:可重定位文件:也就是通常稱的目標(biāo)文件,后綴為.o。共享文件:也就是通常稱的庫(kù)文件,后綴為.so。可執(zhí)行文件:本文主要討論的文件格式,總的來(lái)說(shuō),可執(zhí)行文件的格式與上述兩種文件的格式之間的區(qū)別主要在于觀察的角度不同:一種稱為連接視圖(Linking View),一種稱為執(zhí)行視圖(Execution View)。
首先看看ELF文件的總體布局:
ELF header(ELF頭部) |