CSAPP--第七章:鏈接 學習

生成可執(zhí)行文件的過程:
//用linux gcc編譯器飒炎,編譯main.c亏镰,sum.c

①預處理(preprocess):生成main.i
cpp main.c -o main.i

②編譯(compile):生成main.s
gcc main.i -o main.s
//CSAPP上說的是cc1横侦,但linux找不到這個见擦,只有cc抖甘,但是會報錯曙蒸。

③匯編(assembly):生成main.o
as mian.s -o main.o

④鏈接(linked):生成可執(zhí)行文件
ld -o prog main.o sum.o




目標文件

  • 三種形式:

    可重定位目標文件(file.o):包含二進制的代碼和數(shù)據(jù)憨降,可在鏈接時和其他目標文件合并起來父虑,生成可執(zhí)行目標文件。

共享目標文件:特殊類型的可重定向目標文件授药,可以再加載士嚎、運行時被動態(tài)加載進內(nèi)存并鏈接。

可執(zhí)行目標文件:包含二進制的代碼和數(shù)據(jù)悔叽,其可被直接復制到內(nèi)存并執(zhí)行莱衩。

可重定位目標文件
  • 不同系統(tǒng)格式:

    windows:可移植可執(zhí)行格式(Portable Executable),PE格式娇澎。

    Max OS-X:Mach-O格式笨蚁。

    Linux和Unix:可執(zhí)行可鏈接模式(Executable and Linkable Format),ELF格式趟庄。

  • linux的可重定位目標文件:

    ELF格式為一個序列:{ELF括细,... , 節(jié)頭部表}

    ELF和節(jié)頭部表中間,包含了很多個節(jié)戚啥, 如:

    .text .rodate .data等等奋单,如下圖:


    ELF格式
  • 符號和符號表

    //linux中,用readelf name -s查看符號表猫十。

    每個目標文件(模塊)中都有一個符號表symtab览濒,其包含了本文件中定義、引用的符號的信息拖云。

    三種不同符號:

    1:模塊自己定義贷笛,并能被其他模塊引用的全局符號(函數(shù)或者變量,非靜態(tài))宙项。

    2:由其他模塊定義乏苦,被本模塊引用的全局符號。

    3:模塊自己定義的靜態(tài)全局符號尤筐,僅被自己使用汇荐。

    單個符號的表,如下:


    某個符號表

    可以在linux中叔磷,用objdump -dx file.o 來得到符號表的反匯編代碼:


    符號表反匯編

    //ndx代表節(jié)索引

全局符號根據(jù)初始化與否拢驾,被分到不同的節(jié):

1:分配到 .data:全局變量初始化,且不為0改基。

2:分配到 .bss :全局變量初始化為0繁疤;未初始化的靜態(tài)變量符號 //(Block Storage Start)

3:分配到 .COMMON :沒有初始化的全局變量咖为。

4:分配到 .UND:沒有定義的全局函數(shù)。

//UND稠腊、COMMON是偽節(jié)躁染,僅在重定位文件中,執(zhí)行文件無架忌。

  • 鏈接器解析多重定義的全局符號

    解析:將全局符號的引用和定義關聯(lián)起來吞彤。

    強符號:已初始化的全局符號。

    弱符號:未初始化的全局符號叹放。

    重定義 有三種情況:

    1:兩個文件中饰恕,都有同樣的強符號出現(xiàn),會報錯井仰。

    2:兩個文件有同名符號埋嵌,但只有一個強符號,則選擇強符號俱恶。

    3:都是弱符號雹嗦,則隨機選擇一個。

    如圖:


與靜態(tài)庫的鏈接
  • 靜態(tài)庫定義:

    所有的編譯系統(tǒng)都提供一種機制合是,將所有相關的目標模塊打包成一個單獨的文件了罪,稱之為靜態(tài)庫。格式為 lib.a

    如圖:

    靜態(tài)庫鏈接過程

    //(.a表示archive 存檔聪全,里面包含了很多個.o模塊泊藕,當某模塊引用了庫中的模塊名時,變會將其復制鏈接到可執(zhí)行文件)

    //通常編譯器會自動隱式鏈接libc.a 標準函數(shù)庫荔烧,而自定義的一些庫吱七,需要顯式鏈接汽久。創(chuàng)建靜態(tài)庫用AR工具鹤竭。

    不使用靜態(tài)庫的實現(xiàn)方法及自定義庫:CSAPP P475。

