如何使用相對路徑連結到共享庫?
在ld.so(8) 的手冊頁中,它說
解析庫依賴項時,動態連結器首先檢查每個依賴項字元串以查看它是否包含斜杠(如果在連結時指定了包含斜杠的庫路徑名,則會發生這種情況)。如果找到斜線,則依賴字元串被解釋為(相對或絕對)路徑名,並使用該路徑名載入庫。
如何
gcc
連結到帶有斜杠路徑的庫?我已經嘗試過,-l
但這似乎只適用於用於搜尋各種路徑的庫名稱,而不是路徑參數本身。一個後續問題:當以這種方式連結到相對路徑時,相對路徑是什麼(例如包含二進製文件的目錄或執行時的工作目錄)?
我在搜尋時找到的所有連結指南都使用
RPATH
、LD_LIBRARY_PATH
和RUNPATH
.RPATH
已棄用,大多數討論不鼓勵使用LD_LIBRARY_PATH
.RUNPATH
以 開頭的路徑$ORIGIN
允許連結到相對路徑,但它有點脆弱,因為它可以被LD_LIBRARY_PATH
. 我想知道相對路徑是否會更健壯(因為我找不到任何討論這個的東西,我猜不是,可能是因為路徑是相對於執行時目錄的)。
如果我們(暫時)忽略
gcc
問題的或連結部分,而是patchelf
在 linux 系統上修改二進製文件$ ldd hello linux-vdso.so.1 => (0x00007ffd35584000) libhello.so.1 => not found libc.so.6 => /lib64/libc.so.6 (0x00007f02e4f6f000) /lib64/ld-linux-x86-64.so.2 (0x00007f02e533c000) $ patchelf --remove-needed libhello.so.1 hello $ patchelf --add-needed ./libhello.so.1 hello $ ldd hello linux-vdso.so.1 => (0x00007ffdb74fc000) ./libhello.so.1 => not found libc.so.6 => /lib64/libc.so.6 (0x00007f2ad5c28000) /lib64/ld-linux-x86-64.so.2 (0x00007f2ad5ff5000)
我們現在有一個帶有相對路徑庫的二進製文件,如果存在合適的目錄,其中存在
libhello.so.1
文件$ cd english/ $ ../hello hello, world $ cd ../lojban/ $ ../hello coi rodo
我們發現路徑是相對於程序的工作目錄的,這就帶來了各種各樣的問題,尤其是安全 問題。這可能有一些生產用途,也許可以測試不同版本的庫。編譯兩個不同的二進製文件可能會更簡單,或者
patchelf
在必要的庫中編譯而不需要相對工作目錄的複雜性。編譯步驟
libhello
只有一個helloworld
電話$ cat libhello.c #include <stdio.h> void helloworld(void) { printf("coi rodo\n"); }
並通過編譯
CFLAGS="-fPIC" make libhello.o gcc -shared -fPIC -Wl,-soname,libhello.so.1 -o libhello.so.1.0.0 libhello.o -lc ln -s libhello.so.1.0.0 libhello.so.1 ln -s libhello.so.1.0.0 libhello.so
並且
hello
進行呼叫的那個helloworld
是通過編譯的$ cat hello.c int main(void) { helloworld(); return 0; } $ CFLAGS="-lhello -L`pwd`/english" make hello
沒有更新檔
事後看來,修改
gcc
命令以使用相對目錄路徑:$ gcc -shared -fPIC -Wl,-soname,./libhello.so.1 -o libhello.so.1.0.0 libhello.o -lc $ cd .. $ rm hello $ CFLAGS="-lhello -L`pwd`/lojban" make hello $ ldd hello | grep hello ./libhello.so.1 => not found $ english $ ../hello hello, world
以正常方式編譯庫,然後根據需要使用
patchelf
.