在x86下,為了查看程序所依賴的庫,可以使用ldd命令
但如果是使用arm-linux-gcc 等交叉編譯環境編譯出來的程序,則要使用readelf
命令來查看了
庫用於將相似函數打包在一個單元中.然後這些單元就可為其他開發人員所共享,並因此有了模塊化編程這種說法 — 即,從模塊中構建程序.Linux 支持兩種類型的庫,每一種庫都有各自的優缺點.靜態庫包含在編譯時靜態綁定到一個程序的函數.
動態庫則不同,它是在載入應用程序時被載入的,而且它與應用程序是在運行時綁定的.圖 1 展示了 Linux 中的庫的層次結構.圖 1. Linux 中的庫層次結構
使用共享庫的方法有兩種:您既可以在運行時動態鏈接庫,也可以動態載入庫並在程序控制之下使用它們.本文對這兩種方法都做了探討.
靜態庫較適宜於較小的應用程序,它們只需要最小限度的函數.而對於需要多個庫的應用程序來說,則適合使用共享庫,它們可以減少應用程序對內存(包括運行時中的磁碟佔用和內存佔用)的佔用.這是多個應用程序可以同時使用一個共享庫;因此,每次只需要在內存上複製一個庫.要是靜態庫的話,每一個運行的程序都要有一份庫的副本.
GNU/Linux 提供兩種處理共享庫的方法(每種方法都源於 Sun Solaris).您可以動態地將程序和共享庫鏈接並讓 Linux 在執行時載入庫(如果它已經在內存中了,則無需再載入).另外一種方法是使用一個稱為動態載入的過程,這樣程序可以有選擇地調用庫中的函數.使用動態載入過程,程序可以先載入一個特定的庫(已載入則不必),然後調用該庫中的某一特定函數(圖 2 展示了這兩種方法).這是構建支持插件的應用程序的一個普遍的方法.
圖 2. 靜態鏈接與動態鏈接
Linux 提供了很多種查看和解析 ELF 對象(包括共享庫)的工具.其中最有用的一個當屬ldd
命令,您可以使用它來發送共享庫依賴項.例如,在
dl
應用程序上使用 ldd
命令會顯示如下內容: mtj@camus:~/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) mtj@camus:~/dl$
ldd
所告訴您的是:該 ELF 映像依賴於 linux-gate.so(一個特殊的共享對象,它處理系統調用,它在文件系統中無關聯文件)、libdl.so(DL API)、GNU C
庫(libc.so)以及 Linux 動態載入器(它裡面有共享庫依賴項).
readelf
命令是一個有很多特性的實用程序,它讓您能夠解析和讀取 ELF 對象.readelf
有一個有趣的用途,就是用來識別對象內可再定位的項.對於我們這個簡單的程序來說(清單 2展示的程序),您可以看到需要再定位的符號為: mtj@camus:~/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 mtj@camus:~/dl$
從這個列表中,您可以看到各種各樣的需要再定位(到 libc.so)的 C
庫調用,包括對 DL API(libdl.so)的調用.函數 __libc_start_main
是一個 C
庫函數,它優先於程序的 main
函數(一個提供必要初始化的 shell)而被調用.
其他操作對象文件的實用程序包括:objdump
,它展示了關於對象文件的信息;nm
,它列出來自對象文件(包括調試信息)的符號.還可以將 EFL 程序作為參數,直接調用 Linux 動態鏈接器,從而手動啟動映像:
mtj@camus:~/dl$ /lib/ld-linux.so.2 ./dl > libm.so expf 0.0 1.000000 >
另外,可以使用 ld-linux.so 的 --list
選項來羅列 ELF 映像的依賴項(ldd
命令也如此).切記,它僅僅是一個用戶空間程序,是由內核在需要時引導的.
本文出自 「娜一片天空」 博客,請務必保留此出處http://wanwentao.blog.51cto.com/2406488/569291
[火星人 ] linux下查看程序依賴的庫已經有489次圍觀