http://fcamel-life.blogspot.tw/2012/01/ld-ldso-ldconfig.html
ld, ld.so 和 ldconfig 的行為
TLPI ch41 相當值得一看, 從開發者使用 library 的角度說明 library 的生成、靜態連結、動態連結 (載入) 的行為, 內容不多不少, 正好就是我想知道的, 省了看 linker、loader 的時間。
讀出 soname:
關於 static linking 找檔名的順序, 可用 strace 觀察:
ps.
結論是別隨便手動更新 soname 的檔案, 執行 ldconfig 後可能會出問題。裝套件後, 系統工具會自動跑 ldconfig 更新目錄, 可能會蓋掉自己手動更新的同檔名檔案。另外 ldconfig 沒有管 linker name, 若是自己編的 shared library, 要自己產生。
shared library 的名詞介紹
- soname: 記錄在 shared library header 裡的名稱, 格式為 libX.so.MAJOR。要有同名檔案, 供之後程式載入 shared library 時使用
- real name: shared library 的檔名, 格式為 libX.so.MAJOR.MINOR.NUMBER
- linker name: 對 library X 來說, 就是 libX.so, 一般會是 symbolic link 指向最新的 major shared library
libjpeg.so -> libjpeg.so.62.0.0 # linker name libjpeg.so.62 -> libjpeg.so.62.0.0 # soname libjpeg.so.62.0.0 # real name這是我在 Ubuntu 裝好 package 後的樣子, 照理說 libjpeg.so 指向 libjpeg.so.62 應該會更彈性。
讀出 soname:
$ readelf -d libjpeg.so | grep SONAME 0x000000000000000e (SONAME) Library soname: [libjpeg.so.62]
static 和 dynamic linker
- ld (ld.bfd) 是 static linker。Google 開發的 gold 是取代 ld.bfs 的 static linker。用 gcc 連結 shared library 或 executable 時就是呼叫 ld, 並將需要的參數傳給它。不論連結的是 static library 或 shared library, 都是 static linking。
- ld 在連結 shared library 或 executable 時, 會將需要的 shared library 的 soname 寫入結果檔裡。注意, 只有 soname 而已, 沒有完整路徑。
- ld-VERSION.so 是 dynamic (runtime) linker, 執行程式時, 由 runtime linker 載入 executable 開始。若 OS 用的 glibc 版本為 2.13, 就叫 ld-2.13.so。用 ldd 看所有執行檔, 都會找到它 (某個 symbolic link 連到 ld-2.13.so)。
- gcc 透過 -lm 的指示告知 ld 要連結 libm.so
- ld 會找到某處的 libm.so 指向 /lib/x86_64-linux-gnu/libm.so.6, 確認要用到的 symbol 都有, 沒有 link error
- ld 從 libm.so.6 的 header 讀出 soname "libm.so.6", 寫入 "libm.so.6" 到 prog 的 header。
關於 static linking 找檔名的順序, 可用 strace 觀察:
$ strace -e open,execve -f -o gcc.trace gcc -lm prog.c -o prog在 gcc.trace 裡可看出一二。
ps.
- 使用 execve 的目的是知道 child process 是那一個程式, 目標是看 ld 開敋的檔案
- 可由 man 2 exec<TAB> 得知 system call 使用的 exec 函式為 execve。
ldconfig
執行 ldconfig 後, 它做的事如下:- 讀出 /lib, /usr/lib, /etc/ld.so.conf 內的路徑之下的 shared library (ldconfig 會略過 symbolic link), 將結果寫入 /etc/ld.so.cache。之後 ld-2.13.so 會用 ld.so.cache 的記錄來找 shared library。
- ldconfig 會自動產生 symbolic link "libX.so.MAJOR" 指向最新版本的 shared library。例如 /lib/libfoo.so.2.0.1 的 soname 是 libbar.so.2, 執行 ldconfig 後, 它會產生 /lib/libbar.so.2 指向 /lib/libfoo.so.2.0.1。
結論是別隨便手動更新 soname 的檔案, 執行 ldconfig 後可能會出問題。裝套件後, 系統工具會自動跑 ldconfig 更新目錄, 可能會蓋掉自己手動更新的同檔名檔案。另外 ldconfig 沒有管 linker name, 若是自己編的 shared library, 要自己產生。
沒有留言:
張貼留言