linux下查看程序依赖的库

在x86下,为了查看程序所依赖的库,可使用ldd命令linux

p_w_picpath thumb8 linux下查看程序依赖的库

但若是是使用arm-linux-gcc 等交叉编译环境编译出来的程序,则要使用readelf命令来查看了web

p_w_picpath thumb9 linux下查看程序依赖的库

 

库用于将类似函数打包在一个单元中。而后这些单元就可为其余开发人员所共享,并所以有了模块化编程这种说法 — 即,从模块中构建程序。Linux 支持两种类型的库,每一种库都有各自的优缺点。静态库包含在编译时静态绑定到一个程序的函数。动态库则不一样,它是在加载应用程序时被加载的,并且它与应用程序是在运行时绑定的。图 1 展现了 Linux 中的库的层次结构。shell

图 1. Linux 中的库层次结构编程

figure11 thumb linux下查看程序依赖的库

使用共享库的方法有两种:您既能够在运行时动态连接库,也能够动态加载库并在程序控制之下使用它们。本文对这两种方法都作了探讨。ide

静态库较适宜于较小的应用程序,由于它们只须要最小限度的函数。而对于须要多个库的应用程序来讲,则适合使用共享库,由于它们能够减小应用程序对内存(包括运行时中的磁盘占用和内存占用)的占用。这是由于多个应用程序能够同时使用一个共享库;所以,每次只须要在内存上复制一个库。要是静态库的话,每个运行的程序都要有一份库的副本。模块化

GNU/Linux 提供两种处理共享库的方法(每种方法都源于 Sun Solaris)。您能够动态地将程序和共享库连接并让 Linux 在执行时加载库(若是它已经在内存中了,则无需再加载)。另一种方法是使用一个称为动态加载的过程,这样程序能够有选择地调用库中的函数。使用动态加载过程,程序能够先加载一个特定的库(已加载则没必要),而后调用该库中的某一特定函数(图 2 展现了这两种方法)。这是构建支持插件的应用程序的一个广泛的方法。函数

图 2. 静态连接与动态连接工具

figure21 thumb linux下查看程序依赖的库

Linux 提供了不少种查看和解析 ELF 对象(包括共享库)的工具。其中最有用的一个当属ldd 命令,您可使用它来发送共享库依赖项。例如,在 dl 应用程序上使用 ldd 命令会显示以下内容:spa

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命令也如此)。切记,它仅仅是一个用户空间程序,是由内核在须要时引导的。

相关文章
相关标签/搜索