Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I set DT_RPATH or DT_RUNPATH?

On Linux, the ld.so(8) man page discusses the search order for dynamic libraries. It says that DT_RPATH is deprecated, and also mentions DT_RUNPATH. There is no mention of the -rpath linker option.

The ld(1) man page mentions the -rpath and -rpath-link options, but never mentions DT_RPATH or DT_RUNPATH except in a describing the library search order, which of course does not match the information given in ld.so(8).

Finally there is an LD_RUN_PATH environment variable. ld(1) says it used if the -rpath and -rpath-link options are not set, but ld.so(8) does not mention it.

My intuition is that -rpath actually sets DT_RPATH, and -rpath-link sets DT_RUNPATH, but I cannot find this confirmed anywhere. I have always used -rpath; if it is the same as DT_RPATH than I should not use it, but the how-to articles I've found on dynamic linking say to use it, so I'm not sure it's the same.

Could someone clarify how DT_RPATH and DT_RUNPATH are set, and whether they are the same as -rpath and -rpath-link?

like image 464
Alcamtar Avatar asked Apr 16 '21 20:04

Alcamtar


2 Answers

When you are compiling a program, you create object files and then link them together. You may use GNU ld(1) to link them, there are also other linkers, LLVM linker. A linker combines object files into executable. GNU ld(1) is part of binutils with documentation available here.

When you execute an already compiled ready to use executable then the dynamic linker ld.so(8) finds the libraries on the system that the executable depends on, loads them and executes the executable. ld.so(8) is a shared library usually distributed as part of C standard library, usually on linux that's glibc, but there are also other, like musl.

I think it's confusing that both these programs are named "linker". One is like "compiling linker" and the other is "executable linker".

How do I set DT_RPATH or DT_RUNPATH?

Edit the elf file to include specific section.

When creating the elf file with GNU ld, nowadays you set RUNPATH section with -rpath=something. You can set RPATH section with --disable-new-dtags -rpath=something. RPATH is deprecated, so normally -rpath sets RUNPATH. https://www.javaer101.com/en/article/1127068.html *This does not check out on my system and I have to compile with gcc -Wl,--enable-new-dtags -Wl,-rpath=/tmp to set RUNPATH...

You can also set sections in any ELF file after compilation. See Can I change 'rpath' in an already compiled binary?

whether they are the same as -rpath and -rpath-link?

From ld documentation:

The difference between -rpath and -rpath-link is that directories specified by -rpath options are included in the executable and used at runtime, whereas the -rpath-link option is only effective at link time.

And the documentation also explains how -rpath-link works. It's to specify directories for searching dependent shared libraries.

Finally there is an LD_RUN_PATH environment variable

When compiling an executable GNU ld(1) also searches libraries in directories specified in this variable.

like image 146
KamilCuk Avatar answered Oct 02 '22 18:10

KamilCuk


The -rpath command line option used to create a DT_RPATH entry in the .dynamic section, but since DT_RPATH was deprecated in favor of DT_RUNPATH, modern linker versions use DT_RUNPATH instead. This means that using -rpath on a really old linker, you will create a dynamic section entry with .d_val = DT_RPATH, but if your linker is up to date, you will create one with .d_val = DT_RUNPATH instead.

The -rpath-link option is an option which does not create any entry, but is used to supersede the DT_RUNPATH entry present in the dynamic section of a library that is being linked. Therefore, when compiling, you should usually not need it. You can find more information on man 1 ld (scroll down to -rpath-link=) or in this other answer.

like image 41
Marco Bonelli Avatar answered Oct 02 '22 19:10

Marco Bonelli