【问题标题】:Order in which library directories are searched and linked搜索和链接库目录的顺序
【发布时间】:2016-07-01 03:00:50
【问题描述】:

我很难理解搜索目录以链接到库的顺序。我有一个 CentOS6 系统和 3 个版本的 gcc,4.4.7、4.7.2、4.9.2。系统版本为 4.4.7,版本 4.7.2 和 4.9.2 为模块。在 /etc/ld.so.conf.d/ 中有两个文件,gcc-4.7.2.confgcc-4.9.2.conf,其中包含 4.7.2 和 4.9.2 库的路径。

我创建了一个简单的 C++ 程序,main.cpp

#include <cstdio>
#include <iostream>

using namespace std;


int main(void)
{
    cout << "Hello You!" << endl;
    printf("Back at you!\n");

    return 0;
}

用g++-4.4.7编译并运行ldd a.out,我明白了

linux-vdso.so.1 =>  (0x00007fff5535b000)
libstdc++.so.6 => /nonstandardpath/gcc-4.7.2/lib64/libstdc++.so.6 (0x00002ac12de73000)
libm.so.6 => /lib64/libm.so.6 (0x00002ac12e17a000)
libgcc_s.so.1 => /nonstandardpath/gcc-4.7.2/lib64/libgcc_s.so.1 (0x00002ac12e3ff000)
libc.so.6 => /lib64/libc.so.6 (0x00002ac12e614000)
/lib64/ld-linux-x86-64.so.2 (0x00002ac12dc51000)

看着man ld,它说(在-rpath-link=dir下):

链接器使用以下搜索路径来定位所需的共享 图书馆:

  1. -rpath-link 选项指定的任何目录。

  2. -rpath 选项指定的任何目录。 -rpath 和 -rpath 的区别 -rpath-link 是由 -rpath 选项指定的目录包含在 可执行并在运行时使用,而 -rpath-link 选项仅在 链接时间。只有本机链接器支持以这种方式搜索 -rpath,并且 已使用 --with-sysroot 选项配置的交叉链接器。

  3. 在 ELF 系统上,对于本机链接器,如果没有 -rpath 和 -rpath-link 选项 使用,搜索环境变量“LD_RUN_PATH”的内容。

  4. 在 SunOS 上,如果未使用 -rpath 选项,则搜索使用指定的任何目录 -L 选项。

  5. 对于本机链接器,搜索环境变量的内容 “LD_LIBRARY_PATH”。

  6. 对于本机 ELF 链接器,共享的“DT_RUNPATH”或“DT_RPATH”中的目录 库被搜索它需要的共享库。 “DT_RPATH”条目是 如果存在“DT_RUNPATH”条目,则忽略。

  7. 默认目录,通常是 /lib 和 /usr/lib。

  8. 对于 ELF 系统上的本机链接器,如果文件 /etc/ld.so.conf 存在,则列表 在该文件中找到的目录。

    如果找不到所需的共享库,链接器将发出警告并 继续链接。

它没有说明搜索目录的顺序。从我上面的例子来看,/etc/ld.so.conf.d 似乎在/usr/lib/lib 之前被搜索过

问题:链接器搜索库的顺序是什么(例如 LD_LIBRARY_PATH、ld.so.conf.d、-rpath、-L)?

【问题讨论】:

    标签: gcc linker centos ld


    【解决方案1】:

    The online man page 说明ld 的顺序:

    解析共享对象依赖时,动态链接器首先 检查每个依赖字符串以查看它是否包含斜杠(这 如果包含斜杠的共享对象路径名是 在链接时指定)。

    如果找到斜线,则依赖 string 被解释为(相对或绝对)路径名,并且 使用该路径名加载共享对象。

    如果共享对象依赖项不包含斜线,则按以下顺序搜索它:

    • 使用二进制文件的 DT_RPATH 动态部分属性中指定的目录(如果存在)且 DT_RUNPATH 属性不存在。不推荐使用 DT_RPATH。

    • 使用环境变量 LD_LIBRARY_PATH(除非可执行文件在安全执行模式下运行;见下文)。在这种情况下,它会被忽略。

    • 使用在二进制文件的 DT_RUNPATH 动态部分属性中指定的目录(如果存在)。仅搜索此类目录以查找 DT_NEEDED(直接依赖项)条目所需的那些对象,并且不适用于这些对象的子对象,这些对象本身必须具有自己的 DT_RUNPATH 条目。这与 DT_RPATH 不同,后者用于搜索依赖关系树中的所有子节点。

    • 来自缓存文件 /etc/ld.so.cache,其中包含先前在扩充库路径中找到的候选共享对象的编译列表。但是,如果使用 -z nodeflib 链接器选项链接二进制文件,则会跳过默认路径中的共享对象。安装在硬件功能目录(见下文)中的共享对象优先于其他共享对象。

    • 在默认路径 /lib 中,然后是 /usr/lib。 (在某些 64 位架构上,64 位共享对象的默认路径是 /lib64,然后是 /usr/lib64。)如果二进制文件是使用 -z nodeflib 链接器选项链接的,则跳过此步骤。

    取自 2017-09-15 版本。我假设旧版本的 ld 是相似的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-28
      • 2011-11-26
      • 1970-01-01
      • 1970-01-01
      • 2018-04-21
      • 2014-12-27
      • 2011-11-09
      相关资源
      最近更新 更多