ldd [-d | -r] [ -c] [-D] [-e envar] [ -f] [-i] [-L] [-l] [ -p] [-s] [-U | -u] [ -v] [-w] filename...
ldd 实用程序列出可执行文件和共享目标文件的动态依赖项。ldd 使用运行时链接程序 ld.so.1 生成诊断信息。该运行时链接程序获取正在检查的目标文件并将其准备妥当,正如在正在运行的进程中将发生的一样。缺省情况下,ldd 会触发装入任何“懒惰”依赖项和延迟依赖项的操作。
ldd 可列出在装入 filename 时装入的所有共享目标文件的路径名。ldd 期望正在检查的共享目标文件具备执行权限。如果共享目标文件不具备执行权限,ldd 在尝试处理文件前会发出警告。
ldd 按照一次一个文件的方式处理其输入。对于每个文件,ldd 会执行以下操作之一:
如果存在依赖项,则列出目标文件依赖项。
如果不存在依赖项,则会以静默方式成功执行。
如果处理失败,则输出一条错误消息。
不会执行 ldd 检查的动态目标文件。因此,ldd 不会列出使用 dlopen(3C) 显式附加的任何共享目标文件。要显示由某个进程或核心文件使用的所有目标文件,请使用 pldd(1)。
ldd 还可以检查 filename 与共享目标文件 filename 用途的兼容性。指定了以下选项时,ldd 可以针对装入 filename 时可能会出现的任何未解析符号引用显示警告信息。
检查立即引用。
检查立即引用和延迟引用。
每次调用 ldd 期间,选项 –d 和 –r 两者只能指定其一。
立即引用通常引用可执行或共享目标文件代码使用的数据项。立即引用也可以是指向函数的指针,甚至是从共享目标文件相关位置执行的函数调用。延迟引用通常是从共享目标文件无关位置执行的全局函数调用,或者从可执行文件执行的外部函数调用。此外,目标文件装入也受重定位处理的影响。有关更多详细信息,请参见“用法”下的“延迟装入”部分。
缺省情况下,不会报告某些无法解析的符号引号。可使用以下选项报告来这些无法解析的引用。仅当与 –d 或 –r 选项一起使用时,这些选项才有用。
向显式父代引用和外部引用公开任何符号无法解析错误。
公开任何无法解析的弱符号引用。
共享目标文件可以引用应当由共享目标文件的调用者提供的符号。在创建共享目标文件时,可以显式将这些引用归类为可从父代使用的引用,或将其简单地归类为外部引用。请参见 ld(1) 的 –M mapfile 选项以及 PARENT 和 EXTERN 符号定义关键字。检查动态可执行文件时,无法解析的父代或外部引用会标记为错误。然而,缺省情况下,检查共享目标文件时,系统不会将无法解析的父代或外部引用标记为错误。–p 选项在与 –d 或 –r 选项一起使用时,会将无法解析的父代或外部引用标记为重定位错误。
重定位使用的符号可以定义为弱引用。缺省情况下,如果弱符号引用无法解析,则会忽略重定位,并将零写入到重定位偏移。–w 选项在与 –d 或 –r 选项一起使用时,会将针对弱符号引用的任何无法解析的重定位标记为重定位错误。
ldd 还能够检查依赖项使用情况。指定了以下每个选项时,ldd 可以针对装入 filename 时装入的任何未引用或未使用的依赖项显示警告信息。仅当某个符号引用绑定到了依赖项时,才认为依赖项已被使用。因此,这些选项仅在检查符号引用时才有用。如果 –r 选项未生效,则会启用 –d 选项。
由目标文件定义的但未从该目标文件绑定的依赖项称为未引用的依赖项。在装入 filename 时未由任何其他目标文件绑定的依赖项称为未使用的目标文件。
依赖项可能位于缺省系统位置,也可能位于必须由搜索路径指定的位置。可以全局指定搜索路径,例如使用环境变量 LD_LIBRARY_PATH。此外,也可以在动态目标文件中将搜索路径定义为 runpath。请参见 ld(1) 的 – R 选项。不能用于满足任何依赖项的搜索路径会导致不必要的文件系统处理工作。
显示任何未引用或未使用的依赖项。如果未引用的依赖项未由随 filename 装入的其他目标文件绑定,该依赖项还会被标记为未使用的依赖项。没有从循环外部的目标文件绑定的循环依赖项也会被视为未引用的依赖项。
此选项还会显示任何未使用的搜索路径。
显示任何未使用的目标文件。
每次调用 ldd 期间,选项 –U 和 –u 两者只能指定其一,尽管 –U 是 –u 的超集。使用 –r 选项时发现的未引用或未使用的目标文件应当从依赖项中删除。这些目标文件未提供引用,但在装入 filename 时会导致不必要的开销。使用 –d 选项时发现的任何未引用或未使用的目标文件都不是装入 filename 时立即需要的。这些目标文件是延迟装入的候选者。有关更多详细信息,请参见“用法”下的“延迟装入”部分。
删除未使用的依赖项可以降低运行时链接开销。删除未引用的依赖项可以进一步降低运行时链接开销。不过,在与其他目标文件一起使用时或在会衍生其他目标文件依赖项时,删除未引用的依赖项可防止有未使用的依赖项。
删除未使用的搜索路径会减少定位依赖项时需做的工作量。通过网络访问文件服务器中的文件时,这可以节省大量的工作量。请注意,搜索路径可以编码到目标文件中,以满足 dlopen(3C) 的要求。由于可能不需要通过搜索路径获取此目标文件的依赖项,因此,在 ldd 看来,它是未使用的。
还支持以下其他选项:
禁用对任何配置文件的使用。配置文件可用来更改缺省搜索路径,提供备选的目标文件依赖项。请参见 crle(1)。
跳过延迟依赖项装入。缺省情况下,ldd 会强制处理“懒惰”依赖项和延迟依赖项。另请参见 –L 选项。在正常进程执行过程中,只有在运行时首次绑定到延迟引用时才会装入延迟依赖项。当使用了 –D 选项时,使用 –d 或 –r 选项不会触发任何延迟依赖项装入操作。请参见 ld(1) 的 –z deferred 选项。
设置环境变量 envar。
此选项对于试用由运行时链接程序识别并可能会对 ldd 产生负面影响的环境变量(如 LD_PRELOAD)非常有用。
此选项还可用来仅从正在检查的目标文件(例如 LD_DEBUG)提取附加信息。请参见 ld.so.1(1) 和 lari(1)。
强制 ldd 检查不安全的可执行文件。超级用户调用 ldd 时,缺省情况下,ldd 不会处理任何不安全的可执行文件。如果可执行文件指定的解释程序没有驻留在 /lib 或 /usr/lib 下,则不会将可执行文件视为安全的文件。如果无法确定解释程序,也不会将可执行文件视为安全的文件。请参见“用法”下的“安全性”部分。
显示初始化部分的执行顺序。使用 –d 或 –r 选项时可能会影响所发现的顺序。请参见“用法”下的“初始化顺序”部分。
启用延迟装入。缺省情况下,ldd 会强制处理“懒惰”依赖项和延迟依赖项。另请参见 –D 选项。在正常的进程执行期间,延迟装入是缺省操作模式。在此情况下,任何延迟依赖项或过滤器仅在对延迟目标文件中定义的符号进行引用时才会装入到进程中。–d 或 –r 选项与 –L 选项一起使用时,可用于检查依赖项及其在正在运行的进程中的装入顺序。请参见 ld(1) 的 –z lazyload 选项。
强制对任何过滤器立即进行处理,以便列出所有 filtee 及其依赖项。目前,立即处理过滤器是 ldd 的缺省操作模式。然而,在此缺省模式下,无法找到的任何辅助 filtee 会被忽略,且不进行任何提示。在 –l 选项下,缺少辅助 filtee 会生成错误消息。
显示用于定位共享目标文件依赖项的搜索路径。
显示处理 filename 时引起的所有依赖项关系。此选项还会显示任何依赖项版本要求。请参见 pvs(1)。
只有已知要检查的可执行文件值得信任时,超级用户才应使用 –f 选项。超级用户对不可信任的可执行文件使用 –f 会危害系统安全。如果可执行文件的可信任度未知,超级用户应暂时换成一般用户。然后,以一般用户身份调用 ldd。
只要不使用 :r 子命令,使用 dump(1)、elfdump(1)、elfedit(1) 和 mdb(1) 就可以安全地检查不可信任的目标文件。此外,非超级用户可以使用 mdb 的 :r 子命令或 truss(1) 检查不可信任的可执行文件,同时又不会构成太大的安全风险。针对不可信任的可执行文件使用 ldd、mdb :r 或 truss 时,要最大程度地降低风险,请使用 UID "nobody"。
延迟装入可以由指定的延迟依赖项直接应用。请参见 ld(1) 的 –z lazyload 选项。延迟装入也可以通过过滤器间接应用。请参见 ld(1) 的 –f 选项和 – F 选项。受所用选项的影响,采用延迟装入技术的目标文件在 ldd 输出中可能会变化。如果目标文件将其所有依赖项都表示为延迟依赖项,ldd 的缺省操作是按依赖项在该目标文件中的记录顺序列出所有依赖项。
example% ldd main libelf.so.1 => /lib/libelf.so.1 libnsl.so.1 => /lib/libnsl.so.1 libc.so.1 => /lib/libc.so.1
使用 –L 选项时,可以启用在运行时使用此目标文件时发生的延迟装入行为。在此模式下,延迟依赖项在对延迟目标文件中定义的符号进行引用时装入。因此,结合使用 –L 选项与 –d 和 –r 选项可以显示分别满足立即引用和延迟引用所需的依赖项:
example% ldd –L main example% ldd –d main libc.so.1 => /lib/libc.so.1 example% ldd –r main libc.so.1 => /lib/libc.so.1 libelf.so.1 => /lib/libelf.so.1
请注意,在本例中,依赖项的列出顺序不同于未使用选项时 ldd 显示的顺序。即使使用了 –r 选项,对依赖项的延迟引用的顺序可能也不同于在正在运行的程序中的引用顺序。
观察延迟装入也可以查明满足任何引用时不需要的目标文件。这类目标文件(在本例中,为 libnsl.so.1)可以从用来构建要检查的目标文件的链接行中删除。
受所用选项的影响,未显式定义所需依赖项的目标文件可能会看到 ldd 显示的初始化部分的顺序有所不同。例如,简单的应用程序可能会显示:
example% ldd -i main libA.so.1 => ./libA.so.1 libc.so.1 => /lib/libc.so.1 libB.so.1 => ./libB.so.1 init object=./libB.so.1 init object=./libA.so.1 init object=/lib/libc.so.1
然而,当应用了重定位时,初始化部分的顺序为:
example% ldd -ir main ......... init object=/lib/libc.so.1 init object=./libB.so.1 init object=./libA.so.1
在此情况下,libB.so.1 会引用 /usr/lib/libc.so.1 中的函数。但是,libB.so.1 对此库没有显式依赖关系。仅当发现了重定位后才会建立依赖关系。此隐式依赖关系会影响初始化部分的顺序。
通常,在应用程序执行时建立的初始化部分的顺序等同于使用 –d 选项的 ldd。如果所有目标文件都完整地定义了其依赖项,则可以获得最佳顺序。构建动态目标文件时,建议使用 ld(1) 选项 – z defs 和 –z ignore。
一个或多个动态目标文件彼此引用时,会产生循环依赖关系。应当避免循环依赖关系,因为无法为这些循环依赖项建立唯一的初始化排序顺序。
如果用户更喜欢对目标文件执行较为静态的分析,则可以使用 dump(1) 和 elfdump(1) 等工具来检查依赖项。
装入虚构的 32 位可执行文件,以检查共享目标文件的依赖项。
装入虚构的 64 位可执行文件,以检查共享目标文件的依赖项。
有关下列属性的说明,请参见 attributes(5):
|
crle(1)、dump(1)、elfdump(1)、elfedit(1)、lari(1)、ld(1)、ld.so.1(1)、mdb(1)、pldd(1)、pvs(1)、truss(1)、dlopen(3C)、attributes(5)
ldd 将共享目标文件路径名记录输出到 stdout。还可以选择将符号解析问题的列表输出到 stderr。如果 filename 不是可执行文件或共享目标文件,或者无法打开 filename 进行读取,则将返回非零退出状态。
为共享目标文件使用 –d 或 –r 选项可能会产生误导性结果。ldd 会对共享目标文件执行最坏情形分析。然而,实际上,报告为无法解析的符号的符号可以由引用共享目标文件的可执行文件解析。可以使用运行时链接程序预装入机制为正在检查的目标文件添加依赖项。请参见 LD_PRELOAD。
ldd 与运行时链接程序使用相同的算法来定位共享目标文件。