Dealing with symbol-table formats is one of the most machine-dependent aspects of debuggers. ldb eliminates this machine dependence by using one format on all machines. The format is a language---a dialect of PostScript, which is extensible and can represent procedures. ldb reduces retargeting effort associated with variations in run-time support by controlling its target process using a debug nub, which is a small piece of object code linked with the target program.
Much of a debugger's job is to undo what the compiler has done or to do what the compiler could do, but at run time. For example, to print the value of a variable, the debugger must undo the compiler's mapping of source-level data to the machine level. To evaluate an expression, the debugger must check that it is syntactically and semantically correct and translate it into an executable form. ldb makes the compiler do as much of this work as possible. The compiler emits PostScript that ldb uses to print values. A variant of the compiler runs at debug time and compiles expressions into other PostScript, which ldb uses to evaluate the expressions.
Debugging tasks like planting breakpoints and walking the call stack have no analogs in a compiler. ldb reduces retargeting effort for these tasks by using layers of abstraction to minimize machine-dependent code, which is confined to the innermost layers.
These techniques produce a debugger with little machine-dependent code. ldb's total code size is about 15,000 lines of Modula-3 and C, but it needs no more than 550 lines of machine-dependent code for any of its 4 targets.
The thesis of which this is the abstract is available, as is the software described therein.