Linux動態庫常見問題之-"cannot open shared object file No such file or directory"的解決辦法

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對於動態庫的搜索路徑的配置方式包括以下幾種方式:

  1. 通過配置gcc編譯器的參數-Wl,-rpath指定;
  2. 通過LD_LIBRARY_PATH環境變量指定;
  3. 通過/etc/ld.so.conf指定,切記修改完ld.so.conf之後必須執行/sbin/ldconfig -v同步動態庫;
  4. 默認搜素路徑/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

  1. 如果一個可執行程序(常見於第三方庫提供的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架構相匹配的動態庫;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章