mkogg.py: Fix 'self.get_mp4_metadata(self, source)'
[blog.git] / posts / rpath.mdwn
1 [[!meta  title="RPATH, RUNPATH, and dynamic linking"]]
2
3 Recently I've been working on the [[Comedi]] ebuild in my
4 [[Gentoo_overlay]], wrestling with the following error:
5
6     * QA Notice: The following files contain insecure RUNPATHs
7     *  Please file a bug about this at http://bugs.gentoo.org/
8     *  with the maintaining herd of the package.
9     * /usr/lib:/var/tmp/portage/sci-libs/comedilib-9999/work/comedilib-9999/lib/.libs usr/lib/ruby/site_ruby/1.8/i686-linux/comedi.so
10
11 While tracking this down the source of this error, I learned a lot
12 about dynamic linking on Linux, so here's the condensed version.
13
14 `RPATH`, `RUNPATH`, and `LD_LIBRARY_PATH`.  The current state of
15 affairs is well summarized on the [Debian wiki][wiki], which lists
16 the library search path:
17
18 1. the `RPATH` binary header (set at build-time) of the library
19    causing the lookup (if any)
20 2. the `RPATH` binary header (set at build-time) of the executable
21 3. the `LD_LIBRARY_PATH` environment variable (set at run-time)
22 4. the `RUNPATH` binary header (set at build-time) of the executable
23 5. `/etc/ld.so.cache`
24 6. base library directories (`/lib` and `/usr/lib`) 
25
26 There was a big dust-up between Debian and libtool back in 1999 when
27 libtool-generated `RPATH`s caused problems during the libc5 to libc6
28 transition.  The [mailing list discussion][list] makes for amusing and
29 informative reading, if you've got a spare hour or two ;).  If not,
30 you should at least read the opening post, the description of
31 [competing][c1] [contracts][c2], and Buddha Buck's description of [how
32 linking works][works], although I imagine things might have changed
33 since then.  The Debian / libtool compromise (don't set RPATH by
34 default for directories in the dynamic linker search path) was
35 implemented in libtool 1.5.2 (released in 2004, see the [Debian
36 wiki][wiki]), so this is not as big an issue as it once was.
37
38 By the way, it looks like `RUNPATH` was added since 1999 as a version
39 of `RPATH` that did not override `LD_LIBRARY_PATH`, which is good,
40 since `LD_LIBARY_PATH` gives you a way to link against libraries in,
41 say,
42 `/var/tmp/portage/sci-libs/comedilib-9999/work/comedilib-9999/lib/.libs`
43 to test your executable before installation.
44
45 Anyhow, [issues with rpaths persist][persist].  Since it both hard to
46 predict all installation configurations at compile time, and tools to
47 change rpaths later on (i.e. [chrpath][] and [patchelf][]) aren't able
48 to increase the size of the rpath string on Linux ([they can on
49 Solaris][solaris], because Solaris leaves a bit of padding at the end
50 of the dynamic string table in the compiled [ELF][] file).  This means
51 you will have trouble moving a library out of the standard library
52 path into some out-of-the-way location.  However, in the more common
53 case of installing a library *into* the standard library path,
54 `chrpath` is the tool you need, and it solved my comedilib QA issue.
55
56 Along the way, I ran across two other interesting posts by Diego
57 Pettenò about not [bundling][] [libraries][].
58
59 Setting `RPATH` and `RUNPATH`
60 -----------------------------
61
62 Most of the time, you'll want to avoid setting `RPATH` and `RUNPATH`
63 and just use libraries in your usual linking path.  However, sometimes
64 they are useful.  For example, [[SimulAVR]] depends on the
65 AVR-specific `libbfd`, which is hopefully not in your usual path.  On
66 Gentoo, [[crossdev|AVR]] installs under `/usr/lib/binutils/`:
67
68     $ binutils-config -c avr
69     avr-git
70     $ grep PATH /etc/env.d/binutils/avr-git 
71     LIBPATH="/usr/lib/binutils/avr/git"
72
73 When you link against this library, you'll want to set `RUNPATH` so
74 you don't have to remember to use `LD_LIBRARY_PATH` every time you run
75 `simulavr`.  Of course, if you switch to a different binutils version
76 (e.g. not `git`), you'll need to fix the `RUNPATH` to point to the new
77 target (or just rebuild `simulavr` against the new version).
78
79 Since you're probably not calling the linker directly when you build
80 `simulavr`, you'll want to set some linker flags at configure time:
81
82     $ LDFLAGS=-Wl,-rpath=/usr/lib/binutils/avr/git,--enable-new-dtags ./configure â€¦
83
84 The relevant linker flags are `-rpath` and `--enable-new-dtags`.
85 Without `--enable-new-dtags`, you'll just set the `RPATH` flag, which
86 is probably not what you want.  With `--enable-new-dtags`, you'll set
87 both `RPAH` and `RUNPATH` to the same value.  From `ld(1)`:
88
89 > The `DT_RPATH` entries are ignored if `DT_RUNPATH` entries exist.
90
91 so setting both is the same as just setting `RUNPATH` (except for
92 tools like `chrpath` which are only designed to handle a single tag).
93 You can use [readelf][] to see if the tags were set:
94
95     $ readelf --dynamic /usr/bin/simulavr | grep PATH
96      0x000000000000000f (RPATH)    Library rpath: [/usr/lib/binutils/avr/git]
97      0x000000000000001d (RUNPATH)  Library runpath: [/usr/lib/binutils/avr/git]
98
99 On Gentoo, `--enable-new-dtags` has been [the default since
100 2005][default], but explicitly including the flag can't hurt ;).
101
102 [wiki]: http://wiki.debian.org/RpathIssue
103 [list]: http://www.mail-archive.com/debian-devel@lists.debian.org/msg61772.html
104 [c1]: http://www.mail-archive.com/debian-devel@lists.debian.org/msg61787.html
105 [c2]: http://www.mail-archive.com/debian-devel@lists.debian.org/msg61796.html
106 [works]: http://www.mail-archive.com/debian-devel@lists.debian.org/msg61967.html
107 [persist]: http://blog.flameeyes.eu/2010/06/20/the-why-and-how-of-rpath
108 [chrpath]: http://directory.fsf.org/wiki/Chrpath
109 [patchelf]: http://nixos.org/patchelf.html
110 [solaris]: http://blogs.sun.com/ali/entry/changing_elf_runpaths
111 [ELF]: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
112 [bundling]: http://blog.flameeyes.eu/2009/01/02/bundling-libraries-for-despair-and-insecurity
113 [libraries]: http://blog.flameeyes.eu/2009/03/23/bundling-libraries-the-curse-of-the-ancients
114 [readelf]: http://www.gnu.org/software/binutils/
115 [default]: http://comments.gmane.org/gmane.comp.gnu.binutils/57379
116
117 [[!tag tags/linux]]