鏈接器使用靜態(tài)庫來解析引用
  • 編譯驅(qū)動器按照命令行從左到右景醇,進行順序掃描臀稚。

    鏈接器維護了三個集合:E(將被合并成可執(zhí)行文件)、U(還未被解析的引用符號)三痰、D(已經(jīng)解析的有定義的符號集合)

    1:如果為file.o吧寺,則將其放入E,并修改U散劫,D稚机。

    2:如果為libx.a,則將其與U中符號進行匹配获搏,如果匹配赖条,則將該模塊.o 放入E中。并修改U、D(U中清空已解析引用纬乍,并添加模塊.o中未解析引用)碱茁,存檔文件掃描完后,將無引用的模塊丟棄仿贬。

    3:鏈接器完成對命令行的遍歷后纽竣,若U非空,則進行報錯并終止茧泪。否則蜓氨,會合并E中目標文件,生成可執(zhí)行文件队伟。

    //所以切記语盈,不要將.o和.a順序弄錯,否則會無法解析引用缰泡,鏈接失敗刀荒。

重定位
  • 解析引用之后,便是要重定位:

    1:將不同模塊的相同節(jié)進行拼接:
    如.text棘钞,形成一個新的.text節(jié):其包含了所有模塊的指令代碼缠借。數(shù)據(jù)代碼、符號表等待也一樣宜猜。

    2:對引用的符號進行重定位:
    對全局變量泼返、全局函數(shù)等進行重定位,使其調(diào)用時姨拥,指向可執(zhí)行代碼中的定義位置绅喉。

    在可重定位目標程序中,如果有未定義的引用叫乌,則會將其放在.rel.text柴罐、.rel.data中(rel=relocation),使編譯器知道在生成可執(zhí)行代碼時憨奸,對這些符號進行重定位革屠。

  • 每個重定位條目,類似結(jié)構(gòu)體排宰,包含:

    offset :在代碼中的偏移信息似芝。如main函數(shù)內(nèi)部調(diào)用一個全局函數(shù)f()時,則offset = f()相對于main首地址的偏移量板甘。

    type:重定位之后的類型党瓮。

    symbol:模塊拼接之后,f()在符號表中的偏移量盐类。

    addend:這個值是針對不同情況寞奸,如f()的實現(xiàn)在mian()之后時痕寓,因為到call時,PC指令已經(jīng)指到下一個代碼位置蝇闭,需要減去f()偏移量的大小呻率,64位=8,32位=4呻引;

    如下圖:


    重定位entry
可執(zhí)行目標文件

當鏈接器將所有模塊解析及重定位之后礼仗,會生成一個可執(zhí)行文件的ELF表,其與可重定位目標文件表類似逻悠,但是沒有了兩個.rel節(jié)元践,因為不需要重定位了。


可執(zhí)行目標文件ELF表

增加的節(jié):

init:定義了一個_init函數(shù)童谒,程序的初始化代碼會調(diào)用它单旁。

段頭部表:描述了可執(zhí)行文件中,代碼段和數(shù)據(jù)段對內(nèi)存的映射關系饥伊。


段頭部表的反匯編

加載可執(zhí)行目標文件

在linux中使用 ./prog 可以運行目標文件象浑。

  • 加載流程://無動態(tài)鏈接

    1:將代碼復制到內(nèi)存:
    操作系統(tǒng)常駐在內(nèi)存的加載器(loader),會將可執(zhí)行目標文件中的代碼和數(shù)據(jù)從磁盤復制到內(nèi)存琅豆。

    2:將控制交給prog:
    通過跳轉(zhuǎn)到程序的第一條指令或者入口點(entry point)來運行程序愉豺。

