This chapter discusses the significant features of MDB and the benefits derived from this architecture.
2.1. Building Blocks
The target is the program being inspected by the debugger. MDB currently provides support for the following types of targets:
User process core files
Live operating system without kernel execution control (through
Live operating system with kernel execution control (through the kmdb(1) command)
Operating system crash dumps
User process images recorded inside an operating system crash dump
ELF object files
Raw data files
Each target exports a standard set of properties, including one or more address spaces, one or more symbol tables, a set of load objects, and a set of threads. MDB architecture shows an overview of the MDB architecture, including two of the built-in targets and a pair of sample modules.
A debugger command, or dcmd (pronounced dee-command) in MDB terminology, is a routine in the debugger that can access any of the properties of the current target. MDB parses commands from standard input, then executes the corresponding dcmds. Each dcmd can also accept a list of string or numerical arguments, as shown in Syntax. MDB contains a set of built-in dcmds that are always available. These built-in dcmds are described in Built-In Commands. You can also extend the capabilities of MDB by writing dcmds using a programming API provided with MDB.
A walker is a set of routines that describe how to walk, or iterate, through the elements of a particular program data structure. A walker encapsulates the data structure's implementation from dcmds and from MDB. You can use walkers interactively, or you can use walkers as primitives to build other dcmds or walkers. As with dcmds, you can extend MDB by implementing additional walkers as part of a debugger module.
A debugger module, or dmod (pronounced dee-mod), is a dynamically loaded library that contains a set of dcmds and walkers. During initialization, MDB attempts to load dmods corresponding to the load objects present in the target. You can subsequently load or unload dmods at any time while running MDB. MDB provides a set of standard dmods for debugging the illumos kernel.
A macro file is a text file that
contains a set of commands to execute. Macro files are typically used
to automate the process of displaying a simple data structure. MDB provides
complete backward compatibility for the execution of macro files written for
adb. The set of macro files provided with the illumos
installation can therefore be used with either tool.
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
MDB architecture. 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
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 illumos kernel is the list
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
proc_t structures is encapsulated in the
MDB provides both
but neither of these dcmds has any knowledge of how
are accessed in the kernel. Instead, these dcmds invoke the
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 illumos 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.