ldd命令用于输出程序或者库文件所依赖的共享库列表。
语法
选项
参数
文件:指定可执行程序或者文库。
ldd原理
首先,ldd不是一个可执行程序,而只是一个shell脚本。
ldd能够显示可执行模块的dependency,其原理是通过设置一系列的环境变量,如下: LD_TRACE_LOADED_OBJECTS、LD_WARN、LD_BIN_NOW、LD_LIBRARY_VERSION、LD_VERBOSE 等。当 LD_TRACE_LOADED_OBJECTS 环境变量不为空时,任何可执行程序在运行时,它都只会显示模块的dependency,而程序并不真正执行。测试结果如下:
ldd 显示可执行模块的dependency的工作原理,其肢或实质是通过ld-linux.so(elf动态库的装载器)来实现的。ld-linux.so模块会先于executable模块程序工作,并获得控制权。因此当上述的那些变量设置时,ld-linux.so选择了显示可执行模块的dependency。
ld-linux.so读取可执行程序的头信息,这些信息采用 Executable and Linking Format 或者(ELF)格式。 它们通过这些消息,来确定哪些库是必须的,历尘伍以及哪些库需要加载。兄薯 然后执行动态链接,把可执行程序当中所有的地址指针与需要加载的库联系起来, 这样程序就可以运行了。
实际上可以直接执行ld-linux.so模块,如: /lib64/ld-linux-x86-64.so.2 --list ./a.out (这相当于 ldd a.out )。
示例
通过上面的信息,我们可以得到以下几个信息:
Linux 系统,也同样面临和Window一样的问题,如何控制动态库的多个版本问题。Window之前没有处理好,为此专门有个名词来形容这个问题 “Dll hell”,其严重影响软件的升级和维护。 Dll hell 是指windows 上动态库新版本覆盖旧版本,但是却不兼容老版本。常常发生在程序升级之后,动态库更新,原有程逗雹序运行不起来;或者装新软件,但是已有的软件运行不起来。 同样Linux *** 作系统,也有同样的问题,那么它是怎么解决的呢?Linux 为解决这个问题,引入了一套机制,如果遵守这个机制来做,就可以避免这个问题。 但是这只事一个约定,不是强制的。但是建议遵守这个约定,否则同样也会出现 Linux 版的Dll hell 问题。 下面来介绍一个这个机制。 这个机制是通过文件名,来控制dll (shared library) 的版本。
Linux 上的Dll ,叫shared library,其有三个名字,分别有不同的目的。
第一个是共享库本身的文件名(real name),其通常包含版本号,常常是是这样: libmath.so.1.1.1234 。 lib是Linux 上的库的约定前缀,math 是共享库名字,so 是共享库的后缀名,1.1.1234的是共享库的版本号,其主版本号+小版本号+build号。主版本号,代表当前动态库的版本,如果动态库的接口有变化,那么这个版本号就要加1;后面的两个版本号(小版本号 和 build 号)是告诉你详细的信山亏帆息,比如为一个hot-fix 而生成的一个版本,其小版本号加1,build号也应有变化。 这个文件名包含共享库的代码。
第二个是动态库的soname( Short for shared object name),其是应用程序加载dll 时候,其寻找共享库用的文件名。其格式为
lib + math+.so + ( major version number)
其只包含major version number,换句话说,也就是只要其接口没有变,应用程序都可以用,不管你其后minor build version or build version。
问题来了,程序运行时怎么通过soname 找个real name? Soname 存在哪里?如果与real name 关联起来?什么时候存的?
这就是接下来要介绍的第三个共享库的名字,link name,顾名思义,就是在编译过程,link 阶段用的文件名。 其将sonmae 和real name 关联起来。
第三个名字,共享库的连接名(link name),是专门为build 阶段连接而用的名字。这个名字就是lib + math +.so ,比如libmath.so。其是不带任何版本信息的。在共享库编译过程中,连接(link) 阶段,编译器将生成一个共享库及real name,同时将共享库空喊的soname,写在共享库文件里的文件头里面。可以用命令 readelf -d sharelibrary 去查看。
名称 ldd - 打印共享库的依赖关系大纲 ldd [选项]... 文件...
描述 ldd 输出在命令行上指定的每个程序或共享库需要的共享库。
选项
--version
打印ldd的版本号
-v --verbose
打印所有信息,例如包括符号的版本信息
-d --data-relocs
执行符号重部署,并报告缺少的目标对象(只对ELF格式适用)困扰
-r --function-relocs
对目标对象和函数执行重新部隐尺猜署,并报告缺少的目标对象和函数(只对ELF格式适用)
--help 用法信息
或者看看《灶型linux就该这么学》,具体关于这一章地址3w(dot)linuxprobe/chapter-02(dot)html.
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)