其在內(nèi)存中,圖示如下:


內(nèi)存映像茫因,省略了空隙

動態(tài)鏈接共享庫

靜態(tài)庫的缺點是太耗磁盤和內(nèi)存空間蚪拦,尤其是當同時運行了上百個程序的時候,幾乎每個程序中都有標準I/O函數(shù)及其他重復函數(shù)冻押,占用了很大的內(nèi)存的資源驰贷。

  • 共享庫
    (shared library)用.so后綴表示。是第三種目標文件洛巢,即共享目標文件括袒。在運行或加載時,可以加載到任意的內(nèi)存地址狼渊,并和一個在內(nèi)存中的程序鏈接起來箱熬,這個過程稱為動態(tài)鏈接(dynamic linking)类垦。

    動態(tài)連接器:dynamic linker狈邑。執(zhí)行動態(tài)鏈接過程。

    "共享"說明:

    1:磁盤中蚤认,對于一個動態(tài)庫只有一個.so文件米苹,所有引用該文件的可執(zhí)行目標文件共享一個庫,而非靜態(tài)庫砰琢,需要將其內(nèi)容復制鏈接到可執(zhí)行文件中蘸嘶。

    2:在內(nèi)存中良瞧,共享庫的.text節(jié)的副本,可以被不同的正在運行的進程所共享训唱。大大節(jié)約了內(nèi)存空間褥蚯。


    動態(tài)鏈接過程

    動態(tài)鏈接時:

    1:和靜態(tài)庫不同,生成prog21時况增,并沒有復制代碼和數(shù)據(jù)赞庶。反而是鏈接器,復制了一些重定位和符號表信息澳骤。

    2:在內(nèi)存中時歧强,鏈接器根據(jù)這些信息,復制動態(tài)庫中的文本和數(shù)據(jù)到另一個內(nèi)存段为肮,并對prog21中摊册,有引用動態(tài)庫里定義的符號進行重定位。

    3:動態(tài)鏈接器將控制傳遞給prog21颊艳,開始運行茅特。共享庫的位置固定不變了。


從應用程序中加載和鏈接共享庫棋枕、位置無關代碼PIC(Position Independent Code)温治、庫打樁機制沒有學,因為書里比較簡略戒悠。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末熬荆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子绸狐,更是在濱河造成了極大的恐慌卤恳,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寒矿,死亡現(xiàn)場離奇詭異突琳,居然都是意外死亡,警方通過查閱死者的電腦和手機符相,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門拆融,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人啊终,你說我怎么就攤上這事镜豹。” “怎么了蓝牲?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵趟脂,是天一觀的道長。 經(jīng)常有香客問我例衍,道長昔期,這世上最難降的妖魔是什么已卸? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮硼一,結(jié)果婚禮上累澡,老公的妹妹穿的比我還像新娘。我一直安慰自己般贼,他們只是感情好永乌,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著具伍,像睡著了一般翅雏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上人芽,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天望几,我揣著相機與錄音,去河邊找鬼萤厅。 笑死橄抹,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的惕味。 我是一名探鬼主播楼誓,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼名挥!你這毒婦竟也來了疟羹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤禀倔,失蹤者是張志新(化名)和其女友劉穎榄融,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體救湖,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡愧杯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鞋既。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片力九。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖邑闺,靈堂內(nèi)的尸體忽然破棺而出跌前,到底是詐尸還是另有隱情,我是刑警寧澤检吆,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布舒萎,位于F島的核電站,受9級特大地震影響蹭沛,放射性物質(zhì)發(fā)生泄漏臂寝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一摊灭、第九天 我趴在偏房一處隱蔽的房頂上張望咆贬。 院中可真熱鬧,春花似錦帚呼、人聲如沸掏缎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽眷蜈。三九已至,卻和暖如春沈自,著一層夾襖步出監(jiān)牢的瞬間酌儒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工枯途, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留忌怎,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓酪夷,卻偏偏與公主長得像榴啸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子晚岭,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360