aboutsummaryrefslogtreecommitdiffstats
path: root/doc/prelink.tex
diff options
context:
space:
mode:
Diffstat (limited to 'doc/prelink.tex')
-rw-r--r--doc/prelink.tex3643
1 files changed, 3643 insertions, 0 deletions
diff --git a/doc/prelink.tex b/doc/prelink.tex
new file mode 100644
index 0000000..5075030
--- /dev/null
+++ b/doc/prelink.tex
@@ -0,0 +1,3643 @@
+\documentclass[twoside]{article}
+
+\def\docversion{0.7}
+% timezone: +01 == CET
+\def\timezone{+01}
+% Uncomment for draft print.
+\def\isdraft{1}
+
+\newif\ifpdf
+\ifx\pdfoutput\undefined
+ \pdffalse % we are not running PDFLaTeX
+\else
+ \pdfoutput=1 % we are running PDFLaTeX
+ \pdftrue
+\fi
+
+\usepackage{linuxtag}
+\usepackage{times}
+\usepackage{makeidx}
+\usepackage{nomencl}
+\usepackage[square]{natbib}
+\usepackage{marvosym}
+\usepackage{longtable}
+\renewcommand\bibsection{\chapter{\bibname}}
+
+\ifpdf
+ \usepackage[pdftex]{graphics}
+ \usepackage{type1cm}
+ \usepackage{thumbpdf}
+ \pdfcompresslevel9
+ \pdfinfo{/CreationDate (D:20030924012900\timezone'00')}
+ % The following code to set /ModDate comes from Heiko Oberdiek's paper
+ % one PDF & hyperref. I only added the \timezone stuff.
+ \begingroup
+ \def\twodigits#1{\ifnum#1<10 0\fi\the#1}%
+ \count0=\time \divide\count0 by 60
+ \edef\x{\twodigits{\count0}}%
+ \multiply\count0 by 60
+ \count1=\time \advance\count1 by -\count0
+ \edef\x{\x\twodigits{\count1}}%
+ \edef\x{/ModDate (D:\the\year \twodigits\month \twodigits\day \x 00\timezone'00')}%
+ \expandafter\endgroup
+ \expandafter\pdfinfo\expandafter{\x}%
+ \input pdfcolor
+
+ %% For a "Draft" mark on the pages uncomment the following:
+ \ifx\isdraft\undefined
+ \relax
+ \else
+ \usepackage{eso-pic}
+ \usepackage{color}
+ \makeatletter
+ \AddToShipoutPicture{\rm%
+ \setlength{\@tempdimb}{.5\paperwidth}%
+ \setlength{\@tempdimc}{.5\paperheight}%
+ \setlength{\unitlength}{1pt}%
+ \put(\strip@pt\@tempdimb,\strip@pt\@tempdimc){%
+ \makebox(0,0){\rotatebox{45}{\textcolor[gray]{0.9}{\fontsize{5cm}{5cm}\selectfont{Draft}}}}
+ }
+ }
+ \makeatother
+ \fi
+\else
+ \usepackage[dvips]{graphics}
+\fi
+
+\def\titlecolor{NavyBlue}
+\makeatletter
+\def\@sect#1#2#3#4#5#6[#7]#8{%
+ \ifnum #2>\c@secnumdepth
+ \let\@svsec\@empty
+ \else
+ \refstepcounter{#1}%
+ \protected@edef\@svsec{\@seccntformat{#1}\relax}%
+ \fi
+ \@tempskipa #5\relax
+ \ifdim \@tempskipa>\z@
+ \begingroup
+ \hbox{\expandafter\csname\titlecolor\endcsname#6{%
+ \@hangfrom{\hskip #3\relax\@svsec}%
+ \interlinepenalty \@M #8\@@par}\Black}%
+ \endgroup
+ \csname #1mark\endcsname{#7}%
+ \addcontentsline{toc}{#1}{%
+ \ifnum #2>\c@secnumdepth \else
+ \protect\numberline{\csname the#1\endcsname}%
+ \fi
+ #7}%
+ \else
+ \def\@svsechd{%
+ \hbox{\expandafter\csname\titlecolor\endcsname#6{\hskip #3\relax
+ \@svsec #8}%
+ \csname #1mark\endcsname{#7}\Black}%
+ \addcontentsline{toc}{#1}{%
+ \ifnum #2>\c@secnumdepth \else
+ \protect\numberline{\csname the#1\endcsname}%
+ \fi
+ #7}}%
+ \fi
+ \@xsect{#5}}
+\def\@ssect#1#2#3#4#5{%
+ \@tempskipa #3\relax
+ \ifdim \@tempskipa>\z@
+ \begingroup
+ \expandafter\csname\titlecolor\endcsname#4{%
+ \@hangfrom{\hskip #1}%
+ \interlinepenalty \@M #5\@@par}\Black%
+ \endgroup
+ \else
+ \def\@svsechd{\expandafter\csname\titlecolor\endcsname#4{\hskip #1\relax #5}\Black}%
+ \fi
+ \@xsect{#3}}
+\makeatother
+
+\usepackage{fancyheadings}
+\pagestyle{fancy}
+\rhead{}
+\chead{}
+\lhead{}
+\rfoot[\sl Prelink]{\thepage}
+\lfoot[\thepage]{\sl Jakub Jel\'\i nek}
+\ifx\isdraft\undefined
+\cfoot{Version \docversion}
+\else
+\cfoot{Draft \docversion}
+\fi
+\renewcommand{\headrulewidth}{0.4pt}
+\renewcommand{\footrulewidth}{0.4pt}
+
+\ifx\isdraft\undefined
+\relax
+\else
+\usepackage[mathlines]{lineno}
+\fi
+
+\usepackage{graphicx}
+\usepackage{hyperref}
+\hypersetup{
+ bookmarksnumbered,
+ bookmarksopen=true,
+ pdfpagemode=UseOutlines,
+ pdfkeywords={Prelink, ELF, DSO, Shared Library, Dynamic Linking, Linux}
+}
+\usepackage{prelinklisting}
+
+\def\tts#1{\texttt{\small #1}}
+
+\setcounter{dbltopnumber}{3}
+
+
+\makeatletter
+\newcommand{\annotate}[2][]{%
+ \marginpar{%
+ \pdfstringdef\x@title{#1}%
+ \edef\r{\string\r}%
+ \pdfstringdef\x@contents{#2}%
+ \pdfannot
+ width 50em%\linewidth
+ height .5\baselineskip
+ depth 2.5\baselineskip
+ {
+ /Subtype /Text
+ /T (\x@title)
+ /Contents (\x@contents)
+ }%
+ }
+ }
+\makeatother
+
+\makeglossary
+\makeindex
+
+\begin{document}
+
+ \makeatletter
+ \newcommand\orgmaketitle{}
+ \let\orgmaketitle\maketitle
+ \def\maketitle{%
+ \hypersetup{
+ pdftitle={\@title},
+ pdfsubject={Description of prelink tool},
+ pdfauthor={\@author}
+ }%
+ \orgmaketitle
+ }
+ \makeatother
+
+\title{Prelink}
+\author{Jakub Jel\'\i nek\\
+Red Hat, Inc.\\
+{\small\tt\href{mailto:jakub@redhat.com}{jakub@redhat.com}}}
+
+%\maketitle
+
+%\tableofcontents
+%\vfil\break
+%\listoftables
+%\vfil\break
+%\listofprelinklistings
+%\vfil\break
+%\listoffigures
+%\vfil\break
+
+\maketitle
+
+\begin{center}
+\begin{abstract}
+\vspace*{.5\baselineskip}
+\parbox{0.8\textwidth}{%
+Prelink is a tool designed to speed up dynamic linking of ELF
+programs on various Linux architectures.
+It speeds up start up of OpenOffice.org 1.1 by 1.8s from 5.5s on 651MHz Pentium III.}
+\end{abstract}
+\end{center}
+
+\ifx\isdraft\undefined
+ \relax
+\else
+ \linenumbers
+ \linenumbersep4pt
+\fi
+
+\section{Preface}
+
+In 1995, Linux changed its binary format from \tts{a.out} to \tts{ELF}.
+The \tts{a.out} binary format was very inflexible and shared libraries
+were pretty hard to build. Linux's shared libraries in \tts{a.out} are position
+dependent and each had to be given a unique virtual address space slot
+at link time. Maintaining these assignments was pretty hard even when
+there were just a few shared libraries, there used to be a central address
+registry maintained by humans in form of a text file, but it is certainly
+impossible to do these days when there are thousands of different shared libraries
+and their size, version and exported symbols are constantly changing.
+On the other side, there was just minimum amount of work the dynamic
+linker had to do in order to load these shared libraries, as relocation
+handling and symbol lookup was only done at link time. The dynamic linker
+used the \tts{uselib} system call which just mapped the named library
+into the address space (with no segment or section protection differences,
+the whole mapping was writable and executable).
+
+The \href{http://www.caldera.com/developers/devspecs/gabi41.pdf}%
+{\tts{ELF}}
+\footnote{As described in generic ABI document [1] and various processor
+specific ABI supplements [2], [3], [4], [5], [6], [7], [8].}
+binary format is one of the most flexible binary formats,
+its shared libraries are easy to build and there is no need for a central
+assignment of virtual address space slots. Shared libraries are position
+independent and relocation handling and symbol lookup are done partly
+at the time the executable is created and partly at runtime. Symbols in shared
+libraries can be overridden at runtime by preloading a new shared
+library defining those symbols or without relinking an executable by adding
+symbols to a shared library which is searched up earlier during symbol
+lookup or by adding new dependent shared libraries to a library used by the
+program. All these improvements have their price, which is a slower
+program startup, more non-shareable memory per process and runtime cost
+associated with position independent code in shared libraries.
+
+Program startup of \tts{ELF} programs is slower than startup of \tts{a.out}
+programs with shared libraries, because the dynamic linker has much more work
+to do before calling program's entry point. The cost of loading libraries
+is just slightly bigger, as \tts{ELF} shared libraries have typically
+separate read-only and writable segments, so the dynamic linker
+has to use different memory protection for each segment.
+The main difference is in relocation handling and associated symbol lookup.
+In the \tts{a.out} format there was no relocation handling or symbol lookup at runtime.
+In \tts{ELF}, this cost is much more important today than it used to be
+during \tts{a.out} to \tts{ELF} transition in Linux, as especially GUI
+programs keep constantly growing and start to use more and more shared
+libraries. 5 years ago programs using more than 10 shared libraries
+were very rare, these days most of the GUI programs link against around
+40 or more shared and in extreme cases programs use even more than 90
+shared libraries. Every shared library adds its set of dynamic relocations
+to the cost and enlarges symbol search scope,
+\nomenclature{Symbol Search Scope}{The sequence of \tts{ELF} objects in
+which a symbol is being looked up. When a symbol definition is found,
+the searching stops and the found symbol is returned. Each program
+has a global search scope, which starts by the executable, is typically
+followed by the immediate dependencies of the executable and then their
+dependencies in breadth search order (where only first occurrence
+of each shared library is kept). If \tts{DT\_FILTER}
+or \tts{DT\_AUXILIARY} dynamic tags are used the order is slightly
+different. Each shared library loaded with \tts{dlopen} has its
+own symbol search scope which contains that shared library and
+its dependencies. \tts{Prelink} operates also with natural
+symbol search scope of each shared library, which is the global
+symbol search scope the shared library would have if it were started
+as the main program}
+so in addition to doing more symbol lookups, each symbol
+lookup the application has to perform is on average more expensive.
+Another factor increasing the cost is the length of symbol names
+which have to be compared when finding symbol in the symbol hash table of
+a shared library. C++ libraries tend to have extremely long symbol
+names and unfortunately the new \href{http://www.codesourcery.com/cxx-abi/}%
+{C++ ABI} puts namespaces and class names first and method names last
+in the mangled names, so often symbol names differ only in last
+few bytes of very long names.
+
+Every time a relocation is applied the entire memory page
+\nomenclature{Page}{Memory block of fixed size which virtual memory
+subsystem deals with as a unit. The size of the page depends on
+the addressing hardware of the processor, typically pages are 4K or 8K,
+in some cases bigger}
+containing the address which is written to must be loaded into memory.
+The operating system does a copy-on-write operation which also has the
+consequence that the physical memory of the memory page cannot anymore
+be shared with other processes.
+With \tts{ELF}, typically all of program's Global Offset Table,
+\nomenclature{Global Offset Table (\tts{GOT})}{When position independent
+code needs to build address which requires dynamic relocation, instead
+of building it as constant in registers and applying a dynamic relocation
+against the read-only segment (which would mean that any pages of the
+read-only segment where relocations are applied cannot be shared between
+processes anymore), it loads the address from an offset table
+private to each shared library, which is created by the linker.
+The table is in writable segment and relocations are applied against it.
+Position independent code uses on most architectures a special \tts{PIC}
+register which points to the start of the Global Offset Table}
+constants and variables containing pointers to objects in shared libraries, etc.
+are written into before the dynamic linker passes control over to the program.
+
+On most architectures (with some exceptions like \tts{AMD64} architecture)
+position independent code requires that one register needs to be dedicated as
+\tts{PIC} register and thus cannot be used in the functions for other purposes.
+This especially degrades performance on register-starved
+architectures like \tts{IA-32}. Also, there needs to be some code to
+set up the \tts{PIC} register, either invoked as part of function prologues,
+or when using function descriptors in the calling sequence.
+
+\tts{Prelink} is a tool which (together with corresponding dynamic linker
+and linker changes) attempts to bring back some of the \tts{a.out}
+advantages (such as the speed and less COW'd pages) to the \tts{ELF}
+binary format while retaining all of its flexibility. In a limited way
+it also attempts to decrease number of non-shareable pages created by
+relocations.
+\tts{Prelink} works closely with the dynamic linker in the GNU C library,
+but probably it wouldn't be too hard to port it to some other \tts{ELF}
+using platforms where the dynamic linker can be modified in similar
+ways.
+
+\section{Caching of symbol lookup results}
+
+Program startup can be speeded up by caching of symbol lookup
+results\footnote{Initially, this has been implemented in the \tts{prelink}
+tool and \tts{glibc} dynamic linker, where \tts{prelink} was sorting
+relocation sections of existing executables and shared libraries.
+When this has been implemented in the linker as well and most executables
+and shared libraries are already built with \tts{-z combreloc},
+the code from \tts{prelink} has been removed, as it was no longer
+needed for most objects and just increasing the tool's complexity.}.
+Many shared libraries need more than one lookup of a particular symbol.
+This is especially true for C++ shared libraries, where e.g. the same method
+is present in multiple virtual tables or {\sl RTTI} data structures.
+\nomenclature{RTTI}{C++ runtime type identification}
+Traditionally, each \tts{ELF} section which needs dynamic relocations has an
+associated \tts{.rela*} or \tts{.rel*} section (depending on whether
+the architecture is defined to use \tts{RELA} or \tts{REL} relocations).
+\nomenclature{RELA}{Type of relocation structure which includes offset,
+relocation type, symbol against which the relocation is and an integer
+addend which is added to the symbol. Memory at offset is not supposed
+to be used by the relocation. Some architectures got this implemented
+incorrectly and memory at offset is for some relocation types used
+by the relocation, either in addition to addend or addend is not used
+at all. \tts{RELA} relocations are generally better for \tts{prelink},
+since when \tts{prelink} stores a pre-computed value into the memory location
+at offset, the addend value is not lost}
+\nomenclature{REL}{Type of relocation structure which includes just offset,
+relocation type and symbol. Addend is taken from memory location at
+offset}
+The relocations in those sections are typically sorted by ascending
+\tts{r\_offset} values.
+Symbol lookups are usually the most expensive operation during program
+startup, so caching the symbol lookups has potential to decrease time
+spent in the dynamic linker.
+One way to decrease the cost of symbol lookups is to create a table with the
+size equal to number of entries
+in dynamic symbol table (\tts{.dynsym}) in the dynamic linker when resolving
+a particular shared library, but that would in some cases need a lot of
+memory and some time spent in initializing the table. Another option
+would be to use a hash table with chained lists, but that needs both
+extra memory and would also take extra time for computation of the hash value
+and walking up the chains when doing new lookups.
+Fortunately, neither of this is really necessary if we modify the linker
+to sort relocations so that relocations against the same symbol
+are adjacent. This has been done first in the \tts{Sun} linker and dynamic
+linker, so the GNU linker and dynamic linker use the same \tts{ELF} extensions
+and linker flags. Particularly, the following new \tts{ELF} dynamic tags have been introduced:
+
+\tts{\#define DT\_RELACOUNT 0x6ffffff9}\\
+\tts{\#define DT\_RELCOUNT 0x6ffffffa}
+
+New options \tts{-z combreloc} and \tts{-z nocombreloc} have been
+added to the linker. The latter causes the previous linker behavior,
+i.e. each section requiring relocations has a corresponding relocation section,
+which is sorted by ascending \tts{r\_offset}. \tts{-z combreloc}
+\footnote{\tts{-z combreloc} is the default in GNU linker versions
+2.13 and later.} instructs the linker to create just one relocation
+section for dynamic relocations other than symbol jump table (\tts{PLT})
+relocations.
+\nomenclature{PLT}{Process Linkage Table. Stubs in \tts{ELF} shared
+libraries and executables which allow lazy relocations of function calls.
+They initially point to code which will do the symbol lookup. The
+result of this symbol lookup is then stored in the Process Linkage Table
+and control transfered to the address symbol lookup returned. All
+following calls to the \tts{PLT} slot just branch to the already looked
+up address directly, no further symbol lookup is needed}
+This single relocation section (either \tts{.rela.dyn} or \tts{.rel.dyn})
+is sorted, so that relative relocations come first (sorted by ascending
+\tts{r\_offset}), followed by other relocations, sorted again by ascending
+\tts{r\_offset}. If more relocations are against the same
+symbol, they immediately follow the first relocation against that symbol
+with lowest \tts{r\_offset}.
+\footnote{In fact the sorting needs to take into account also the type of
+lookup. Most of the relocations will resolve to a \tts{PLT} slot in the executable
+if there is one for the lookup symbol, because the executable might have a
+pointer against that symbol without any dynamic relocations. But e.g.
+relocations used for the \tts{PLT} slots must avoid these.}.
+\nomenclature{relative relocation}{Relocation, which doesn't need a symbol
+lookup, just adds a shared library load offset to certain memory location
+(or locations)}
+The number of relative relocations at the beginning of the section
+is stored in the \tts{DT\_RELACOUNT} resp. \tts{DT\_RELCOUNT} dynamic tag.
+
+The dynamic linker can use the new dynamic tag for two purposes.
+If the shared library is successfully mapped at the same address
+as the first \tts{PT\_LOAD} segment's virtual address, the load offset
+is zero and the dynamic linker can avoid all the relative relocations which
+would just add zero to various memory locations. Normally shared libraries are
+linked with first \tts{PT\_LOAD} segment's virtual address set to zero, so
+the load offset is non-zero. This can be changed through a linker script or by
+using a special \tts{prelink} option \tts{--reloc-only} to change
+the base address of a shared library. All prelinked shared libraries
+have non-zero base address as well. If the load offset is non-zero, the
+dynamic linker can still make use of this dynamic tag, as relative
+relocation handling is typically way simpler than handling other
+relocations (since symbol lookup is not necessary) and thus it can
+handle all relative relocations in a tight loop in one place and
+then handle the remaining relocations with the fully featured
+relocation handling routine. The second and more important point is
+that if relocations against the same symbol are adjacent, the dynamic
+linker can use a cache with single entry.
+
+The dynamic linker in \tts{glibc}, if it sees \tts{statistics}
+as part of the \tts{LD\_DEBUG} environment variable, displays statistics
+which can show how useful this optimization is.
+Let's look at some big C++ application, e.g. konqueror.
+If not using the cache, the statistics looks like this:
+
+\noindent{\small\begin{verbatim}
+18000: runtime linker statistics:
+18000: total startup time in dynamic loader: 270886059 clock cycles
+18000: time needed for relocation: 266364927 clock cycles (98.3%)
+18000: number of relocations: 79067
+18000: number of relocations from cache: 0
+18000: number of relative relocations: 31169
+18000: time needed to load objects: 4203631 clock cycles (1.5%)
+\end{verbatim}}
+
+This program run is with hot caches, on non-prelinked system, with lazy
+binding.
+\nomenclature{Lazy Binding}{A way to postpone symbol lookups for calls until
+a function is called for the first time in particular shared library.
+This decreases number of symbol lookups done during startup and symbols
+which are never called don't need to be looked up at all. Calls requiring
+relocations jump into \tts{PLT}, which is initially set up so that a
+function in the dynamic linker is called to do symbol lookup. The looked
+up address is then stored either into the \tts{PLT} slot directly
+(if \tts{PLT} is writable) or into \tts{GOT} entry corresponding
+to the \tts{PLT slot} and any subsequent calls already go directly to that
+address. Lazy binding can be turned off by setting \tts{LD\_BIND\_NOW=1}
+in the environment. Prelinked programs never use lazy binding for the
+executable or any shared libraries not loaded using \tts{dlopen}}
+The numbers show that the dynamic linker spent most of its time
+in relocation handling and especially symbol lookups. If using symbol
+lookup cache, the numbers look different:
+
+\noindent{\small\begin{verbatim}
+18013: total startup time in dynamic loader: 132922001 clock cycles
+18013: time needed for relocation: 128399659 clock cycles (96.5%)
+18013: number of relocations: 25473
+18013: number of relocations from cache: 53594
+18013: number of relative relocations: 31169
+18013: time needed to load objects: 4202394 clock cycles (3.1%)
+\end{verbatim}}
+
+On average, for one real symbol lookup there were two cache hits and total
+time spent in the dynamic linker decreased by 50\%.
+
+\section{Prelink design}
+
+\tts{Prelink} was designed, so that it requires as few \tts{ELF} extensions
+as possible. It should not be tied to a particular architecture, but
+should work on all \tts{ELF} architectures. During program startup it
+should avoid all symbol lookups which, as has been shown above, are
+very expensive. It needs to work in an environment where shared
+libraries and executables are changing from time to time, whether it is
+because of security updates or feature enhancements. It should avoid big code
+duplication between the dynamic linker and the tool. And prelinked
+shared libraries need to be usable even in non-prelinked executables,
+or when one of the shared libraries is upgraded and the prelinking of the
+executable has not been updated.
+
+To minimize the number of performed relocations during startup,
+the shared libraries (and executables) need to be relocated
+already as much as possible. For relative relocations this means the library
+needs to be loaded always at the same base address, for other relocations
+this means all shared libraries with definitions those relocations resolve
+to (often this includes all shared libraries the library or executable depends on)
+must always be loaded at the same addresses. \tts{ELF} executables
+(with the exception of {\sl Position Independent Executables})
+\nomenclature{Position Independent Executable}{A hybrid between
+classical \tts{ELF} executables and \tts{ELF} shared libraries.
+It has a form of a \tts{ET\_DYN} object like shared libraries and should
+contain position independent code, so that the kernel can load
+the executable starting at random address to make certain security attacks
+harder. Unlike shared libraries it contains \tts{DT\_DEBUG} dynamic
+tag, must have \tts{PT\_INTERP} segment with dynamic linker's path,
+must have meaningful code at its \tts{e\_entry} and can use symbol
+lookup assumptions normal executables can make, particularly that
+no symbol defined in the executable can be overridden by a shared
+library symbol} have their load address fixed already during linking.
+For shared libraries, \tts{prelink} needs something similar to \tts{a.out}
+registry of virtual address space slots. Maintaining such registry
+across all installations wouldn't scale well, so \tts{prelink} instead
+assigns these virtual address space slots on the fly after looking at
+all executables it is supposed to speed up and all their dependent shared
+libraries. The next step is to actually relocate shared libraries
+to the assigned base address.
+
+When this is done, the actual prelinking of shared libraries can be done.
+First, all dependent shared libraries need to be prelinked (\tts{prelink}
+doesn't support circular dependencies between shared libraries, will just
+warn about them instead of prelinking the libraries in the cycle), then for each
+relocation in the shared library \tts{prelink} needs to look up the symbol
+in natural symbol search scope of the shared library (the shared library
+itself first, then breadth first search of all dependent shared libraries) and
+apply the relocation to the symbol's target section. The symbol lookup code
+in the dynamic linker is quite complex and big, so to avoid duplicating all
+this, \tts{prelink} has chosen to use dynamic linker to do the symbol lookups.
+Dynamic linker is told via a special environment variable it should print
+all performed symbol lookups and their type and \tts{prelink} reads this
+output through a pipe. As one of the requirements was that
+prelinked shared libraries must be usable even for non-prelinked executables
+(duplicating all shared libraries so that there are pristine and prelinked
+copies would be very unfriendly to RAM usage), \tts{prelink} has to ensure
+that by applying the relocation no information is lost and thus relocation
+processing can be cheaply done at startup time of non-prelinked executables.
+For \tts{RELA} architectures this is easier, because the content
+of the relocation's target memory is not needed when processing the relocation.
+\footnote{Relative relocations on certain \tts{RELA} architectures use
+relocation target's memory, either alone or together with \tts{r\_addend}
+field.} For \tts{REL} architectures this is not the case.
+\tts{prelink} attempts some tricks described
+later and if they fail, needs to convert the \tts{REL} relocation section
+to \tts{RELA} format where addend is stored in the relocation section
+instead of relocation target's memory.
+
+When all shared libraries an executable (directly or indirectly) depends on
+are prelinked, relocations in the executable are handled similarly to
+relocations in shared libraries. Unfortunately, not all symbols resolve the
+same when looked up in a shared library's natural symbol search scope
+(i.e. as it is done at the time the shared library is prelinked) and when
+looked up in application's global symbol search scope. Such symbols are
+herein called {\sl conflicts} and the relocations against those symbols
+{\sl conflicting relocations}. Conflicts depend on the executable, all its
+shared libraries and their respective order. They are only computable
+for the shared libraries linked to the executable (libraries mentioned in
+\tts{DT\_NEEDED} dynamic tags and shared libraries they transitively need).
+The set of shared libraries loaded via \tts{dlopen(3)} cannot be predicted
+by \tts{prelink}, neither can the order in which this happened, nor the time
+when they are unloaded. When the dynamic linker prints symbol lookups
+done in the executable, it also prints conflicts. \tts{Prelink} then
+takes all relocations against those symbols and builds a special
+\tts{RELA} section with conflict fixups and stores it into the
+prelinked executable. Also a list of all dependent shared libraries
+in the order they appear in the symbol search scope, together
+with their checksums and times of prelinking is stored in another special
+section.
+
+The dynamic linker first checks if it is itself prelinked. If yes,
+it can avoid its preliminary relocation processing (this one is done
+with just the dynamic linker itself in the search scope, so that
+all routines in the dynamic linker can be used easily without too many
+limitations). When it is about to start a program, it first looks
+at the library list section created by \tts{prelink} (if any) and
+checks whether they are present in symbol search scope in the same
+order, none have been modified since prelinking and that there aren't any
+new shared libraries loaded either. If all these conditions are
+satisfied, prelinking can be used. In that case the dynamic linker
+processes the fixup section and skips all normal relocation handling.
+If one or more of the conditions are not met, the dynamic linker continues
+with normal relocation processing in the executable and all shared libraries.
+
+\section{Collecting executables and libraries which should be prelinked}
+
+Before the actual work can start the \tts{prelink} tool needs to collect the
+filenames of executables and libraries it is supposed to prelink.
+It doesn't make any sense to prelink a shared library if no executable is
+linked against it because the prelinking information will not be used anyway.
+Furthermore, when \tts{prelink} needs to do a \tts{REL} to \tts{RELA}
+conversion of relocation sections in the shared library (see later)
+or when it needs to convert \tts{SHT\_NOBITS} \tts{PLT} section to
+\tts{SHT\_PROGBITS}, a prelinked shared library might grow in size and so
+prelinking is only desirable if it will speed up startup of some
+program. The only change which might be useful even for shared libraries
+which are never linked against, only loaded using \tts{dlopen}, is
+relocating to a unique address. This is useful if there are many relative
+relocations and there are pages in the shared library's writable segment
+which are never written into with the exception of those relative
+relocations. Such shared libraries are rare, so \tts{prelink} doesn't
+handle these automatically, instead the administrator or developer can
+use \tts{prelink --reloc-only={\sl ADDRESS}} to relocate it manually.
+Prelinking an executable requires all shared libraries it is linked against
+to be prelinked already.
+
+\tts{Prelink} has two main modes in which it collects filenames.
+One is {\sl incremental prelinking}, where \tts{prelink} is invoked without
+the \tts{-a} option. In this mode, \tts{prelink} queues for prelinking
+all executables and shared libraries given on the command line, all executables
+in directory trees specified on the command line, and all shared libraries
+those executables and shared libraries are linked against.
+For the reasons mentioned earlier a shared library is queued only if a
+program is linked with it or the user tells the tool to do it anyway
+by explicitly mentioning it on the command line.
+The second mode is {\sl full prelinking}, where the \tts{-a} option is
+given on the command line. This in addition to incremental prelinking
+queues all executables found in directory trees specified in \tts{prelink.conf}
+(which typically includes all or most directories where system executables
+are found). For each directory subtree in the config file the user
+can specify whether symbolic links to places outside of the tree are to be followed
+or not and whether searching should continue even across filesystem
+boundaries.
+
+There is also an option to blacklist some executables or directory trees
+so that the executables or anything in the directory trees will not
+be prelinked. This can be specified either on the command line or in
+the config file.
+
+\tts{Prelink} will not attempt to change executables which use a non-standard
+dynamic linker
+\footnote{Standard dynamic linker path is hardcoded in the executable for each
+architecture. It can be overridden from the command line, but only with
+one dynamic linker name (normally, multiple standard dynamic linkers are
+used when prelinking mixed architecture systems).}
+for security reasons, because it actually needs to execute the dynamic
+linker for symbol lookup and it needs to avoid executing some random
+unknown executable with the permissions with which \tts{prelink} is run
+(typically \tts{root}, with the permissions at least for changing all
+executables and shared libraries in the system). The administrator should
+ensure that \tts{prelink.conf} doesn't contain world-writable directories
+and such directories are not given to the tool on the command line either,
+but the tool should be distrustful of the objects nevertheless.
+
+Also, \tts{prelink} will not change shared libraries which are not specified
+directly on the command line or located in the directory trees specified on the
+command line or in the config file. This is so that
+e.g. \tts{prelink} doesn't try to change shared libraries on shared
+networked filesystems, or at least it is possible to configure the tool
+so that it doesn't do it.
+
+For each executable and shared library it collects, \tts{prelink} executes
+the dynamic linker to list all shared libraries it depends on, checks if
+it is already prelinked and whether any of its dependencies changed.
+Objects which are already prelinked and have no dependencies which changed
+don't have to be prelinked again (with the exception when e.g. virtual
+address space layout code finds out it needs to assign new virtual address space slots
+for the shared library or one of its dependencies). Running the dynamic
+linker to get the symbol lookup information is a quite costly
+operation especially on systems with many executables and shared libraries
+installed, so \tts{prelink} offers a faster \tts{-q} mode. In all modes,
+\tts{prelink} stores modification and change times of each shared library
+and executable together with all object dependencies and other information
+into \tts{prelink.cache} file. When prelinking in \tts{-q} mode, it
+just compares modification and change times of the executables and shared
+libraries (and all their dependencies). Change time is needed because
+\tts{prelink} preserves modification time when prelinking (as well as
+permissions, owner and group). If the times match, it assumes the
+file has not changed since last prelinking. Therefore the file can be
+skipped if it is already prelinked and none of the dependencies changed.
+If any time changed or one of the dependencies changed, it invokes the
+dynamic linker the same way as in normal mode to find out real dependencies,
+whether it has been prelinked or not etc. The collecting phase in normal
+mode can take a few minutes, while in quick mode usually takes just a few
+seconds, as the only operation it does is it calls just lots of \tts{stat}
+system calls.
+
+\section{Assigning virtual address space slots}
+
+\tts{Prelink} has to ensure at least that for all successfully prelinked
+executables all shared libraries they are (transitively) linked against
+have non-overlapping virtual address space slots (furthermore they
+cannot overlap with the virtual address space range used by the executable
+itself, its \tts{brk} area, typical stack location and \tts{ld.so.cache}
+and other files mmaped by the dynamic linker in early stages of dynamic
+linking (before all dependencies are mmaped). If there were any overlaps,
+the dynamic linker (which mmaps the shared libraries at the desired location
+without \tts{MAP\_FIXED} mmap flag so that it is only soft requirement) would
+not manage to mmap them at the assigned locations and the prelinking
+information would be invalidated (the dynamic linker would have to do all
+normal relocation handling and symbol lookups). Executables are linked against
+very wide variety of shared library combinations and that has to be taken
+into account.
+
+The simplest approach is to sort shared libraries by descending
+usage count (so that most often used shared libraries like the dynamic
+linker, \tts{libc.so} etc. are close to each other) and assign them
+consecutive slots starting at some architecture specific base address
+(with a page or two in between the shared libraries to allow for a limited
+growth of shared libraries without having to reposition them).
+\tts{Prelink} has to find out which shared libraries will need
+a \tts{REL} to \tts{RELA} conversion of relocation sections
+and for those which will need the conversion count with the increased size
+of the library's loadable segments. This is \tts{prelink} behavior without
+\tts{-m} and \tts{-R} options.
+
+The architecture specific base address is best located a few megabytes above
+the location where \tts{mmap} with \tts{NULL} first argument and without
+\tts{MAP\_FIXED} starts allocating memory areas (in Linux this is the value
+of \tts{TASK\_UNMAPPED\_BASE} macro).
+\footnote{\tts{TASK\_UNMAPPED\_BASE} has been chosen
+on each platform so that there is enough virtual memory for both the
+\tts{brk} area (between executable's end and this memory address) and \tts{mmap}
+area (between this address and bottom of stack).} The reason for not
+starting to assign addresses in \tts{prelink} immediately at
+\tts{TASK\_UNMAPPED\_BASE} is that \tts{ld.so.cache} and other mappings by
+the dynamic linker will end up in the same range and could overlap with
+the shared libraries. Also, if some application uses \tts{dlopen} to load
+a shared library which has been prelinked,
+\footnote{Typically this is because some other executable is linked against that
+shared library directly.}
+those few megabytes above \tts{TASK\_UNMAPPED\_BASE} increase the probability
+that the stack slot will be still unused (it can clash with e.g.
+non-prelinked shared libraries loaded by \tts{dlopen} earlier
+\footnote{If shared libraries have first \tts{PT\_LOAD} segment's virtual
+address zero, the kernel typically picks first empty slot above
+\tts{TASK\_UNMAPPED\_BASE} big enough for the mapping.} or other kinds
+of mmap calls with \tts{NULL} first argument like \tts{malloc} allocating
+big chunks of memory, mmaping of locale database, etc.).
+
+This simplest approach is unfortunately problematic on 32-bit (or 31-bit)
+architectures where the total virtual address space for a process is
+somewhere between 2GB (S/390) and almost 4GB (Linux IA-32 4GB/4GB kernel
+split, AMD64 running 32-bit processes, etc.). Typical installations these
+days contain thousands of shared libraries and if each of them is given a
+unique address space slot, on average executables will have pretty sparse
+mapping of its shared libraries and there will be less contiguous virtual
+memory for application's own use
+\footnote{Especially databases look these days for every byte of virtual
+address space on 32-bit architectures.}.
+
+\tts{Prelink} has a special mode, turned on with \tts{-m} option, in which
+it computes what shared libraries are ever loaded together in some executable
+(not considering \tts{dlopen}). If two shared libraries are ever loaded
+together, \tts{prelink} assigns them different virtual address space slots,
+but if they never appear together, it can give them overlapping addresses.
+For example applications using \tts{KDE} toolkit link typically against many
+\tts{KDE} shared libraries, programs written using the \tts{Gtk+} toolkit
+link typically against many \tts{Gtk+} shared libraries, but there are just
+very few programs which link against both \tts{KDE} and \tts{Gtk+} shared
+libraries, and even if they do, they link against very small subset of those
+shared libraries. So all \tts{KDE} shared libraries not in that subset can
+use overlapping addresses with all \tts{Gtk+} shared libraries but the
+few exceptions. This leads to considerably smaller virtual address space
+range used by all prelinked shared libraries, but it has its own
+disadvantages too. It doesn't work too well with incremental prelinking,
+because then not all executables are investigated, just those which are given
+on \tts{prelink}'s command line. \tts{Prelink} also considers executables
+in \tts{prelink.cache}, but it has no information about executables which have
+not been prelinked yet. If a new executable, which links against some shared
+libraries which never appeared together before, is prelinked later,
+\tts{prelink} has to assign them new, non-overlapping addresses.
+This means that any executables, which linked against the library
+that has been moved and re-prelinked, need to be prelinked again.
+If this happened during incremental prelinking, \tts{prelink} will
+fix up only the executables given on the command line, leaving other
+executables untouched. The untouched executables would not be able to
+benefit from prelinking anymore.
+
+Although with the above two layout schemes shared library addresses can
+vary slightly between different hosts running the same distribution
+(depending on the exact set of installed executables and libraries), especially
+the most often used shared libraries will have identical base addresses
+on different computers. This is often not desirable for security reasons,
+because it makes it slightly easier for various exploits to jump to routines
+they want. Standard Linux kernels assign always the same addresses to
+shared libraries loaded by the application at each run, so with these
+kernels \tts{prelink} doesn't make things worse. But there are kernel
+patches, such as Red Hat's \tts{Exec-Shield}, which randomize memory
+mappings on each run. If shared libraries are prelinked, they cannot
+be assigned different addresses on each run (prelinking information can
+be only used to speed up startup if they are mapped at the base addresses
+which was used during prelinking), which
+means prelinking might not be desirable on some edge servers.
+\tts{Prelink} can assign different addresses on different hosts though,
+which is almost the same as assigning random addresses on each run
+for long running processes such as daemons. Furthermore, the administrator
+can force full prelinking and assignment of new random addresses every few
+days (if he is also willing to restart the services, so that the old
+shared libraries and executables don't have to be kept in memory).
+
+To assign random addresses \tts{prelink} has the \tts{-R} option.
+This causes a random starting address somewhere in the architecture specific
+range in which shared libraries are assigned, and minor random reshuffling
+in the queue of shared libraries which need address assignment (normally
+it is sorted by descending usage count, with randomization shared libraries
+which are not very far away from each other in the sorted list can be
+swapped). The \tts{-R} option should work orthogonally to the \tts{-m}
+option.
+
+Some architectures have special further requirements on shared library
+address assignment. On 32-bit PowerPC, if shared libraries are located
+close to the executable, so that everything fits into 32MB area, \tts{PLT}
+slots resolving to those shared libraries can use the branch relative
+instruction instead of more expensive sequences involving memory load
+and indirect branch. If shared libraries are located in the
+first 32MB of address space, \tts{PLT} slots resolving to those shared
+libraries can use the branch absolute instruction (but already \tts{PLT}
+slots in those shared libraries resolving to addresses in the executable
+cannot be done cheaply). This means for optimization \tts{prelink}
+should assign addresses from a 24MB region below the executable first, assuming
+most of the executables are smaller than those remaining 8MB.
+\tts{prelink} assigns these from higher to lower addresses. When this
+region is full, \tts{prelink} starts from address 0x40000
+\footnote{To leave some pages unmapped to catch \tts{NULL} pointer
+dereferences.} up till the bottom of the first area. Only when
+all these areas are full, \tts{prelink} starts picking addresses high above
+the executable, so that sufficient space is left in between to leave room
+for \tts{brk}.
+When \tts{-R} option is specified, \tts{prelink} needs to honor it, but
+in a way which doesn't totally kill this optimization. So it picks up
+a random start base within each of the 3 regions separately, splitting
+them into 6 regions.
+
+Another architecture which needs to be handled specially is IA-32
+when using \tts{Exec-Shield}. The IA-32 architecture doesn't have an
+bit to disable execution for each page, only for each segment. All readable
+pages are normally executable. This means the stack is usually executable,
+as is memory allocated by \tts{malloc}. This is undesirable for security reasons,
+exploits can then overflow a buffer on the stack to transfer control
+to code it creates on the stack.
+Only very few programs actually need an executable stack. For example
+programs using GCC trampolines for nested functions need it or when
+an application itself creates executable code on the stack and calls it.
+\tts{Exec-Shield} works around this IA-32 architecture deficiency
+by using a separate code segment, which starts at address 0 and spans
+address space until its limit, highest page which needs to
+be executable. This is dynamically changed when some page with higher
+address than the limit needs to be executable (either because of \tts{mmap}
+with \tts{PROT\_EXEC} bit set, or \tts{mprotect} with \tts{PROT\_EXEC}
+of an existing mapping). This kind of protection is of course only
+effective if the limit is as low as possible. The kernel tries to
+put all new mappings with \tts{PROT\_EXEC} set and \tts{NULL} address low.
+If possible into {\sl ASCII Shield area} (first 16MB of address space)
+\nomenclature{ASCII Shield area}{First 16MB of address space on 32-bit
+architectures. These addresses have zeros in upper 8 bits,
+which on little endian architectures are stored as last byte of the address
+and on big endian architectures as first byte of the address.
+A zero byte terminates string, so it is hard to control the exact
+arguments of a function if they are placed on the stack above the
+address. On big endian machines, it is even hard to control the
+low 24 bits of the address}, if not, at least below the executable.
+If \tts{prelink} detects \tts{Exec-Shield}, it tries to do the same as
+kernel when assigning addresses, i.e. prefers to assign addresses in
+{\sl ASCII Shield area} and continues with other addresses below
+the program. It needs to leave first 1MB plus 4KB of address space
+unallocated though, because that range is often used by programs
+using \tts{vm86} system call.
+
+\section{Relocation of libraries}
+
+When a shared library has a base address assigned, it needs to be relocated
+so that the base address is equal to the first \tts{PT\_LOAD} segment's
+\tts{p\_vaddr}. The effect of this operation should be bitwise identical
+as if the library were linked with that base address originally.
+That is, the following scripts should produce identical output:
+
+\noindent{{\small\begin{verbatim}
+$ gcc -g -shared -o libfoo.so.1.0.0 -Wl,-h,libfoo.so.1 \
+ input1.o input2.o somelib.a
+$ prelink --reloc-only=0x54321000 libfoo.so.1.0.0
+\end{verbatim}
+\prelinklistingcaption{Script to relocate a shared library after linking using \tts{prelink}}}
+
+and:
+\noindent{\small\begin{verbatim}
+$ gcc -shared -Wl,--verbose 2>&1 > /dev/null \
+ | sed -e '/^======/,/^======/!d' \
+ -e '/^======/d;s/0\( + SIZEOF_HEADERS\)/0x54321000\1/' \
+ > libfoo.so.lds
+$ gcc -Wl,-T,libfoo.so.lds -g -shared -o libfoo.so.1.0.0 \
+ -Wl,-h,libfoo.so.1 input1.o input2.o somelib.a
+\end{verbatim}}
+\prelinklistingcaption{Script to link a shared library at non-standard base}}
+
+The first script creates a normal shared library with the default
+base address 0 and then uses \tts{prelink}'s special mode when it just
+relocates a library to a given address. The second script first modifies
+a built-in GNU linker script for linking of shared libraries, so that
+the base address is the one given instead of zero and stores it into a
+temporary file. Then it creates a shared library using that linker script.
+
+The relocation operation involves mostly adding the difference between
+old and new base address to all \tts{ELF} fields which contain values
+representing virtual addresses of the shared library
+(or in the program header table also representing physical addresses).
+File offsets need to be unmodified. Most places where the adjustments
+need to be done are clear, \tts{prelink} just has to watch \tts{ELF} spec
+to see which fields contain virtual addresses.
+
+One problem is with absolute symbols. \tts{Prelink} has no way to find
+out if an absolute symbol in a shared library is really meant as
+absolute and thus not changing during relocation, or if it is an address
+of some place in the shared library outside of any section or on their
+edge. For instance symbols created in the GNU linker's script outside
+of section directives have all \tts{SHN\_ABS} section, yet they can be
+location in the library (e.g. \tts{symbolfoo~=~.}) or they can be absolute
+(e.g. \tts{symbolbar~=~0x12345000}). This distinction is lost at link
+time. But the dynamic linker when looking up symbols doesn't make any
+distinction between them, all addresses during dynamic lookup have the
+load offset added to it. \tts{Prelink} chooses to relocate any absolute
+symbols with value bigger than zero, that way \tts{prelink --reloc-only}
+gets bitwise identical output with linking directly at the different base
+in almost all real-world cases. Thread Local Storage symbols (those with
+\tts{STT\_TLS} type) are never relocated, as their values are relative
+to start of shared library's thread local area.
+
+When relocating the dynamic section there are no bits which tell if
+a particular dynamic tag uses \tts{d\_un.d\_ptr} (which needs to
+be adjusted) or \tts{d\_un.d\_val} (which needs to be left as is).
+So \tts{prelink} has to hardcode a list of well known architecture
+independent dynamic tags which need adjusting and have a hook for
+architecture specific dynamic tag adjustment. Sun came up with
+\tts{DT\_ADDRRNGLO} to \tts{DT\_ADDRRNGHI} and \tts{DT\_VALRNGLO}
+to \tts{DT\_VALRNGHI} dynamic tag number ranges, so at least as
+long as these ranges are used for new dynamic tags \tts{prelink}
+can relocate correctly even without listing them all explicitly.
+
+When relocating \tts{.rela.*} or \tts{.rel.*} sections, which is
+done in architecture specific code, relative relocations and on \tts{.got.plt}
+using architectures also \tts{PLT} relocations typically need an
+adjustment. The adjustment needs to be done in either \tts{r\_addend} field
+of the \tts{ElfNN\_Rela} structure, in the memory pointed by \tts{r\_offset},
+or in both locations.
+On some architectures what needs adjusting is not even the same for all relative relocations.
+Relative relocations against some sections need to have \tts{r\_addend}
+adjusted while others need to have memory adjusted.
+On many architectures, first few words in \tts{GOT} are special and some
+of them need adjustment.
+
+The hardest part of the adjustment is handling the debugging sections.
+These are non-allocated sections which typically have no corresponding
+relocation section associated with them. \tts{Prelink} has to match the various
+debuggers in what fields it adjusts and what are skipped.
+As of this writing \tts{prelink} should handle
+\href{http://www.eagercon.com/dwarf/dwarf-2.0.0.pdf}%
+{\tts{DWARF 2} [15]} standard as corrected (and extended) by
+\href{http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf}%
+{\tts{DWARF 3 draft} [16]},
+\href{http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gdb/doc/stabs.texinfo?cvsroot=src}%
+{\tts{Stabs} [17]} with GCC extensions and Alpha or MIPS \tts{Mdebug}.
+
+\tts{DWARF 2} debugging information involves many separate sections,
+each of them with a unique format which needs to be relocated differently.
+For relocation of the \tts{.debug\_info} section compilation units \tts{prelink} has to
+parse the corresponding part of the \tts{.debug\_abbrev} section, adjust all
+values of attributes that are using the \tts{DW\_FORM\_addr} form and adjust embedded
+location lists. \tts{.debug\_ranges} and \tts{.debug\_loc} section
+portions depend on the exact place in \tts{.debug\_info} section from
+which they are referenced, so that \tts{prelink} can keep track of their
+base address. \tts{DWARF} debugging format is very extendable, so
+\tts{prelink} needs to be very conservative when it sees unknown extensions.
+It needs to fail prelinking instead of silently break debugging information
+if it sees an unknown \tts{.debug\_*} section, unknown attribute form
+or unknown attribute with one of the \tts{DW\_FORM\_block*} forms, as
+they can potentially embed addresses which would need adjustment.
+
+For \tts{stabs} \tts{prelink} tried to match GDB behavior. For
+\tts{N\_FUN}, it needs to differentiate between function start and
+function address which are both encoded with this type, the rest of types
+either always need relocating or never. And similarly to \tts{DWARF 2}
+handling, it needs to reject unknown types.
+
+The relocation code in \tts{prelink} is a little bit more generic
+than what is described above, as it is used also by other parts of
+\tts{prelink}, when growing sections in a middle of the shared library
+during \tts{REL} to \tts{RELA} conversion. All adjustment functions
+get passed both the offset it should add to virtual addresses and
+a start address. Adjustment is only done if the old virtual address
+was bigger or equal than the start address.
+
+\section{REL to RELA conversion}
+
+On architectures which normally use the \tts{REL} format for relocations instead
+of \tts{RELA} (IA-32, ARM and MIPS), if certain relocation types use the
+memory \tts{r\_offset} points to during relocation, \tts{prelink} has to
+either convert them to a different relocation type which doesn't use
+the memory value, or the whole \tts{.rel.dyn} section needs to be converted
+to \tts{RELA} format. Let's describe it on an example on IA-32 architecture:
+
+\noindent{{\small\begin{verbatim}
+$ cat > test1.c <<EOF
+extern int i[4];
+int *j = i + 2;
+EOF
+$ cat > test2.c <<EOF
+int i[4];
+EOF
+$ gcc -nostdlib -shared -fpic -s -o test2.so test2.c
+$ gcc -nostdlib -shared -fpic -o test1.so test1.c ./test2.so
+$ readelf -l test1.so | grep LOAD | head -1
+ LOAD 0x000000 0x00000000 0x00000000 0x002b8 0x002b8 R E 0x1000
+$ readelf -l test2.so | grep LOAD | head -1
+ LOAD 0x000000 0x00000000 0x00000000 0x00244 0x00244 R E 0x1000
+$ readelf -r test1.so
+
+Relocation section '.rel.dyn' at offset 0x2b0 contains 1 entries:
+ Offset Info Type Sym.Value Sym. Name
+000012b8 00000d01 R_386_32 00000000 i
+$ objdump -s -j .data test1.so
+
+test1.so: file format elf32-i386
+
+Contents of section .data:
+ 12b8 08000000 ....
+$ readelf -s test2.so | grep i\$
+ 11: 000012a8 16 OBJECT GLOBAL DEFAULT 8 i
+$ prelink -N ./test1.so ./test2.so
+$ readelf -l test1.so | grep LOAD | head -1
+ LOAD 0x000000 0x04dba000 0x04dba000 0x002bc 0x002bc R E 0x1000
+$ readelf -l test2.so | grep LOAD | head -1
+ LOAD 0x000000 0x04db6000 0x04db6000 0x00244 0x00244 R E 0x1000
+$ readelf -r test1.so
+
+Relocation section '.rel.dyn' at offset 0x2b0 contains 1 entries:
+ Offset Info Type Sym.Value Sym. Name + Addend
+04dbb2bc 00000d01 R_386_32 00000000 i + 8
+$ objdump -s -j .data test1.so
+
+test1.so: file format elf32-i386
+
+Contents of section .data:
+ 4dbb2bc b072db04 .r..
+$ readelf -s test2.so | grep i\$
+ 11: 04db72a8 16 OBJECT GLOBAL DEFAULT 8 i
+\end{verbatim}}
+\prelinklistingcaption{\tts{REL} to \tts{RELA} conversion example}}
+
+This relocation is against {\sl i + 8}, where the addend is stored at the memory
+location pointed by \tts{r\_offset}. \tts{Prelink} assigned base address
+0x4dba000 to \tts{test1.so} and 0x4db6000 to \tts{test2.so}.
+\tts{Prelink} above converted the \tts{REL} section in \tts{test1.so} to
+\tts{RELA}, but let's assume it did not. All output containing {\sl 2bc}
+above would change to {\sl 2b8} (that changed above only because \tts{.rel.dyn}
+section grew up by 4 bytes during the conversion to \tts{RELA} format),
+the rest would stay unchanged.
+When some program linked against \tts{test1.so} was prelinked,
+the (only) relocation in \tts{test1.so} would not be used and {\sl j} would
+contain the right value, 0x4db72b0 (address of {\sl i + 8}; note that IA-32
+is little endian, so the values in .data section are harder to read
+for a human). Now, let's assume one of the shared libraries the executable
+is linked against is upgraded. This means prelink information cannot
+be used, as it is out of date. Let's assume it was a library other
+than \tts{test2.so}. Normal relocation processing for \tts{test1.so}
+needs to happen. Standard \tts{R\_386\_32} calculation is \tts{S~+~A},
+in this case 0x4db72a8 + 0x4db72b0 = 0x9b6e558 and {\sl j} contains wrong
+value. Either \tts{test2.so} could change and now the {\sl i} variable would
+have different address, or some other shared library linked to the executable
+could overload symbol {\sl i}. Without additional information the dynamic
+linker cannot find out the addend is 8.
+
+The original value of a symbol could perhaps be stored in some special
+allocated section and the dynamic linker could do some magic to locate it,
+but it would mean standard relocation handling code in the dynamic linker
+cannot be used for relocation processing of prelinked shared libraries
+where prelinking information cannot be used.
+So \tts{prelink} in this case converts the whole \tts{.rel.dyn} section
+into the \tts{RELA} format, the addend is stored in \tts{r\_addend} field
+and when doing relocation processing, it really doesn't matter what
+value is at the memory location pointed by \tts{r\_offset}.
+The disadvantage of this is that the relocation section
+grew by 50\%. If prelinking information can be used, it shouldn't matter much,
+since the section is never loaded at runtime because it is not accessed.
+If prelinking cannot be used, whether because it is out of date or
+because the shared library has been
+loaded by \tts{dlopen}, it will increase memory footprint, but it is read-only
+memory which is typically not used after startup and can be discarded
+as it is backed out by the file containing the shared library.
+
+At least on IA-32, \tts{REL} to \tts{RELA} conversion is not always
+necessary. If \tts{R\_386\_32} added is originally 0, \tts{prelink}
+can instead change its type to \tts{R\_386\_GLOB\_DAT}, which is a
+similar dynamic relocation, but calculated as \tts{S} instead of
+\tts{S~+~A}. There is no similar conversion for \tts{R\_386\_PC32}
+possible though, on the other side this relocation type should never
+appear in position independent shared libraries, only in position
+dependent code. On ARM, the situation is the same, just using
+different relocation names (\tts{R\_ARM\_32}, \tts{R\_ARM\_GLOB\_DAT}
+and \tts{R\_ARM\_PC24}).
+
+The \tts{.rel.plt} section doesn't have to be converted to \tts{RELA}
+format on either of these architectures, if the conversion is needed,
+all other \tts{.rel.*} allocated sections, which have to be adjacent
+as they are pointed to by \tts{DT\_REL} and \tts{DT\_RELSZ} dynamic tags,
+have to be converted together. The conversion itself is fairly easy,
+some architecture specific code just has to fetch the original addend
+from memory pointed by the relocation and store it into \tts{r\_addend}
+field (or clear \tts{r\_addend} if the particular relocation type
+never uses the addend). The main problem is that when the conversion
+happens, the \tts{.rel.dyn} section grows by 50\% and there needs to be
+room for that in the read-only loadable segment of the shared library.
+
+In shared libraries it is always possible to grow the first read-only
+\tts{PT\_LOAD} segment by adding the additional data at the beginning
+of the read-only segment, as the shared library is relocatable.
+\tts{Prelink} can relocate the whole shared library to a higher address
+than it has assigned for it. The file offsets of all sections
+and the section header table file offset need to be increased,
+but the \tts{ELF} header and program headers need to stay at the beginning
+of the file. The relocation section can then be moved to the newly created
+space between the end of the program header table and the first section.
+
+Moving the section from the old location to the newly created space
+would leave often very big gap in virtual address space as well as in
+the file at the old location of the relocation section. Fortunately the
+linker typically puts special \tts{ELF} sections including allocated
+relocation section before the code section and other read-only sections
+under user's control. These special sections are intended for dynamic
+linking only. Their addresses are stored just in the \tts{.dynamic} section
+and \tts{prelink} can easily adjust them there. There is no need for
+a shared library to store address of one of the special sections
+into its code or data sections and existing linkers in fact don't create
+such references. When growing the relocation section, \tts{prelink}
+checks whether all sections before the relocation section are
+special
+\footnote{As special sections \tts{prelink} considers sections with
+\tts{SHT\_NOTE}, \tts{SHT\_HASH}, \tts{SHT\_DYNSYM}, \tts{SHT\_STRTAB},
+\tts{SHT\_GNU\_verdef}, \tts{SHT\_GNU\_verneed}, \tts{SHT\_GNU\_versym},
+\tts{SHT\_REL} or \tts{SHT\_RELA} type or the \tts{.interp} section.}
+and if they are, just moves them to lower addresses, so that the
+newly created space is right above the relocation section.
+The advantage is that instead of moving all sections by the size of
+the new relocation section they can be adjusted ideally just by the
+difference between old and new relocation section size.
+
+There are two factors which can increase the necessary adjustment of
+all higher sections. The first is required section alignment of any
+allocated section above the relocation section. \tts{Prelink} needs
+to find the highest section alignment among those sections and
+increase the adjustment from the difference between old and new
+relocation section up to the next multiple of that alignment.
+
+The second factor is only relevant to shared libraries where linker
+optimized the data segment placement. Traditionally linker assigned
+the end address of the read-only segment plus the architecture's
+maximum \tts{ELF} page size as the start address of the read-write
+segment. While this created smallest file sizes of the shared libraries,
+it often wasted one page in the read-write segment because of partial
+pages. When linker optimizes such that less space is wasted in partial
+pages, the distance between read-only and read-write segments can be
+smaller than architecture specific maximum \tts{ELF} page size.
+\tts{Prelink} has to take this into account, so that when adjusting
+the sections the read-only and read-write segment don't end up on the
+same page. Unfortunately \tts{prelink} cannot increase or decrease
+the distance between the read-only and read-write segments, since
+it is possible that the shared library has relative addresses of
+any allocated code, data or \tts{.bss} sections
+stored in its sections without any relocations which would allow
+\tts{prelink} to change them. \tts{Prelink} has to move all sections
+starting with the first allocated \tts{SHT\_PROGBITS} section other
+than \tts{.interp} up to the last allocated \tts{SHT\_PROGBITS} or
+\tts{SHT\_NOBITS} section as a block and thus needs to increase
+the adjustment in steps of the highest section alignment as many times
+times as needed so that the segments end up in different pages.
+Below are 3 examples:
+
+\noindent{{\small\begin{verbatim}
+$ cat > test1.c <<EOF
+int i[2] __attribute__((aligned (32)));
+#define J1(N) int *j##N = &i[1];
+#define J2(N) J1(N##0) J1(N##1) J1(N##2) J1(N##3) J1(N##4)
+#define J3(N) J2(N##0) J2(N##1) J2(N##2) J2(N##3) J2(N##4)
+#define J4(N) J3(N##0) J3(N##1) J3(N##2) J3(N##3) J3(N##4)
+J4(0) J4(1) J3(2) J3(3) J1(4)
+const int l[256] = { [10] = 1 };
+/* Put a zero sized section at the end of read-only segment,
+ so that the end address of the segment is printed. */
+asm (".section ro_seg_end, \"a\"; .previous");
+EOF
+$ gcc -shared -O2 -nostdlib -fpic -o test1.so test1.c
+$ readelf -S test1.so | grep '^ \['
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .hash HASH 000000b4 0000b4 000930 04 A 2 0 4
+ [ 2] .dynsym DYNSYM 000009e4 0009e4 001430 10 A 3 d 4
+ [ 3] .dynstr STRTAB 00001e14 001e14 000735 00 A 0 0 1
+ [ 4] .rel.dyn REL 0000254c 00254c 000968 08 A 2 0 4
+ [ 5] .text PROGBITS 00002eb4 002eb4 000000 00 AX 0 0 4
+ [ 6] .rodata PROGBITS 00002ec0 002ec0 000400 00 A 0 0 32
+ [ 7] ro_seg_end PROGBITS 000032c0 0032c0 000000 00 A 0 0 1
+ [ 8] .data PROGBITS 000042c0 0032c0 0004b4 00 WA 0 0 4
+ [ 9] .dynamic DYNAMIC 00004774 003774 000070 08 WA 3 0 4
+ [10] .got PROGBITS 000047e4 0037e4 00000c 04 WA 0 0 4
+ [11] .bss NOBITS 00004800 003800 000008 00 WA 0 0 32
+ [12] .comment PROGBITS 00000000 003800 000033 00 0 0 1
+ [13] .shstrtab STRTAB 00000000 003833 000075 00 0 0 1
+ [14] .symtab SYMTAB 00000000 003b28 001470 10 15 11 4
+ [15] .strtab STRTAB 00000000 004f98 000742 00 0 0 1
+$ readelf -l test1.so | grep LOAD
+ LOAD 0x000000 0x00000000 0x00000000 0x032c0 0x032c0 R E 0x1000
+ LOAD 0x0032c0 0x000042c0 0x000042c0 0x00530 0x00548 RW 0x1000
+$ prelink -N ./test1.so
+$ readelf -l test1.so | grep LOAD
+ LOAD 0x000000 0x02000000 0x02000000 0x03780 0x03780 R E 0x1000
+ LOAD 0x003780 0x02004780 0x02004780 0x00530 0x00548 RW 0x1000
+$ readelf -S test1.so | grep '^ \['
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .hash HASH 020000b4 0000b4 000930 04 A 2 0 4
+ [ 2] .dynsym DYNSYM 020009e4 0009e4 001430 10 A 3 d 4
+ [ 3] .dynstr STRTAB 02001e14 001e14 000735 00 A 0 0 1
+ [ 4] .rel.dyn RELA 0200254c 00254c 000e1c 0c A 2 0 4
+ [ 5] .text PROGBITS 02003374 003374 000000 00 AX 0 0 4
+ [ 6] .rodata PROGBITS 02003380 003380 000400 00 A 0 0 32
+ [ 7] ro_seg_end PROGBITS 02003780 003780 000000 00 A 0 0 1
+ [ 8] .data PROGBITS 02004780 003780 0004b4 00 WA 0 0 4
+ [ 9] .dynamic DYNAMIC 02004c34 003c34 000070 08 WA 3 0 4
+ [10] .got PROGBITS 02004ca4 003ca4 00000c 04 WA 0 0 4
+ [11] .bss NOBITS 02004cc0 003cc0 000008 00 WA 0 0 32
+ [12] .comment PROGBITS 00000000 003cc0 000033 00 0 0 1
+ [13] .gnu.liblist GNU_LIBLIST 00000000 003cf3 000000 14 14 0 4
+ [14] .gnu.libstr STRTAB 00000000 003cf3 000000 00 0 0 1
+ [15] .gnu.prelink_undo PROGBITS 00000000 003cf4 00030c 01 0 0 4
+ [16] .shstrtab STRTAB 00000000 004003 0000a0 00 0 0 1
+ [17] .symtab SYMTAB 00000000 0043a0 001470 10 18 11 4
+ [18] .strtab STRTAB 00000000 005810 000742 00 0 0 1
+\end{verbatim}}
+\prelinklistingcaption{Growing read-only segment with segment distance one page}}
+
+\begin{figure}[!ht]
+\centering
+\includegraphics[width=0.8\textwidth]{dso1}
+\caption{Growing read-only segment with segment distance one page}
+\end{figure}
+
+In this example the read-write segment starts at address \tts{0x42c0}, which
+is one page above the end of read-only segment. \tts{Prelink} needs to grow
+the read-only \tts{PT\_LOAD} segment by 50\% of \tts{.rel.dyn} size, i.e.
+\tts{0x4b4} bytes. \tts{Prelink} just needs to round that up for the
+highest alignment (32 bytes required by \tts{.rodata} or \tts{.bss}
+sections) and moves all sections above \tts{.rel.dyn} by \tts{0x4c0} bytes.
+
+\noindent{{\small\begin{verbatim}
+$ cat > test2.c <<EOF
+int i[2] __attribute__((aligned (32)));
+#define J1(N) int *j##N = &i[1];
+#define J2(N) J1(N##0) J1(N##1) J1(N##2) J1(N##3) J1(N##4)
+#define J3(N) J2(N##0) J2(N##1) J2(N##2) J2(N##3) J2(N##4)
+#define J4(N) J3(N##0) J3(N##1) J3(N##2) J3(N##3) J3(N##4)
+J4(0) J4(1) J3(2) J3(3) J1(4)
+const int l[256] = { [10] = 1 };
+int k[670];
+asm (".section ro_seg_end, \"a\"; .previous");
+EOF
+$ gcc -shared -O2 -nostdlib -fpic -o test2.so test2.c
+$ readelf -S test2.so | grep '^ \['
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .hash HASH 000000b4 0000b4 000934 04 A 2 0 4
+ [ 2] .dynsym DYNSYM 000009e8 0009e8 001440 10 A 3 d 4
+ [ 3] .dynstr STRTAB 00001e28 001e28 000737 00 A 0 0 1
+ [ 4] .rel.dyn REL 00002560 002560 000968 08 A 2 0 4
+ [ 5] .text PROGBITS 00002ec8 002ec8 000000 00 AX 0 0 4
+ [ 6] .rodata PROGBITS 00002ee0 002ee0 000400 00 A 0 0 32
+ [ 7] ro_seg_end PROGBITS 000032e0 0032e0 000000 00 A 0 0 1
+ [ 8] .data PROGBITS 00004000 004000 0004b4 00 WA 0 0 4
+ [ 9] .dynamic DYNAMIC 000044b4 0044b4 000070 08 WA 3 0 4
+ [10] .got PROGBITS 00004524 004524 00000c 04 WA 0 0 4
+ [11] .bss NOBITS 00004540 004540 000a88 00 WA 0 0 32
+ [12] .comment PROGBITS 00000000 004540 000033 00 0 0 1
+ [13] .shstrtab STRTAB 00000000 004573 000075 00 0 0 1
+ [14] .symtab SYMTAB 00000000 004868 001480 10 15 11 4
+ [15] .strtab STRTAB 00000000 005ce8 000744 00 0 0 1
+$ readelf -l test2.so | grep LOAD
+ LOAD 0x000000 0x00000000 0x00000000 0x032e0 0x032e0 R E 0x1000
+ LOAD 0x004000 0x00004000 0x00004000 0x00530 0x00fc8 RW 0x1000
+$ prelink -N ./test2.so
+$ readelf -l test2.so | grep LOAD
+ LOAD 0x000000 0x02000000 0x02000000 0x037a0 0x037a0 R E 0x1000
+ LOAD 0x0044c0 0x020044c0 0x020044c0 0x00530 0x00fc8 RW 0x1000
+$ readelf -S test2.so | grep '^ \['
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .hash HASH 020000b4 0000b4 000934 04 A 2 0 4
+ [ 2] .dynsym DYNSYM 020009e8 0009e8 001440 10 A 3 d 4
+ [ 3] .dynstr STRTAB 02001e28 001e28 000737 00 A 0 0 1
+ [ 4] .rel.dyn RELA 02002560 002560 000e1c 0c A 2 0 4
+ [ 5] .text PROGBITS 02003388 003388 000000 00 AX 0 0 4
+ [ 6] .rodata PROGBITS 020033a0 0033a0 000400 00 A 0 0 32
+ [ 7] ro_seg_end PROGBITS 020037a0 0037a0 000000 00 A 0 0 1
+ [ 8] .data PROGBITS 020044c0 0044c0 0004b4 00 WA 0 0 4
+ [ 9] .dynamic DYNAMIC 02004974 004974 000070 08 WA 3 0 4
+ [10] .got PROGBITS 020049e4 0049e4 00000c 04 WA 0 0 4
+ [11] .bss NOBITS 02004a00 004a00 000a88 00 WA 0 0 32
+ [12] .comment PROGBITS 00000000 004a00 000033 00 0 0 1
+ [13] .gnu.liblist GNU_LIBLIST 00000000 004a33 000000 14 14 0 4
+ [14] .gnu.libstr STRTAB 00000000 004a33 000000 00 0 0 1
+ [15] .gnu.prelink_undo PROGBITS 00000000 004a34 00030c 01 0 0 4
+ [16] .shstrtab STRTAB 00000000 004d43 0000a0 00 0 0 1
+ [17] .symtab SYMTAB 00000000 0050e0 001480 10 18 11 4
+ [18] .strtab STRTAB 00000000 006560 000744 00 0 0 1
+\end{verbatim}}
+\prelinklistingcaption{Growing read-only segment not requiring additional padding}}
+
+\begin{figure}[!ht]
+\centering
+\includegraphics[width=0.8\textwidth]{dso2}
+\caption{Growing read-only segment not requiring additional padding}
+\end{figure}
+
+In the second example \tts{prelink} can grow by just \tts{0x4c0} bytes as
+well, eventhough the distance between read-write and read-only segment
+is just \tts{0xd20} bytes. With this distance, hypothetical adjustment
+by any size less than \tts{0xd21} bytes (modulo 4096) would need just
+rounding up to the next multiple of 32 bytes, while adjustments
+from \tts{0xd21} up to \tts{0xfe0} would require adjustments in
+multiples of 4096 bytes.
+
+\noindent{{\small\begin{verbatim}
+$ cat > test3.c <<EOF
+int i[2] __attribute__((aligned (32)));
+#define J1(N) int *j##N = &i[1];
+#define J2(N) J1(N##0) J1(N##1) J1(N##2) J1(N##3) J1(N##4)
+#define J3(N) J2(N##0) J2(N##1) J2(N##2) J2(N##3) J2(N##4)
+#define J4(N) J3(N##0) J3(N##1) J3(N##2) J3(N##3) J3(N##4)
+J4(0) J4(1) J3(2) J3(3) J1(4)
+int k[670];
+asm (".section ro_seg_end, \"a\"; .previous");
+EOF
+$ gcc -shared -O2 -nostdlib -fpic -o test3.so test3.c
+$ readelf -S test3.so | grep '^ \['
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .hash HASH 000000b4 0000b4 00092c 04 A 2 0 4
+ [ 2] .dynsym DYNSYM 000009e0 0009e0 001420 10 A 3 c 4
+ [ 3] .dynstr STRTAB 00001e00 001e00 000735 00 A 0 0 1
+ [ 4] .rel.dyn REL 00002538 002538 000968 08 A 2 0 4
+ [ 5] .text PROGBITS 00002ea0 002ea0 000000 00 AX 0 0 4
+ [ 6] ro_seg_end PROGBITS 00002ea0 002ea0 000000 00 A 0 0 1
+ [ 7] .data PROGBITS 00003000 003000 0004b4 00 WA 0 0 4
+ [ 8] .dynamic DYNAMIC 000034b4 0034b4 000070 08 WA 3 0 4
+ [ 9] .got PROGBITS 00003524 003524 00000c 04 WA 0 0 4
+ [10] .bss NOBITS 00003540 003540 000a88 00 WA 0 0 32
+ [11] .comment PROGBITS 00000000 003540 000033 00 0 0 1
+ [12] .shstrtab STRTAB 00000000 003573 00006d 00 0 0 1
+ [13] .symtab SYMTAB 00000000 003838 001460 10 14 10 4
+ [14] .strtab STRTAB 00000000 004c98 000742 00 0 0 1
+$ readelf -l test3.so | grep LOAD
+ LOAD 0x000000 0x00000000 0x00000000 0x02ea0 0x02ea0 R E 0x1000
+ LOAD 0x003000 0x00003000 0x00003000 0x00530 0x00fc8 RW 0x1000
+$ prelink -N ./test3.so
+$ readelf -l test3.so | grep LOAD
+ LOAD 0x000000 0x02000000 0x02000000 0x03ea0 0x03ea0 R E 0x1000
+ LOAD 0x004000 0x02004000 0x02004000 0x00530 0x00fc8 RW 0x1000
+$ readelf -S test3.so | grep '^ \['
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .hash HASH 020000b4 0000b4 00092c 04 A 2 0 4
+ [ 2] .dynsym DYNSYM 020009e0 0009e0 001420 10 A 3 c 4
+ [ 3] .dynstr STRTAB 02001e00 001e00 000735 00 A 0 0 1
+ [ 4] .rel.dyn RELA 02002538 002538 000e1c 0c A 2 0 4
+ [ 5] .text PROGBITS 02003ea0 003ea0 000000 00 AX 0 0 4
+ [ 6] ro_seg_end PROGBITS 02003ea0 003ea0 000000 00 A 0 0 1
+ [ 7] .data PROGBITS 02004000 004000 0004b4 00 WA 0 0 4
+ [ 8] .dynamic DYNAMIC 020044b4 0044b4 000070 08 WA 3 0 4
+ [ 9] .got PROGBITS 02004524 004524 00000c 04 WA 0 0 4
+ [10] .bss NOBITS 02004540 004540 000a88 00 WA 0 0 32
+ [11] .comment PROGBITS 00000000 004540 000033 00 0 0 1
+ [12] .gnu.liblist GNU_LIBLIST 00000000 004573 000000 14 13 0 4
+ [13] .gnu.libstr STRTAB 00000000 004573 000000 00 0 0 1
+ [14] .gnu.prelink_undo PROGBITS 00000000 004574 0002e4 01 0 0 4
+ [15] .shstrtab STRTAB 00000000 00485b 000098 00 0 0 1
+ [16] .symtab SYMTAB 00000000 004bc8 001460 10 17 10 4
+ [17] .strtab STRTAB 00000000 006028 000742 00 0 0 1
+\end{verbatim}}
+\prelinklistingcaption{Growing read-only segment if page padding needed}}
+
+\begin{figure}[!ht]
+\centering
+\includegraphics[width=0.8\textwidth]{dso3}
+\caption{Growing read-only segment if page padding needed}
+\end{figure}
+
+In the last example the distance between \tts{PT\_LOAD} segments is very
+small, just \tts{0x160} bytes and the adjustment had to be done by 4096
+bytes.
+
+% Fortunately, shared libraries are position independent, so all absolute
+% values in them are either stored in well known \tts{ELF} structures,
+% or have corresponding dynamic relocations. The only problem might be
+% with relative relocations, which are resolved at link time.
+% The start of read-only \tts{PT\_LOAD} segment of shared libraries is
+% typically used by special sections used by the dynamic linker
+% (\tts{.hash}, \tts{.dynsym}, \tts{.dynstr}, \tts{.gnu.version*},
+% \tts{.rel*}, \tts{.note*}). It makes no sense for a shared library to
+% have relocations against these sections or some addresses inside of them,
+% furthermore it is impossible to do it without specially crafted
+% linker script. So \tts{prelink} makes the assumption that it can grow
+% freely the shared library after \tts{.rel.dyn} section, as long
+% as only sections mentioned above come before \tts{.rel.dyn} (it actually
+% checks section types, not names). \tts{Prelink} certainly can grow the shared library
+% size in multiplies of \tts{ELF} architecture specific maximum page size,
+% but usually it can do better. Particularly, \tts{prelink} can grow by the 50\% size
+% of \tts{.rel.dyn} section rounded up to the largest section alignment
+% in all sections following it, but it has to make sure that two
+% different \tts{PT\_LOAD} segments (typically the read-only and read-write)
+% will not share the same page, otherwise it needs to grow it more in
+% multiplies of the maximum section alignment until they are on different
+% pages. Growing is done by using the shared library relocation code with
+% start address set to end of \tts{.rel.dyn} section. \tts{.rel.plt}
+% section is then moved right to the end of \tts{.rel.dyn} section,
+% \tts{.dynamic} section needs updating all addresses, type of
+% relocation section, segment table needs to be adjusted accordingly
+% and file offsets in section header table as well.
+
+\section{Conflicts}
+
+As said earlier, if symbol lookup of some symbol in particular shared
+library results in different values when that shared library's natural
+search scope is used and when using search scope of the application the
+DSO is used in, this is considered a {\sl conflict}.
+Here is an example of a conflict on IA-32:
+
+\noindent{{\small\begin{verbatim}
+$ cat > test1.c <<EOF
+int i;
+int *j = &i;
+int *foo (void) { return &i; }
+EOF
+$ cat > test2.c <<EOF
+int i;
+int *k = &i;
+int *bar (void) { return &i; }
+EOF
+$ cat > test.c <<EOF
+#include <stdio.h>
+extern int i, *j, *k, *foo (void), bar (void);
+int main (void)
+{
+#ifdef PRINT_I
+ printf ("%p\n", &i);
+#endif
+ printf ("%p %p %p %p\n", j, k, foo (), bar ());
+}
+EOF
+$ gcc -nostdlib -shared -fpic -s -o test1.so test1.c
+$ gcc -nostdlib -shared -fpic -o test2.so test2.c ./test1.so
+$ gcc -o test test.c ./test2.so ./test1.so
+$ ./test
+0x16137c 0x16137c 0x16137c 0x16137c
+$ readelf -r ./test1.so
+
+Relocation section '.rel.dyn' at offset 0x2bc contains 2 entries:
+ Offset Info Type Sym.Value Sym. Name
+000012e4 00000d01 R_386_32 00001368 i
+00001364 00000d06 R_386_GLOB_DAT 00001368 i
+$ prelink -N ./test ./test1.so ./test2.so
+$ LD_WARN= LD_TRACE_PRELINKING=1 LD_BIND_NOW=1 /lib/ld-linux.so.2 ./test1.so
+ ./test1.so => ./test1.so (0x04db6000, 0x00000000)
+$ LD_WARN= LD_TRACE_PRELINKING=1 LD_BIND_NOW=1 /lib/ld-linux.so.2 ./test2.so
+ ./test2.so => ./test2.so (0x04dba000, 0x00000000)
+ ./test1.so => ./test1.so (0x04db6000, 0x00000000)
+$ LD_WARN= LD_TRACE_PRELINKING=1 LD_BIND_NOW=1 /lib/ld-linux.so.2 ./test \
+ | sed 's/^[[:space:]]*/ /'
+ ./test => ./test (0x08048000, 0x00000000)
+ ./test2.so => ./test2.so (0x04dba000, 0x00000000)
+ ./test1.so => ./test1.so (0x04db6000, 0x00000000)
+ libc.so.6 => /lib/tls/libc.so.6 (0x00b22000, 0x00000000) TLS(0x1, 0x00000028)
+ /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00b0a000, 0x00000000)
+$ readelf -S ./test1.so | grep '\.data\|\.got'
+ [ 6] .data PROGBITS 04db72e4 0002e4 000004 00 WA 0 0 4
+ [ 8] .got PROGBITS 04db7358 000358 000010 04 WA 0 0 4
+$ readelf -r ./test1.so
+
+Relocation section '.rel.dyn' at offset 0x2bc contains 2 entries:
+ Offset Info Type Sym.Value Sym. Name
+04db72e4 00000d06 R_386_GLOB_DAT 04db7368 i
+04db7364 00000d06 R_386_GLOB_DAT 04db7368 i
+$ objdump -s -j .got -j .data test1.so
+
+test1.so: file format elf32-i386
+
+Contents of section .data:
+ 4db72e4 6873db04 hs..
+Contents of section .got:
+ 4db7358 e8120000 00000000 00000000 6873db04 ............hs..
+$ readelf -r ./test | sed '/\.gnu\.conflict/,$!d'
+Relocation section '.gnu.conflict' at offset 0x7ac contains 18 entries:
+ Offset Info Type Sym.Value Sym. Name + Addend
+04db72e4 00000001 R_386_32 04dbb37c
+04db7364 00000001 R_386_32 04dbb37c
+00c56874 00000001 R_386_32 fffffff0
+00c56878 00000001 R_386_32 00000001
+00c568bc 00000001 R_386_32 fffffff4
+00c56900 00000001 R_386_32 ffffffec
+00c56948 00000001 R_386_32 ffffffdc
+00c5695c 00000001 R_386_32 ffffffe0
+00c56980 00000001 R_386_32 fffffff8
+00c56988 00000001 R_386_32 ffffffe4
+00c569a4 00000001 R_386_32 ffffffd8
+00c569c4 00000001 R_386_32 ffffffe8
+00c569d8 00000001 R_386_32 080485b8
+00b1f510 00000007 R_386_JUMP_SLOT 00b91460
+00b1f514 00000007 R_386_JUMP_SLOT 00b91080
+00b1f518 00000007 R_386_JUMP_SLOT 00b91750
+00b1f51c 00000007 R_386_JUMP_SLOT 00b912c0
+00b1f520 00000007 R_386_JUMP_SLOT 00b91200
+$ ./test
+0x4dbb37c 0x4dbb37c 0x4dbb37c 0x4dbb37c
+\end{verbatim}}
+\prelinklistingcaption{Conflict example}}
+
+In the example, among some conflicts caused by the dynamic linker and the C library,
+\footnote{Particularly in the example, the 5 \tts{R\_386\_JUMP\_SLOT} fixups
+are \tts{PLT} slots in the dynamic linker for memory allocator functions
+resolving to C library functions instead of dynamic linker's own trivial
+implementation. First 10 \tts{R\_386\_32} fixups at offsets 0xc56874
+to 0xc569c4 are Thread Local Storage fixups in the C library and
+the fixup at 0xc569d8 is for {\sl \_IO\_stdin\_used} weak undefined symbol
+in the C library, resolving to a symbol with the same name in the executable.}
+there is a conflict for the symbol {\sl i} in \tts{test1.so} shared library.
+\tts{test1.so} has just itself in its natural symbol lookup scope (as proved
+by
+
+\tts{LD\_WARN= LD\_TRACE\_PRELINKING=1 LD\_BIND\_NOW=1 /lib/ld-linux.so.2 ./test1.so}
+
+command output), so when looking up symbol {\sl i} in this
+scope the definition in \tts{test1.so} is chosen. \tts{test1.so} has two
+relocations against the symbol {\sl i}, one \tts{R\_386\_32} against \tts{.data}
+section and one \tts{R\_386\_GLOB\_DAT} against \tts{.got} section. When
+prelinking \tts{test1.so} library, the dynamic linker stores the address of
+{\sl i} (0x4db7368) into both locations (at offsets 0x4db72e4 and 0x4db7364).
+The global symbol search scope in \tts{test} executable contains the executable
+itself, \tts{test2.so} and \tts{test1.so} libraries, \tts{libc.so.6} and
+the dynamic linker in the listed order.
+When doing symbol lookup for symbol {\sl i}
+in \tts{test1.so} when doing relocation processing of the whole executable,
+address of {\sl i} in \tts{test2.so} is returned as that symbol comes earlier
+in the global search scope. So, when none of the libraries nor the executable
+is prelinked, the program prints 4 identical addresses. If prelink didn't
+create conflict fixups for the two relocations against the symbol {\sl i}
+in \tts{test1.so}, prelinked executable (which bypasses normal relocation
+processing on startup) would print instead of the desired
+
+\tts{0x4dbb37c 0x4dbb37c 0x4dbb37c 0x4dbb37c}
+
+different addresses,
+
+\tts{0x4db7368 0x4dbb37c 0x4db7368 0x4dbb37c}
+
+That is a functionality change that \tts{prelink} cannot be permitted to
+make, so instead it fixes up the two locations by storing the desired
+value in there. In this case \tts{prelink} really cannot avoid that
+- \tts{test1.so} shared library could be also used without \tts{test2.so}
+in some other executable's symbol search scope.
+Or there could be some executable linked with:
+
+\noindent{{\small\begin{verbatim}
+$ gcc -o test2 test.c ./test1.so ./test2.so
+\end{verbatim}}
+\prelinklistingcaption{Conflict example with swapped order of libraries}}
+
+where {\sl i} lookup in \tts{test1.so} and \tts{test2.so} is supposed
+to resolve to {\sl i} in \tts{test1.so}.
+
+Now consider what happens if the executable is linked with \tts{-DPRINT\_I}:
+
+\noindent{{\small\begin{verbatim}
+$ gcc -DPRINT_I -o test3 test.c ./test2.so ./test1.so
+$ ./test3
+0x804972c
+0x804972c 0x804972c 0x804972c 0x804972c
+$ prelink -N ./test3 ./test1.so ./test2.so
+$ readelf -S ./test2.so | grep '\.data\|\.got'
+ [ 6] .data PROGBITS 04dbb2f0 0002f0 000004 00 WA 0 0 4
+ [ 8] .got PROGBITS 04dbb36c 00036c 000010 04 WA 0 0 4
+$ readelf -r ./test2.so
+
+Relocation section '.rel.dyn' at offset 0x2c8 contains 2 entries:
+ Offset Info Type Sym.Value Sym. Name
+04dbb2f0 00000d06 R_386_GLOB_DAT 04dbb37c i
+04dbb378 00000d06 R_386_GLOB_DAT 04dbb37c i
+$ objdump -s -j .got -j .data test2.so
+
+test2.so: file format elf32-i386
+
+Contents of section .data:
+ 4dbb2f0 7cb3db04 |...
+Contents of section .got:
+ 4dbb36c f4120000 00000000 00000000 7cb3db04 ............|...
+$ readelf -r ./test3
+
+Relocation section '.rel.dyn' at offset 0x370 contains 4 entries:
+ Offset Info Type Sym.Value Sym. Name
+08049720 00000e06 R_386_GLOB_DAT 00000000 __gmon_start__
+08049724 00000105 R_386_COPY 08049724 j
+08049728 00000305 R_386_COPY 08049728 k
+0804972c 00000405 R_386_COPY 0804972c i
+
+Relocation section '.rel.plt' at offset 0x390 contains 4 entries:
+ Offset Info Type Sym.Value Sym. Name
+08049710 00000607 R_386_JUMP_SLOT 080483d8 __libc_start_main
+08049714 00000707 R_386_JUMP_SLOT 080483e8 printf
+08049718 00000807 R_386_JUMP_SLOT 080483f8 foo
+0804971c 00000c07 R_386_JUMP_SLOT 08048408 bar
+
+Relocation section '.gnu.conflict' at offset 0x7f0 contains 20 entries:
+ Offset Info Type Sym.Value Sym. Name + Addend
+04dbb2f0 00000001 R_386_32 0804972c
+04dbb378 00000001 R_386_32 0804972c
+04db72e4 00000001 R_386_32 0804972c
+04db7364 00000001 R_386_32 0804972c
+00c56874 00000001 R_386_32 fffffff0
+00c56878 00000001 R_386_32 00000001
+00c568bc 00000001 R_386_32 fffffff4
+00c56900 00000001 R_386_32 ffffffec
+00c56948 00000001 R_386_32 ffffffdc
+00c5695c 00000001 R_386_32 ffffffe0
+00c56980 00000001 R_386_32 fffffff8
+00c56988 00000001 R_386_32 ffffffe4
+00c569a4 00000001 R_386_32 ffffffd8
+00c569c4 00000001 R_386_32 ffffffe8
+00c569d8 00000001 R_386_32 080485f0
+00b1f510 00000007 R_386_JUMP_SLOT 00b91460
+00b1f514 00000007 R_386_JUMP_SLOT 00b91080
+00b1f518 00000007 R_386_JUMP_SLOT 00b91750
+00b1f51c 00000007 R_386_JUMP_SLOT 00b912c0
+00b1f520 00000007 R_386_JUMP_SLOT 00b91200
+$ ./test3
+0x804972c
+0x804972c 0x804972c 0x804972c 0x804972c
+\end{verbatim}}
+\prelinklistingcaption{Conflict example with COPY relocation for conflicting symbol}}
+
+Because the executable is not compiled as position independent code and
+\tts{main} function takes address of {\sl i} variable, the object
+file for \tts{test3.c} contains a \tts{R\_386\_32} relocation against
+{\sl i}. The linker cannot make dynamic relocations against read-only
+segment in the executable, so the address of {\sl i} must be constant.
+This is accomplished by creating a new object {\sl i} in the executable's
+\tts{.dynbss} section and creating a dynamic \tts{R\_386\_COPY} relocation
+for it. The relocation ensures that during startup the content of
+{\sl i} object earliest in the search scope without the executable
+is copied to this {\sl i} object in executable. Now, unlike \tts{test}
+executable, in \tts{test3} executable {\sl i} lookups in both \tts{test1.so}
+and \tts{test2.so} libraries result in address of {\sl i} in the executable
+(instead of \tts{test2.so}). This means that two conflict fixups
+are needed again for \tts{test1.so} (but storing 0x804972c instead of
+0x4dbb37c) and two new fixups are needed for \tts{test2.so}.
+
+If the executable is compiled as position independent code,
+
+\noindent{{\small\begin{verbatim}
+$ gcc -fpic -DPRINT_I -o test4 test.c ./test2.so ./test1.so
+$ ./test4
+0x4dbb37c
+0x4dbb37c 0x4dbb37c 0x4dbb37c 0x4dbb37c
+\end{verbatim}}
+\prelinklistingcaption{Conflict example with position independent code in the executable}}
+
+the address of {\sl i} is stored in executable's \tts{.got} section,
+which is writable and thus can have dynamic relocation against it.
+So the linker creates a \tts{R\_386\_GLOB\_DAT} relocation against
+the \tts{.got} section, the symbol {\sl i} is undefined in the executable
+and no copy relocations are needed. In this case, only \tts{test1.so}
+will need 2 fixups, \tts{test2.so} will not need any.
+
+There are various reasons for conflicts:
+\begin{itemize}
+\item Improperly linked shared libraries. If a shared library always needs
+symbols from some particular shared library, it should be linked against
+that library, usually by adding \tts{-lLIBNAME} to \tts{gcc -shared} command
+line used during linking of the shared library. This both reduces conflict
+fixups in \tts{prelink} and makes the library easier to load using
+\tts{dlopen}, because applications don't have to remember that they have
+to load some other library first. The best place to record the dependency
+is in the shared library itself. Another reason is if the needed library
+uses symbol versioning for its symbols. Not linking against that library
+can result in malfunctioning shared library. \tts{Prelink} issues a warning for
+such libraries - \tts{Warning: {\sl library} has undefined non-weak symbols}.
+When linking a shared library, the \tts{-Wl,-z,defs} option can be used to
+ensure there are no such undefined non-weak symbols. There are exceptions,
+when undefined non-weak symbols in shared libraries are desirable.
+One exception is when there are multiple shared libraries providing the
+same functionality, and a shared library doesn't care which one is used.
+An example can be e.g. \tts{libreadline.so.4}, which needs some terminal
+handling functions, which are provided be either \tts{libtermcap.so.2},
+or \tts{libncurses.so.5}. Another exception is with plugins or other
+shared libraries which expect some symbols to be resolved to symbols
+defined in the executable.
+\item A library overriding functionality of some other library. One example
+is e.g. C library and POSIX thread library. Older versions of the GNU C library
+did not provide cancelable entry points required by the standard. This is
+not needed for non-threaded applications. So only the \tts{libpthread.so.0} shared
+library which provides POSIX threading support then overrode the
+cancellation entry points required by the standard by wrapper functions
+which provided the required functionality. Although most recent versions
+of the GNU C library handle cancellation even in entry points in \tts{libc.so.6}
+(this was needed for cases when \tts{libc.so.6} comes earlier before
+\tts{libpthread.so.0} in symbol search scope and used to be worked around
+by non-standard handling of weak symbols in the dynamic linker), because
+of symbol versioning the symbols had to stay in \tts{libpthread.so.0}
+as well as in \tts{libc.so.6}. This means every program using POSIX
+threads on Linux will have a couple of conflict fixups because of this.
+\item Programs which need copy relocations. Although \tts{prelink} will
+resolve the copy relocations at prelinking time, if any shared library
+has relocations against the symbol which needed copy relocation, all such
+relocations will need conflict fixups. Generally, it is better to not
+export variables from shared libraries in their APIs, instead provide
+accessor functions.
+\item Function pointer equality requirement for functions called from
+executables. When address of some global function is taken, at least
+C and C++ require that this pointer is the same in the whole program.
+Executables typically contain position dependent code, so when code in the
+executable takes address of some function not defined in the executable itself,
+that address must be link time constant. Linker accomplishes this by
+creating a \tts{PLT} slot for the function unless there was one already
+and resolving to the address of \tts{PLT} slot. The symbol for the function
+is created with \tts{st\_value} equal to address of the \tts{PLT} slot,
+but \tts{st\_shndx} set to \tts{SHN\_UNDEF}. Such symbols are treated
+specially by the dynamic linker, in that \tts{PLT} relocations
+resolve to first symbol in the global search scope after the executable,
+while symbol lookups for all other relocation types return the
+address of the symbol in the executable. Unfortunately, GNU linker doesn't
+differentiate between taking address of a function in an executable (especially
+one for which no dynamic relocation is possible in case it is in read-only
+segment) and just calling the function, but never taking its address.
+If it cleared the \tts{st\_value} field of the \tts{SHN\_UNDEF} function symbols
+in case nothing in the executable takes the function's address, several \tts{prelink}
+conflict could disappear (\tts{SHN\_UNDEF} symbols with \tts{st\_value} set
+to 0 are treated always as real undefined symbols by the dynamic linker).
+\item \tts{COMDAT} code and data in C++. C++ language has several places where
+it may need to emit some code or data without a clear unique
+compilation unit owning it. Examples include taking address of an
+\tts{inline} function, local static variable in \tts{inline} functions,
+virtual tables for some classes (this depends on \tts{\#pragma interface}
+or \tts{\#pragma implementation} presence, presence of non-inline
+non-pure-virtual member function in the class, etc.), {\sl RTTI} info for them.
+Compilers and linkers handle these using various \tts{COMDAT} schemes,
+e.g. GNU linker's \tts{.gnu.linkonce*} special sections or using
+\tts{SHT\_GROUP}. Unfortunately, all these duplicate merging schemes
+work only during linking of shared libraries or executables, no duplicate
+removal is done across shared libraries. Shared libraries typically
+have relocations against their \tts{COMDAT} code or data objects (otherwise
+they wouldn't be at least in most cases emitted at all), so if there are
+\tts{COMDAT} duplicates across shared libraries or the executable, they
+lead to conflict fixups. The linker theoretically could try to
+merge \tts{COMDAT} duplicates across shared libraries if specifically
+requested by the user (if a \tts{COMDAT} symbol is already present in
+one of the dependent shared libraries and is \tts{STB\_WEAK}, the linker
+could skip it). Unfortunately, this only works as long as the user has
+full control over the dependent shared libraries, because the \tts{COMDAT}
+symbol could be exported from them just as a side effect of their
+implementation (e.g. they use some class internally). When such libraries
+are rebuilt even with minor changes in their implementation (unfortunately
+with C++ shared libraries it is usually not very clear what part is exported
+ABI and what is not), some of those \tts{COMDAT} symbols in them could go
+away (e.g. because suddenly they use a different class internally and
+the previously used class is not referenced anywhere). When \tts{COMDAT}
+objects are not merged across shared libraries, this makes no problems,
+as each library which needs the \tts{COMDAT} has its own copy. But with
+\tts{COMDAT} duplicate removal between shared libraries there could suddenly
+be unresolved references and the shared libraries would need to be relinked.
+The only place where this could work safely is when a single package
+includes several C++ shared libraries which depend on each other. They are
+then shipped always together and when one changes, all others need changing
+too.
+\end{itemize}
+
+\section{Prelink optimizations to reduce number of conflict fixups}
+
+\tts{Prelink} can optimize out some conflict fixups if it can prove that
+the changes are not observable by the application at runtime (opening its
+executable and reading it doesn't count). If there is a data object in some
+shared library with a symbol that is overridden by a symbol in a different
+shared library earlier in global symbol lookup scope or in the executable, then
+that data object is likely never referenced and it shouldn't matter what it
+contains. Examine the following example:
+
+\noindent{{\small\begin{verbatim}
+$ cat > test1.c <<EOF
+int i, j, k;
+struct A { int *a; int *b; int *c; } x = { &i, &j, &k };
+struct A *y = &x;
+EOF
+$ cat > test2.c <<EOF
+int i, j, k;
+struct A { int *a; int *b; int *c; } x = { &i, &j, &k };
+struct A *z = &x;
+EOF
+$ cat > test.c <<EOF
+#include <stdio.h>
+extern struct A { int *a; int *b; int *c; } *y, *z;
+int main (void)
+{
+ printf ("%p: %p %p %p\n", y, y->a, y->b, y->c);
+ printf ("%p: %p %p %p\n", z, z->a, z->b, z->c);
+}
+EOF
+$ gcc -nostdlib -shared -fpic -s -o test1.so test1.c
+$ gcc -nostdlib -shared -fpic -o test2.so test2.c ./test1.so
+$ gcc -o test test.c ./test2.so ./test1.so
+$ ./test
+0xaf3314: 0xaf33b0 0xaf33a8 0xaf33ac
+0xaf3314: 0xaf33b0 0xaf33a8 0xaf33ac
+\end{verbatim}}
+\prelinklistingcaption{C example where conflict fixups could be optimized out}}
+
+In this example there are 3 conflict fixups pointing into the 12 byte
+long {\sl x} object in \tts{test1.so} shared library (among other
+conflicts). And nothing in the program can poke at {\sl x} content
+in \tts{test1.so}, simply because it has to look at it through
+{\sl x} symbol which resolves to \tts{test2.so}. So in this
+case \tts{prelink} could skip those 3 conflicts. Unfortunately
+it is not that easy:
+
+\noindent{{\small\begin{verbatim}
+$ cat > test3.c <<EOF
+int i, j, k;
+static struct A { int *a; int *b; int *c; } local = { &i, &j, &k };
+extern struct A x;
+struct A *y = &x;
+struct A *y2 = &local;
+extern struct A x __attribute__((alias ("local")));
+EOF
+$ cat > test4.c <<EOF
+#include <stdio.h>
+extern struct A { int *a; int *b; int *c; } *y, *y2, *z;
+int main (void)
+{
+ printf ("%p: %p %p %p\n", y, y->a, y->b, y->c);
+ printf ("%p: %p %p %p\n", y2, y2->a, y2->b, y2->c);
+ printf ("%p: %p %p %p\n", z, z->a, z->b, z->c);
+}
+EOF
+$ gcc -nostdlib -shared -fpic -s -o test3.so test3.c
+$ gcc -nostdlib -shared -fpic -o test4.so test2.c ./test3.so
+$ gcc -o test4 test4.c ./test4.so ./test3.so
+$ ./test4
+0x65a314: 0x65a3b0 0x65a3a8 0x65a3ac
+0xbd1328: 0x65a3b0 0x65a3a8 0x65a3ac
+0x65a314: 0x65a3b0 0x65a3a8 0x65a3ac
+\end{verbatim}}
+\prelinklistingcaption{Modified C example where conflict fixups cannot be removed}}
+
+In this example, there are again 3 conflict fixups pointing into the
+12 byte long {\sl x} object in \tts{test3.so} shared library.
+The fact that variable local is located at the same 12 bytes
+is totally invisible to prelink, as local is a \tts{STB\_LOCAL}
+symbol which doesn't show up in \tts{.dynsym} section. But if those
+3 conflict fixups are removed, then suddenly program's observable
+behavior changes (the last 3 addresses on second line would be
+different than those on first or third line).
+
+Fortunately, there are at least some objects where \tts{prelink}
+can be reasonably sure they will never be referenced through some
+local alias. Those are various compiler generated objects with
+well defined meaning which is \tts{prelink} able to identify
+in shared libraries. The most important ones are C++ virtual tables
+and {\sl RTTI} data. They are emitted as COMDAT data by the compiler,
+in GCC into \tts{.gnu.linkonce.d.*} sections. Data or code in these
+sections can be accessed only through global symbols, otherwise linker
+might create unexpected results when two or more of these sections
+are merged together (all but one deleted). When \tts{prelink} is checking
+for such data, it first checks whether the shared library in question
+is linked against \tts{libstdc++.so}. If not, it is not a C++ library
+(or incorrectly built one) and thus it makes no sense to search any further.
+It looks only in \tts{.data} section, for \tts{STB\_WEAK} \tts{STT\_OBJECT}
+symbols whose names start with certain prefixes
+\footnote{\tts{\_\_vt\_} for GCC 2.95.x and 2.96-RH virtual tables,
+\tts{\_ZTV} for GCC 3.x virtual tables and \tts{\_ZTI} for GCC 3.x {\sl RTTI} data.}
+and where no other symbols (in dynamic symbol table) point into the objects.
+If these objects are unused because there is a conflict on their symbol,
+all conflict fixups pointing into the virtual table or {\sl RTTI} structure
+can be discarded.
+
+Another possible optimization is again related to C++ virtual tables.
+Function addresses in them are not intended for pointer comparisons.
+C++ code only loads them from the virtual tables and calls through
+the pointer. Pointers to member functions are handled differently.
+As pointer equivalence is the only reason why all function pointers
+resolve to \tts{PLT} slots in the executable even when the executable doesn't
+include implementation of the function (i.e. has \tts{SHN\_UNDEF} symbol
+with non-zero \tts{st\_value} pointing at the \tts{PLT} slot in the
+executable), \tts{prelink} can resolve method addresses in virtual tables
+to the actual method implementation. In many cases this is in the same
+library as the virtual table (or in one of libraries in its natural
+symbol lookup scope), so a conflict fixup is unnecessary.
+This optimization speeds up programs also after control is transfered
+to the application and not just the time to start up the application,
+although just a few cycles per method call.
+
+The conflict fixup reduction is quite big on some programs.
+Below is statistics for \tts{kmail} program on completely unprelinked box:
+
+\noindent{{\small\begin{verbatim}
+$ LD_DEBUG=statistics /usr/bin/kmail 2>&1 | sed '2,8!d;s/^ *//'
+10621: total startup time in dynamic loader: 240724867 clock cycles
+10621: time needed for relocation: 234049636 clock cycles (97.2%)
+10621: number of relocations: 34854
+10621: number of relocations from cache: 74364
+10621: number of relative relocations: 35351
+10621: time needed to load objects: 6241678 clock cycles (2.5%)
+$ ls -l /usr/bin/kmail
+-rwxr-xr-x 1 root root 2149084 Oct 2 12:05 /usr/bin/kmail
+$ ( Xvfb :3 & ) >/dev/null 2>&1 </dev/null; sleep 20
+$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10; killall kmail
+$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10
+$ cat /proc/`/sbin/pidof kmail`/statm
+4164 4164 3509 224 33 3907 655
+$ killall Xvfb kdeinit kmail
+\end{verbatim}}
+\prelinklistingcaption{Statistics for unprelinked \tts{kmail}}}
+
+\tts{statm} special file for a process contains its memory statistics.
+The numbers in it mean in order total number of used pages (on IA-32
+Linux a page is 4KB), number of resident pages (i.e. not swapped out),
+number of shared pages, number of text pages, number of library pages,
+number of stack and other pages and number of dirty pages used by the
+process. Distinction between text and library pages is very rough,
+so those numbers aren't that much useful. Of interest are mainly
+first number, third number and last number.
+
+Statistics for \tts{kmail} on completely prelinked box:
+
+\noindent{{\small\begin{verbatim}
+$ LD_DEBUG=statistics /usr/bin/kmail 2>&1 | sed '2,8!d;s/^ *//'
+14864: total startup time in dynamic loader: 8409504 clock cycles
+14864: time needed for relocation: 3024720 clock cycles (35.9%)
+14864: number of relocations: 0
+14864: number of relocations from cache: 8961
+14864: number of relative relocations: 0
+14864: time needed to load objects: 4897336 clock cycles (58.2%)
+$ ls -l /usr/bin/kmail
+-rwxr-xr-x 1 root root 2269500 Oct 2 12:05 /usr/bin/kmail
+$ ( Xvfb :3 & ) >/dev/null 2>&1 </dev/null; sleep 20
+$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10; killall kmail
+$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10
+$ cat /proc/`/sbin/pidof kmail`/statm
+3803 3803 3186 249 33 3521 617
+$ killall Xvfb kdeinit kmail
+\end{verbatim}}
+\prelinklistingcaption{Statistics for prelinked \tts{kmail}}}
+
+Statistics for \tts{kmail} on completely prelinked box with C++ conflict fixup
+optimizations turned off:
+
+\noindent{{\small\begin{verbatim}
+$ LD_DEBUG=statistics /usr/bin/kmail 2>&1 | sed '2,8!d;s/^ *//'
+20645: total startup time in dynamic loader: 9704168 clock cycles
+20645: time needed for relocation: 4734715 clock cycles (48.7%)
+20645: number of relocations: 0
+20645: number of relocations from cache: 59871
+20645: number of relative relocations: 0
+20645: time needed to load objects: 4487971 clock cycles (46.2%)
+ls -l /usr/bin/kmail
+-rwxr-xr-x 1 root root 2877360 Oct 2 12:05 /usr/bin/kmail
+$ ( Xvfb :3 & ) >/dev/null 2>&1 </dev/null; sleep 20
+$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10; killall kmail
+$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10
+$ cat /proc/`/sbin/pidof kmail`/statm
+3957 3957 3329 398 33 3526 628
+$ killall Xvfb kdeinit kmail
+\end{verbatim}}
+\prelinklistingcaption{Statistics for prelinked \tts{kmail} without conflict fixup reduction}}
+
+On this application, C++ conflict fixup optimizations saved 50910 unneeded
+conflict fixups, speeded up startup by 13.3\% and decreased number of dirty
+pages by 11, which means the application needs 44KB less memory per-process.
+
+\section{Thread Local Storage support}
+
+Thread Local Storage ([12], [13], [14]) support has been recently added to
+GCC, GNU binutils and GNU C Library. \tts{TLS} support is a set of new
+relocations which together with dynamic linker and POSIX thread library
+additions provide faster and easier to use alternative to traditional
+POSIX thread local data API (\tts{pthread\_getspecific},
+\tts{pthread\_setspecific}, \tts{pthread\_key\_*}).
+
+\tts{TLS} necessitated several changes to \tts{prelink}. Thread Local
+symbols (with type \tts{STT\_TLS}) must not be relocated, as they are
+relative to the start of \tts{PT\_TLS} segment and thus not virtual
+addresses. The dynamic linker had to be enhanced so that it tells
+\tts{prelink} at \tts{LD\_TRACE\_PRELINKING} time what \tts{TLS} module
+IDs have been assigned and what addresses relative to start of \tts{TLS}
+block have been given to \tts{PT\_TLS} segment of each library or executable.
+There are 3 classes of new \tts{TLS} dynamic relocations \tts{prelink}
+is interested in (with different names on different architectures).
+
+In first class are module ID relocations, which are used for \tts{TLS}
+Global Dynamic and Local Dynamic models (for Global Dynamic model
+they are supposed to resolve to module ID of the executable or shared library
+of particular \tts{STT\_TLS} symbol, for Local Dynamic model this
+resolves to module ID of the containing shared library). These
+relocations are hard to prelink in any useful way without moving
+\tts{TLS} module ID assignment from the dynamic linker to \tts{prelink}.
+Although \tts{prelink} can find out what shared library will contain
+particular \tts{STT\_TLS} symbol unless there will be conflicts
+for that symbol, it doesn't know how many shared libraries with
+\tts{PT\_TLS} segment will precede it or whether executable will or
+will not have \tts{PT\_TLS} segment. Until \tts{TLS} is widely
+deployed by many libraries, \tts{prelink} could guess that
+only \tts{libc.so} will have \tts{PT\_TLS} and store 1 (first module ID
+the dynamic linker assigns), but given that \tts{libc.so} uses just
+one such relocation it is not probably worth doing this when soon other
+shared libraries besides \tts{libc.so} and \tts{libGL.so} start using
+it heavily. Because of this \tts{prelink} doesn't do anything special
+when prelinking shared libraries with these relocations and for each
+relocations in this class creates one conflict fixup.
+
+In second class are relocations which resolve to \tts{st\_value}
+of some \tts{STT\_TLS} symbol. These relocations are used in
+Global Dynamic \tts{TLS} model (in Local Dynamic they are resolved
+at link time already) and from \tts{prelink} point of view they are
+much more similar to normal relocations than the other two classes.
+When the \tts{STT\_TLS} symbol is looked up successfully in shared library's
+natural search scope, \tts{prelink} just stores its \tts{st\_value}
+into the relocation. The chances there will be a conflict are even
+smaller than with normal symbol lookups, since overloading \tts{TLS}
+symbols means wasted memory in each single thread and thus library
+writers will try to avoid it if possible.
+
+The third class includes relocations which resolve to offsets within
+program's initial \tts{TLS} block
+\footnote{Negative on architectures which have
+\tts{TLS} block immediately below thread pointer (e.g. IA-32, AMD64,
+SPARC, S/390) and positive on architectures which have \tts{TLS} block
+at thread pointer or a few bytes above it (e.g. PowerPC, Alpha, IA-64,
+SuperH).}
+Relocation in this class are used in Initial Exec \tts{TLS} model
+(or in Local Exec model if this model is supported in shared libraries).
+These offsets are even harder to predict than module IDs and unlike
+module IDs it wouldn't be very helpful if they were assigned by
+\tts{prelink} instead of dynamic linker (which would just read them
+from some dynamic tag). That's because \tts{TLS} block needs to be
+packed tightly and any assignments in \tts{prelink} couldn't take
+into account other shared libraries linked into the same executable
+and the executable itself. Similarly to module ID relocations,
+\tts{prelink} doesn't do anything about them when prelinking shared
+libraries and for each such relocation creates a conflict fixup.
+
+\section{Prelinking of executables and shared libraries}
+
+Rewriting of executables is harder than for shared libraries, both because
+there are more changes necessary and because shared libraries are
+relocatable and thus have dynamic relocations for all absolute addresses.
+
+After collecting all information from the dynamic linker and assigning
+virtual address space slots to all shared libraries, prelinking of shared
+libraries involves following steps:
+\begin{itemize}
+\item Relocation of the shared library to the assigned base address.
+\item \tts{REL} to \tts{RELA} conversion if needed (the only step which
+changes sizes of allocated sections in the middle).
+\item On architectures which have \tts{SHT\_NOBITS} \tts{.plt} sections,
+before relocations are applied the section needs to be converted to
+\tts{SHT\_PROGBITS}. As the section needs to be at the end (or after it)
+of file backed part of some \tts{PT\_LOAD} segment, this just means that
+the file backed up part needs to be enlarged, the file filled with zeros
+and all following section file offsets or program header entry file
+offsets adjusted. All \tts{SHT\_NOBITS} sections in the same \tts{PT\_LOAD}
+segment with virtual addresses lower than the \tts{.plt} start address
+need to be converted from \tts{SHT\_NOBITS} to \tts{SHT\_PROGBITS} too.
+Without making the section \tts{SHT\_PROGBITS}, \tts{prelink} cannot
+apply relocations against it as such sections contain only zeros.
+Architectures with \tts{SHT\_NOBITS} \tts{.plt} section supported by
+\tts{prelink} are PowerPC and PowerPC64.
+\item Applying relocations. For each dynamic relocation in the shared
+library, address of relocation's symbol looked up in natural symbol lookup
+search scope of the shared library (or 0 if the symbol is not found in
+that search scope) is stored in an architecture and relocation type
+dependent way to memory pointed by \tts{r\_offset} field of the relocation.
+This step uses symbol lookup information provided by dynamic linker.
+\item Addition or modification of \tts{DT\_CHECKSUM} and
+\tts{DT\_GNU\_PRELINKED} dynamic tags.
+\footnote{\tts{Prelink} is not able to grow \tts{.dynamic} section, so it
+needs some spare dynamic tags (DT\_NULL) at the end of \tts{.dynamic}
+section. GNU linker versions released after August 2001 leave space by
+default.} The former is set to checksum of allocated sections in the
+shared library, the latter to time of prelinking.
+\item On architectures which don't use writable \tts{.plt}, but instead use
+\tts{.got.plt} (this section is merged during linking into \tts{.got})
+section, \tts{prelink} typically stores address into the first PLT slot
+in \tts{.plt} section to the reserved second word of \tts{.got} section.
+On these architectures, the dynamic linker has to initialize \tts{.plt}
+section if lazy binding. On non-prelinked executables or shared libraries
+this typically means adding load offset to the values in \tts{.got.plt}
+section, for prelinked shared libraries or executables if prelinking
+information cannot be used it needs to compute the right values in
+\tts{.got.plt} section without looking at this section's content
+(since it contains prelinking information). The second word in \tts{.got}
+section is used for this computation.
+\item Addition of \tts{.gnu\_prelink\_undo} unallocated section if not
+present yet. This section is used by \tts{prelink} internally during
+undo operation.
+\item Addition of \tts{.gnu\_liblist} and \tts{.gnu\_libstr} unallocated
+sections or, if they are already present, their update including possible
+growing or shrinking. These sections are used only by \tts{prelink} to
+compare the dependent libraries (and their order) at the time when the
+shared library was prelinked against current dependencies. If a shared
+library has no dependencies (e.g. dynamic linker), these sections are not
+present.
+\end{itemize}
+
+Adding or resizing unallocated section needs just file offsets of following
+unallocated sections recomputed (ensuring proper alignment), growing section
+header table and \tts{.shstrtab} and adding new section names to that section.
+
+Prelinking of executables involves following steps:
+\begin{itemize}
+\item \tts{REL} to \tts{RELA} conversion if needed.
+\item \tts{SHT\_NOBITS} to \tts{SHT\_PROGBITS} conversion of \tts{.plt} section
+if needed.
+\item Applying relocations.
+\item Addition or resizing of allocated \tts{.gnu.conflict} section containing
+list of conflict fixups.
+\item Addition or resizing of allocated \tts{.gnu.liblist} section which is used
+by the dynamic linker at runtime to see if none of the dependencies changed
+or were reordered. If they were, it continues normal relocation processing,
+otherwise they can be skipped and only conflict fixups applied.
+\item Growing of allocated \tts{.dynstr} section, where strings referenced from
+\tts{.gnu.liblist} section need to be added.
+\item If there are any COPY relocations (which \tts{prelink} wants to handle
+rather than deferring them as conflict fixups to runtime), they need to be applied.
+\item Modifying second word in \tts{.got} section for \tts{.got.plt} using
+architectures.
+\item Addition or adjusting of dynamic tags which allow the dynamic linker
+to find the \tts{.gnu.liblist} and \tts{.gnu.conflict} sections and their
+sizes. \tts{DT\_GNU\_CONFLICT} and \tts{DT\_GNU\_CONFLICTSZ} should be present
+if there are any conflict fixups. It should contain the virtual address of
+the \tts{.gnu.conflict} section start resp. its size in bytes.
+\tts{DT\_GNU\_LIBLIST} and \tts{DT\_GNU\_LIBLISTSZ} need to be present in
+all prelinked executables and must be equal the to virtual address of
+the \tts{.gnu.liblist} section and its size in bytes.
+\item Addition of \tts{.gnu\_prelink\_undo} unallocated section if not present.
+\end{itemize}
+
+Executables can have absolute relocations already applied (and without a
+dynamic relocation) to virtually any allocated \tts{SHT\_PROGBITS} section
+\footnote{One exception is \tts{.interp} special section. It shouldn't have
+relocations applied to it, nor any other section should reference it.},
+against almost all allocated \tts{SHT\_PROGBITS} and \tts{SHT\_NOBITS}
+sections. This means that when growing, adding or shrinking allocated
+sections in executables, all \tts{SHT\_PROGBITS} and \tts{SHT\_NOBITS} section
+must keep their original virtual addresses and sizes
+\footnote{With a notable exception of splitting one section into two
+covering the same virtual address range.}. \tts{Prelink} tries various
+places where to put allocated sections which were added or grew:
+\begin{itemize}
+\item In the unlikely case if there is already some gap between
+sections in read-only \tts{PT\_LOAD} segment where the section fits.
+\item If the \tts{SHT\_NOBITS} sections are small enough to fit
+into a page together with the preceding \tts{SHT\_PROGBITS} section and there
+is still some space in the page after the \tts{SHT\_NOBITS} sections.
+In this case, \tts{prelink} converts the \tts{SHT\_NOBITS} sections into
+\tts{SHT\_PROGBITS} sections, fills them with zeros and adds the new section
+after it. This doesn't increase number of \tts{PT\_LOAD} segments, but
+unfortunately those added sections are writable. This doesn't matter
+much for e.g. \tts{.gnu.conflict} section which is only used before control
+is transfered to the program, but could matter for \tts{.dynstr} which is
+used even during \tts{dlopen}.
+\item On IA-32, executables have for historical reasons base address 0x8048000.
+The reason for this was that when stack was put immediately below executables,
+stack and the executable could coexist in the same second level page table.
+Linux puts the stack typically at the end of virtual address space and so
+keeping this exact base address is not really necessary. \tts{Prelink} can
+decrease the base address and thus increase size of read-only \tts{PT\_LOAD}
+segment while \tts{SHT\_PROGBITS} and \tts{SHT\_NOBITS} section can stay
+at their previous addresses. Just their file offsets need to be increased.
+All these segment header adjustments need to be done in multiplies of
+\tts{ELF} page sizes, so even if \tts{prelink} chose to do similar things
+on architectures other than IA-32 which typically start executables on some address
+which is a power of 2, it would be only reasonable if \tts{ELF} page size
+on that architecture (which can be much bigger than page size used by the
+operating system) is very small.
+\item Last possibility is to create a new \tts{PT\_LOAD} segment.
+\footnote{Linux kernels before 2.4.10 loaded executables which had middle \tts{PT\_LOAD}
+segment with \tts{p\_memsz} bigger than \tts{p\_filesz} incorrectly, so
+\tts{prelink} should be only used on systems with 2.4.10 or later kernels.}
+Section immediately above program header table (typically \tts{.interp})
+has to be moved somewhere else, but if possible close to the beginning
+of the executable. The new \tts{PT\_LOAD} segment is then added after the
+last \tts{PT\_LOAD} segment. The segment has to be writable even when
+all the sections in it are read-only, unless it ends exactly on a page
+boundary, because \tts{brk} area starts immediately after the end of last
+\tts{PT\_LOAD} segment and the executable expects it to be writable.
+\end{itemize}
+
+So that verification works properly, if there is \tts{.gnu.prelink\_undo}
+section in the executable, \tts{prelink} first reshuffles the sections and
+segments for the purpose of finding places for the sections to the original
+sequence as recorded in the \tts{.gnu.prelink\_undo} section.
+Examples of the above mentioned cases:
+
+\noindent{{\small\begin{verbatim}
+$ SEDCMD='s/^.* \.plt.*$/.../;/\[.*\.text/,/\[.*\.got/d'
+$ SEDCMD2='/Section to Segment/,$d;/^Key to/,/^Program/d;/^[A-Z]/d;/^ *$/d'
+$ cat > test1.c <<EOF
+int main (void) { return 0; }
+EOF
+$ gcc -Wl,--verbose 2>&1 \
+ | sed '/^===/,/^===/!d;/^===/d;s/\.rel\.dyn/. += 512; &/' > test1.lds
+$ gcc -s -O2 -o test1 test1.c -Wl,-T,test1.lds
+$ readelf -Sl ./test1 | sed -e "$SEDCMD" -e "$SEDCMD2"
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1
+ [ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4
+ [ 3] .hash HASH 08048148 000148 000024 04 A 4 0 4
+ [ 4] .dynsym DYNSYM 0804816c 00016c 000040 10 A 5 1 4
+ [ 5] .dynstr STRTAB 080481ac 0001ac 000045 00 A 0 0 1
+ [ 6] .gnu.version VERSYM 080481f2 0001f2 000008 02 A 4 0 2
+ [ 7] .gnu.version_r VERNEED 080481fc 0001fc 000020 00 A 5 1 4
+ [ 8] .rel.dyn REL 0804841c 00041c 000008 08 A 4 0 4
+ [ 9] .rel.plt REL 08048424 000424 000008 08 A 4 b 4
+ [10] .init PROGBITS 0804842c 00042c 000017 00 AX 0 0 4
+...
+ [22] .bss NOBITS 080496f8 0006f8 000004 00 WA 0 0 4
+ [23] .comment PROGBITS 00000000 0006f8 000132 00 0 0 1
+ [24] .shstrtab STRTAB 00000000 00082a 0000be 00 0 0 1
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
+ INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1
+ [Requesting program interpreter: /lib/ld-linux.so.2]
+ LOAD 0x000000 0x08048000 0x08048000 0x005fc 0x005fc R E 0x1000
+ LOAD 0x0005fc 0x080495fc 0x080495fc 0x000fc 0x00100 RW 0x1000
+ DYNAMIC 0x000608 0x08049608 0x08049608 0x000c8 0x000c8 RW 0x4
+ NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4
+ STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
+$ prelink -N ./test1
+$ readelf -Sl ./test1 | sed -e "$SEDCMD" -e "$SEDCMD2"
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1
+ [ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4
+ [ 3] .hash HASH 08048148 000148 000024 04 A 4 0 4
+ [ 4] .dynsym DYNSYM 0804816c 00016c 000040 10 A 8 1 4
+ [ 5] .gnu.liblist GNU_LIBLIST 080481ac 0001ac 000028 14 A 8 0 4
+ [ 6] .gnu.version VERSYM 080481f2 0001f2 000008 02 A 4 0 2
+ [ 7] .gnu.version_r VERNEED 080481fc 0001fc 000020 00 A 8 1 4
+ [ 8] .dynstr STRTAB 0804821c 00021c 000058 00 A 0 0 1
+ [ 9] .gnu.conflict RELA 08048274 000274 0000c0 0c A 4 0 4
+ [10] .rel.dyn REL 0804841c 00041c 000008 08 A 4 0 4
+ [11] .rel.plt REL 08048424 000424 000008 08 A 4 d 4
+ [12] .init PROGBITS 0804842c 00042c 000017 00 AX 0 0 4
+...
+ [24] .bss NOBITS 080496f8 0006f8 000004 00 WA 0 0 4
+ [25] .comment PROGBITS 00000000 0006f8 000132 00 0 0 1
+ [26] .gnu.prelink_undo PROGBITS 00000000 00082c 0004d4 01 0 0 4
+ [27] .shstrtab STRTAB 00000000 000d00 0000eb 00 0 0 1
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
+ INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1
+ [Requesting program interpreter: /lib/ld-linux.so.2]
+ LOAD 0x000000 0x08048000 0x08048000 0x005fc 0x005fc R E 0x1000
+ LOAD 0x0005fc 0x080495fc 0x080495fc 0x000fc 0x00100 RW 0x1000
+ DYNAMIC 0x000608 0x08049608 0x08049608 0x000c8 0x000c8 RW 0x4
+ NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4
+ STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
+\end{verbatim}}
+\prelinklistingcaption{Reshuffling of an executable with a gap between sections}}
+
+\begin{figure}[!ht]
+\centering
+\includegraphics[width=\textwidth]{gap}
+\caption{Reshuffling of an executable with a gap between sections}
+\end{figure}
+
+In the above sample, there was enough space between sections (particularly
+between the end of the \tts{.gnu.version\_r} section and the start of \tts{.rel.dyn})
+that the new sections could be added there.
+
+\noindent{{\small\begin{verbatim}
+$ SEDCMD='s/^.* \.plt.*$/.../;/\[.*\.text/,/\[.*\.got/d'
+$ SEDCMD2='/Section to Segment/,$d;/^Key to/,/^Program/d;/^[A-Z]/d;/^ *$/d'
+$ cat > test2.c <<EOF
+int main (void) { return 0; }
+EOF
+$ gcc -s -O2 -o test2 test2.c
+$ readelf -Sl ./test2 | sed -e "$SEDCMD" -e "$SEDCMD2"
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1
+ [ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4
+ [ 3] .hash HASH 08048148 000148 000024 04 A 4 0 4
+ [ 4] .dynsym DYNSYM 0804816c 00016c 000040 10 A 5 1 4
+ [ 5] .dynstr STRTAB 080481ac 0001ac 000045 00 A 0 0 1
+ [ 6] .gnu.version VERSYM 080481f2 0001f2 000008 02 A 4 0 2
+ [ 7] .gnu.version_r VERNEED 080481fc 0001fc 000020 00 A 5 1 4
+ [ 8] .rel.dyn REL 0804821c 00021c 000008 08 A 4 0 4
+ [ 9] .rel.plt REL 08048224 000224 000008 08 A 4 b 4
+ [10] .init PROGBITS 0804822c 00022c 000017 00 AX 0 0 4
+...
+ [22] .bss NOBITS 080494f8 0004f8 000004 00 WA 0 0 4
+ [23] .comment PROGBITS 00000000 0004f8 000132 00 0 0 1
+ [24] .shstrtab STRTAB 00000000 00062a 0000be 00 0 0 1
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
+ INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1
+ [Requesting program interpreter: /lib/ld-linux.so.2]
+ LOAD 0x000000 0x08048000 0x08048000 0x003fc 0x003fc R E 0x1000
+ LOAD 0x0003fc 0x080493fc 0x080493fc 0x000fc 0x00100 RW 0x1000
+ DYNAMIC 0x000408 0x08049408 0x08049408 0x000c8 0x000c8 RW 0x4
+ NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4
+ STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
+$ prelink -N ./test2
+$ readelf -Sl ./test2 | sed -e "$SEDCMD" -e "$SEDCMD2"
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1
+ [ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4
+ [ 3] .hash HASH 08048148 000148 000024 04 A 4 0 4
+ [ 4] .dynsym DYNSYM 0804816c 00016c 000040 10 A 23 1 4
+ [ 5] .gnu.liblist GNU_LIBLIST 080481ac 0001ac 000028 14 A 23 0 4
+ [ 6] .gnu.version VERSYM 080481f2 0001f2 000008 02 A 4 0 2
+ [ 7] .gnu.version_r VERNEED 080481fc 0001fc 000020 00 A 23 1 4
+ [ 8] .rel.dyn REL 0804821c 00021c 000008 08 A 4 0 4
+ [ 9] .rel.plt REL 08048224 000224 000008 08 A 4 b 4
+ [10] .init PROGBITS 0804822c 00022c 000017 00 AX 0 0 4
+...
+ [22] .bss PROGBITS 080494f8 0004f8 000004 00 WA 0 0 4
+ [23] .dynstr STRTAB 080494fc 0004fc 000058 00 A 0 0 1
+ [24] .gnu.conflict RELA 08049554 000554 0000c0 0c A 4 0 4
+ [25] .comment PROGBITS 00000000 000614 000132 00 0 0 1
+ [26] .gnu.prelink_undo PROGBITS 00000000 000748 0004d4 01 0 0 4
+ [27] .shstrtab STRTAB 00000000 000c1c 0000eb 00 0 0 1
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
+ INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1
+ [Requesting program interpreter: /lib/ld-linux.so.2]
+ LOAD 0x000000 0x08048000 0x08048000 0x003fc 0x003fc R E 0x1000
+ LOAD 0x0003fc 0x080493fc 0x080493fc 0x00218 0x00218 RW 0x1000
+ DYNAMIC 0x000408 0x08049408 0x08049408 0x000c8 0x000c8 RW 0x4
+ NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4
+ STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
+\end{verbatim}}
+\prelinklistingcaption{Reshuffling of an executable with small \tts{.bss}}}
+
+\begin{figure}[!ht]
+\centering
+\includegraphics[width=\textwidth]{bss}
+\caption{Reshuffling of an executable with small \tts{.bss}}
+\end{figure}
+
+In this case \tts{.bss} section was small enough that \tts{prelink}
+converted it to \tts{SHT\_PROGBITS}.
+
+\noindent{{\small\begin{verbatim}
+$ SEDCMD='s/^.* \.plt.*$/.../;/\[.*\.text/,/\[.*\.got/d'
+$ SEDCMD2='/Section to Segment/,$d;/^Key to/,/^Program/d;/^[A-Z]/d;/^ *$/d'
+$ cat > test3.c <<EOF
+int foo [4096];
+int main (void) { return 0; }
+EOF
+$ gcc -s -O2 -o test3 test3.c
+$ readelf -Sl ./test3 | sed -e "$SEDCMD" -e "$SEDCMD2"
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1
+ [ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4
+ [ 3] .hash HASH 08048148 000148 000024 04 A 4 0 4
+ [ 4] .dynsym DYNSYM 0804816c 00016c 000040 10 A 5 1 4
+ [ 5] .dynstr STRTAB 080481ac 0001ac 000045 00 A 0 0 1
+ [ 6] .gnu.version VERSYM 080481f2 0001f2 000008 02 A 4 0 2
+ [ 7] .gnu.version_r VERNEED 080481fc 0001fc 000020 00 A 5 1 4
+ [ 8] .rel.dyn REL 0804821c 00021c 000008 08 A 4 0 4
+ [ 9] .rel.plt REL 08048224 000224 000008 08 A 4 b 4
+ [10] .init PROGBITS 0804822c 00022c 000017 00 AX 0 0 4
+...
+ [22] .bss NOBITS 08049500 000500 004020 00 WA 0 0 32
+ [23] .comment PROGBITS 00000000 000500 000132 00 0 0 1
+ [24] .shstrtab STRTAB 00000000 000632 0000be 00 0 0 1
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
+ INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1
+ [Requesting program interpreter: /lib/ld-linux.so.2]
+ LOAD 0x000000 0x08048000 0x08048000 0x003fc 0x003fc R E 0x1000
+ LOAD 0x0003fc 0x080493fc 0x080493fc 0x000fc 0x04124 RW 0x1000
+ DYNAMIC 0x000408 0x08049408 0x08049408 0x000c8 0x000c8 RW 0x4
+ NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4
+ STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
+$ prelink -N ./test3
+$ readelf -Sl ./test3 | sed -e "$SEDCMD" -e "$SEDCMD2"
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .interp PROGBITS 08047114 000114 000013 00 A 0 0 1
+ [ 2] .note.ABI-tag NOTE 08047128 000128 000020 00 A 0 0 4
+ [ 3] .dynstr STRTAB 08047148 000148 000058 00 A 0 0 1
+ [ 4] .gnu.liblist GNU_LIBLIST 080471a0 0001a0 000028 14 A 3 0 4
+ [ 5] .gnu.conflict RELA 080471c8 0001c8 0000c0 0c A 7 0 4
+ [ 6] .hash HASH 08048148 001148 000024 04 A 7 0 4
+ [ 7] .dynsym DYNSYM 0804816c 00116c 000040 10 A 3 1 4
+ [ 8] .gnu.version VERSYM 080481f2 0011f2 000008 02 A 7 0 2
+ [ 9] .gnu.version_r VERNEED 080481fc 0011fc 000020 00 A 3 1 4
+ [10] .rel.dyn REL 0804821c 00121c 000008 08 A 7 0 4
+ [11] .rel.plt REL 08048224 001224 000008 08 A 7 d 4
+ [12] .init PROGBITS 0804822c 00122c 000017 00 AX 0 0 4
+...
+ [24] .bss NOBITS 08049500 0014f8 004020 00 WA 0 0 32
+ [25] .comment PROGBITS 00000000 0014f8 000132 00 0 0 1
+ [26] .gnu.prelink_undo PROGBITS 00000000 00162c 0004d4 01 0 0 4
+ [27] .shstrtab STRTAB 00000000 001b00 0000eb 00 0 0 1
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ PHDR 0x000034 0x08047034 0x08047034 0x000e0 0x000e0 R E 0x4
+ INTERP 0x000114 0x08047114 0x08047114 0x00013 0x00013 R 0x1
+ [Requesting program interpreter: /lib/ld-linux.so.2]
+ LOAD 0x000000 0x08047000 0x08047000 0x013fc 0x013fc R E 0x1000
+ LOAD 0x0013fc 0x080493fc 0x080493fc 0x000fc 0x04124 RW 0x1000
+ DYNAMIC 0x001408 0x08049408 0x08049408 0x000c8 0x000c8 RW 0x4
+ NOTE 0x000128 0x08047128 0x08047128 0x00020 0x00020 R 0x4
+ STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
+\end{verbatim}}
+\prelinklistingcaption{Reshuffling of an executable with decreasing of base address}}
+
+\begin{figure}[!ht]
+\centering
+\includegraphics[width=\textwidth]{basemove}
+\caption{Reshuffling of an executable with decreasing of the base address}
+\end{figure}
+
+In \tts{test3} the base address of the executable was decreased by one page and
+the new sections added there.
+
+\noindent{{\small\begin{verbatim}
+$ SEDCMD='s/^.* \.plt.*$/.../;/\[.*\.text/,/\[.*\.got/d'
+$ SEDCMD2='/Section to Segment/,$d;/^Key to/,/^Program/d;/^[A-Z]/d;/^ *$/d'
+$ cat > test4.c <<EOF
+int foo [4096];
+int main (void) { return 0; }
+EOF
+$ gcc -Wl,--verbose 2>&1 \
+ | sed '/^===/,/^===/!d;/^===/d;s/0x08048000/0x08000000/' > test4.lds
+$ gcc -s -O2 -o test4 test4.c -Wl,-T,test4.lds
+$ readelf -Sl ./test4 | sed -e "$SEDCMD" -e "$SEDCMD2"
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .interp PROGBITS 08000114 000114 000013 00 A 0 0 1
+ [ 2] .note.ABI-tag NOTE 08000128 000128 000020 00 A 0 0 4
+ [ 3] .hash HASH 08000148 000148 000024 04 A 4 0 4
+ [ 4] .dynsym DYNSYM 0800016c 00016c 000040 10 A 5 1 4
+ [ 5] .dynstr STRTAB 080001ac 0001ac 000045 00 A 0 0 1
+ [ 6] .gnu.version VERSYM 080001f2 0001f2 000008 02 A 4 0 2
+ [ 7] .gnu.version_r VERNEED 080001fc 0001fc 000020 00 A 5 1 4
+ [ 8] .rel.dyn REL 0800021c 00021c 000008 08 A 4 0 4
+ [ 9] .rel.plt REL 08000224 000224 000008 08 A 4 b 4
+ [10] .init PROGBITS 0800022c 00022c 000017 00 AX 0 0 4
+...
+ [22] .bss NOBITS 08001500 000500 004020 00 WA 0 0 32
+ [23] .comment PROGBITS 00000000 000500 000132 00 0 0 1
+ [24] .shstrtab STRTAB 00000000 000632 0000be 00 0 0 1
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ PHDR 0x000034 0x08000034 0x08000034 0x000e0 0x000e0 R E 0x4
+ INTERP 0x000114 0x08000114 0x08000114 0x00013 0x00013 R 0x1
+ [Requesting program interpreter: /lib/ld-linux.so.2]
+ LOAD 0x000000 0x08000000 0x08000000 0x003fc 0x003fc R E 0x1000
+ LOAD 0x0003fc 0x080013fc 0x080013fc 0x000fc 0x04124 RW 0x1000
+ DYNAMIC 0x000408 0x08001408 0x08001408 0x000c8 0x000c8 RW 0x4
+ NOTE 0x000128 0x08000128 0x08000128 0x00020 0x00020 R 0x4
+ STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
+$ prelink -N ./test4
+$ readelf -Sl ./test4 | sed -e "$SEDCMD" -e "$SEDCMD2"
+ [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ [ 0] NULL 00000000 000000 000000 00 0 0 0
+ [ 1] .interp PROGBITS 08000134 000134 000013 00 A 0 0 1
+ [ 2] .note.ABI-tag NOTE 08000148 000148 000020 00 A 0 0 4
+ [ 3] .hash HASH 08000168 000168 000024 04 A 4 0 4
+ [ 4] .dynsym DYNSYM 0800018c 00018c 000040 10 A 22 1 4
+ [ 5] .gnu.version VERSYM 080001f2 0001f2 000008 02 A 4 0 2
+ [ 6] .gnu.version_r VERNEED 080001fc 0001fc 000020 00 A 22 1 4
+ [ 7] .rel.dyn REL 0800021c 00021c 000008 08 A 4 0 4
+ [ 8] .rel.plt REL 08000224 000224 000008 08 A 4 a 4
+ [ 9] .init PROGBITS 0800022c 00022c 000017 00 AX 0 0 4
+...
+ [21] .bss NOBITS 08001500 0004f8 004020 00 WA 0 0 32
+ [22] .dynstr STRTAB 080064f8 0004f8 000058 00 A 0 0 1
+ [23] .gnu.liblist GNU_LIBLIST 08006550 000550 000028 14 A 22 0 4
+ [24] .gnu.conflict RELA 08006578 000578 0000c0 0c A 4 0 4
+ [25] .comment PROGBITS 00000000 000638 000132 00 0 0 1
+ [26] .gnu.prelink_undo PROGBITS 00000000 00076c 0004d4 01 0 0 4
+ [27] .shstrtab STRTAB 00000000 000c40 0000eb 00 0 0 1
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ PHDR 0x000034 0x08000034 0x08000034 0x000e0 0x000e0 R E 0x4
+ INTERP 0x000134 0x08000134 0x08000134 0x00013 0x00013 R 0x1
+ [Requesting program interpreter: /lib/ld-linux.so.2]
+ LOAD 0x000000 0x08000000 0x08000000 0x003fc 0x003fc R E 0x1000
+ LOAD 0x0003fc 0x080013fc 0x080013fc 0x000fc 0x04124 RW 0x1000
+ LOAD 0x0004f8 0x080064f8 0x080064f8 0x00140 0x00140 RW 0x1000
+ DYNAMIC 0x000408 0x08001408 0x08001408 0x000c8 0x000c8 RW 0x4
+ NOTE 0x000148 0x08000148 0x08000148 0x00020 0x00020 R 0x4
+ STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
+\end{verbatim}}
+\prelinklistingcaption{Reshuffling of an executable with addition of a new segment}}
+
+\begin{figure}[!ht]
+\centering
+\includegraphics[width=\textwidth]{newseg}
+\caption{Reshuffling of an executable with addition of a new segment}
+\end{figure}
+
+In the last example, base address was not decreased but instead a new
+\tts{PT\_LOAD} segment has been added.
+
+\tts{R\_<arch>\_COPY} relocations are typically against first part of the
+\tts{SHT\_NOBITS} \tts{.bss} section. So that \tts{prelink} can apply them,
+it needs to first change their section to \tts{SHT\_PROGBITS}, but as \tts{.bss}
+section typically occupies much larger part of memory, it is not desirable
+to convert \tts{.bss} section into \tts{SHT\_PROGBITS} as whole. A section
+cannot be partly \tts{SHT\_PROGBITS} and partly \tts{SHT\_NOBITS}, so \tts{prelink}
+first splits the section into two parts, first \tts{.dynbss} which covers area
+from the start of \tts{.bss} section up to highest byte to which some COPY
+relocation is applied and then the old \tts{.bss}. The first is converted
+to \tts{SHT\_PROGBITS} and its size is decreased, the latter stays \tts{SHT\_NOBITS}
+and its start address and file offset are adjusted as well as its size decreased.
+The dynamic linker handles relocations in the executable last, so \tts{prelink}
+cannot just copy memory from the shared library where the symbol of the COPY
+relocation has been looked up in. There might be relocations applied by the
+dynamic linker in normal relocation processing to the objects, so \tts{prelink}
+has to first process the relocations against that memory area. Relocations
+which don't need conflict fixups are already applied, so \tts{prelink} just
+needs to apply conflict fixups against the memory area, then copy it
+to the newly created \tts{.dynbss} section.
+
+Here is an example which shows various things which COPY relocation handling
+in \tts{prelink} needs to deal with:
+
+\noindent{{\small\begin{verbatim}
+$ cat > test1.c <<EOF
+struct A { char a; struct A *b; int *c; int *d; };
+int bar, baz;
+struct A foo = { 1, &foo, &bar, &baz };
+int *addr (void) { return &baz; }
+EOF
+$ cat > test.c <<EOF
+#include <stdio.h>
+struct A { char a; struct A *b; int *c; int *d; };
+int bar, *addr (void), big[8192];
+extern struct A foo;
+int main (void)
+{
+ printf ("%p: %d %p %p %p %p %p\n", &foo, foo.a, foo.b, foo.c, foo.d,
+ &bar, addr ());
+}
+EOF
+$ gcc -nostdlib -shared -fpic -s -o test1.so test1.c
+$ gcc -s -o test test.c ./test1.so
+$ ./test
+0x80496c0: 1 0x80496c0 0x80516e0 0x4833a4 0x80516e0 0x4833a4
+$ readelf -r test | sed '/\.rel\.dyn/,/\.rel\.plt/!d;/^0/!d'
+080496ac 00000c06 R_386_GLOB_DAT 00000000 __gmon_start__
+080496c0 00000605 R_386_COPY 080496c0 foo
+$ readelf -S test | grep bss
+ [22] .bss NOBITS 080496c0 0006c0 008024 00 WA 0 0 32
+$ prelink -N ./test ./test1.so
+$ readelf -s test | grep foo
+ 6: 080496c0 16 OBJECT GLOBAL DEFAULT 25 foo
+$ readelf -s test1.so | grep foo
+ 15: 004a9314 16 OBJECT GLOBAL DEFAULT 6 foo
+$ readelf -r test | sed '/.gnu.conflict/,/\.rel\.dyn/!d;/^0/!d'
+004a9318 00000001 R_386_32 080496c0
+004a931c 00000001 R_386_32 080516e0
+005f9874 00000001 R_386_32 fffffff0
+005f9878 00000001 R_386_32 00000001
+005f98bc 00000001 R_386_32 fffffff4
+005f9900 00000001 R_386_32 ffffffec
+005f9948 00000001 R_386_32 ffffffdc
+005f995c 00000001 R_386_32 ffffffe0
+005f9980 00000001 R_386_32 fffffff8
+005f9988 00000001 R_386_32 ffffffe4
+005f99a4 00000001 R_386_32 ffffffd8
+005f99c4 00000001 R_386_32 ffffffe8
+005f99d8 00000001 R_386_32 08048584
+004c2510 00000007 R_386_JUMP_SLOT 00534460
+004c2514 00000007 R_386_JUMP_SLOT 00534080
+004c2518 00000007 R_386_JUMP_SLOT 00534750
+004c251c 00000007 R_386_JUMP_SLOT 005342c0
+004c2520 00000007 R_386_JUMP_SLOT 00534200
+$ objdump -s -j .dynbss test
+
+test: file format elf32-i386
+
+Contents of section .dynbss:
+ 80496c0 01000000 c0960408 e0160508 a4934a00 ..............J.
+$ objdump -s -j .data test1.so
+
+test1.so: file format elf32-i386
+
+Contents of section .data:
+ 4a9314 01000000 14934a00 a8934a00 a4934a00 ......J...J...J.
+$ readelf -S test | grep bss
+ [24] .dynbss PROGBITS 080496c0 0016c0 000010 00 WA 0 0 32
+ [25] .bss NOBITS 080496d0 0016d0 008014 00 WA 0 0 32
+$ sed 's/8192/1/' test.c > test2.c
+$ gcc -s -o test2 test2.c ./test1.so
+$ readelf -S test2 | grep bss
+ [22] .bss NOBITS 080496b0 0006b0 00001c 00 WA 0 0 8
+$ prelink -N ./test2 ./test1.so
+$ readelf -S test2 | grep bss
+ [22] .dynbss PROGBITS 080496b0 0006b0 000010 00 WA 0 0 8
+ [23] .bss PROGBITS 080496c0 0006c0 00000c 00 WA 0 0 8
+\end{verbatim}}
+\prelinklistingcaption{Relocation handling of \tts{.dynbss} objects}}
+
+Because \tts{test.c} executable is not compiled as position independent code and
+takes address of {\sl foo} variable, a COPY relocation is needed to avoid
+dynamic relocation against executable's read-only \tts{PT\_LOAD} segment.
+The {\sl foo} object in \tts{test1.so} has one field with no relocations
+applied at all, one relocation against the variable itself, one relocation
+which needs a conflict fixup (as it is overridden by the variable in the
+executable) and one with relocation which doesn't need any fixups.
+The first and last field contain already the right values in prelinked
+\tts{test1.so}, while second and third one need to be changed for symbol
+addresses in the executable (as shown in the \tts{objdump} output).
+The conflict fixups against {\sl foo} in \tts{test1.so} need to stay
+(unless it is a C++ virtual table or {\sl RTTI} data, i.e. not in this testcase).
+In \tts{test}, \tts{prelink} changed \tts{.dynbss} to \tts{SHT\_PROGBITS}
+and kept \tts{SHT\_NOBITS} \tts{.bss}, while in slightly modified testcase
+(\tts{test2}) the size of \tts{.bss} was small enough that \tts{prelink}
+chose to make it \tts{SHT\_PROGBITS} too and grow the read-write
+\tts{PT\_LOAD} segment and put \tts{.dynstr} and \tts{.gnu.conflict}
+sections after it.
+
+\section{Prelink undo operation}
+
+Prelinking of shared libraries and executables is designed to be reversible,
+so that prelink operation followed by undo operation generates bitwise
+identical file to the original before prelinking. For this operation
+\tts{prelink} stores the original \tts{ELF} header, all the program and
+all section headers into a \tts{.gnu.prelink\_undo} section before it starts prelinking
+an unprelinked executable or shared library. When undoing the modifications,
+\tts{prelink} has to convert \tts{RELA} back to \tts{REL} first if \tts{REL}
+to \tts{RELA} conversion was done during prelinking and all allocated
+sections above it relocated down to adjust for the section shrink.
+Relocation types which were changed when trying to avoid \tts{REL} to
+\tts{RELA} conversion need to be changed back (e.g. on IA-32, it is
+assumed \tts{R\_386\_GLOB\_DAT} relocations should be only those
+against \tts{.got} section and \tts{R\_386\_32} relocations in the
+remaining places). On \tts{RELA} architectures, the memory pointed
+by \tts{r\_offset} field of the relocations needs to be reinitialized
+to the values stored there by the linker originally.
+For \tts{prelink} it doesn't matter much what this value is (e.g.
+always 0, copy of \tts{r\_addend}, etc.), as long as it is computable
+from the information \tts{prelink} has during undo operation
+\footnote{Such as relocation type, \tts{r\_addend} value,
+type, binding, flags or other attributes of relocation's symbol,
+what section the relocation points into or the offset within
+section it points to.}. The GNU linker had to be changed on several
+architectures, so that it stores there such a value, as in several places
+the value e.g. depended on original addend before final link (which is
+not available anywhere after final link time, since \tts{r\_addend}
+field could be adjusted during the final link).
+If second word of \tts{.got} section has been modified, it needs
+to be reverted back to the original value (on most architectures zero).
+In executables, sections which were moved during prelinking need to be
+put back and segments added while prelinking must be removed.
+
+There are 3 different ways how an undo operation can be performed:
+\begin{itemize}
+\item Undoing individual executables or shared libraries specified on the
+command line in place (i.e. when the undo operation is successful,
+the prelinked executable or library is atomically replaced with the
+undone object).
+\item With \tts{-o} option, only a single executable or shared library
+given on the command line is undone and stored to the file specified
+as \tts{-o} option's argument.
+\item With \tts{-ua} options, \tts{prelink} builds a list of executables
+in paths written in its config file (plus directories and executables
+or libraries from command line) and all shared libraries these executables
+depend on. All executables and libraries in the list are then unprelinked.
+This option is used to unprelink the whole system. It is not perfect
+and needs to be worked on, since e.g. if some executable uses some shared
+library which no other executable links against, this executable (and shared
+library) is prelinked, then the executable is removed (e.g. uninstalled)
+but the shared library is kept, then the shared library is not
+unprelinked unless specifically mentioned on the command line.
+\end{itemize}
+
+\section{Verification of prelinked files}
+
+As \tts{prelink} needs to modify executables and shared libraries installed
+on a system, it complicates system integrity verification (e.g. \tts{rpm -V},
+TripWire). These systems store checksums of installed files into some
+database and during verification compute them again and compare to the
+values stored in the database. On a prelinked system most of the executables
+and shared libraries would be reported as modified. \tts{Prelink} offers
+a special mode for these systems, in which it verifies that unprelinking
+the executable or shared library followed by immediate prelinking (with the
+same base address) creates bitwise identical output with the executable
+or shared library that's being verified. Furthermore, depending on
+other \tts{prelink} options, it either writes the unprelinked image
+to its standard output or computes MD5 or SHA1 digest from this unprelinked
+image. Mere undo operation to a file and checksumming it is not good
+enough, since an intruder could have modified e.g. conflict fixups or
+memory which relocations point at, changing a behavior of the program
+while file after unprelinking would be unmodified.
+
+During verification, both \tts{prelink} executable and the dynamic linker
+are used, so a proper system integrity verification first checks whether
+\tts{prelink} executable (which is statically linked for this reason) hasn't
+been modified, then uses \tts{prelink --verify} to verify the dynamic linker
+(when verificating \tts{ld.so} the dynamic linker is not executed)
+followed by verification of other executables and libraries.
+
+Verification requires all dependencies of checked object to be unmodified
+since last prelinking. If some dependency has been changed or is missing,
+\tts{prelink} will report it and return with non-zero exit status.
+This is because prelinking depends on their content and so if they are
+modified, the executable or shared library might be different to one after
+unprelinking followed by prelinking again. In the future, perhaps it
+would be possible to even verify executables or shared libraries without
+unmodified dependencies, under the assumption that in such case the prelink
+information will not be used. It would just need to verify that nothing
+else but the information only used when dependencies are up to date
+has changed between the executable or library on the filesystem and file
+after unprelink followed by prelink cycle. The prelink operation
+would need to be modified in this case, so that no information is
+collected from the dynamic linker, the list of dependencies is assumed
+to be the one stored in the executable and expect it to have identical
+number of conflict fixups.
+
+\section{Measurements}
+
+There are two areas where \tts{prelink} can speed things up noticeably.
+The primary is certainly startup time of big GUI applications where the
+dynamic linker spends from 100ms up to a few seconds before giving control
+to the application. Another area is when lots of small programs are started
+up, but their execution time is rather short, so the startup time which
+\tts{prelink} optimizes is a noticeable fraction of the total time.
+This is typical for shell scripting.
+
+First numbers are from \tts{lmbench} benchmark, version 3.0-a3.
+Most of the benchmarks in \tts{lmbench} suite measure kernel speed,
+so it doesn't matter much whether \tts{prelink} is used or not.
+Only in \tts{lat\_proc} benchmark \tts{prelink} shows up visibly.
+This benchmark measures 3 different things:
+\begin{itemize}
+\item {\sl fork proc}, which is \tts{fork()} followed by immediate
+\tts{exit(1)} in the child and \tts{wait(0)} in the parent. The results
+are (as expected) about the same between unprelinked and prelinked systems.
+\item {\sl exec proc}, i.e. \tts{fork()} followed by immediate
+\tts{close(1)} and \tts{execve()} of a simple hello world program (this
+program is compiled and linked during the benchmark into a temporary
+directory and is never prelinked). The numbers are 160$\mu$s to 200$\mu$s
+better on prelinked systems, because there is no relocation processing needed
+initially in the dynamic linker and because all relative relocations
+in \tts{libc.so.6} can be skipped.
+\item {\sl sh proc}, i.e. \tts{fork()} followed by immediate \tts{close(1)}
+and \tts{execlp("/bin/sh", "sh", "-c", "/tmp/hello", 0)}. Although
+the hello world program is not prelinked in this case either, the shell is,
+so out of the 900$\mu$s to 1000$\mu$s speedup less than 200$\mu$s can be
+accounted on the speed up of the hello world program as in {\sl exec proc}
+benchmark and the rest to the speedup of shell startup.
+\end{itemize}
+
+First 4 rows are from running the benchmark on a fully unprelinked system,
+the last 4 rows on the same system, but fully prelinked.
+
+\noindent{{\small\begin{verbatim}
+ L M B E N C H 3 . 0 S U M M A R Y
+ ------------------------------------
+ (Alpha software, do not distribute)
+
+Processor, Processes - times in microseconds - smaller is better
+-------------------------------------------------------------------------
+Host OS Mhz null null open slct sig sig fork exec sh
+ call I/O stat clos TCP inst hndl proc proc proc
+---- ------------ ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
+pork Linux 2.4.22 651 0.53 0.97 6.20 8.10 41.2 1.44 4.30 276. 1497 5403
+pork Linux 2.4.22 651 0.53 0.95 6.14 7.91 37.8 1.43 4.34 274. 1486 5391
+pork Linux 2.4.22 651 0.56 0.94 6.18 8.09 43.4 1.41 4.30 251. 1507 5423
+pork Linux 2.4.22 651 0.53 0.94 6.12 8.09 41.0 1.43 4.40 256. 1497 5385
+pork Linux 2.4.22 651 0.56 0.94 5.79 7.58 39.1 1.41 4.30 271. 1319 4460
+pork Linux 2.4.22 651 0.56 0.92 5.76 7.40 38.9 1.41 4.30 253. 1304 4417
+pork Linux 2.4.22 651 0.56 0.95 6.20 7.83 37.7 1.41 4.37 248. 1323 4481
+pork Linux 2.4.22 651 0.56 1.01 6.04 7.77 37.9 1.43 4.32 256. 1324 4457
+\end{verbatim}}
+\prelinklistingcaption{\tts{lmbench} results without and with prelinking}}
+
+Below is a sample timing of a 239K long configure shell script from GCC
+on both unprelinked and prelinked system. Preparation step was following:
+
+\noindent{{\small\begin{verbatim}
+cd; cvs -d :pserver:anoncvs@subversions.gnu.org:/cvsroot/gcc login
+# Empty password
+cvs -d :pserver:anoncvs@subversions.gnu.org:/cvsroot/gcc -z3 co -D20031103 gcc
+mkdir ~/gcc/obj
+cd ~/gcc/obj; ../configure i386-redhat-linux; make configure-gcc
+\end{verbatim}}
+\prelinklistingcaption{Preparation script for shell script tests}}
+
+On an unprelinked system, the results were:
+
+\noindent{{\small\begin{verbatim}
+cd ~/gcc/obj/gcc
+for i in 1 2; do ./config.status --recheck > /dev/null 2>&1; done
+for i in 1 2 3 4; do time ./config.status --recheck > /dev/null 2>&1; done
+
+real 0m4.436s
+user 0m1.730s
+sys 0m1.260s
+
+real 0m4.409s
+user 0m1.660s
+sys 0m1.340s
+
+real 0m4.431s
+user 0m1.810s
+sys 0m1.300s
+
+real 0m4.432s
+user 0m1.670s
+sys 0m1.210s
+\end{verbatim}}
+\prelinklistingcaption{Shell script test results on unprelinked system}}
+
+and on a fully prelinked system:
+
+\noindent{{\small\begin{verbatim}
+cd ~/gcc/obj/gcc
+for i in 1 2; do ./config.status --recheck > /dev/null 2>&1; done
+for i in 1 2 3 4; do time ./config.status --recheck > /dev/null 2>&1; done
+
+real 0m4.126s
+user 0m1.590s
+sys 0m1.240s
+
+real 0m4.151s
+user 0m1.620s
+sys 0m1.230s
+
+real 0m4.161s
+user 0m1.600s
+sys 0m1.190s
+
+real 0m4.122s
+user 0m1.570s
+sys 0m1.230s
+\end{verbatim}}
+\prelinklistingcaption{Shell script test results on prelinked system}}
+
+Now timing of a few big GUI programs. All timings were done without X
+server running and with \tts{DISPLAY} environment variable not set
+(so that when control is transfered to the application, it very soon
+finds out there is no X server it can talk to and bail out). The
+measurements are done by the dynamic linker in ticks on a 651MHz
+dual Pentium III machine, i.e. ticks have to be divided by 651000000
+to get times in seconds. Each application has been run 4 times
+and the results with smallest total time spent in the dynamic
+linker was chosen. Epiphany WWW browser and Evolution mail client
+were chosen as examples of \tts{Gtk+} applications (typically they use
+really many shared libraries, but many of them are quite small,
+there aren't really many relocations nor conflict fixups and most
+of the libraries are written in C) and Konqueror WWW browser and
+KWord word processor were chosen as examples of \tts{KDE} applications
+(typically they use slightly fewer shared libraries, though
+still a lot, most of the shared libraries are written in C++,
+have many relocations and cause many conflict fixups, especially
+without C++ conflict fixup optimizations in \tts{prelink}).
+On non-prelinked system, the timings are done with lazy binding,
+i.e. without \tts{LD\_BIND\_NOW=1} set in the environment.
+This is because that's how people generally run programs, on the other
+side it is not exact apples to apples comparison, since on prelinked
+system there is no lazy binding with the exception of shared libraries
+loaded through \tts{dlopen}. So when control is passed to the application,
+prelinked programs should be slightly faster for a while since non-prelinked
+programs will have to do symbol lookups and processing relocations
+(and on various architectures flushing instruction caches) whenever
+they call some function they haven't called before in particular shared
+library or in the executable.
+
+\noindent{{\small\begin{verbatim}
+$ ldd `which epiphany-bin` | wc -l
+ 64
+$ # Unprelinked system
+$ LD_DEBUG=statistics epiphany-bin 2>&1 | sed 's/^ *//'
+18960:
+18960: runtime linker statistics:
+18960: total startup time in dynamic loader: 67336593 clock cycles
+18960: time needed for relocation: 58119983 clock cycles (86.3%)
+18960: number of relocations: 6999
+18960: number of relocations from cache: 4770
+18960: number of relative relocations: 31494
+18960: time needed to load objects: 8696104 clock cycles (12.9%)
+
+(epiphany-bin:18960): Gtk-WARNING **: cannot open display:
+18960:
+18960: runtime linker statistics:
+18960: final number of relocations: 7692
+18960: final number of relocations from cache: 4770
+$ # Prelinked system
+$ LD_DEBUG=statistics epiphany-bin 2>&1 | sed 's/^ *//'
+25697:
+25697: runtime linker statistics:
+25697: total startup time in dynamic loader: 7313721 clock cycles
+25697: time needed for relocation: 565680 clock cycles (7.7%)
+25697: number of relocations: 0
+25697: number of relocations from cache: 1205
+25697: number of relative relocations: 0
+25697: time needed to load objects: 6179467 clock cycles (84.4%)
+
+(epiphany-bin:25697): Gtk-WARNING **: cannot open display:
+25697:
+25697: runtime linker statistics:
+25697: final number of relocations: 31
+25697: final number of relocations from cache: 1205
+
+$ ldd `which evolution` | wc -l
+ 68
+$ # Unprelinked system
+$ LD_DEBUG=statistics evolution 2>&1 | sed 's/^ *//'
+19042:
+19042: runtime linker statistics:
+19042: total startup time in dynamic loader: 54382122 clock cycles
+19042: time needed for relocation: 43403190 clock cycles (79.8%)
+19042: number of relocations: 3452
+19042: number of relocations from cache: 2885
+19042: number of relative relocations: 34957
+19042: time needed to load objects: 10450142 clock cycles (19.2%)
+
+(evolution:19042): Gtk-WARNING **: cannot open display:
+19042:
+19042: runtime linker statistics:
+19042: final number of relocations: 4075
+19042: final number of relocations from cache: 2885
+$ # Prelinked system
+$ LD_DEBUG=statistics evolution 2>&1 | sed 's/^ *//'
+25723:
+25723: runtime linker statistics:
+25723: total startup time in dynamic loader: 9176140 clock cycles
+25723: time needed for relocation: 203783 clock cycles (2.2%)
+25723: number of relocations: 0
+25723: number of relocations from cache: 525
+25723: number of relative relocations: 0
+25723: time needed to load objects: 8405157 clock cycles (91.5%)
+
+(evolution:25723): Gtk-WARNING **: cannot open display:
+25723:
+25723: runtime linker statistics:
+25723: final number of relocations: 31
+25723: final number of relocations from cache: 525
+
+$ ldd `which konqueror` | wc -l
+ 37
+$ # Unprelinked system
+$ LD_DEBUG=statistics konqueror 2>&1 | sed 's/^ *//'
+18979:
+18979: runtime linker statistics:
+18979: total startup time in dynamic loader: 131985703 clock cycles
+18979: time needed for relocation: 127341077 clock cycles (96.4%)
+18979: number of relocations: 25473
+18979: number of relocations from cache: 53594
+18979: number of relative relocations: 31171
+18979: time needed to load objects: 4318803 clock cycles (3.2%)
+konqueror: cannot connect to X server
+18979:
+18979: runtime linker statistics:
+18979: final number of relocations: 25759
+18979: final number of relocations from cache: 53594
+$ # Prelinked system
+$ LD_DEBUG=statistics konqueror 2>&1 | sed 's/^ *//'
+25733:
+25733: runtime linker statistics:
+25733: total startup time in dynamic loader: 5533696 clock cycles
+25733: time needed for relocation: 1941489 clock cycles (35.0%)
+25733: number of relocations: 0
+25733: number of relocations from cache: 2066
+25733: number of relative relocations: 0
+25733: time needed to load objects: 3217736 clock cycles (58.1%)
+konqueror: cannot connect to X server
+25733:
+25733: runtime linker statistics:
+25733: final number of relocations: 0
+25733: final number of relocations from cache: 2066
+
+$ ldd `which kword` | wc -l
+ 40
+$ # Unprelinked system
+$ LD_DEBUG=statistics kword 2>&1 | sed 's/^ *//'
+19065:
+19065: runtime linker statistics:
+19065: total startup time in dynamic loader: 153684591 clock cycles
+19065: time needed for relocation: 148255294 clock cycles (96.4%)
+19065: number of relocations: 26231
+19065: number of relocations from cache: 55833
+19065: number of relative relocations: 30660
+19065: time needed to load objects: 5068746 clock cycles (3.2%)
+kword: cannot connect to X server
+19065:
+19065: runtime linker statistics:
+19065: final number of relocations: 26528
+19065: final number of relocations from cache: 55833
+$ # Prelinked system
+$ LD_DEBUG=statistics kword 2>&1 | sed 's/^ *//'
+25749:
+25749: runtime linker statistics:
+25749: total startup time in dynamic loader: 6516635 clock cycles
+25749: time needed for relocation: 2106856 clock cycles (32.3%)
+25749: number of relocations: 0
+25749: number of relocations from cache: 2130
+25749: number of relative relocations: 0
+25749: time needed to load objects: 4008585 clock cycles (61.5%)
+kword: cannot connect to X server
+25749:
+25749: runtime linker statistics:
+25749: final number of relocations: 0
+25749: final number of relocations from cache: 2130
+\end{verbatim}}
+\prelinklistingcaption{Dynamic linker statistics for unprelinked and prelinked GUI programs}}
+
+In the case of above mentioned \tts{Gtk+} applications, the original startup
+time spent in the dynamic linker decreased into 11\% to 17\% of the original
+times, with \tts{KDE} applications it decreased even into around 4.2\% of original
+times.
+
+The startup time reported by the dynamic linker is only part of the total
+startup time of a GUI program. Unfortunately it cannot be measured very
+accurately without patching each application separately, so that it would
+print current process CPU time at the point when all windows are painted and
+the process starts waiting for user input. The following table contains
+values reported by \tts{time(1)} command on each of the 4 GUI programs
+running under X, both on unprelinked and fully prelinked system.
+As soon as each program painted its windows, it was killed by
+application's quit hot key
+\footnote{\tts{Ctrl+W} for Epiphany, \tts{Ctrl+Q} for Evolution and
+Konqueror and \tts{Enter} in Kword's document type choice dialog.}.
+Especially the \tts{real} time values depend also on the speed of
+human reactions, so each measurement was repeated 10 times. All timings
+were done with hot caches, after running the applications two times
+before measurement.
+
+\noindent{\small\begin{center}
+\begin{longtable}{l|llllllllll|ll}
+{\bf Type} & \multicolumn{10}{l|}{\bf Values (in seconds)} & {\bf Average} & {\bf Std.Dev.} \\
+\hline
+\endhead
+& \multicolumn{10}{l|}{unprelinked epiphany} && \\
+\hline
+{real} & {3.053} & {2.84} & {2.996} & {2.901} & {3.019} & {2.929} & {2.883} & {2.975} & {2.922} & {3.026} & {2.954} & {0.0698} \\
+{user} & {2.33} & {2.31} & {2.28} & {2.32} & {2.44} & {2.37} & {2.29} & {2.35} & {2.34} & {2.41} & {2.344} & {0.0508} \\
+{sys} & {0.2} & {0.23} & {0.23} & {0.19} & {0.19} & {0.12} & {0.25} & {0.16} & {0.14} & {0.14} & {0.185} & {0.0440} \\
+\hline
+& \multicolumn{10}{l|}{prelinked epiphany} && \\
+\hline
+{real} & {2.773} & {2.743} & {2.833} & {2.753} & {2.753} & {2.644} & {2.717} & {2.897} & {2.68} & {2.761} & {2.755} & {0.0716} \\
+{user} & {2.18} & {2.17} & {2.17} & {2.12} & {2.23} & {2.26} & {2.13} & {2.17} & {2.15} & {2.15} & {2.173} & {0.0430} \\
+{sys} & {0.13} & {0.15} & {0.18} & {0.15} & {0.11} & {0.04} & {0.18} & {0.14} & {0.1} & {0.15} & {0.133} & {0.0416} \\
+\hline
+& \multicolumn{10}{l|}{unprelinked evolution} && \\
+\hline
+{real} & {2.106} & {1.886} & {1.828} & {2.12} & {1.867} & {1.871} & {2.242} & {1.871} & {1.862} & {2.241} & {1.989} & {0.1679} \\
+{user} & {1.12} & {1.09} & {1.15} & {1.19} & {1.17} & {1.23} & {1.15} & {1.11} & {1.17} & {1.14} & {1.152} & {0.0408} \\
+{sys} & {0.1} & {0.11} & {0.13} & {0.07} & {0.1} & {0.05} & {0.11} & {0.11} & {0.09} & {0.08} & {0.095} & {0.0232} \\
+\hline
+& \multicolumn{10}{l|}{prelinked evolution} && \\
+\hline
+{real} & {1.684} & {1.621} & {1.686} & {1.72} & {1.694} & {1.691} & {1.631} & {1.697} & {1.668} & {1.535} & {1.663} & {0.0541} \\
+{user} & {0.92} & {0.87} & {0.92} & {0.95} & {0.79} & {0.86} & {0.94} & {0.87} & {0.89} & {0.86} & {0.887} & {0.0476} \\
+{sys} & {0.06} & {0.1} & {0.06} & {0.05} & {0.11} & {0.08} & {0.07} & {0.1} & {0.12} & {0.07} & {0.082} & {0.0239} \\
+\hline
+& \multicolumn{10}{l|}{unprelinked kword} && \\
+\hline
+{real} & {2.111} & {1.414} & {1.36} & {1.356} & {1.259} & {1.383} & {1.28} & {1.321} & {1.252} & {1.407} & {1.414} & {0.2517} \\
+{user} & {1.04} & {0.9} & {0.93} & {0.88} & {0.89} & {0.89} & {0.87} & {0.89} & {0.9} & {0.8} & {0.899} & {0.0597} \\
+{sys} & {0.07} & {0.04} & {0.06} & {0.05} & {0.06} & {0.1} & {0.09} & {0.08} & {0.08} & {0.12} & {0.075} & {0.0242} \\
+\hline
+& \multicolumn{10}{l|}{prelinked kword} && \\
+\hline
+{real} & {1.59} & {1.052} & {0.972} & {1.064} & {1.106} & {1.087} & {1.066} & {1.087} & {1.065} & {1.005} & {1.109} & {0.1735} \\
+{user} & {0.61} & {0.53} & {0.58} & {0.6} & {0.6} & {0.58} & {0.59} & {0.61} & {0.57} & {0.6} & {0.587} & {0.0241} \\
+{sys} & {0.08} & {0.08} & {0.06} & {0.06} & {0.03} & {0.07} & {0.06} & {0.03} & {0.06} & {0.04} & {0.057} & {0.0183} \\
+\hline
+& \multicolumn{10}{l|}{unprelinked konqueror} && \\
+\hline
+{real} & {1.306} & {1.386} & {1.27} & {1.243} & {1.227} & {1.286} & {1.262} & {1.322} & {1.345} & {1.332} & {1.298} & {0.0495} \\
+{user} & {0.88} & {0.86} & {0.88} & {0.9} & {0.87} & {0.83} & {0.83} & {0.86} & {0.86} & {0.89} & {0.866} & {0.0232} \\
+{sys} & {0.07} & {0.11} & {0.12} & {0.1} & {0.12} & {0.08} & {0.13} & {0.12} & {0.09} & {0.08} & {0.102} & {0.0210} \\
+\hline
+& \multicolumn{10}{l|}{prelinked konqueror} && \\
+\hline
+{real} & {1.056} & {0.962} & {0.961} & {0.906} & {0.927} & {0.923} & {0.933} & {0.958} & {0.955} & {1.142} & {0.972} & {0.0722} \\
+{user} & {0.56} & {0.6} & {0.56} & {0.52} & {0.57} & {0.58} & {0.5} & {0.57} & {0.61} & {0.55} & {0.562} & {0.0334} \\
+{sys} & {0.1} & {0.13} & {0.08} & {0.15} & {0.07} & {0.09} & {0.09} & {0.09} & {0.1} & {0.08} & {0.098} & {0.0244} \\
+\hline
+\multicolumn{13}{l}{} \\
+\caption{GUI program start up times without and with prelinking} \\
+\end{longtable}
+\end{center}}
+
+\tts{OpenOffice.org} is probably the largest program these days in Linux,
+mostly written in C++. In \tts{OpenOffice.org} 1.1, the main executable,
+\tts{soffice.bin}, links directly against 34 shared libraries, but typically
+during startup it loads using \tts{dlopen} many others. As has been
+mentioned earlier, \tts{prelink} cannot speed up loading shared libraries
+using \tts{dlopen}, since it cannot predict in which order and what
+shared libraries will be loaded (and thus cannot compute conflict fixups).
+The \tts{soffice.bin} is typically started through a wrapper script
+and depending on what arguments are passed to it, different
+\tts{OpenOffice.org} application is started. With no options, it starts
+just empty window with menu from which the applications can be started,
+with say \tts{private:factory/swriter} argument it starts
+a word processor, with \tts{private:factory/scalc} it starts a spreadsheet
+etc. When \tts{soffice.bin} is already running, if you start another
+copy of it, it just instructs the already running copy to pop up a new
+window and exits.
+
+In an experiment, \tts{soffice.bin} has been invoked 7 times against running
+X server, with no arguments, \tts{private:factory/swriter},
+\tts{private:factory/scalc}, \tts{private:factory/sdraw},
+\tts{private:factory/simpress}, \tts{private:factory/smath} arguments
+(in all these cases nothing was pressed at all) and last with
+the \tts{private:factory/swriter} argument where the menu item \tts{New Presentation}
+was selected and the word processor window closed.
+In all these cases, \tts{/proc/`pidof soffice.bin`/maps} file was
+captured and the application then killed. This file contains among
+other things list of all shared libraries mmapped by the process at
+the point where it started waiting for user input after loading up.
+These lists were then summarized, to get number of the runs in
+which particular shared library was loaded up out of the total 7
+runs. There were 38 shared libraries shipped as part of \tts{OpenOffice.org}
+package which have been loaded in all 7 times, another 3 shared
+libraries included in \tts{OpenOffice.org} (and also one shared
+library shipped in another package, \tts{libdb\_cxx-4.1.so})
+which were loaded 6 times.
+\footnote{In all runs but when ran without
+arguments. But when the application is started without any
+arguments, it cannot do any useful work, so one loads one of the
+applications afterward anyway.} There was one shared library
+loaded in 5 runs, but was locale specific and thus not worth
+considering. Inspecting \tts{OpenOffice.org} source, these shared
+libraries are never unloaded with \tts{dlclose}, so \tts{soffice.bin}
+can be made much more \tts{prelink} friendly and thus save substantial
+amount of startup time by linking against all those 76 shared libraries
+instead of just 34 shared libraries it is linked against.
+In the timings below, \tts{soffice1.bin} is the original \tts{soffice.bin}
+as created by the \tts{OpenOffice.org} makefiles and \tts{soffice3.bin} is
+the same executable linked dynamically against additional 42 shared libraries.
+The ordering of those 42 shared libraries matters for the number of conflict
+fixups, unfortunately with large C++ shared libraries there is no obvious rule
+for ordering them as sometimes it is more useful when a shared library precedes
+its dependency and sometimes vice versa, so a few different orderings were
+tried in several steps and always the one with smallest number of conflict
+fixups was chosen. Still, the number of conflict fixups is quite high
+and big part of the fixups are storing addresses of \tts{PLT} slots in
+the executable into various places in shared libraries
+\footnote{This might get better when the linker is modified to handle
+calls without ever taking address of the function in executables specially,
+but only testing it will actually show it up.}
+\tts{soffice2.bin} is another experiment, where the executable itself is empty
+source file, all objects which were originally in \tts{soffice.bin}
+executable with the exception of start files were recompiled as position independent
+code and linked into a new shared library. This reduced number of conflicts
+a lot and speeded up start up times against \tts{soffice3.bin} when caches
+are hot. It is a little bit slower than \tts{soffice3.bin} when running
+with cold caches (e.g. for the first time after bootup), as there is one
+more shared library to load etc.
+
+In the timings below, numbers for \tts{soffice1.bin} and \tts{soffice2.bin}
+resp. \tts{soffice3.bin} cannot be easily compared, as \tts{soffice1.bin}
+loads less than half of the needed shared libraries which the remaining
+two executables load and the time to load those shared libraries doesn't
+show up there. Still, when it is prelinked it takes just slightly more
+than two times longer to load \tts{soffice2.bin} than \tts{soffice1.bin}
+and the times are still less than 7\% of how long it takes to load
+just the initial 34 shared libraries when not prelinking.
+
+\noindent{{\small\begin{verbatim}
+$ S='s/^ *//'
+$ ldd /usr/lib/openoffice/program/soffice1.bin | wc -l
+ 34
+$ # Unprelinked system
+$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice1.bin 2>&1 | sed "$S"
+19095:
+19095: runtime linker statistics:
+19095: total startup time in dynamic loader: 159833582 clock cycles
+19095: time needed for relocation: 155464174 clock cycles (97.2%)
+19095: number of relocations: 31136
+19095: number of relocations from cache: 31702
+19095: number of relative relocations: 18284
+19095: time needed to load objects: 3919645 clock cycles (2.4%)
+/usr/lib/openoffice/program/soffice1.bin X11 error: Can't open display:
+Set DISPLAY environment variable, use -display option
+or check permissions of your X-Server
+(See "man X" resp. "man xhost" for details)
+19095:
+19095: runtime linker statistics:
+19095: final number of relocations: 31715
+19095: final number of relocations from cache: 31702
+$ # Prelinked system
+$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice1.bin 2>&1 | sed "$S"
+25759:
+25759: runtime linker statistics:
+25759: total startup time in dynamic loader: 4252397 clock cycles
+25759: time needed for relocation: 1189840 clock cycles (27.9%)
+25759: number of relocations: 0
+25759: number of relocations from cache: 2142
+25759: number of relative relocations: 0
+25759: time needed to load objects: 2604486 clock cycles (61.2%)
+/usr/lib/openoffice/program/soffice1.bin X11 error: Can't open display:
+Set DISPLAY environment variable, use -display option
+or check permissions of your X-Server
+(See "man X" resp. "man xhost" for details)
+25759:
+25759: runtime linker statistics:
+25759: final number of relocations: 24
+25759: final number of relocations from cache: 2142
+$ ldd /usr/lib/openoffice/program/soffice2.bin | wc -l
+ 77
+$ # Unprelinked system
+$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice2.bin 2>&1 | sed "$S"
+19115:
+19115: runtime linker statistics:
+19115: total startup time in dynamic loader: 947793670 clock cycles
+19115: time needed for relocation: 936895741 clock cycles (98.8%)
+19115: number of relocations: 69164
+19115: number of relocations from cache: 94502
+19115: number of relative relocations: 59374
+19115: time needed to load objects: 10046486 clock cycles (1.0%)
+/usr/lib/openoffice/program/soffice2.bin X11 error: Can't open display:
+Set DISPLAY environment variable, use -display option
+or check permissions of your X-Server
+(See "man X" resp. "man xhost" for details)
+19115:
+19115: runtime linker statistics:
+19115: final number of relocations: 69966
+19115: final number of relocations from cache: 94502
+$ # Prelinked system
+$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice2.bin 2>&1 | sed "$S"
+25777:
+25777: runtime linker statistics:
+25777: total startup time in dynamic loader: 10952099 clock cycles
+25777: time needed for relocation: 3254518 clock cycles (29.7%)
+25777: number of relocations: 0
+25777: number of relocations from cache: 5309
+25777: number of relative relocations: 0
+25777: time needed to load objects: 6805013 clock cycles (62.1%)
+/usr/lib/openoffice/program/soffice2.bin X11 error: Can't open display:
+Set DISPLAY environment variable, use -display option
+or check permissions of your X-Server
+(See "man X" resp. "man xhost" for details)
+25777:
+25777: runtime linker statistics:
+25777: final number of relocations: 24
+25777: final number of relocations from cache: 5309
+$ ldd /usr/lib/openoffice/program/soffice3.bin | wc -l
+ 76
+$ # Unprelinked system
+$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice3.bin 2>&1 | sed "$S"
+19131:
+19131: runtime linker statistics:
+19131: total startup time in dynamic loader: 852275754 clock cycles
+19131: time needed for relocation: 840996859 clock cycles (98.6%)
+19131: number of relocations: 68362
+19131: number of relocations from cache: 89213
+19131: number of relative relocations: 55831
+19131: time needed to load objects: 10170207 clock cycles (1.1%)
+/usr/lib/openoffice/program/soffice3.bin X11 error: Can't open display:
+Set DISPLAY environment variable, use -display option
+or check permissions of your X-Server
+(See "man X" resp. "man xhost" for details)
+19131:
+19131: runtime linker statistics:
+19131: final number of relocations: 69177
+19131: final number of relocations from cache: 89213
+$ # Prelinked system
+$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice3.bin 2>&1 | sed "$S"
+25847:
+25847: runtime linker statistics:
+25847: total startup time in dynamic loader: 12277407 clock cycles
+25847: time needed for relocation: 4232915 clock cycles (34.4%)
+25847: number of relocations: 0
+25847: number of relocations from cache: 8961
+25847: number of relative relocations: 0
+25847: time needed to load objects: 6925023 clock cycles (56.4%)
+/usr/lib/openoffice/program/soffice3.bin X11 error: Can't open display:
+Set DISPLAY environment variable, use -display option
+or check permissions of your X-Server
+(See "man X" resp. "man xhost" for details)
+25847:
+25847: runtime linker statistics:
+25847: final number of relocations: 24
+25847: final number of relocations from cache: 8961
+\end{verbatim}}
+\prelinklistingcaption{Dynamic linker statistics for unprelinked and prelinked OpenOffice.org}}
+
+Below are measurement using \tts{time(1)} for each of the \tts{soffice.bin}
+variants, prelinked and unprelinked. \tts{OpenOffice.org} was killed
+immediately after painting \tts{Writer}'s window using \tts{Ctrl+Q}.
+
+\noindent{\small\begin{center}
+\begin{longtable}{l|llllllllll|ll}
+{\bf Type} & \multicolumn{10}{l|}{\bf Values (in seconds)} & {\bf Average} & {\bf Std.Dev.} \\
+\hline
+\endhead
+& \multicolumn{10}{l|}{unprelinked soffice1.bin private:factory/swriter} && \\
+\hline
+{real} & {5.569} & {5.149} & {5.547} & {5.559} & {5.549} & {5.139} & {5.55} & {5.559} & {5.598} & {5.559} & {5.478} & {0.1765} \\
+{user} & {4.65} & {4.57} & {4.62} & {4.64} & {4.57} & {4.55} & {4.65} & {4.49} & {4.52} & {4.46} & {4.572} & {0.0680} \\
+{sys} & {0.29} & {0.24} & {0.19} & {0.21} & {0.21} & {0.21} & {0.25} & {0.25} & {0.27} & {0.26} & {0.238} & {0.0319} \\
+\hline
+& \multicolumn{10}{l|}{prelinked soffice1.bin private:factory/swriter} && \\
+\hline
+{real} & {4.946} & {4.899} & {5.291} & {4.879} & {4.879} & {4.898} & {5.299} & {4.901} & {4.887} & {4.901} & {4.978} & {0.1681} \\
+{user} & {4.23} & {4.27} & {4.18} & {4.24} & {4.17} & {4.22} & {4.15} & {4.25} & {4.26} & {4.31} & {4.228} & {0.0494} \\
+{sys} & {0.22} & {0.22} & {0.24} & {0.26} & {0.3} & {0.26} & {0.29} & {0.17} & {0.21} & {0.23} & {0.24} & {0.0389} \\
+\hline
+& \multicolumn{10}{l|}{unprelinked soffice2.bin private:factory/swriter} && \\
+\hline
+{real} & {5.575} & {5.166} & {5.592} & {5.149} & {5.571} & {5.559} & {5.159} & {5.157} & {5.569} & {5.149} & {5.365} & {0.2201} \\
+{user} & {4.59} & {4.5} & {4.57} & {4.37} & {4.47} & {4.57} & {4.56} & {4.41} & {4.63} & {4.5} & {4.517} & {0.0826} \\
+{sys} & {0.24} & {0.24} & {0.21} & {0.34} & {0.27} & {0.19} & {0.19} & {0.27} & {0.19} & {0.29} & {0.243} & {0.0501} \\
+\hline
+& \multicolumn{10}{l|}{prelinked soffice2.bin private:factory/swriter} && \\
+\hline
+{real} & {3.69} & {3.66} & {3.658} & {3.661} & {3.639} & {3.638} & {3.649} & {3.659} & {3.65} & {3.659} & {3.656} & {0.0146} \\
+{user} & {2.93} & {2.88} & {2.88} & {2.9} & {2.84} & {2.63} & {2.89} & {2.85} & {2.77} & {2.83} & {2.84} & {0.0860} \\
+{sys} & {0.22} & {0.18} & {0.23} & {0.2} & {0.18} & {0.29} & {0.22} & {0.23} & {0.24} & {0.22} & {0.221} & {0.0318} \\
+\hline
+& \multicolumn{10}{l|}{unprelinked soffice3.bin private:factory/swriter} && \\
+\hline
+{real} & {5.031} & {5.02} & {5.009} & {5.028} & {5.019} & {5.019} & {5.019} & {5.052} & {5.426} & {5.029} & {5.065} & {0.1273} \\
+{user} & {4.31} & {4.35} & {4.34} & {4.3} & {4.38} & {4.29} & {4.45} & {4.37} & {4.38} & {4.44} & {4.361} & {0.0547} \\
+{sys} & {0.27} & {0.25} & {0.26} & {0.27} & {0.27} & {0.31} & {0.18} & {0.17} & {0.16} & {0.15} & {0.229} & {0.0576} \\
+\hline
+& \multicolumn{10}{l|}{prelinked soffice3.bin private:factory/swriter} && \\
+\hline
+{real} & {3.705} & {3.669} & {3.659} & {3.669} & {3.66} & {3.659} & {3.659} & {3.661} & {3.668} & {3.649} & {3.666} & {0.0151} \\
+{user} & {2.86} & {2.88} & {2.85} & {2.84} & {2.83} & {2.86} & {2.84} & {2.91} & {2.86} & {2.8} & {2.853} & {0.0295} \\
+{sys} & {0.26} & {0.19} & {0.27} & {0.25} & {0.24} & {0.23} & {0.28} & {0.21} & {0.21} & {0.27} & {0.241} & {0.0303} \\
+\hline
+\multicolumn{13}{l}{} \\
+\caption{OpenOffice.org start up times without and with prelinking} \\
+\end{longtable}
+\end{center}}
+
+\section{Similar tools on other ELF using Operating Systems}
+
+Something similar to \tts{prelink} is available on other \tts{ELF}
+platforms. On Irix there is \tts{QUICKSTART} and on Solaris \tts{crle}.
+
+SGI \tts{QUICKSTART} is much closer to \tts{prelink} from these two.
+The \tts{rqs} program relocates libraries to (if possible) unique
+virtual address space slot. The base address is either specified
+on the command line with the \tts{-l} option, or \tts{rqs} uses
+a \tts{so\_locations} registry with \tts{-c} or \tts{-u} options
+and finds a not yet occupied slot. This is similar to how \tts{prelink}
+lays out libraries without the \tts{-m} option.
+
+\tts{QUICKSTART} uses the same data structure for library lists
+(\tts{ElfNN\_Lib}) as \tts{prelink}, but uses more fields in it
+(\tts{prelink} doesn't use \tts{l\_version} and \tts{l\_flags} fields at
+the moment) and uses different dynamic tags and section type for
+it. Another difference is that \tts{QUICKSTART} makes all liblist
+section \tts{SHF\_ALLOC}, whether in shared libraries or executables.
+\tts{prelink} only needs liblist section in the executable be allocated,
+liblist sections in shared libraries are not allocated and used
+at \tts{prelink} time only.
+
+The biggest difference between \tts{QUICKSTART} and \tts{prelink}
+is in how conflicts are encoded. SGI stores them in a very compact
+format, as array of \tts{.dynsym} section indexes for symbols which
+are conflicting. There is no information publicly available
+what exactly SGI dynamic linker does when it is resolving the conflicts,
+so this is just a guess. Given that the conflicts can be stored
+in a shared library or executable different to the shared library with the
+relocations against the conflicting symbol and different to the shared
+library which the symbol was originally resolved to, there doesn't seem
+to be an obvious way how to handle the conflicts very cheaply.
+The dynamic linker probably collects list of all conflicting symbol
+names, for each such symbol computes \tts{ELF} hash and walks hash buckets
+for this hash of all shared libraries, looking for the symbol.
+Every time it finds the symbol, all relocations against it need to be
+redone. Unlike this, \tts{prelink} stores conflicts as an array of
+\tts{ElfNN\_Rela} structures, with one entry for each shared relocation
+against conflicting symbol in some shared library. This guarantees
+that there are no symbol lookups during program startup (provided
+that shared libraries have not been changed after prelinking), while
+with \tts{QUICKSTART} will do some symbol lookups if there are any
+conflicts. \tts{QUICKSTART} puts conflict sections into the executable
+and every shared library where \tts{rqs} determines conflicts while
+\tts{prelink} stores them in the executable only (but the array is typically
+much bigger). Disk space requirements for prelinked executables are certainly
+bigger than for requickstarted executables, but which one has bigger runtime
+memory requirements is unclear. If prelinking can be used, all \tts{.rela*}
+and \tts{.rel*} sections in the executable and all shared libraries are skipped,
+so they will not need to be paged in during whole program's life (with the
+exception of first and last pages in the relocation sections which can be
+paged in because of other sections on the same page), but whole
+\tts{.gnu.conflict} section needs to be paged in (read-only) and processed.
+With \tts{QUICKSTART}, probably all (much smaller) conflict sections need
+to be paged in and also likely for each conflict whole relocation sections
+of each library which needs the conflict to be applied against.
+
+In \tts{QUICKSTART} documentation, SGI says that conflicts are very costly
+and that developers should avoid them. Unfortunately, this is sometimes quite
+hard, especially with C++ shared libraries. It is unclear whether \tts{rqs}
+does any optimizations to trim down the number of conflicts.
+
+Sun took completely different approach. The dynamic linker provides a
+\tts{dldump (const char *ipath, const char *opath, int flags);} function.
+{\sl ipath} is supposed to be a path to an \tts{ELF} object loaded already in
+the current process. This function creates a new \tts{ELF} object at
+{\sl opath}, which is like the {\sl ipath} object, but relocated to the
+base address which it has actually been mapped at in the current process
+and with some relocations (specified in {\sl flags} bitmask) applied as
+they have been resolved in the current process. Relocations, which have
+been applied, are overwritten in the relocation sections with
+\tts{R\_*\_NONE} relocations. The \tts{crle} executable, in addition to other
+functions not related to startup times, with some specific options uses the
+\tts{dldump} function to dump all shared libraries a particular executable
+uses (and the executable itself) into a new directory, with selected
+relocation classes being already applied. The main disadvantage of this
+approach is that such alternate shared libraries are at least for
+most relocation classes not shareable across different programs at all
+(and for those where they could be shareable a little bit there will
+be many relocations left for the dynamic linker, so the speed gains will
+be small). Another disadvantage is that all relocation sections need to
+be paged into the memory, just to find out that most of the relocations
+are \tts{R\_*\_NONE}.
+
+\section{ELF extensions for prelink}
+
+\tts{Prelink} needs a few \tts{ELF} extensions for its data structures
+in \tts{ELF} objects. For list of dependencies at the time of prelinking,
+a new section type \tts{SHT\_GNU\_LIBLIST} is defined:
+
+\noindent{{\small\begin{verbatim}
+#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
+
+typedef struct
+{
+ Elf32_Word l_name; /* Name (string table index) */
+ Elf32_Word l_time_stamp; /* Timestamp */
+ Elf32_Word l_checksum; /* Checksum */
+ Elf32_Word l_version; /* Unused, should be zero */
+ Elf32_Word l_flags; /* Unused, should be zero */
+} Elf32_Lib;
+
+typedef struct
+{
+ Elf64_Word l_name; /* Name (string table index) */
+ Elf64_Word l_time_stamp; /* Timestamp */
+ Elf64_Word l_checksum; /* Checksum */
+ Elf64_Word l_version; /* Unused, should be zero */
+ Elf64_Word l_flags; /* Unused, should be zero */
+} Elf64_Lib;
+\end{verbatim}}
+\prelinklistingcaption{New structures and section type constants used by \tts{prelink}}}
+
+Introduces a few new special sections:
+
+\noindent{\begin{center}
+\begin{longtable}{l|lc}
+{\bf Name} & {\bf Type} & {\bf Attributes} \\
+\hline
+& {\sl In shared libraries} & \\
+{.gnu.liblist} & {SHT\_GNU\_LIBLIST} & {0} \\
+{.gnu.libstr} & {SHT\_STRTAB} & {0} \\
+{.gnu.prelink\_undo} & {SHT\_PROGBITS} & {0} \\
+\hline
+& {\sl In executables} & \\
+{.gnu.liblist} & {SHT\_GNU\_LIBLIST} & {SHF\_ALLOC} \\
+{.gnu.conflict} & {SHT\_RELA} & {SHF\_ALLOC} \\
+{.gnu.prelink\_undo} & {SHT\_PROGBITS} & {0} \\
+\multicolumn{3}{l}{} \\
+\caption{Special sections introduced by \tts{prelink}} \\
+\end{longtable}
+\end{center}}
+
+\begin{description}
+\item[\tts{.gnu.liblist}] This section contains one \tts{ElfNN\_Lib} structure
+for each shared library which the object has been prelinked against,
+in the order in which they appear in symbol search scope.
+Section's \tts{sh\_link} value should contain section index of \tts{.gnu.libstr}
+for shared libraries and section index of \tts{.dynsym} for executables.
+\tts{l\_name} field contains the dependent library's name as index
+into the section pointed by\tts{sh\_link} field. \tts{l\_time\_stamp}
+resp. \tts{l\_checksum} should contain copies of \tts{DT\_GNU\_PRELINKED}
+resp. \tts{DT\_CHECKSUM} values of the dependent library.
+
+\item[\tts{.gnu.conflict}] This section contains one \tts{ElfNN\_Rela}
+structure for each needed \tts{prelink} conflict fixup. \tts{r\_offset}
+field contains the absolute address at which the fixup needs to be applied,
+\tts{r\_addend} the value that needs to be stored at that location.
+\tts{ELFNN\_R\_SYM} of \tts{r\_info} field should be zero,
+\tts{ELFNN\_R\_TYPE} of \tts{r\_info} field should be architecture
+specific relocation type which should be handled the same as
+for \tts{.rela.*} sections on the architecture. For \tts{EM\_ALPHA} machine,
+all types with \tts{R\_ALPHA\_JMP\_SLOT} in lowest 8 bits of \tts{ELF64\_R\_TYPE}
+should be handled as \tts{R\_ALPHA\_JMP\_SLOT} relocation, the upper
+24 bits contains index in original \tts{.rela.plt} section of the
+\tts{R\_ALPHA\_JMP\_SLOT} relocation the fixup was created for.
+
+\item[\tts{.gnu.libstr}] This section contains strings for \tts{.gnu.liblist}
+section in shared libraries where \tts{.gnu.liblist} section is not
+allocated.
+
+\item[\tts{.gnu.prelink\_undo}] This section contains \tts{prelink} private
+data used for \tts{prelink --undo} operation. This data includes the
+original \tts{ElfNN\_Ehdr} of the object before prelinking and all its
+original \tts{ElfNN\_Phdr} and \tts{ElfNN\_Shdr} headers.
+\end{description}
+
+\tts{Prelink} also defines 6 new dynamic tags:
+
+\noindent{{\small\begin{verbatim}
+#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */
+#define DT_CHECKSUM 0x6ffffdf8 /* Library checksum */
+
+#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */
+\end{verbatim}}
+\prelinklistingcaption{\tts{Prelink} dynamic tags}}
+
+\tts{DT\_GNU\_PRELINKED} and \tts{DT\_CHECKSUM} dynamic tags must
+be present in prelinked shared libraries. The corresponding
+\tts{d\_un.d\_val} fields should contain time when the library
+has been prelinked (in seconds since January, 1st, 1970, 00:00 UTC)
+resp. \tts{CRC32} checksum of all sections with one of
+\tts{SHF\_ALLOC}, \tts{SHF\_WRITE} or \tts{SHF\_EXECINSTR} bit set
+whose type is not \tts{SHT\_NOBITS}, in the order they appear in the
+shared library's section header table, with \tts{DT\_GNU\_PRELINKED}
+and \tts{DT\_CHECKSUM} \tts{d\_un.v\_val} values set to 0 for
+the time of checksum computation.
+
+The \tts{DT\_GNU\_LIBLIST} and \tts{DT\_GNU\_LIBLISTSZ} dynamic tags
+must be present in all prelinked executables. The \tts{d\_un.d\_ptr} value of
+the \tts{DT\_GNU\_LIBLIST} dynamic tag contains the virtual address
+of the \tts{.gnu.liblist} section in the executable and \tts{d\_un.d\_val}
+of \tts{DT\_GNU\_LIBLISTSZ} tag contains its size in bytes.
+
+\tts{DT\_GNU\_CONFLICT} and \tts{DT\_GNU\_CONFLICTSZ} dynamic tags
+may be present in prelinked executables. \tts{d\_un.d\_ptr} of
+\tts{DT\_GNU\_CONFLICT} dynamic tag contains the virtual address
+of \tts{.gnu.conflict} section in the executable (if present)
+and \tts{d\_un.d\_val} of \tts{DT\_GNU\_CONFLICTSZ} tag contains
+its size in bytes.
+
+\begin{appendix}
+
+\section{Glossary}
+\printglossary
+
+\section{References}
+
+\begin{description}
+\item[\textrm{[1]}]
+\href{http://www.caldera.com/developers/devspecs/gabi41.pdf}%
+{\sl System V Application Binary Interface, Edition 4.1}.
+
+\item[\textrm{[2]}]
+\href{http://www.caldera.com/developers/devspecs/abi386-4.pdf}%
+{\sl System V Application Binary Interface, Intel 386 Architecture Processor
+Supplement}.
+
+\item[\textrm{[3]}]
+\href{http://www.x86-64.org/cgi-bin/cvsweb.cgi/x86-64-ABI/}%
+{\sl System V Application Binary Interface, AMD64 Architecture Processor
+Supplement}.
+
+\item[\textrm{[4]}]
+\href{http://refspecs.freestandards.org/elf/IA64-SysV-psABI.pdf}%
+{{\sl System V Application Binary Interface, Intel Itanium Architecture Processor
+Supplement}, Intel Corporation, 2001}.
+
+\item[\textrm{[5]}]
+\href{http://refspecs.freestandards.org/elf/elfspec_ppc.pdf}%
+{Steve Zucker, Kari Karhi, {\sl System V Application Binary Interface,
+PowerPC Architecture Processor Supplement}, SunSoft, IBM, 1995}.
+
+\item[\textrm{[6]}]
+\href{ftp://ftp.linuxppc64.org/pub/people/amodra/PPC-elf64abi.txt.gz}%
+{\sl System V Application Binary Interface, PowerPC64 Architecture Processor
+Supplement}.
+
+\item[\textrm{[7]}]
+\href{http://www.arm.com/support/566FHT/$File/ARMELF.pdf}%
+{\sl System V Application Binary Interface, ARM Architecture Processor
+Supplement}.
+
+\item[\textrm{[8]}]
+\href{http://www.sparc.com/standards/SCD.2.4.1.ps.Z}%
+{{\sl SPARC Compliance Definition, Version 2.4.1},
+SPARC International, Inc., 1999}.
+
+\item[\textrm{[9]}]
+\href{http://people.redhat.com/drepper/dsohowto.pdf}%
+{Ulrich Drepper, {\sl How To Write Shared Libraries}, Red Hat, Inc., 2003}.
+
+\item[\textrm{[10]}]
+\href{http://docs.sun.com/db/doc/816-1386}%
+{{\sl Linker And Library Guide}, Sun Microsystems, 2002}.
+
+\item[\textrm{[11]}]
+\href{http://www.gzlinux.org/docs/category/dev/c/linkerandloader.pdf}%
+{John R. Levine, {\sl Linkers and Loaders}, 1999}.
+
+\item[\textrm{[12]}]
+\href{http://people.redhat.com/drepper/tls.pdf}%
+{Ulrich Drepper, {\sl ELF Handling For Thread-Local Storage}, Red Hat, Inc.,
+2003}.
+
+\item[\textrm{[13]}]
+\href{ftp://ftp.linuxppc64.org/pub/people/amodra/ppc32tls.txt.gz}%
+{Alan Modra, {\sl PowerPC Specific Thread Local Storage ABI}, 2003}.
+
+\item[\textrm{[14]}]
+\href{ftp://ftp.linuxppc64.org/pub/people/amodra/ppc64tls.txt.gz}%
+{Alan Modra, {\sl PowerPC64 Specific Thread Local Storage ABI}, 2003}.
+
+\item[\textrm{[15]}]
+\href{http://www.eagercon.com/dwarf/dwarf-2.0.0.pdf}%
+{\sl DWARF Debugging Information Format Version 2}.
+
+\item[\textrm{[16]}]
+\href{http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf}%
+{{\sl DWARF Debugging Information Format Version 3}, Draft, 2001}.
+
+\item[\textrm{[17]}]
+\href{http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gdb/doc/stabs.texinfo?cvsroot=src}%
+{\sl The "stabs" debugging information format}.
+\end{description}
+
+
+\section{Revision History}
+
+\begin{description}
+\item[2003-11-03] First draft.
+
+
+\end{description}
+
+\end{appendix}
+
+\end{document}