ldd命令的做用是查看程序依赖的动态连接库信息。使用nm命令也能够获取库函数的信息;nm命令能够列出一个函数库文件中的符号表,它对静态的库函数和共享的库函数都能起做用。 html
Linux动态库的默认搜索路径是/lib和/usr/lib。动态库被建立后,通常都复制到这两个目录中。当程序执行时须要某动态库,而且该动态库还未加载到内存中,则系统会自动到这两个默认搜索路径中去查找相应的动态库文件,而后加载该文件到内存中,这样程序就可使用该动态库中的函数,以及该动态库的其它资源了。在Linux 中,动态库的搜索路径除了默认的搜索路径外,还能够经过如下三种方法来指定。
方法一:在配置文件/etc/ld.so.conf中指定动态库搜索路径。
能够经过编辑配置文件/etc/ld.so.conf来指定动态库的搜索路径,该文件中每行为一个动态库搜索路径。每次编辑完该文件后,都必须运行命令ldconfig使修改后的配置生效。咱们经过例1来讲明该方法。 node
方法二:经过环境变量LD_LIBRARY_PATH指定动态库搜索路径。
经过设定环境变量LD_LIBRARY_PATH也能够指定动态库搜索路径。当经过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔。下面经过例2来讲明本方法。 linux
方法三:在编译目标代码时指定该程序的动态库搜索路径。
在编译目标代码时指定程序的动态库搜索路径。这是经过gcc 的参数"-Wl,-rpath,"指定。当指定多个动态库搜索路径时,路径之间用冒号":"分隔。 shell
当连接某个程序时,在运行期您能够指定另外的搜索路径。在 gcc 中,其 语法是 -Wl,-R/path。若是程序已经被连接,那么您也能够设置环境变量 LD_LIBRARY_PATH 来改变这一行为。一般只是在应用程序须要搜索的路径 不是系统级默认路径的一部分时才须要这样作,对大部分 Linux 系统来讲,这种状况不多见。 理论上,Mozilla 用户能够发布某个使用这个路径设置所编译的二进制程序,可是他们 更倾向于发布包装器(wrapper)脚本,在启动可执行程序以前正确地设置程序库路径。
设置程序库路径能够为两个应用程序须要同一程序库的不兼容版本的这种罕见状况提供一个迂回解决方案。可使用包装器脚本使某一应用程序在使用特殊版本程序库的目录中进行搜索。这称不上是一个 完美的解决方案,可是在某些状况下,这是您能采用的最佳方法。
若是出于不得已的缘由须要为不少程序添加某个路径,那么也能够修改系统的默认搜索路径。经过 /etc/ld.so.conf 控制动态连接器,该文件包含默认搜索路径的列表。 对 LD_LIBRARY_PATH 中指定的任何路径的搜索都要先于 ld.so.conf 中列出的路径,因此用户能够覆盖这些设置。
大部分用户没有理由修改系统默认程序库搜索路径;一般环境变量更适用于修改搜索路径,好比 链接某个工具包中的程序库,或者使用某个程序库的较新版本的测试程序。
app
ldd的做用是打印可执行档依赖的共享库文件。它是glibc的一部分,由Roland McGrath和Ulrich Drepper维护:
$ ldd --version
ldd (GNU libc) 2.9
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
可是ldd自己不是一个程序,而仅是一个shell脚本:
$ which ldd
/usr/bin/ldd
$ file /usr/bin/ldd
/usr/bin/ldd: Bourne-Again shell script text executable
ldd命令实际上是依靠设置一些环境变量而实现的(也就是说ldd的做用只是设置一些环境变量的值)
如:LD_TRACE_LOADED_OBJECTS
只要设置其值非空便可。
$ export LD_TRACE_LOADED_OBJECTS=1
$ ls /usr
linux-gate.so.1 => (0xb7fac000)
librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0xb7f93000)
libselinux.so.1 => /lib/libselinux.so.1 (0xb7f79000)
libacl.so.1 => /lib/libacl.so.1 (0xb7f70000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7e0d000)
libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb7df4000)
/lib/ld-linux.so.2 (0xb7fad000)
libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb7df0000)
libattr.so.1 => /lib/libattr.so.1 (0xb7dea000)
撤销该环境变量,ls即又能够恢复正常使用:
$ unset LD_TRACE_LOADED_OBJECTS
$ ls /usr/
bin games include lib lib32 lib64 local sbin share src X11R6
更多的环境变量:
一、LD_TRACE_LOADED_OBJECTS
二、LD_WARN
三、LD_BIND_NOW
四、LD_LIBRARY_VERSION
五、LD_VERBOSE
六、LD_DEBUG
ldd默认开启的环境变量是:LD_TRACE_LOADED_OBJECTS=1
其余的变量(和值)分别对应一些选项:
-d, --data-relocs -> LD_WARN=yes
-r, --function-relocs ->LD_WARN和LD_BIND_NOW=yes
-u, --unused -> LD_DEBUG="unused"
-v, --verbose -> LD_VERBOSE=yes
LD_TRACE_LOADED_OBJECTS为必要环境变量,其余视具体状况。
更为详细的命令选项(或者参看man、info):
$ ldd --help
Usage: ldd [OPTION]... FILE...
--help print this help and exit
--version print version information and exit
-d, --data-relocs process data relocations
-r, --function-relocs process data and function relocations
-u, --unused print unused direct dependencies
-v, --verbose print all information
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
可是ldd命令的本质是执行了:/lib/ld-linux.so.*
咱们能够从以上的内容中(ls /usr中)发现:/lib/ld-linux.so.2 (0xb7fad000)。
$ ls -l /lib/ld-linux.so.*
lrwxrwxrwx 1 root root 9 2009-09-05 22:54 /lib/ld-linux.so.2 -> ld-2.9.so
刚编译后的文件多是:/lib/ld.so。若是是libc5则是/lib/ld-linux.so.1, 而glibc2应该是/lib/ld-linux.so.2。
$ /lib/ld-linux.so.2 --list /bin/ls
linux-gate.so.1 => (0xb8050000)
librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0xb8037000)
libselinux.so.1 => /lib/libselinux.so.1 (0xb801d000)
libacl.so.1 => /lib/libacl.so.1 (0xb8014000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7eb1000)
libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb7e98000)
/lib/ld-linux.so.2 (0xb8051000)
libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb7e94000)
libattr.so.1 => /lib/libattr.so.1 (0xb7e8e000)
咱们能够看到以上等同于ldd ls。/lib/ld-linux.so.2还有其余一些选项:
一、--verify
二、--library-path PATH
三、--inhibit-rpath LIST
ldd能够得到的共享库文件,实际上是经过读取ldconfig命令组建起来的文件(/etc/ld.so.cache)。
默认的共享库文件搜索/lib优先于/usr/lib,并且也只有这个2个目录。若是想要加入其余路径,则须要经过ldconfig命令配置相关文件。
通常ld-linux.so会按照如下顺序搜索共享库:
一、DT_RPATH或DT_RUNPATH段
二、环境变量LD_LIBRARY_PATH
三、/etc/ld.so.cache文件中的路径,但若是可执行程序在链接时候添加了-z nodeflib选项,则跳过。
四、默认路径/lib和/usr/lib,但若是添加了-z nodeflib,则跳过。
还有一些额外的环境变量能够参看man ld.so。
更为详细的内容:
一、man ldd(http://www.kernel.org/doc/man-pages/online/pages/man1/ldd.1.html)
二、man ldconfig(http://www.kernel.org/doc/man-pages/online/pages/man8/ldconfig.8.html)
三、man ld.so(http://www.kernel.org/doc/man-pages/online/pages/man8/ld.so.8.html)
能够参见的文章:
一、Linux 动态库剖析(http://www.ibm.com/developerworks/cn/linux/l-dynamic-libraries/)
二、剖析共享程序库http://www.ibm.com/developerworks/cn/linux/l-shlibs.html)
三、ldd命令的原理与使用方法(http://hi.baidu.com/wstone_h/blog/item/af67700a80a01e1594ca6b29.html) 函数