Linux編寫程序時,會經常的接觸動態庫,而在程序運行時可能會遇到類似於:libxxx.so cannot open shared object file No such file or directory的問題,這個代表什麼含義,該怎麼解決呢?
含義
這個問題代表的含義是,可執行程序在加載libxxx.so庫時,找不到該庫。至於找不到的情況分爲兩種:系統里根本不存在libxxx.so庫;libxxx.so庫在系統中存在,但是ld找不到,即libxxx.so庫的位置沒有告知ld。
解決辦法
對於第一種情況,需要將libxxx.so放到系統ld的搜索路徑中;對於第二種情況,通過locate工具定位libxxx.so的位置,然後將其放到ld的搜索路徑中。
動態庫的搜索路徑配置
Linux下ld對於動態庫的搜索路徑的配置方式包括以下幾種方式:
- 通過配置gcc編譯器的參數-Wl,-rpath指定;
- 通過LD_LIBRARY_PATH環境變量指定;
- 通過/etc/ld.so.conf指定,切記修改完ld.so.conf之後必須執行/sbin/ldconfig -v同步動態庫;
- 默認搜素路徑/lib、/usr/lib/指定;
同時,上述幾種方式存在一定的搜索順序,按照搜索的先後依次爲:1 > 2 > 3 > 4。對於動態庫的搜索路徑的配置可以參考21aspnet的這篇博文。
依賴動態庫的查看
我們可以通過ldd(x86環境)或者CROSS_COMPILE-readelf -d(ARM環境,CROSS_COMPILE爲具體交叉編譯前綴,-d 爲讀取動態庫信息的參數)來分析相應平臺下可執行程序所依賴的動態庫的情況,我們可以舉一例:
test.c:
#include <stdio.h>
void test()
{
printf("test()\n");
}
$ $(CC) -fPIC -c test.c //生成test.o,-fPIC(Position-independent code)爲了生成位置無關的代碼,一般用於動態庫編譯選項。
$ $(CC) -static -fPIC -o libtest.so test.o
extern void test();
main.c:
int main()
{
test();
return 0;
}
$ $(CC) -c main.c
$ $(CC) main.o -o main -L. -ltest
其中,CC代表不同平臺的編譯器;
通過,修改CC爲gcc或者arm-linux-gnueabi-gcc分別生成X86、ARM平臺下的main可執行程序,下面分別通過ldd和arm-linux-gnueabi-readelf查看main所依賴的動態庫:
-
X86:
ldd main linux-vdso.so.1 => (0x00007ffc98f6a000) libtest.so => /home/qihua/develop/linux/static_dynamic_libs/code/libtest.so (0x00007fe850df4000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe850a10000) /lib64/ld-linux-x86-64.so.2 (0x000055950a132000)
-
ARM:
arm-linux-gnueabi-readelf -d main Dynamic section at offset 0xf10 contains 25 entries: 標記 類型 名稱/值 0x00000001 (NEEDED) 共享庫:[libtest.so] 0x00000001 (NEEDED) 共享庫:[libc.so.6] 0x0000000c (INIT) 0x10430 0x0000000d (FINI) 0x10590 0x00000019 (INIT_ARRAY) 0x20f08 0x0000001b (INIT_ARRAYSZ) 4 (bytes) 0x0000001a (FINI_ARRAY) 0x20f0c 0x0000001c (FINI_ARRAYSZ) 4 (bytes) 0x00000004 (HASH) 0x101ac 0x00000005 (STRTAB) 0x10300 0x00000006 (SYMTAB) 0x10200 0x0000000a (STRSZ) 200 (bytes) 0x0000000b (SYMENT) 16 (bytes) 0x00000015 (DEBUG) 0x0 0x00000003 (PLTGOT) 0x21000 0x00000002 (PLTRELSZ) 32 (bytes) 0x00000014 (PLTREL) REL 0x00000017 (JMPREL) 0x10410 0x00000011 (REL) 0x10408 0x00000012 (RELSZ) 8 (bytes) 0x00000013 (RELENT) 8 (bytes) 0x6ffffffe (VERNEED) 0x103e8 0x6fffffff (VERNEEDNUM) 1 0x6ffffff0 (VERSYM) 0x103c8 0x00000000 (NULL) 0x0
NOTE
-
如果一個可執行程序(常見於第三方庫提供的bin)依賴了某些動態庫,但可執行程序的CPU架構與本地的CPU架構不同(例如,可執行程序爲32位,但本地系統爲64位,本地系統安裝的動態庫也爲64位的),那麼程序運行時,通過會提示:libxxx.so cannot open shared object file No such file or directory。這是,我們通過locate是可以定位到libxxx.so庫,並且libxxx.so處於合適的ld搜索路徑之下,這是我們通過修改libxxx.so路徑是沒有用的。解決問題的方式有這麼幾種:
1)下載與本地系統CPU架構相匹配的程序;
2)在本地系統重新編譯該程序;
3)編譯、更新與可執行程序CPU架構相匹配的動態庫;