# Linking ## what do linkers do ### symbol resolution 1. define and dreference symbol ```c void swap() {…} /* define symbol swap */ swap(); /* reference symbol swap */ int *xp = &x; /* define symbol xp, reference x */ ``` 2. 把這些 symbol defination 存進 object file 的 symbol table #### linker symbols - global symbols - 就一般的全域變數,可被其他 module 存取(linking 的部份存取) - external symbols - 由外部定義的全域變數,對應到 c 的 `extern` 或是 header file 定義的函式(不是 static) - local symbols - 不會被其他 module 存取 - 對應到 c 的 `static` - local static value 會直接在 .data or .bss 配置一段記憶體 ### Relocation - 把 .o 檔的 symbol 從原本的相對位置轉換到最終執行檔的絕對位置 ### three kind of object file - relocatable object file (.o file) - 每個 .o 都是由一個 .c 生成 - 存放 code and data ,並且在 linker relocation 時跟其他 .o 組成最後的執行檔 - executable object file (a.out file) - shared object file (.so file) - 一種特別的 relocatable object file ,可以動態的載入記憶體跟連結,不管是 load time or run time - 在 windows 上它就是 dynamic link libraries (DLLs) ## Executable and Linkable Format (ELF) - object 的標準格式   ## resolve duplicate symbol defination - strong strong $\to$ not allow - strong strong $\to$ choose the strong symbol , weak 的 ref 會是 strong 的 - weak weak $\to$ 任選一個,沒辦法確定是哪個 ### 觀察 .o ```c int value_x = 1; int value_y = 0; int value_z; __attribute__((weak)) int value_v; __attribute__((weak)) void func1(); void func2(); void func3() { return; } int main() { return 0; } ``` ```shell gcc -c sw_attr.c nm sw_attr.o ``` - output ``` 0000000000000000 W func1 000000000000000b T func3 0000000000000016 T main 0000000000000008 V value_v 0000000000000000 D value_x 0000000000000000 B value_y 0000000000000004 B value_z ``` 根據 `man nm` | 符號 | 意義 | 代表的 section | | --- | ------------------- | ------------------------------- | | `T` | Text (code) | `.text` | | `D` | Data (initialized) | `.data` | | `B` | BSS (uninitialized) | `.bss` | | `U` | Undefined | 來自別處的引用 | | `W` | Weak function | 由 `__attribute__((weak))` 宣告的函式 | | `V` | Weak object (變數) | 由 `__attribute__((weak))` 宣告的變數 | - 簡報上說 `int x` 這種會是 `weak` ,但這邊的結果是 `BSS (uninitialized)` ### strong weak - strong_weak.c ```c #include <stdio.h> #include "meow.h" int x = 0; int y = 0; int main() { set_x(1ULL << 33); printf("%d, %d\n", x, y); } ``` - meow.c ```c #include "meow.h" __attribute__((weak)) long long x; void set_x(long long meow) { x = meow; } ``` - meow.h ```c void set_x(long long meow); ``` - output ``` 0, 2 ``` 由於 `meow.c` 的 `x` 是 weak , linking 的時候會把讓它的位址與 `strong_weak.c` 上的 `x` 一樣,然後又把它當成 `long long` 操作,結果就是覆蓋到 `y` 的部份 ### 關於 header file 以前一直很納悶, include header file 是怎麼做到使用別的 .c 檔定義的函式的 有 strong weak 的知識後,嘗試實驗一下 ```c gcc -c strong_weak.c meow.c ``` ``` $ nm strong_weak.o 0000000000000000 T main U printf U set_x 0000000000000000 B x 0000000000000004 B y $ nm meow.o 0000000000000000 T set_x 0000000000000000 V x ``` 這下真相大白了,所謂 include 某個 header ,其實就是把 header 內的那些函式變成 weak function 放進 .o ,然後藉由 linker 把他們串起來 實際上,不需要 header 也能使用別的 .c 的函式 ```c //sw_func_main.c __attribute__((weak)) void func1() { return; } int main() { func1(); } //sw_func.c #include <stdio.h> int func1() { printf("meowmeow\n"); } ``` 而變數,像是 `extern int global_var;` 也是同個道理 ## static library - 整合多個 relocatable object file 成一個有 index 的 .a (archive)files - linker 會在編譯時把 .a 中用到的 .o link 到執行檔 - 例如: 只用到 `printf` 那就只 link printf.o ### create static library  ### linking with static library  ### 缺點 - 每份執行檔都要複製一份重複的程式 (libc) - 浪費磁碟空間 - 浪費記憶體 - 若 libc 之類的 static library 存在問題,修改不能將執行檔的問題一起改掉,必須重編譯 ## share library - 可以在 load 和 run 的時候 linking - 可以利用 [`dlopen()`](https://man7.org/linux/man-pages/man3/dlopen.3.html) 在執行時進行 linking - share library 可以同時被多個 process 存取 - 詳情可以參考[虛擬記憶體的筆記](https://hackmd.io/@weiso131/ry_tbocUgg) ### load time linking  ### run time linking 
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up