Gentoo Linux Prelink Guide
1. Introduction
What is Prelink and how can it help me?
Most common applications make use of shared libraries. These shared
libraries need to be loaded into memory at runtime and the various symbol
references need to be resolved. For most small programs this dynamic
linking is very quick. But for programs written in C++ and that have many
library dependencies, the dynamic linking can take a fair amount of time.
On most systems, libraries are not changed very often and when a program is
run, the operations taken to link the program are the same every time.
Prelink takes advantage of this by carrying out the linking and storing it
in the executable, in effect prelinking it. In order for the linker, you
need ld-linux.so in glibc; to recognize the prelinking you need
>=glibc-2.3.1-r2.
Prelinking can cut the startup times of applications. For example,
a typical KDE program's loading time can be cut by as much as 50%. The only
maintenance required is re-running prelink every time a library is upgraded
for a pre-linked executable.
Summary
-
Prelinking is done via a program called, surprisingly, prelink.
It changes the binary to make it start faster.
-
If an application's dependent libraries change after you have prelinked it,
you need to re-prelink the application, otherwise you lose the speed
advantage. This is to say, everytime you update a package via portage that
updates libraries, they need to be re-prelinked.
-
The change to the binary is fully reversible. prelink has an
undo function.
-
Newer versions of Portage can handle, via prelink, the changing
MD5sums and mtimes of the binaries.
-
You need to have glibc-2.3.1-r2 or greater installed with the binaries
compiled with binutils-2.13.90.0.xx or greater.
2. Setting up Prelink
Installing the Programs
Note:
I assume you have a Gentoo-1.4 system and it was built with gcc-3.2 or
better and binutils-2.13.90.0.xx or better. This needs to be so in order for
your binaries to be prelinkable.
|
Warning:
You must have glibc-2.3.1-r2 or newer installed otherwise prelink
will zap all your binaries!
|
First update your portage tree, as many of the needed applications are new
and bug-fixes are constantly added.
Code Listing 2.1: Updating your Portage Tree |
# emerge --sync
|
Next make sure you have portage-2.0.46 or better installed. This is needed so
that portage can recognize the prelinked binaries and thus uninstall them
correctly when requested. This is because prelinking changes the MD5sum of a
binary.
Code Listing 2.2: Checking Portage Version |
# emerge ">=portage-2.0.46"
|
Now you can emerge the prelinking tool. The emerge process automatically
verifies that your system can prelink safely.
Code Listing 2.3: Installing Prelink |
# emerge prelink
|
A number of people get errors in emerging prelink because of the failed
tests. The tests were put in for safety reasons, prelink's behavior is
undefined if you disable them. The emerge errors are usually only dependent
on the core packages; binutils, gcc, and glibc. Try re-emerging those
packages in that order.
Note:
Tip: If you get an error try compiling and testing prelink yourself
(./configure ; make ; make check ). On a failure you can
view the *.log files in the testsuite directory. They may provide you with
some useful clues.
|
If you have a set of steps that reproduces the emerge error on another system
please e-mail them to Stefan Jones.
Configuration
Portage automatically generates the file /etc/prelink.conf
that tells prelink which files to prelink.
Unfortunately you cannot prelink files that were compiled by old versions
of binutils. Most of these applications come from pre-compiled, binary
only packages which are installed in /opt. Making the
following file will tell prelink not to attempt to prelink them.
Code Listing 2.4: /etc/env.d/60prelink |
PRELINK_PATH_MASK="/opt"
|
Note:
You can add more or less directories to the colon separated list.
|
3. Prelinking
Prelink Usage
I use the following command to prelink all the binaries in the directories
given by /etc/prelink.conf.
Code Listing 3.1: Prelinking listed files |
# prelink -afmR
|
Warning:
It has been observed that if you are low on disk space and you prelink your
entire system then there is a possibility that your binaries may be truncated.
The result being a b0rked system. Use the file or readelf
command to check the state of a binary file. Alternatively, check the amount
of free space on your harddrive ahead of time with df -h.
|
The options explained: |
-a |
"All": prelinks all the binaries |
-f |
Force prelink to re-prelink already
prelinked binaries. This is needed as prelink
aborts if old prelinked files are present and their library
dependencies have changed.
|
-m |
Conserve the virtual memory space. This is needed if you
have a lot of libraries that need to be prelinked.
|
-R |
Random -- randomize the address ordering, this enhances
security against buffer overflows.
|
Note:
For more options and details see man prelink.
|
Speeding Up KDE After Prelinking
KDE's loading time can be greatly reduced after prelinking. If you inform KDE
that it has been prelinked it will disable the loading of kdeinit (as it
isn't required anymore) which speeds up KDE even more.
Set KDE_IS_PRELINKED="true" in /etc/env.d/99kde-env to
inform KDE about the prelinking.
4. Known Problems and Fixes
"Cannot prelink against non-PIC shared library"
The cause of this problem is from badly compiled shared libraries that were
compiled without the -fPIC gcc option for all their object files.
The following is a list of the problem libraries and which packages to
re-emerge if you have the above error.
Code Listing 4.1: Fixes |
# emerge ">=sys-apps/tcp-wrappers-7.6-r4" ORBit
# emerge ">=sys-libs/zlib-1.1.4"
# emerge ">=media-libs/svgalib-1.9.16"
# emerge ">=x11-base/xfree-4.2.1-r2"
# emerge ">=net-libs/libpcap-0.7.1-r2"
# emerge ">=media-libs/lcms-1.09"
|
Note:
Many libraries link statically to zlib and/or tcp-wrappers so first try
emerging those and re-emerging the problem library.
|
If you are having trouble with prelinking QT/KDE, then first try upgrading to
>=x11-base/xfree-4.2.1-r2 and >=x11-libs/qt-3.1.0-r1. If QT still fails then
try compiling QT without xinerama support by adding myconf="-no-xinerama
${myconf}" in the qt ebuild.
Here are the libraries that haven't been fixed or cannot be fixed:
-
The libraries in the wine package, including winex. Prelinking
wouldn't speed up MS Windows executables anyway.
-
The library in media-video/mjpegtools,
/usr/lib/liblavfile-1.6.so.0.
If your problem library was not listed please report it with, preferably, a
patch to add -fPIC to the relevant CFLAGS.
Abort while prelinking a file, like "1631 Aborted ...."
You need to use the -f option for prelink;
i.e., reprelink the entire system from scratch. Try prelink -af.
"<file>: error while loading shared libraries: unexpected
reloc type..."
This has been fixed in sys-libs/glibc-2.3.1-r2 on 2002/11/18,
re-emerge glibc if yours is older.
Also doing prelink -u -a -m ; prelink -a -m has been known
to help. If all else fails just do prelink -u <file>.
I have problems with Nvidia openGL libraries
The accelerated openGL libraries that come in the nvidia-glx package have
been compiled in a non-standard way and so prelink will throw
warnings. This is nothing to worry about and cannot be fixed by anyone except
nvidia. You can always revert to the xfree version of libGL.so if you don't
need 3D acceleration. The nvidia xfree driver works fine though.
When I prelink my system some static binaries don't work anymore
Where glibc is concerned, there is no such thing as a 100% static binary.
If you statically compile a binary with glibc, it may still depend on other
system files. Below is an explanation by Dick Howell,
"I suppose the idea is that everything will be in the downloaded file,
so nothing depends on the local libraries on the target system. Unfortunately
with Linux, and I think anything else using GLIBC, this still isn't quite
true. There's this "libnss" (name service switch, some people seem to call it
network security system) which provides functions for accessing various
databases for authentication, network information, and other things. It's
supposed to make application programs independent of the separately configured
actual network environment of the machine. A nice idea, but changes to GLIBC
can lead to problems loading it. And you can't statically link "libnss", since
it is configured for each machine individually. The problem comes, I think,
mainly from statically linking other GLIBC libraries, notably "libpthread",
"libm", and "libc", from which come incompatible calls to "libnss"
functions."
Prelink aborts with "prelink: dso.c:306: fdopen_dso: Assertion
`j == k' failed."
This a known problem, kindly diagnosed here.
Prelink cannot cope with UPX-compressed executables. As of prelink-20021213
there is no fix except to hide the executables while you are prelinking.
See the Configuration section
above for an easy way to do this.
I use grsecurity and it seems that prelinking doesn't work.
In order to prelink on a system with grsecurity using a
randomized mmap() base, it is necessary to turn "randomized mmap()
base" OFF for /lib/ld-2.3.*.so. This can be done with
the chpax utility, but it must be done when the file is not
in use (f.i. boot from a rescue CD).
5. Conclusion
Prelinking can drastically speed up the start up times for a number of
large applications. Support is built into Portage. Prelinking is also safe
as you can always undo the prelinking for any binary if you come across any
problems. Just remember that when you update glibc or other libraries that
you prelinked with, you need to rerun prelink!
In short good luck!
The contents of this document are licensed under the Creative Commons - Attribution / Share Alike license.
|