Dynamic Loading
This section is a tad short right now; it will be expanded over time
as I gut the ELF howto
Concepts
Linux has shared libraries, as you will by now be sick of hearing if you
read the whole of the last section at a sitting. Some of the matching-names-to-places
work which was traditionally done at link time must be deferred to load
time.
Error messages
Send me your link errors! I won't do anything about them, but I might write
them up ...
-
can't load library: /lib/libxxx.so, Incompatible version
(a.out only) This means that you don't have the correct major version
of the xxx library. No, you can't just make a symlink to another version
that you do have; if you are lucky this will cause your program to segfault.
Get the new version. A similar situation with ELF will result in a message
like
ftp: can't load library 'libreadline.so.2'
|
-
warning using incompatible library version xxx
(a.out only) You have an older minor version of the library than the
person who compiled the program used. The program will still run. Probably.
An upgrade wouldn't hurt, though.
Controlling the operation of the dynamic loader
There are a range of environment variables that the dynamic loader will
respond to. Most of these are more use to ldd than they are to
the average user, and can most conveniently be set by running ldd with
various switches. They include
LD_BIND_NOW --- normally, functions are not `looked up' in
libraries until they are called. Setting this flag causes all the lookups
to happen when the library is loaded, giving a slower startup time. It's
useful when you want to test a program to make sure that everything is
linked.
LD_PRELOAD can be set to a file containing `overriding' function
definitions. For example, if you were testing memory allocation strategies,
and wanted to replace `malloc', you could write your replacement routine,
compile it into malloc.o and then
$ LD_PRELOAD=malloc.o; export LD_PRELOAD
$ some_test_program
|
LD_ELF_PRELOAD and LD_AOUT_PRELOAD are similar, but only
apply to the appropriate type of binary. If LD_something_PRELOAD
and LD_PRELOAD are set, the more specific one is used.
LD_LIBRARY_PATH is a colon-separated list of directories in
which to look for shared libraries. It does not affect ld; it only
has effect at runtime. Also, it is disabled for programs that run setuid
or setgid. Again, LD_ELF_LIBRARY_PATH and LD_AOUT_LIBRARY_PATH
can also be used to direct the search differently for different flavours
of binary. LD_LIBRARY_PATH shouldn't be necessary in normal operation;
add the directories to /etc/ld.so.conf/ and rerun ldconfig instead.
LD_NOWARN applies to a.out only. When set (e.g. with LD_NOWARN=true;
export LD_NOWARN) it stops the loader from issuing non-fatal warnings
(such as minor version incompatibility messages).
LD_WARN applies to ELF only. When set, it turns the usually
fatal ``Can't find library'' messages into warnings. It's not much use
in normal operation, but important for ldd.
LD_TRACE_LOADED_OBJECTS applies to ELF only, and causes programs
to think they're being run under ldd:
$ LD_TRACE_LOADED_OBJECTS=true /usr/bin/lynx
libncurses.so.1 => /usr/lib/libncurses.so.1.9.6
libc.so.5 => /lib/libc.so.5.2.18
|
Writing programs with dynamic loading
This is very close to the way that Solaris 2.x dynamic loading support
works, if you're familiar with that. It is covered extensively in H J Lu's
ELF programming document, and the dlopen(3) manual page, which
can be found in the ld.so package. Here's a nice simple example though:
link it with -ldl
#include <dlfcn.h>
#include <stdio.h>
main()
{
void *libc;
void (*printf_call)();
if(libc=dlopen("/lib/libc.so.5",RTLD_LAZY))
{
printf_call=dlsym(libc,"printf");
(*printf_call)("hello, world\n");
}
}
|
|