計(jì)算機(jī)工作原理(二)目標(biāo)文件

一笋妥、簡介

編譯器編譯源代碼后生成的文件叫目標(biāo)文件(Linux下.o或Windows下.obj)挖垛,從結(jié)構(gòu)上講,它是已經(jīng)編譯后的可執(zhí)行文件格式痴昧,只是還沒有經(jīng)過鏈接的過程,其中可能有些符號(hào)或有些地址還沒有被調(diào)整冠王。其實(shí)它本身就是按照可執(zhí)行文件格式存儲(chǔ)的赶撰,只是跟真正的可執(zhí)行文件在結(jié)構(gòu)上稍有不同。

二柱彻、目標(biāo)文件是什么樣的

目標(biāo)文件中的內(nèi)容至少有編譯后的機(jī)器指令代碼豪娜、數(shù)據(jù),除了這些數(shù)據(jù)以外哟楷,還包括了鏈接時(shí)所需要的一些信息瘤载,比如符號(hào)表、調(diào)試信息卖擅、字符串等鸣奔。

一般目標(biāo)文件將這些信息按不同的屬性,以“節(jié)”的形式存儲(chǔ)惩阶,有時(shí)候也叫“段”挎狸,在一般情況下,他們都表示一個(gè)一定長度的區(qū)域断楷。

程序源代碼被編譯后的機(jī)器指令經(jīng)常被放在代碼段(Code Section)里锨匆,代碼段常見的名字有.code.text

全局變量和局部靜態(tài)變量數(shù)據(jù)經(jīng)常放在數(shù)據(jù)段(Data Section)冬筒,數(shù)據(jù)段的名字一般都叫.data恐锣。

File Header
.text section
.data section
.bss section

對(duì)照上面的表格來看,一般C語言的編譯后執(zhí)行語句都編譯成機(jī)器代碼舞痰,保存在.text段土榴。

已初始化的全局變量和局部靜態(tài)變量都保存在.data段。

未初始化的全局變量和局部靜態(tài)變量都保存在.bss段匀奏。

我們知道未初始化的全局變量和局部靜態(tài)變量默認(rèn)值都為0鞭衩,本來他們也可以被在.data段的,但是因?yàn)樗鼈兌际?娃善,示意圖為它們?cè)?code>.data段分配空間并且存放數(shù)據(jù)0是沒有必要的论衍。程序運(yùn)行的時(shí)候它們的確是要占內(nèi)存空間的,并且可執(zhí)行文件必須記錄所有未初始化的全局變量和局部靜態(tài)變量的大小綜合聚磺,記為.bss段坯台,所以.bss段只是為未初始化的全局變量和局部靜態(tài)變量預(yù)留位置而已,它并沒有內(nèi)容瘫寝,所以它在文件中也不占據(jù)空間蜒蕾。

總體來說,程序源代碼被編譯以后主要分成兩種段:程序指令和程序數(shù)據(jù)焕阿,代碼段屬于程序指令咪啡,而數(shù)據(jù)段和.bss段屬于程序數(shù)據(jù)。

為什么要將數(shù)據(jù)和指令的存放分開暮屡?

1.當(dāng)程序被裝載后撤摸,數(shù)據(jù)和指令分別被映射到兩個(gè)虛存區(qū)域,由于數(shù)據(jù)區(qū)對(duì)于進(jìn)程來說是可讀寫的褒纲,而指令區(qū)域?qū)τ谶M(jìn)程來說是只讀的准夷,所以這兩個(gè)虛存區(qū)域的權(quán)限可以被分別設(shè)置成可讀寫和只讀,這樣可以防止程序的指令被有意或無意的改寫莺掠。

2.另外一方面對(duì)于現(xiàn)代CPU來說衫嵌,他們有著極為強(qiáng)大的緩存(Cache)體系,由于緩存在現(xiàn)代的計(jì)算機(jī)中地位非常重要彻秆,所以程序必須盡量提高緩存的命中率楔绞。指令區(qū)和數(shù)據(jù)區(qū)的分離有利于提高程序的局部性。

3.第3個(gè)原因是最重要的原因唇兑,就是當(dāng)系統(tǒng)中運(yùn)行著多個(gè)該程序的副本時(shí)墓律,它們的指令都是一樣的,所以內(nèi)存中只須要保存一份改程序的指令部分幔亥,對(duì)于指令這種只讀的區(qū)域是這樣耻讽,對(duì)于其他的只讀數(shù)據(jù)也一樣,比如很多程序里面帶有的圖標(biāo)帕棉、圖片针肥、文本等資源也是屬于可以共享的,這樣就可以節(jié)省大量內(nèi)存香伴。

3慰枕、深入目標(biāo)文件的具體細(xì)節(jié)

下面列舉一個(gè)簡單的C語言demo(SimpleSection.c)作為分析對(duì)象:


int printf(const char *format);
int global_init_var = 84;
int global_uninit_var;

void func1(int i){
    printf("%d\n", i);
}

int main(void){
    static int static_var = 85;
    static int static_var2;
    int a = 1;
    int b;
    
    func1(static_var + static_var2 + a + b);
    
    return a;
}

使用GCC來編譯這個(gè)文件:

$ gcc -c SimpleSection.c

使用binutilsodjdump工具查看object內(nèi)部的結(jié)構(gòu):

$ objdump -h SimpleSection.o

會(huì)得到如下幾個(gè)段的信息:

0 .text
1 .data
2 .bss
3 .rodata
4 .comment
5 .note.GNU-stack

