Use Shared Library in Linux

執行檔如何尋找 shared library

ELF 將依賴的 shared library 存在 .dynamic section 的 DT_NEED 欄位。

1
2
3
4
5
6
7
$ readelf -d main

Dynamic section at offset 0x868 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [./libfoo.so]
0x0000000000000001 (NEEDED) Shared library: [./libbar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]

如果是絕對路徑, dynamic linker 直接去該路徑存取 shared library。如果是相對路徑,則會依照以下順序到不同路徑下找 library:

  • LD_LIBRARY_PATH 環境變數指定的路徑
  • .dynamic section 中 DT_RUNPATH 欄位記錄的路徑
  • /etc/ld.so.conf 設定的路徑(實際上是讀取 /etc/ld.so.cache
  • /lib
  • /usr/lib

因為一個個搜尋路徑很慢,所以指令 ldconfig 除了更新系統中 library 的 SO-NAME soft link 外,還會將這些 SO-NAME 以特殊的形式存在 /etc/ld.so.cache 作為 cache 以加快搜尋。所以增加、刪除或更新 shared library 以及修改 /etc/ld.so.conf 後,都要執行 ldconfig 來更新 SO-NAME。

環境變數

幾個跟 dynamic linking 有關的常用環境變數。

LD_LIBRARY_PATH

臨時改變 shared library 的搜尋路徑,開發跟 debug 的時候很好用。

1
$ LD_LIBRARY_PATH=/home/foo ls

LD_PRELOAD

可以指定預先 load 的 shared library 或 object file,無論執行檔或使用的 shared library 有沒有依賴它。因為會使用先 load 的 shared library 的 symbol,所以可以用來改掉原本執行檔使用的 shared library,例如 standard C library。

1
$ LD_PRELOAD=./libfoo.so ./main

LD_DEBUG

可以看 dynamic linker 的 debug 訊息,設成 help 可以看可設定的值。

建立 & 安裝 shared library

build 出 shared library:

1
$ gcc -shared -fPIC -Wl,-soname,mysoname -o library_name sources

-shared 表示輸出 shared library,-fPIC 表示使用 PIC-Wl 可以將參數傳給 linker。-soname 是指定 SO-NAME,如果不指定,shared library 預設沒有 SO-NAME,即無法用 ldconfig 建 soft link。shared library 的 SO-NAME 可以用 readelf -d 查看。

去除 symbol 資訊可以讓 shared library 檔案變小,常用在 release 時:

1
$ strip libfoo.so

安裝 shared library 通常是放到系統相關的路徑下,例如 /lib/usr/lib 等,然後執行 ldconfig 更新 soft link。不過通常安裝會用 make install 之類的指令,不需要手動 copy 跟 ldconfig