2008-02-10
A basic introduction to prelinking on Linux
At least on the x86 architecture, shared libraries are not entirely made up of position independent code. This means that there is a certain amount of relocation that you have to do when you load a shared library into memory at run time. The basic idea behind prelinking is to try to do this relocation ahead of time; for each shared library, you pick a default location in memory and 'prelink' it so that if it is loaded at that location it doesn't need any run-time relocation. Then the dynamic loader tries to load prelinked libraries at their prelinked locations if at all possible.
(The exact details are explained in the prelink manpage.)
Prelinking has two advantages: because they need to do less relocation at runtime, programs both start faster and use less memory (they dirty fewer pages of shared libraries with per-process relocations). It has the downside that it changes shared libraries and binaries on disk for each system (and changes them again any time you upgrade a shared library), which makes various sorts of security verification harder.
Red Hat enables prelinking by default (in both Fedora and Red Hat Enterprise). Ubuntu and Debian do not seem to do so, although you can turn it on by installing the prelink package and configuring it appropriately.
Prelinking is not a new idea. The first implementation I remember seeing was in SGI's Irix, but in a sense its ancestry goes back to some of the first shared library implementations, which had no dynamic relocation and just statically assigned addresses to shared libraries.
Sidebar: prelink and DT_GNU_HASH
The first time dynamically linked code wants to do something like call
an external function, it has to look through all of the symbol tables in
all of the various bits of code to find the function. DT_GNU_HASH
is the name of a GNU extension to use efficient, fast to search
hash tables for these symbol tables; it and related optimizations can significantly speed up practical
program startup time.
Unlike prelinking, DT_GNU_HASH
is done once when a shared library is
built. Because these lookups have to be done whether or not the shared
libraries involved have been prelinked, prelinking and DT_GNU_HASH
are complementary and systems can do both.
Modern versions of Red Hat (both Fedora and Enterprise) use
DT_GNU_HASH
; Debian stable does not. Ubuntu 6.06 (their long term
support release) does not, but I believe that current versions do.