逐個(gè)來看著幾個(gè)段,看看他們包含了什么內(nèi)容即纲。

(1)代碼段

包含的是func1()main()的指令具帮。

(2)數(shù)據(jù)段和只讀數(shù)據(jù)段

.data段保存的是那些已經(jīng)初始化了的全局靜態(tài)變量和局部靜態(tài)變量,分別是global_init_varstatic_var

.rodata存放的是只讀數(shù)據(jù)蜂厅,不光在語義上支持C++const關(guān)鍵字匪凡,而且操作系統(tǒng)在加載的時(shí)候可以將.rodata段的屬性映射成只讀,這樣對(duì)于這個(gè)段的任何修改操作都會(huì)作為非法操作處理掘猿。保證了程序的安全性病游。

(3)BSS段

.bss段存放的是未初始化的全局變量和局部靜態(tài)變量,上述代碼中只有static_var2被存放在了.bss段稠通,而global_uninit_var卻沒有被存放在任何段衬衬,只是一個(gè)未定義的COMMON符號(hào)。這其實(shí)跟不同的語言與不同的編譯器實(shí)現(xiàn)有關(guān)改橘,有些編譯器會(huì)將全局的未初始化變量存放在目標(biāo)文件的.bss段滋尉,有些則不存放,只是預(yù)留一個(gè)未定義的全局變量符號(hào)飞主,等到最終鏈接成可執(zhí)行文件的時(shí)候再在.bss段分配空間兼砖。

(4)其他段

常用的段名 說明
.rodata1 存放只讀數(shù)據(jù),比如字符串常量、全局const變量
.comment 存放的是編譯器版本信息
.debug 調(diào)試信息
.dynamic 動(dòng)態(tài)鏈接信息
.hash 符號(hào)哈希表
.line 調(diào)試時(shí)的行號(hào)表
.note 額外的編譯器信息
.strtab 字符串表,用于存儲(chǔ)ELF文件中用到的各種字符串
自定義段

正常情況下官辽,GCC編譯出來的目標(biāo)文件中纳账,代碼會(huì)被放到.text段中,全局變量和靜態(tài)變量會(huì)被放到.data.bss段,有時(shí)候我們希望變量或某些代碼能夠放到你所指定的段中去,GCC提供了一個(gè)擴(kuò)展機(jī)制,使得程序員可以指定變量所處的段:

__attribute__((section("Foo"))) int glbal = 42;
__attribute__((section("BAR"))) void foo()
{
    ...
}

鏈接的接口—符號(hào)

鏈接過程的本質(zhì)就是要把多個(gè)不同的目標(biāo)文件之間相互“粘”在一起眼姐,在鏈接中,我們將函數(shù)和變量統(tǒng)稱為符號(hào)佩番,函數(shù)名或變量名就是符號(hào)名众旗,我們可以將符號(hào)看做是鏈接中的粘合劑,整個(gè)鏈接過程正是基于符號(hào)才能正確完成趟畏,鏈接過程中很關(guān)鍵的一部分就是符號(hào)的管理贡歧,每一個(gè)目標(biāo)文件都會(huì)有一個(gè)相應(yīng)的符號(hào)表,這個(gè)表里面記錄了目標(biāo)文件中所用到的所有符號(hào)赋秀,每個(gè)定義的符號(hào)有一個(gè)對(duì)應(yīng)的值利朵,叫做符號(hào)值,對(duì)于變量和函數(shù)來說猎莲,符號(hào)值就是他們的地址绍弟。

函數(shù)簽名

函數(shù)簽名包含了一個(gè)函數(shù)的信息,包括函數(shù)名著洼,它的參數(shù)類型樟遣,它所在的類和名稱空間及其他信息而叼。函數(shù)簽名用于識(shí)別不同的函數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末豹悬,一起剝皮案震驚了整個(gè)濱河市葵陵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屿衅,老刑警劉巖埃难,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莹弊,死亡現(xiàn)場(chǎng)離奇詭異涤久,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)忍弛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門响迂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人细疚,你說我怎么就攤上這事蔗彤。” “怎么了疯兼?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵然遏,是天一觀的道長。 經(jīng)常有香客問我吧彪,道長待侵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任姨裸,我火速辦了婚禮秧倾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘傀缩。我一直安慰自己那先,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布赡艰。 她就那樣靜靜地躺著售淡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪慷垮。 梳的紋絲不亂的頭發(fā)上勋又,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音换帜,去河邊找鬼楔壤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛惯驼,可吹牛的內(nèi)容都是我干的蹲嚣。 我是一名探鬼主播递瑰,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼隙畜!你這毒婦竟也來了抖部?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤议惰,失蹤者是張志新(化名)和其女友劉穎慎颗,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體言询,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俯萎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了运杭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夫啊。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖辆憔,靈堂內(nèi)的尸體忽然破棺而出撇眯,到底是詐尸還是另有隱情,我是刑警寧澤虱咧,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布熊榛,位于F島的核電站,受9級(jí)特大地震影響腕巡,放射性物質(zhì)發(fā)生泄漏玄坦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一逸雹、第九天 我趴在偏房一處隱蔽的房頂上張望营搅。 院中可真熱鬧,春花似錦梆砸、人聲如沸转质。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽休蟹。三九已至,卻和暖如春日矫,著一層夾襖步出監(jiān)牢的瞬間赂弓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工哪轿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盈魁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓窃诉,卻偏偏與公主長得像杨耙,于是被迫代替她去往敵國和親赤套。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容