| Debugging a Program With dbx |
Debugging Shared Libraries
dbxprovides full debugging support for programs that use dynamically-linked, shared libraries, provided that the libraries are compiled using the-goption.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 wherertldis active:
- Program startup - At program startup,
rtldruns 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.
dbxuses 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
.initSectionsA .
initsection is a piece of code belonging to a shared object that is executed when the shared object is loaded. For example, the .initsection 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 .
initsection for each shared object. Thesyncrtldevent occurs between these two phases.Procedure Linkage Tables
Procedure linkage tables (PLTs) are structures used by the
rtldto facilitate calls across shared object boundaries. For instance, the call toprintfgoes 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
dbxto handlestepandnextcommands 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 thertldhandshake.Debugging Support for Preloaded Shared Objects
To put breakpoints in preloaded shared objects,
dbxmust have the addresses of the routines. Fordbxto 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,
dbxautomatically executes the program up to the point wherertldhas completed construction of the link map.dbxthen reads the link map and stores the base addresses. After that, the process is killed and you see the prompt. Thesedbxtasks are conducted silently.At this point, the symbol table for
libc.sois available as well as its base load address. Therefore, the address ofprintfis known.The activity of
dbxwaiting forrtldto construct the link map and accessing the head of the link map is known as the rtld handshake. The eventsyncrtldoccurs whenrtldis done with the link map anddbxhas 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_GLOBALorRTLD_LAZY|RTLD_GLOBAL.Setting a Breakpoint in a Dynamically Linked Library
dbxautomatically detects that adlopenor adlclosehas 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(),dbxremembers the breakpoints placed in it and replaces them if the shared object is again loaded withdlopen(), even if the application is run again. (Versions ofdbxprior 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 fordbxto preload its symbol table intodbxby 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,dbxautomatically 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.dbxcannot place breakpoints in the loaded library until after this initialization is completed. In specific terms, this means you cannot havedbxstop at_init()in a library loaded bydlopen.
|
Sun Microsystems, Inc. Copyright information. All rights reserved. Feedback |
Library | Contents | Previous | Next | Index |