为什么 ldd 输出的某些库的工作包的某些文件返回“未找到”?

为什么 ldd 输出的某些库的工作包的某些文件返回“未找到”?

我发现了一堆东西,其中工作包包含一些文件,其中 ldd 对于某些库返回“未找到”。例如...

/usr/lib64/thunderbird/libprldap60.so
    libldap60.so => not found

/usr/lib64/libreoffice/program/libofficebean.so
    libjawt.so => not found

我们有数百名用户使用 Thunderbird 和 Libre Office,没有人报告任何问题。系统上存在这些文件:

/usr/lib64/thunderbird/libldap60.so
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.33.x86_64/jre/lib/amd64/libjawt.so
/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.71.x86_64/jre/lib/amd64/libjawt.so

对于此示例, /usr/bin/thunderbird 和 /usr/bin/libreoffice 都是用于启动相应程序的包装脚本,我预计这些脚本会设置环境,以便这些库变得可见,但事实并非如此看起来这些脚本中发生了这种情况。

我们的系统中还有数百个这样的例子,我只选择这两个作为例子。谁能解释一下发生了什么事吗?

答案1

直接(也许显而易见)的答案是您正在查看的库的搜索路径ldd不包括库自身依赖项所在的目录。通常,除非在系统范围的标准位置中找到库的依赖项,否则应该使用指定的运行路径构建库(通过使用环境变量$LD_RUN_PATH或适当的链接器选项)。否则,稍后在运行时将无法找到这些库,正如您在ldd.

那么为什么尽管存在这个“问题”,Thunderbird 仍然可以工作呢?

尽管缺少运行路径,但仍有几种方法可以找到必要的库:

  • 环境变量$LD_LIBRARY_PATH在运行时设置,并提供要搜索的其他目录的列表。
  • 必要的目录可能已包含在搜索路径中,因为它是在某个其他不相关库的运行路径中找到的,而这些库恰好在当前库之前加载。顺便说一句,我不确定这是否是标准指定的实施事故。不管怎样,它很脆弱,因为它很大程度上取决于加载库的确切顺序。
  • 该库可能已由应用程序使用dlopen()给定完整路径名的函数手动加载。

Thunderbird 似乎正在使用最后一种技术。我查看了strace它在启动时的输出,它似乎是这样做的:

  • 找到其自己的二进制文件所在的目录。这始终是可能的,因为启动 Thunderbird 的 shell 脚本帮助程序使用完整路径名来执行此操作。
  • dependentlibs.list打开该目录中找到的文本文件。
  • 对于此文本文件中的每个文件名,按顺序在前面添加相同的目录以形成完整路径名,并使用dlopen().
  • 现在,您提到的所有依赖库libldap60.so都已“预加载”,其他需要它们的库不需要再次找到它们。

请注意,中列出的顺序或文件dependentlibs.list很重要。

Thunderbird 这样做的原因是,它所在的目录不必硬编码到应用程序或其任何内部库的运行路径中。

我不知道Java是做什么的,但毫无疑问是类似的东西。

相关内容