动态链接中的RPATH用法及详解

In computing, rpath designates the run-time search path hard-coded in an executable file or libraryDynamic linking loaders use the rpath to find required libraries.

Specifically it encodes a path to shared libraries into the header of an executable (or another shared library). This RPATH header value (so named in the Executable and Linkable Format header standards) may either override or supplement the system default dynamic linking search paths.

The rpath of an executable or shared library is an optional entry in the .dynamic section of the ELF executable or shared libraries, with the type DT_RPATH, called the DT_RPATH attribute. It can be stored there at link time by the linker. Tools such as chrpath and patchelf can create or modify the entry later.

 

Contents

Use of the DT_RPATH entry by the dynamic linker[edit]

The different dynamic linkers for ELF implement the use of the DT_RPATH attribute in different ways.

GNU ld.so[edit]

The dynamic linker of the GNU C Library searches for shared libraries in the following locations:[1]

  1. The (colon-separated) paths in the DT_RPATH dynamic section attribute of the binary if present and the DT_RUNPATH attribute does not exist.
  2. The (colon-separated) paths in the environment variable LD_LIBRARY_PATH, unless the executable is a setuid/setgid binary, in which case it is ignored. LD_LIBRARY_PATH can be overridden by calling the dynamic linker with the option --library-path (e.g. /lib/ld-linux.so.2 --library-path $HOME/mylibs myprogram).
  3. The (colon-separated) paths in the DT_RUNPATH dynamic section attribute of the binary if present.
  4. Lookup based on the ldconfig cache file (often located at /etc/ld.so.cache) which contains a compiled list of candidate libraries previously found in the augmented library path (set by /etc/ld.so.conf). If, however, the binary was linked with the -z nodefaultlib linker option, libraries in the default library paths are skipped.
  5. In the trusted default path /lib, and then /usr/lib. If the binary was linked with the -z nodefaultlib linker option, this step is skipped.

Notes:

      执行/lib64/ld-linux-x86-64.so.2 可看相关参数的解释。

  • The option --inhibit-rpath LIST of the dynamic linker instructs it to ignore DT_RPATH and DT_RUNPATH attributes of the object names in LIST.
  • Libraries specified by the environment variable LD_PRELOAD and then those listed in /etc/ld.so.preload are loaded before the search begins. A preload can thus be used to replace some (or all) of the requested library's normal functionalities, or it can simply be used to supply a library that would otherwise not be found.
  • Static libraries are searched and linked into the ELF file at link time and are not linked at run time.

The role of GNU ld[edit]

The GNU Linker (GNU ld) implements a feature which it calls "new-dtags", which can be used to insert an rpath that has lower precedence than the LD_LIBRARY_PATH environment variable. [2]

If the new-dtags feature is enabled in the linker (--enable-new-dtags), GNU ld, besides setting the DT_RPATH attribute, also sets the DT_RUNPATH attribute to the same string. At run time, if the dynamic linker finds a DT_RUNPATH attribute, it ignores the value of the DT_RPATH attribute, with the effect that LD_LIBRARY_PATH is checked first and the paths in the DT_RUNPATH attribute are only searched afterwards.

The ld dynamic linker does not search DT_RUNPATH locations for transitive dependencies, unlike DT_RPATH. [3]

Instead of specifying the -rpath to the linker, the environment variable LD_RUN_PATH can be set to the same effect.

Solaris ld.so[edit]

The dynamic linker of Solaris, specifically /lib/ld.so of SunOS 5.8 and similar systems looks for libraries in the directories specified in the LD_LIBRARY_PATH variable before looking at the DT_RPATH attribute. Sun Microsystems was the first[citation needed] to introduce dynamic library loading. Sun later added the rpath option to ld and used it in essential libraries as an added security feature. GNU ld did the same to support Sun-style dynamic libraries.

Example[edit]

This article contains instructions, advice, or how-to content. The purpose of Wikipedia is to present facts, not to train. Please help improve this article either by rewriting the how-to content or by moving it to WikiversityWikibooks or Wikivoyage(August 2018)

$ cc -shared -Wl,-soname,termcap.so.4,-rpath,/lib/termcap.so.4 -o termcap.so.4

$ objdump -a -x termcap.so.4
  NEEDED               libc.so.6
  SONAME               termcap.so.4
  RPATH                /lib/termcap.so.4

In this example, GNU or Sun ld (ld.so) will REFUSE to load termcap for a program needing it unless the file termcap.so is in /lib/ and named termcap.so.4. LD_LIBRARY_PATH is ignored. If /lib/termcap.so.4 is removed to remediate, the shell dies (one cannot load an alternate termcap.so and a rescue disk is needed, but also if a new termcap.so.4 has RPATH /lib, ld.so will refuse to use to load it unless it clobbered /lib/termcap.so.4). But there's another issue: it isn't safe to copy over some libs in /lib as they are "in use," further restricting the would-be lib tester. Furthermore, SONAME termcap.so.4 vs. SONAME termcap.so means programs needing basic termcap.so are denied because the library above deleted the ABI access to basic support.

$ cc -shared -Wl,-soname,libtermcap.so.2 -o libtermcap.so.2

$ objdump -a -x termcap.so.2
  NEEDED               libc.so.6
  SONAME               termcap.so.2

Old Linux/Sun used the above, which allows a user to direct any program to use any termcap.so they specify in LD_LIBRARY_PATH, or what is found in /usr/local/lib(n) using the search rules such as ld.so.conf. However, GNU ld always uses /lib or /usr/lib regardless before LD_LIBRARY_PATH, so first /lib/termcap.so is moved to /usr/local/lib and that mentioned in ld.so.conf, which enables use of moving libs and ld.so.conf or use of LD_LIBRARY_PATH to use. A preferred practice is to use "SONAME termcap.so" and have programs check version (all libs do support that) to use features available, but that was often skipped in old releases due to slow computing speed and lack of time to code correctly.

That being said, test this kind of thing thoroughly on a given platform before deciding to rely on it. Release administrators today are not guaranteed to respect past guidelines or documentation. Some UNIX varieties link and load in a completely different way. rpath is specific to ld shipped with a particular distribution.

Lastly, as said, rpath is a security feature however "mandatory access control" (MAC) and other techniques can be as effective or more effective than rpath to control lib reading and writing.

Control over rpath using today's compilers is often nearly impossible given lengthy and convoluted make(1) scripting. Worse, some build scripts ignore --disable-rpath even though they present it as an option. It would be time-consuming and frustrating, and probably unfeasible, to fix build scripting in every odd program to compile.

A simple sh(1) "wrapper" can call the real ld, named ld.bin. The wrapper can filter in/out -rpath option before invoking ld.

  #!/bin/sh
  # - filter ld options here -
  ld.bin $opts

However, note that some builds incorrectly use rpath instead of rpath-link or LD_LIBRARY_PATH or $(TOP)/dir/foo.so to locate intermediate products that stay in the build directory - thus backwardly demand rpath in the final product, which is a new issue concerning "what is rpath".

References[edit]

  1. Jump up^ "Linux / Unix Command: ld.so". man7.org. Retrieved 19 February 2018.
  2. Jump up^ "Shared Libraries: distribution and build-system issues". Official website of the Haskell Compiler. Retrieved 12 October 2011.
  3. Jump up^ https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/1253638
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值