Runtime Linker Debugging Facility
The runtime linker provides a debugging facility that allows you to trace the runtime linking of applications and their dependencies in detail. The type of information that is displayed by using this facility is expected to remain constant. However, the exact format of the information might change slightly from release to release.
Some of the debugging output might be unfamiliar to users who do not have an intimate knowledge of the runtime linker. However, many aspects might be of general interest to you.
Debugging is enabled by using the environment variable
LD_DEBUG
. All debugging output is prefixed
with the process identifier. This environment variable must be
augmented with one or more tokens to indicate the type of debugging
that is required.
The tokens that are available with LD_DEBUG
can be
displayed by using LD_DEBUG=help
.
$ LD_DEBUG=help prog
prog
can be any executable. The process is
terminated following the display of the help information, before
control transfers to prog
. The choice of
executable is unimportant.
If the help
token is specified by itself, output goes
to stdout
, the standard output file. If any other
tokens are specified, debug output is sent to stderr
,
the standard error output file. Debug output can be directed to a file
instead by using the output
token. For example, the
help text can be captured in a file named
rtld-debug.txt
.
$ LD_DEBUG=help,output=rtld-debug.txt prog
Alternatively, debug output can be redirected by setting the
environment variable LD_DEBUG_OUTPUT
. When
LD_DEBUG_OUTPUT
is used, the process
identifier is added as a suffix to the output filename.
If LD_DEBUG_OUTPUT
and the output
token are both specified, LD_DEBUG_OUTPUT
takes
precedence. If LD_DEBUG_OUTPUT
and the
output
token are both specified,
LD_DEBUG_OUTPUT
takes precedence. Use of the
output
token with programs that call
fork
(2) result in each process writing debug
output to the same file. The debug output will become jumbled and
incomplete. LD_DEBUG_OUTPUT
should be used in such
cases to direct debug output for each process to a unique
file.
The debugging of secure applications is not allowed.
One of the most useful debugging options is to display the symbol bindings that occur at runtime. The following example uses a very trivial dynamic executable that has a dependency on two local shared objects.
$ cat bar.c int bar = 10; $ cc -o bar.so.1 -K pic -G bar.c $ cat foo.c int foo(int data) { return (data); } $ cc -o foo.so.1 -K pic -G foo.c $ cat main.c extern int foo(); extern int bar; int main() { return (foo(bar)); } $ cc -o prog main.c -R/tmp:. foo.so.1 bar.so.1
The runtime symbol bindings can be displayed by setting
LD_DEBUG=bindings
.
$ LD_DEBUG=bindings prog
11753: ....
11753: binding file=prog to file=./bar.so.1: symbol bar
11753: ....
11753: transferring control: prog
11753: ....
11753: binding file=prog to file=./foo.so.1: symbol foo
11753: ....
The symbol bar
, which is required by
an immediate relocation, is bound before the
application gains control. Whereas the symbol
foo
, which is required by a lazy relocation, is
bound after the application gains control on
the first call to the function. This relocation demonstrates the
default mode of lazy binding. If the environment variable
LD_BIND_NOW
is set, all symbol bindings occur
before the application gains control.
By setting LD_DEBUG=bindings,detail
, additional
information regarding the real and relative addresses of the actual
binding locations is provided.
You can use LD_DEBUG
to display the various search
paths used. For example, the search path mechanism used to locate
any dependencies can be displayed by setting
LD_DEBUG=libs
.
$ LD_DEBUG=libs prog
11775:
11775: find object=foo.so.1; searching
11775: search path=/tmp:. (RUNPATH/RPATH from file prog)
11775: trying path=/tmp/foo.so.1
11775: trying path=./foo.so.1
11775:
11775: find object=bar.so.1; searching
11775: search path=/tmp:. (RUNPATH/RPATH from file prog)
11775: trying path=/tmp/bar.so.1
11775: trying path=./bar.so.1
11775: ....
The runpath recorded in the application
prog
affects the search for the two
dependencies foo.so.1
and
bar.so.1
.
In a similar manner, the search paths of each symbol lookup can be
displayed by setting LD_DEBUG=symbols
. A combination
of symbols
and bindings
produces a complete picture of the symbol relocation process.
$ LD_DEBUG=bindings,symbols prog
11782: ....
11782: symbol=bar; lookup in file=./foo.so.1 [ ELF ]
11782: symbol=bar; lookup in file=./bar.so.1 [ ELF ]
11782: binding file=prog to file=./bar.so.1: symbol bar
11782: ....
11782: transferring control: prog
11782: ....
11782: symbol=foo; lookup in file=prog [ ELF ]
11782: symbol=foo; lookup in file=./foo.so.1 [ ELF ]
11782: binding file=prog to file=./foo.so.1: symbol foo
11782: ....
In the previous example, the symbol bar
is not
searched for in the application prog
. This
omission of a data reference lookup is due to an optimization used
when processing copy relocations. See Copy Relocations for more details of this relocation
type.