連結練習題 (Practice - Linking)


Question 1 - 連結器兩大任務 [recall]

靜態連結器 ld 接收一組 relocatable object files,輸出 fully linked executable。
請說出連結器必須完成的兩大任務,並各以一句話說明其內容。


Question 2 - 目的檔三種形式 [recall]

目的檔有三種形式。請列出名稱、各自的用途,以及「哪一種只能由 linker 產生」。


Question 3 - Section 歸屬 [recall]

在現代 gcc 的 ELF relocatable object file 慣例下,下列各項分別放在哪個 section(或 pseudosection)?
(a) int g = 42;(global) (b) int g;(global,未初始化) (c) static int s; (d) int z = 0;(global) (e) printf 的格式字串與 switch 的 jump table


Question 4 - Strong/Weak 三規則 [recall]

編譯時每個全域符號以 strong 或 weak 匯出。
請說明哪些符號是 strong、哪些是 weak,以及 Linux linker 處理重複符號名的三條規則。


Question 5 - 靜態函式庫與掃描順序 [recall]

Linker 由左至右掃描命令列上的 object files 與 archives,過程維護三個集合 E、U、D。
請說明三集合的意義,以及遇到 archive 時 linker 做什麼、掃描結束時如何判定成敗。


Question 6 - Executable 與載入 [recall]

相較於 relocatable object file,executable object file 多了什麼、少了什麼?
又,執行 ./prog 時,程式的 entry point 是哪個函式、定義在哪、之後的呼叫鏈為何?


Question 7 - GOT 與 PLT [recall]

PIC 程式碼透過 GOT 與 PLT 呼叫 shared library 中的函式。
請說明兩者各位於哪個 segment、entry 的形式,以及 lazy binding 下「第一次呼叫」與「之後呼叫」的差異。


Question 8 - 插入三時機 [recall]

Library interpositioning 可在三個時間點進行,三者所需的「存取權」遞減。
請列出三種時機、各自的關鍵機制與所需材料。


Question 9 - 目的檔工具 [recall]

GNU binutils 提供多個操作 object file 的工具。下列需求各用哪個工具?
(a) 反組譯 .text (b) 功能涵蓋 sizenm (c) 列出執行檔需要的 shared libraries (d) 刪除 symbol table (e) 建立 static library


Question 10 - 符號分類 [application]

swap.c 內容如下(m.o 中定義了 int buf[2] = {1, 2};)。請對 bufbufp0bufp1swaptemp 逐一判斷:是否在 swap.o.symtab 有 entry?若有,是定義還是參考、屬於哪個 section?

extern int buf[];
int *bufp0 = &buf[0];
int *bufp1;
void swap() { int temp; /* ... */ }

Question 11 - PC-relative Relocation 計算 [application]

main.o.text 中有一條 call sum,其 relocation entry 為:
r.offset = 0xfr.type = R_X86_64_PC32r.symbol = sumr.addend = -4
已知 linker 決定 ADDR(.text) = 0x4004d0ADDR(sum) = 0x4004e8。求重定位後填入指令的 32 位元值,並驗證執行期 call 會跳到 sum


Question 12 - 函式庫命令列順序 [application]

p.o 呼叫 libx.a 中的函式,libx.a 呼叫 liby.a,而 liby.a 又回頭呼叫 libx.a(循環相依)。
(a) gcc p.o libx.a liby.a 為何可能連結失敗?
(b) 給出兩種可成功連結的作法。


Question 13 - 型別不一致的重複定義 [analysis]

兩個模組連結成一個執行檔(x86-64,int 4 bytes、double 8 bytes):

/* foo5.c */                    /* bar5.c */
int y = 15212;                  double x;
int x = 15213;                  void f() { x = -0.0; }
int main() { f(); ... }

連結能否成功?執行 f()xy 的值各是什麼?為什麼這類 bug 特別難除錯?


Question 14 - Run-time 插入與遞迴陷阱 [analysis]

你只有可執行檔 intr(無原始碼、無 .o),想追蹤它的 malloc 呼叫。你寫了 wrapper:

void *malloc(size_t size) {
    void *ptr = malloc(size);   /* 直接呼叫 malloc */
    printf("malloc(%d) = %p\n", (int)size, ptr);
    return ptr;
}

(a) 應選哪種插入機制、如何建置與執行? (b) 上面的 wrapper 有什麼致命問題、如何修正?