Professional Documents
Culture Documents
SEPTEMBER/OCTOBER 2001 91
SCIENTIFIC PROGRAMMING
Cafe Dubois
On most systems, the static linker handles both static and tual library le), the static linker checks for unresolved sym-
shared libraries. For example, consider a simple program bols and reports errors as usual. However, rather than copy-
linked against a few different libraries: ing the contents of the libraries into the target executable,
the linker simply records the names of the libraries in a list
$ gcc hello.c -lpthread -lm in the executable. You can view the contents of the library
dependency list with a command such as ldd:
If the libraries -lpthread and -lm have been compiled as
shared libraries (usually indicated by a .so sufx on the ac- ldd a.out
SEPTEMBER/OCTOBER 2001 93
SCIENTIFIC PROGRAMMING
SEPTEMBER/OCTOBER 2001 95
SCIENTIFIC PROGRAMMING
Dynamic module 1
Figure 3. Linkchains created by
dynamic loading. Each dynamically mod1.so libd.so
loadable module goes on a new
linkchain but can still bind to symbols Dynamic module 2 Executable
defined in the primary executable. mod2.so a.out liba.so libb.so libc.so
Dynamic module 3
handle = dlopen(foo.so, RTLD_NOW | RTLD_LOCAL); agement functions. However, these replacements use dl-
foo = (void (*)(void)) dlsym(handle,foo); sym() to search for the real implementation of malloc()
if (foo) foo(); and free() farther down the linkchain.
...
dlclose(handle); To use this lter, the library can be included on the linkline
like a normal library. Alternatively, the library can be preloaded
by supplying a special environment variable to the dynamic
Unlike standard linking, dynamically loaded modules are linker. The following command illustrates library preloading by
completely decoupled from the underlying application. The dy- running Python with our memory-allocation lter enabled:
namic loader does not use them to resolve any unbound symbols
or any other part of the normal application-linking process. $ LD_PRELOAD=./libmlter.so python
The dynamic linker loads a module and all of its required li-
braries using the exact same procedure as before (that is, it loads Depending on how you tweak the linker, the user can place
libraries in the order specied on the link line, _init() func- lters almost anywhere on the linkchain. For instance, if the
tions are invoked, and so forth). Again, the linker keeps track lter functions were linked to a dynamically loadable module,
of previously loaded libraries and will not reload shared libraries only the memory allocations performed by the module pass
that are already present. The main difference is that when mod- through the lters; all other allocations remain unaffected.
ules are loaded, they normally go on private linkchains. This re-
sults in a tree of library dependencies (see Figure 3). Constructing shared libraries
As symbols are bound in each dynamically loaded mod- Lets examine a few problematic aspects of shared library
ule, the linker searches libraries starting with the module it- construction. First, when shared libraries and dynamically
self and the list of libraries in its corresponding linkchain. loadable modules are compiled, it is fairly common to see spe-
Additionally, the linker searches for symbols in the main ex- cial compiler options for creating position-independent code (-
ecutable and all its libraries. fpic, -FPIC, -KPIC, and so on). When these options are
One consequence of the tree structure is that each dy- present during compilation, the compiler generates code that
namically loaded module gets its own private symbol name- accesses symbols through a collection of indirection registers
space. So, if a symbol name is dened in more than one load- and global offset tables. The primary benet of PIC code is
able module, those symbols remain distinct and do not clash that the text segment of the resulting library (containing ma-
with each other during execution. Similarly, unless the pro- chine instructions) can quickly relocate to any memory address
gram gives special options to the dynamic loader, it doesnt without code patches. This improves program startup time
use symbols dened in previously loaded modules to resolve and is important for libraries that large numbers of running
symbols in newly loaded modules. For users of scripting lan- processes must share. (PIC lets the operating system relocate
guages, this explains why everything still works even when libraries to different virtual memory regions without modify-
two extension modules appear to have a namespace clash. It ing the library instructions.) The downside to PIC is a mod-
also explains why extension modules cant dynamically bind est degradation in application performance (often 5 to 15 per-
to symbols dened in other dynamically loaded modules. cent). A somewhat overlooked point in many shared library
examples is that shared libraries and dynamically loadable
Filters modules generally do not require PIC code. So, if performance
Dynamic linking enables modes of linking that are not eas- is important for a library or dynamically loadable module, you
ily achieved with static libraries. One such example is the im- can compile it as non-PIC code. The primary downside to
plementation of lters that let you alter the behavior of com- compiling the module as non-PIC is that loading time in-
mon library functions. For example, suppose you want to creases because the dynamic linker must make a large number
track calls to dynamic memory-allocation functions mal- of code patches when binding symbols.
loc() and free(). One way to do this with dynamic link- A second problem with shared library construction concerns
ing is to write a simple library as in Figure 4. In the gure, we the inclusion of static libraries when building dynamically
implemented replacements for the standard memory man- loadable modules. When the user or programmer works with
1. J.R. Levine, Linkers & Loaders, Morgan Kaufmann, San Francisco, 2000. the University of Chicago. Contact him at the Dept. of Computer Sci-
2. M.L. Scott, Programming Language Pragmatics, Morgan Kaufmann, San ence, Univ. of Chicago, Chicago, IL 60637; iancooke@cs.uchicago.edu.
Francisco, 2000.
SEPTEMBER/OCTOBER 2001 97