為啥要學 linking?
- 了解 linker 可以幫助你建立更大的程式。
- 了解 linker 可以幫助你避免危險的程式錯誤。
- 了解 linker 可以幫助你了解程式如何實現 scoping 規則。
- 了解 linker 可以幫助你了解其他的系統概念。
- 了解 linker 可以讓你使用 shared libraries。
7.1 Compiler Drivers
- gcc 不是個編譯器,是一個 compiler driver,提供整個編譯系統 (compilation system) 會用的東西。
- 當呼叫 gcc,他會調用 language preprocessor, compiler, assembler 與 linker。
- 可以加上 -v 來看 gcc 實際上如何調用上面提到的東西。
- 假設執行 gcc -o main main.c,gcc 基本上會調用下列工具:
- cpp – preprocessor – 產生 ASCII intermediate file, main.i
- cc1 – compiler – 產生 assemble code, main.s
- as – assembler – 將 main.s 翻譯成 relocatable object file, main.o
- ld (collect2) – linker – 將所需要的其他 system object files 結合在一起,產生 executable object file main
- 不過如果你拆步驟的話 (自己一步一步編譯),到 ld 那邊會掛掉,因為還需要用到 crt1.a 之類的東西,我自己是沒有成功過就是…
- 當要執行程式的時候 unix> ./main,shell 會去執行 loader,然後會將程式碼與資料從 executable file main 中複製到記憶體,接著將控制權還給 main 來執行。
- 可以用 LD_DEBUG 來觀察這段時間系統所做的事情。
7.2 Static Linking
- linker 最主要的兩個工作就是
- Symbol resolution:
- Relocation
- The fact about linker: Object file 只是一塊一塊的位元組集合而已。這些 blocks 有些是程式碼,有些是程式資料,有些是指引 linker 與 loader 的資料。linker 會去把這些資料接好,依照 run-time 位置來接上 blocks,並修改程式碼與資料塊中的各個位置。
7.3 Object Files
7.4 Relocatable Object Files
7.5 Symbols and Symbol Tables
7.6 Symbol Resolution
- 編譯期間,編譯器會把 global symbol 標記為強 (strong) 跟弱 (weak)。
- 強符號 (strong symbol): 函數 (functions) 或是有初始化的全域變數是強符號。
- 弱符號 (weak symbol): 沒有初始化的全域變數是弱符號。
- 好神三規則 (當遇到多重 symbol 時該如何做指示)
- 規則 1: 多重強符號是不被允許的。
- 規則 2: 當有一個強符號跟多個弱符號的時候,使用強符號。
- 規則 3: 當有多個弱符號的時候,隨便選一個。
Leave a Reply