【问题标题】:the shared library RPATH and the binary RPATH priority共享库 RPATH 和二进制 RPATH 优先级
【发布时间】:2014-05-25 06:35:51
【问题描述】:

如果共享库链接到二进制文件,并且共享库还依赖于其他库,那么共享库的 RPATH 和二进制文件的 RPATH 的优先级(链接器搜索顺序)是什么?二进制文件的 RPATH 可以覆盖共享库中的 RPATH 吗?我在共享库 RPATH 中设置的 $ORIGIN 是指 lib 位置还是二进制位置?
提前致谢。

【问题讨论】:

    标签: c++ linux build rpath


    【解决方案1】:

    根据我的观察,如果有一个应用程序main动态加载库first.so,而后者又动态加载库second.so,并且main和first.so都包含RPATH,那么动态链接器将首先使用first.so 的RPATH 搜索second.so,将$ORIGIN 解析为first.so 的目录,并且只有当它失败时,链接器才会继续到main 的RPATH 现在解析$ORIGIN作为main的目录。

    这与dynamic linker doc (look for Rpath token expansion)并不矛盾:

    $ORIGIN(或等效的${ORIGIN}):这将扩展为包含程序或共享对象的目录。 ...

    为了检查这一点,我创建了一个测试应用程序和两个库:分别为 main、liba 和 libb。 main 与liba 相关联,liba 与libb 相关联:

    main -> liba.so -> libb.so
    

    构建的二进制文件是这样定位的:

    /cwd/main
    /cwd/lib/liba.so
    /cwd/lib/libb.so
    

    main 和 liba 均使用 --rpath=\$ORIGIN/lib 链接器标志构建:

    ~$ readelf -a /cwd/main | grep ORIGIN
     0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/lib]
    ~$ readelf -a /cwd/lib/liba.so | grep ORIGIN
     0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/lib]
    

    在LD_DEBUG environment variable 的帮助下,我检查了动态链接器如何处理 RPATH:

    ~$ LD_DEBUG=libs /cwd/main
    :     find library=liba.so [0]; searching
    :      search path=/cwd/lib/tls/x86_64:/cwd/lib/tls:/cwd/lib/x86_64:/cwd/lib              (RPATH from file /cwd/main)
    :       trying file=/cwd/lib/tls/x86_64/liba.so
    :       trying file=/cwd/lib/tls/liba.so
    :       trying file=/cwd/lib/x86_64/liba.so
    :       trying file=/cwd/lib/liba.so
    94313:
    :     find library=libc.so.6 [0]; searching
    :      search path=/cwd/lib                (RPATH from file /cwd/main)
    :       trying file=/cwd/lib/libc.so.6
    :      search cache=/etc/ld.so.cache
    :       trying file=/lib/x86_64-linux-gnu/libc.so.6
    94313:
    :     find library=libb.so [0]; searching
    :      search path=/cwd/lib/lib/tls/x86_64:/cwd/lib/lib/tls:/cwd/lib/lib/x86_64:/cwd/lib/lib              (RPATH from file /cwd/lib/liba.so)
    :       trying file=/cwd/lib/lib/tls/x86_64/libb.so
    :       trying file=/cwd/lib/lib/tls/libb.so
    :       trying file=/cwd/lib/lib/x86_64/libb.so
    :       trying file=/cwd/lib/lib/libb.so
    :      search path=/cwd/lib                (RPATH from file /cwd/main)
    :       trying file=/cwd/lib/libb.so
    

    由此我们可以看出,链接器首先遇到了加载liba.so 的需求,并使用main 二进制文件的RPATH 来解决这个问题。然后它遇到了加载libb.so 的需求,它首先使用liba.so 库的RPATH 来解决这个问题。但是由于 RPATH 是 $ORIGIN/lib 并且 libb.so 与 liba.so 在同一目录中,因此链接器无法使用 liba.so 的 RPATH 找到 libb.so。之后它回退到main 的RPATH 并且仅使用后者成功找到libb.so。

    测试环境:Linux ubuntu 4.15.0-34-generic #37~16.04.1-Ubuntu (64-bit), /lib/x86_64-linux-gnu/ld-2.23.so.

    【讨论】:

      猜你喜欢
      • 2014-11-11
      • 2011-09-13
      • 2018-11-10
      • 2019-04-26
      • 2015-10-07
      • 2018-08-15
      • 1970-01-01
      • 2013-02-22
      • 1970-01-01
      相关资源
      最近更新 更多