搜索和链接库目录的顺序

时间:2016-03-15 15:15:18

标签: gcc linker centos ld

我很难理解搜索目录链接到库的顺序。我有一个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.   
  3. -rpath选项指定的任何目录。 -rpath和.rp之间的区别              -rpath-link是由-rpath选项指定的目录包含在              可执行文件并在运行时使用,而-rpath-link选项仅在              链接时间。以这种方式搜索-rpath仅由本机链接器支持              已使用--with-sysroot选项配置的交叉链接器。

  4.   
  5. 在ELF系统上,对于本机链接器,如果-rpath和-rpath-link选项不是              使用,搜索环境变量的内容&#34; LD_RUN_PATH&#34;。

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

  8.   
  9. 对于本机链接器,搜索环境变量的内容              &#34; LD_LIBRARY_PATH&#34;

  10.   
  11. 对于本机ELF链接器,&#34; DT_RUNPATH&#34;中的目录或者&#34; DT_RPATH&#34;共享的              搜索库以查找它所需的共享库。 &#34; DT_RPATH&#34;条目是              如果&#34; DT_RUNPATH&#34;条目存在。

  12.   
  13. 默认目录,通常为/ lib和/ usr / lib。

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

         

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

  16.   

它没有说明搜索目录的顺序。从上面的示例可以看出,在/etc/ld.so.conf.d/usr/lib之前搜索了/lib

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

1 个答案:

答案 0 :(得分:1)

The online man page说明ld的订单:

  

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

     

如果找到斜杠,那么依赖项          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是相似的。