Provided with the Solaris
linkers is
a debugging library that allows you to trace the runtime linking process in more detail.
This library helps you understand, or debug, the execution of applications and dependencies.
This is a visual aid, and although the type of information displayed
using this library is expected to remain constant, the exact format of the information
might change slightly from release to release.
Some of the debugging output might be unfamiliar to those who do not have an intimate knowledge of the runtime linker. However, many aspects can 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
and by default is directed to the standard error. This environment variable must be
augmented with one or more tokens to indicate the type of debugging required.
The tokens available with this debugging option can be displayed by using LD_DEBUG=help
. Any dynamic executable
can be used to solicit this information, as the process itself will terminate following
the display of the information. For example:
$ LD_DEBUG=help prog 11693: 11693: For debugging the runtime linking of an application: 11693: LD_DEBUG=token1,token2 prog 11693: enables diagnostics to the stderr. The additional 11693: option: 11693: LD_DEBUG_OUTPUT=file 11693: redirects the diagnostics to an output file created 11593: using the specified name and the process id as a 11693: suffix. All diagnostics are prepended with the 11693: process id. 11693: 11693: 11693: basic provide basic trace information/warnings 11693: bindings display symbol binding; detail flag shows 11693: absolute:relative addresses 11693: detail provide more information in conjunction with other 11693: options 11693: files display input file processing (files and libraries) 11693: help display this help message 11693: libs display library search paths 11693: reloc display relocation processing 11693: symbols display symbol table processing; 11693: detail flag shows resolution and linker table addition 11693: versions display version processing $ |
This is an example, and shows the options meaningful to the runtime linker. The exact options might differ from release to release.
The environment variable LD_DEBUG_OUTPUT
can be used to specify an output file for use instead of the standard error. The output
file name will be suffixed with the process identifier.
Debugging of secure applications is not allowed.
One of the most useful debugging options is to display the symbol bindings that occur at runtime. For example, let's take 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 -Kpic -G bar.c $ cat foo.c foo(int data) { return (data); } $ cc -o foo.so.1 -Kpic -G foo.c $ cat main.c extern int foo(); extern int bar; 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: ....... |
Here, the symbol bar, which is required by a data relocation,
is bound before the application gains control. Whereas the symbol foo, which is required by a function relocation, is bound after the application gains control when the function is first called. This
demonstrates the default mode of lazy binding. If the environment
variable LD_BIND_NOW
is set, all symbol
bindings will occur before the application gains control.
Additional information regarding the real, and relative addresses of the actual
binding locations can be obtained by setting LD_DEBUG=bindings,detail
.
When the runtime linker performs a function relocation it rewrites data associated
with the functions .plt so that any subsequent calls will go directly
to the function. The environment variable LD_BIND_NOT
can be set to any value to prevent this data update. By using this variable
together with the debugging request for detailed bindings, you can get a complete
runtime account of all function binding. The output from this combination can be excessive,
and the performance of the application will be degraded.
Another aspect of the runtime environment that can be displayed involves 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 library=foo.so.1; searching 11775: search path=/tmp:. (RPATH from file prog) 11775: trying path=/tmp/foo.so.1 11775: trying path=./foo.so.1 11775: 11775: find library=bar.so.1; searching 11775: search path=/tmp:. (RPATH from file prog) 11775: trying path=/tmp/bar.so.1 11775: trying path=./bar.so.1 11775: ....... |
Here, 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
.
If this is combined with a bindings request, a complete picture
of the symbol relocation process can be obtained:
$ LD_DEBUG=bindings,symbols 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 is due to an optimization used when processing copy relocations (see "Copy Relocations" for more details of this relocation type).