歡迎您光臨本站 註冊首頁

linux下查看程序依賴的庫

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0

在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下查看程序依賴的庫已經有488次圍觀

http://coctec.com/docs/linux/show-post-48402.html