Debugging a Program With dbx |
Debugging Shared Libraries
dbx
provides full debugging support for programs that use dynamically-linked, shared libraries, provided that the libraries are compiled using the-g
option.This chapter is organized into the following sections:
- Dynamic Linker
- Debugging Support for Preloaded Shared Objects
- Fix and Continue
- Setting a Breakpoint in a Dynamically Linked Library
Dynamic Linker
The dynamic linker, also known as
rtld
, Runtimeld
, orld.so
, arranges to bring shared objects (load objects) into an executing application. There are two primary areas wherertld
is active:
- Program startup - At program startup,
rtld
runs first and dynamically loads all shared objects specified at link time. These are preloaded shared objects and may includelibc.so
,libC.so
, orlibX.so
. Useldd
(1) to find out which shared objects a program will load.- Application requests - The application uses the function calls
dlopen
(3) anddlclose
(3) to dynamically load and unload shared objects or executables.
dbx
uses the term loadobject to refer to a shared object (.so
) or executable (a.out
).Link Map
The dynamic linker maintains a list of all loaded objects in a list called a link map, which is maintained in the memory of the program being debugged, and is indirectly accessed through
librtld_db.so
, a special system library for use by debuggers.Startup Sequence and
.init
SectionsA .
init
section is a piece of code belonging to a shared object that is executed when the shared object is loaded. For example, the .init
section is used by the C++ runtime system to call all static initializers in a.so
.The dynamic linker first maps in all the shared objects, putting them on the link map. Then, the dynamic linker traverses the link map and executes the .
init
section for each shared object. Thesyncrtld
event occurs between these two phases.Procedure Linkage Tables
Procedure linkage tables (PLTs) are structures used by the
rtld
to facilitate calls across shared object boundaries. For instance, the call toprintf
goes through this indirect table. The details of how this is done can be found in the generic and processor specific SVR4 ABI reference manuals.For
dbx
to handlestep
andnext
commands across PLTs, it has to keep track of the PLT table of each load object. The table information is acquired at the same time as thertld
handshake.Debugging Support for Preloaded Shared Objects
To put breakpoints in preloaded shared objects,
dbx
must have the addresses of the routines. Fordbx
to have the addresess of the routines, it must have the shared object base address. Doing something as simple as the following requires special consideration bydbx
.
stop in printfrunWhenever you load a new program,
dbx
automatically executes the program up to the point wherertld
has completed construction of the link map.dbx
then reads the link map and stores the base addresses. After that, the process is killed and you see the prompt. Thesedbx
tasks are conducted silently.At this point, the symbol table for
libc.so
is available as well as its base load address. Therefore, the address ofprintf
is known.The activity of
dbx
waiting forrtld
to construct the link map and accessing the head of the link map is known as the rtld handshake. The eventsyncrtld
occurs whenrtld
is done with the link map anddbx
has read all of the symbol tables.Fix and Continue
Using fix and continue with shared object sloaded with
dlopen()
requires a change in how they are opened for fix and continue to work correctly. Use modeRTLD_NOW|RTLD_GLOBAL
orRTLD_LAZY|RTLD_GLOBAL
.Setting a Breakpoint in a Dynamically Linked Library
dbx
automatically detects that adlopen
or adlclose
has occurred and loads the symbol table of the loaded object. Once a shared object has been loaded withdlopen()
you can place breakpoints in it and debug it as you would any part of your program.If a shared object is unloaded using
dlclose()
,dbx
remembers the breakpoints placed in it and replaces them if the shared object is again loaded withdlopen()
, even if the application is run again. (Versions ofdbx
prior to 5.0 would instead mark the breakpoint as '(defunct)', and it had to be deleted and replaced by the user.)However, you do not need to wait for the loading of a shared object with
dlopen()
to place a breakpoint in it, or to navigate its functions and source code. If you know the name of the shared object that the program being debugged will be loading withdlopen()
, you can arrange fordbx
to preload its symbol table intodbx
by using:
loadobjects -p /usr/java1.1/lib/libjava_g.soYou can now navigate the modules and functions in this loadobject and place breakpoints in it before it has ever been loaded with
dlopen()
. Once it is loaded,dbx
automatically places the breakpoints.Setting a breakpoint in a dynamically linked library is subject to the following limitations:
- You cannot set a breakpoint in a "filter" library loaded with
dlopen()
until the first function in it is called.- When a library is loaded by
dlopen()
, an initialization routine named_init()
is called. This routine might call other routines in the library.dbx
cannot place breakpoints in the loaded library until after this initialization is completed. In specific terms, this means you cannot havedbx
stop at_init()
in a library loaded bydlopen
.
Sun Microsystems, Inc. Copyright information. All rights reserved. Feedback |
Library | Contents | Previous | Next | Index |