如何使用GCC / LD设置RPATH和RUNPATH?

时间:2018-08-25 14:09:07

标签: linux gcc shared-libraries ld dynamic-linking

我最近在系统升级后遇到了这个问题:使用GCC primeicons 1.0.0-beta.10选项的工作方式与以前不同。

我用它来设置一些在我的项目子模块中构建的共享库的搜索路径。当时,我认为它比在系统范围内设置-Wl,-rpath=更好(我不想每次打开计算机时都进行设置)。一切正常,这两种方法似乎是等效的。

现在可以看出LD_LIBRARY_PATH的行为已更改。它仍然适用于直接依赖的库,但不适用于通过-rpath链接同一目录中的其他库的库。仍然可以像以前一样导出-rpath=

我使用LD_LIBRARY_PATH检查了编译的输出,但有所不同。在升级之前(带有GCC 5.4的Linux Mint 18.2),动态部分具有以下内容:

readelf

升级后(带有GCC 7.3的Linux Mint 19),该行更改为:

0x000000000000000f (RPATH)            Library rpath: [submod/lib]

use RPATH but not RUNPATH?中,建议将RPATH替换为RUNPATH(或者说,它至少具有不同的用途,因为它的优先级较低),但没有给出答案说明为什么会间接影响RPATH链接。库本身在0x000000000000001d (RUNPATH) Library runpath: [submod/lib] 输出中没有RPATH或RUNPATH。

所以我的问题是:为什么链接器突然开始以不同的方式解释readelf选项,并且有一种方法可以强制执行旧的行为?(或采取其他不同的措施将产生等效的结果。)

另一个问题是:是否可以告诉链接器的旧版本产生新的输出(即RUNPATH而不是RPATH)?


编辑

这不是How to set RunPath of a binary?的副本-我的问题是相反的:我想要RPATH的行为。我知道了(感谢评论中的技巧),我将在这里回答我的问题。

2 个答案:

答案 0 :(得分:4)

  

有没有办法强制旧行为?

是的。您可以使用此选项-Wl,--disable-new-dtags来告诉 new 链接程序使用 old 行为,即RPATH。

  

是否可以告诉链接器的旧版本产生新的输出(即RUNPATH而不是RPATH)?

是的。使用-Wl,--enable-new-dtags告诉 old 链接程序使用 new 行为,即RUNPATH。

我用readelf验证了可执行文件,这两个选项似乎可以控制ELF动态部分中的内容。我认为问题是由新版本默认值的更改引起的,尽管有趣的是,ld的手册页建议它应该仍然相同:

  

-enable-new-dtags
  --disable-new-dtags
                 该链接器可以在ELF中创建新的动态标签。但是较旧的ELF系统可能无法理解它们。如果指定   --enable-new-dtags,将根据需要创建新的动态标签,并                  较旧的动态代码将被省略。如果指定--disable-new-dtags,则不会创建新的动态标签。 默认情况下,不会创建新的动态代码。请注意,这些选项是                  仅适用于ELF系统。

答案 1 :(得分:1)

项目GNU Binutils(包含GNU链接器(ld))并不是这种行为改变的源头,而是Debian(2016)1和Gentoo(2013!)2。 / p>

根据Mike Frysinger于2013年1月提交的gentoo承诺:

  

“新” dtags选项已经存在了14年以上,因此   Linux和GNU目标,默认情况下启用它们。”

345并没有很好地接受此更改,因为RUNPATH和RPATH具有“未记录的行为差异” ... 令人惊讶的是,此更改现已应用于Debian稳定版。

问题是使用RUNPATH会导致无法预料的问题... 但主要只是可行。来自维基百科:

  

ld动态链接器不会在DT_RUNPATH位置中搜索以下内容   传递性依赖项,与DT_RPATH不同。