Modularity
The benefit of MDB's modular architecture extends beyond the ability to load a
module containing additional debugger commands. The MDB architecture defines clear interface boundaries between
each of the layers shown in Figure 2-1. Macro files execute commands written in
the MDB or adb language. Dcmds and walkers in debugger modules are written
using the MDB Module API. The MDB Module API is the basis of
an application binary interface that allows the debugger and its modules to evolve
independently.
The MDB name space of walkers and dcmds also defines a second
set of layers between debugging code. These layers maximize code sharing and limit the
amount of code that must be modified as the target program evolves.
For example, one of the primary data structures in the Solaris kernel is
the list of proc_t structures that represent active processes in the system. The ::ps
dcmd must iterate over this list in order to produce its output. However,
the code to iterate over the list is not in the ::ps dcmd.
The code to iterate over the list of proc_t structures is encapsulated in
the genunix module's proc walker.
MDB provides both ::ps and ::ptree dcmds, but neither of these dcmds has
any knowledge of how proc_t structures are accessed in the kernel. Instead, these
dcmds invoke the proc walker programmatically and format the set of returned structures
appropriately. If the data structure used for proc_t structures ever changed, MDB could provide
a new proc walker, and none of the dependent dcmds would need to
change. The proc walker can also be accessed interactively using the ::walk
dcmd in order to create novel commands as you work during a debugging
session.
In addition to facilitating layering and code sharing, the MDB Module API provides
dcmds and walkers with a single stable interface for accessing various properties of
the underlying target. The same API functions are used to access information from
user process or kernel targets, simplifying the task of developing new debugging facilities.
In addition, you can use a custom MDB module to perform debugging
tasks in a variety of contexts. For example, you might want to develop
an MDB module for a user program you are developing. Once you have
done so, you can use this module when MDB examines a live process
executing your program, a core dump of your program, or even a kernel
crash dump taken on a system where your program was executing.
The Module API provides facilities for accessing the following target properties:
- Address Spaces
The module API provides facilities for reading and writing data from the target's virtual address space. Functions for reading and writing using physical addresses are also provided for kernel debugging modules.
- Symbol Tables
The module API provides access to the static and dynamic symbol tables of the target's primary executable file, its runtime link-editor, and a set of load objects. Load objects are shared libraries in a user process or loadable modules in the Solaris kernel.
- External Data
The module API provides a facility for retrieving a collection of named external data buffers associated with the target. For example, MDB provides programmatic access to the proc(4) structures associated with a user process or user core file target.
In addition, you can use built-in MDB dcmds to access information about target
memory mappings, load objects, register values, and control the execution of user process
targets.