Debugging a Program With dbx HomeContentsPreviousNextIndex


Chapter 19

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

The dynamic linker, also known as rtld, Runtime ld, or ld.so, arranges to bring shared objects (load objects) into an executing application. There are two primary areas where rtld is active:

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 Sections

A .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. The syncrtld 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 to printf 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 handle step and next 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 the rtld handshake.

Debugging Support for Preloaded Shared Objects

To put breakpoints in preloaded shared objects, dbx must have the addresses of the routines. For dbx 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 by dbx.

stop in printf
run

Whenever you load a new program, dbx automatically executes the program up to the point where rtld 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. These dbx 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 of printf is known.

The activity of dbx waiting for rtld to construct the link map and accessing the head of the link map is known as the rtld handshake. The event syncrtld occurs when rtld is done with the link map and dbx 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 mode RTLD_NOW|RTLD_GLOBAL or RTLD_LAZY|RTLD_GLOBAL.

Setting a Breakpoint in a Dynamically Linked Library

dbx automatically detects that a dlopen or a dlclose has occurred and loads the symbol table of the loaded object. Once a shared object has been loaded with dlopen() 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 with dlopen(), even if the application is run again. (Versions of dbx 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 with dlopen(), you can arrange for dbx to preload its symbol table into dbx by using:

loadobjects -p /usr/java1.1/lib/libjava_g.so

You 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:


Sun Microsystems, Inc.
Copyright information. All rights reserved.
Feedback
Library   |   Contents   |   Previous   |   Next   |   Index