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

问题描述 投票:3回答:2

我最近在升级系统后遇到了这个问题:使用GCC -Wl,-rpath=选项的工作方式与以前不同。

我用它来设置一些共享库的搜索路径,这些库是在我项目的子模块中构建的。当时我认为它比在系统范围内设置LD_LIBRARY_PATH更好(我不想每次打开电脑时都设置它)。一切都很好,这两种方法似乎相同。

现在它接近-rpath的行为发生了变化。它仍适用于直接依赖库,但不适用于通过-rpath=链接同一目录集中的其他库的库。出口LD_LIBRARY_PATH仍然像以前一样工作。

我使用readelf检查了编译的输出,并且存在差异。在升级之前(Linux Mint 18.2 with GCC 5.4),Dynamic部分有这一行:

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

升级后(Linux Mint 19 with GCC 7.3),该行改为:

0x000000000000001d (RUNPATH)            Library runpath: [submod/lib]

use RPATH but not RUNPATH?中,建议将RPATH替换为RUNPATH(或者它至少服务器具有不同的目的,因为它具有较低的优先级),但它没有给出为什么这会影响间接链接的答案。库本身在readelf输出中既没有RPATH,也没有RUNPATH。

所以我的问题是:为什么链接器突然开始以不同的方式解释-rpath=选项,有没有办法强制旧的行为? (或者做一些不同的事情,产生相同的结果。)

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


编辑

这不是How to set RunPath of a binary?的重复 - 我的问题恰恰相反:我想要RPATH的行为。我想通了(感谢评论中的提示),我将在这里回答我的问题。

linux gcc shared-libraries ld dynamic-linking
2个回答
4
投票

有没有办法强迫旧的行为?

是。您可以使用此选项-Wl,--disable-new-dtags告诉新链接器使用旧行为,即RPATH。

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

是。使用-Wl,--enable-new-dtags告诉旧链接器使用新行为,即RUNPATH。

我用readelf验证了可执行文件,这两个选项似乎控制了将在ELF Dynamic部分中编写的内容。我认为这个问题是由新版本默认值的变化引起的,尽管有趣的是,ld的手册页表明它应该仍然是相同的:

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


1
投票

项目GNU Binutils(包含GNU链接器(ld))不是这种行为变化的起源,而是Debian(2016)1和Gentoo(2013!)2

根据Mike Frysinger在2013年1月的gentoo提交:

“新的”dtags选项已经存在了14年多,所以对于Linux和GNU目标,默认情况下启用它们。“

这种变化不太受欢迎345,因为RUNPATH和RPATH具有“无证件行为差异”......令人惊讶的是,这种变化现在应用于Debian稳定版。

问题是使用RUNPATH会导致不可预测的问题...但主要是起作用。来自维基百科:

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

© www.soinside.com 2019 - 2024. All rights reserved.