天天看點

linux中檢視庫依賴檔案,linux下檢視程式依賴的庫

在x86下,為了檢視程式所依賴的庫,可以使用

linux中檢視庫依賴檔案,linux下檢視程式依賴的庫

但如果是使用arm-linux-gcc 等交叉編譯環境編譯出來的程式,則要使用

linux中檢視庫依賴檔案,linux下檢視程式依賴的庫

庫用于将相似函數打包在一個單元中。然後這些單元就可為其他開發人員所共享,并是以有了子產品化程式設計這種說法 — 即,從子產品中建構程式。Linux 支援兩種類型的庫,每一種庫都有各自的優缺點。靜态庫包含在編譯時靜态綁定到一個程式的函數。動态庫則不同,它是在加載應用程式時被加載的,而且它與應用程式是在運作時綁定的。圖 1 展示了 Linux 中的庫的層次結構。

linux中檢視庫依賴檔案,linux下檢視程式依賴的庫

使用共享庫的方法有兩種:您既可以在運作時動态連結庫,也可以動态加載庫并在程式控制之下使用它們。本文對這兩種方法都做了探讨。

靜态庫較适宜于較小的應用程式,因為它們隻需要最小限度的函數。而對于需要多個庫的應用程式來說,則适合使用共享庫,因為它們可以減少應用程式對記憶體(包括運作時中的磁盤占用和記憶體占用)的占用。這是因為多個應用程式可以同時使用一個共享庫;是以,每次隻需要在記憶體上複制一個庫。要是靜态庫的話,每一個運作的程式都要有一份庫的副本。

GNU/Linux 提供兩種處理共享庫的方法(每種方法都源于 Sun Solaris)。您可以動态地将程式和共享庫連結并讓 Linux 在執行時加載庫(如果它已經在記憶體中了,則無需再加載)。另外一種方法是使用一個稱為動态加載的過程,這樣程式可以有選擇地調用庫中的函數。使用動态加載過程,程式可以先加載一個特定的庫(已加載則不必),然後調用該庫中的某一特定函數(圖 2 展示了這兩種方法)。這是建構支援插件的應用程式的一個普遍的方法。

linux中檢視庫依賴檔案,linux下檢視程式依賴的庫

Linux 提供了很多種檢視和解析 ELF 對象(包括共享庫)的工具。其中最有用的一個當屬指令,您可以使用它來發送共享庫依賴項。例如,在dl應用程式上使用ldd指令會顯示如下内容:

[email protected]:~/dl$ ldd dl

linux-gate.so.1 => (0xffffe000)

libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb7fdb000)

libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7eac000)

/lib/ld-linux.so.2 (0xb7fe7000)

[email protected]:~/dl$

ldd所告訴您的是:該 ELF 映像依賴于 linux-gate.so(一個特殊的共享對象,它處理系統調用,它在檔案系統中無關聯檔案)、libdl.so(DL API)、GNUC庫(libc.so)以及 Linux 動态加載器(因為它裡面有共享庫依賴項)。

指令是一個有很多特性的實用程式,它讓您能夠解析和讀取 ELF 對象。有一個有趣的用途,就是用來識别對象内可再定位的項。對于我們這個簡單的程式來說(清單 2展示的程式),您可以看到需要再定位的符号為:

[email protected]:~/dl$ readelf -r dl

Relocation section '.rel.dyn' at offset 0x520 contains 2 entries:

Offset Info Type Sym.Value Sym. Name

08049a3c 00001806 R_386_GLOB_DAT 00000000 __gmon_start__

08049a78 00001405 R_386_COPY 08049a78 stdin

Relocation section '.rel.plt' at offset 0x530 contains 8 entries:

Offset Info Type Sym.Value Sym. Name

08049a4c 00000207 R_386_JUMP_SLOT 00000000 dlsym

08049a50 00000607 R_386_JUMP_SLOT 00000000 fgets

08049a54 00000b07 R_386_JUMP_SLOT 00000000 dlerror

08049a58 00000c07 R_386_JUMP_SLOT 00000000 __libc_start_main

08049a5c 00000e07 R_386_JUMP_SLOT 00000000 printf

08049a60 00001007 R_386_JUMP_SLOT 00000000 dlclose

08049a64 00001107 R_386_JUMP_SLOT 00000000 sscanf

08049a68 00001907 R_386_JUMP_SLOT 00000000 dlopen

[email protected]:~/dl$

從這個清單中,您可以看到各種各樣的需要再定位(到 libc.so)的C庫調用,包括對 DL API(libdl.so)的調用。函數__libc_start_main是一個C庫函數,它優先于程式的main函數(一個提供必要初始化的 shell)而被調用。

其他操作對象檔案的實用程式包括:objdump,它展示了關于對象檔案的資訊;nm,它列出來自對象檔案(包括調試資訊)的符号。還可以将 EFL 程式作為參數,直接調用 Linux 動态連結器,進而手動啟動映像:

[email protected]:~/dl$ /lib/ld-linux.so.2 ./dl

> libm.so expf 0.0

1.000000

>

另外,可以使用 ld-linux.so 的--list選項來羅列 ELF 映像的依賴項(ldd指令也如此)。切記,它僅僅是一個使用者空間程式,是由核心在需要時引導的。