BugBane - the Cedar Debugger
Russ Atkinson

May 27, 1983 3:44 pm

BugBane is the standard debugging support in the Cedar environment. It is organized as a collection of facilities, which include a simple Mesa expression interpreter, with support for breakpoints and uncaught signals.
BugBane is usually called from a Work Area. When the input focus is in a Work Area viewer you can type Mesa expressions (preceeded by "←"). Each expression is then evaluated and the results printed to the typescript. Each value is assigned to an interpreter variable for later use.
I. The Mesa subset
The subset of Mesa expressions interpreted by BugBane is roughly described by the following list of constructs. BugBane attempts to perform a reasonable amount of coercion to get values to agree with their targets. This coercion is usually more than the compiled langauge provides.
1, 1.2, "abc", 'A, TRUE, $atom-- fixed, float, rope, char, bool, atom constants
&x, foo, FooImpl -- simple variables, according to search rules below
X.Y -- X is a record, ref to a record, pointer to a record, a global frame
X[Y] -- X is a sequence or array, ref or pointer to a sequence or array
Proc[X, ...] -- Proc is a procedure taking given arguments
Type[X, ...] -- a record or array constructor (Type may be implicit)
NEW [T ← expr] -- only in the local world
X op Y -- for op in {+, -, *, /, MOD}
op[X, ...] -- for op in {MIN, MAX, ALL, LIST, CONS}
XY -- X and Y are expressions, [] ← Y is permitted
II. Actions and multiple processes
Actions
In BugBane, an action represents the occurence of an uncaught signal (or error) or a breakpoint. An address fault is treated as an uncaught signal, and is therefore also an action. When an action occurs, the associated process is stopped. Other processes can continue, subject to the usual constraints (e.g. monitor locks).
The occurence of a new action usually spawns (creates) a new work area or reuses an old work area. When an action is associated with a work area the expression executed in that work area are interpreted with respect to the call stack for that action. Setting of breakpoints, stack display, proceeding and aborting are all performed with respect to that action.
Multiple processes
A process stack may only be examined by BugBane when the associated process is stopped. Any other approach is highly unsafe. The DebugTool can be used to stop processes. Another way to stop a process is to set a breakpoint in code that it executes. One difficulty with stopping processes by either method is that the process may be holding a resource necessary for BugBane. Since no automatic method for determing these resources is available, the decision as to when and where to plant the breakpoint is left to the user (sigh).
Proceeding a breakpoint will continue with program execution. Proceeding an uncaught signal will attempt to resume the signal (although there is no provision for resuming with arguments).
III. Name lookup
Name lookup in BugBane differs from name lookup in Mesa, primarily because the facilities available to the compiler are not available to the runtime, but also because there are more places to look at runtime. Names are found only if they are the right case and in the current "context." A context is like a search path, and is searched in the following order:
Debugger table lookup
The debugger name table contains a name to value association for identifiers. Aside from a few special cases (like TRUE, FALSE, and some built-in types), all names in this table start with "&". There is a separate debugger table, and hence a separate name space, for each work area.
Stack lookup (including global frames)
A stack exists for every action. When a name is looked up from a work area associated with an action the local frames (and associated global frames) are searched (last-created-first-found) for names up to some reasonable depth (currently 8).
Interface names
For lookup of X in expressions of the form X.Y, BugBane will attempt to treat X as an interface record and Y as a selector. This facility is quite new, quite slow, and somewhat frail. The user should try to use implementation module names when this facility does not work.
Global frame table
The global frame table is searched for global frame names only in last-loaded-first-found order. Variables in those global frames will not be found without qualification. The user should note that multiple instances of global frames are not supported.
Default global frame
The default global frame is set whenever one evaluates the expression that is the simple global frame name. Variables in that global frame will be found in this search. There is a separate default global frame for each work area.
IV. Octal commands
The following commands are intended for use by experienced users. They are made available as expressions, since they are applicable to contexts inherited from the interpreter (to allow for remote debugging).
&ar[ptr,len]
Ascii Read - Displays the Ascii characters starting at address ptr for len characters. Values of ptr that are smaller than 64K are interpreted as being MDS pointers.
&ars[ptr,len]
Ascii Read Short - Like &ar, but does not interpret values of ptr that are smaller than 64K as MDS pointers.
&clob[gf,pc]
CLear Octal Break - Clears the breakpoint set at the numerically specified global frame and program counter.
&fm[pattern]
Find Matching - If the pattern (as a ROPE literal) does not contain a period, &fm finds and prints the names of the global frames whose names match the pattern (case does not matter). If the pattern does contain a period, &fm finds the matching components of matching global frames.
&lob[]
List Octal Breaks - List all of the current breakpoints that were set by &sob.
&ofc[gf,pc,b0,b1,b2,b3,...,b9]
Octal Find Code - Starting at the specified global frame and program counter, find the program counter for the given code bytes.
&or[ptr, len ← 4, width ← 16, base ← 8]
Octal Read - Displays the contents of memory in the given base starting at ptr for the number of units given by len. The value of width must be in {1,2,4,8,16,32}. The value of base must be in [2..36]. Values of ptr that are smaller than 64K are interpreted as being MDS pointers.
&orc[gf,pc,len]
Octal Read Code - Displays the code bytes (in octal, unfortunately), starting at the given global frame and program counter for len bytes.
&ors[ptr,len]
Octal Read Short - Like &or, but does not interpret values of ptr that are smaller than 64K as MDS pointers.
&ow[ptr,word,len]
Octal Write - Writes the given 16-bit word into the given address for the number of words given by len. Values of ptr that are smaller than 64K are interpreted as being MDS pointers.
&ows[ptr,word,len]
Octal Write Short - Like &ow, but does not interpret values of ptr that are smaller than 64K as MDS pointers.
&pgf[gf]
Print Global Frame - Prints the components of the specified global frame.
&plf[lf]
Print Local Frame - Prints the components of the specified local frame.
&sob[gf,pc]
Set Octal Break - Sets a breakpoint at the speicifed global frame and program counter.
&tgf[gf]
Trust Global Frame - "Trusts" the given number as a global frame. This allows examining or setting named components, as in &tgf[gf].name.
&tlf[lf]
Trust Local Frame - "Trusts" the given number as a local frame. This allows examining or setting named components, as in &tgf[lf].name.
V. Shortfalls
Performance is only moderately acceptable.
Although there is substantial caching of results in AMTypes and in BugBane, the first time through for many expressions may take a long time, particularly if the symbols are not available on your local disk. Patience is the only current recommendation, although we are certainly concerned about performance.
One name - one global frame.
Recompiling and reloading a module will work only with very simple systems. BugBane only provides a linear search space for global frame names (last loaded, first found). Therefore you can only find one instance of a global frame with a given name.
Peculiar name interpretation.
BugBane has both better and worse interpretation of names than the compiler or CoPilot. Unlike the compiler, BugBane knows nothing about OPEN, so many names that can be left unqualified in compiled programs must be fully qualified for interpreted expressions. BugBane will search for names both in the current call stack and in the global frame table.
Opaque types are not fully supported.
The mapping between opaque and concrete types is not supplied by the runtime system. This leads to type clashes when you try to hand a value of opaque type to a procedure that expects a concrete type, and vice versa. There is only one automatic coercion practiced, which is when a REF opaque is passed to a routine that expects a REF concrete. In this one case, the object carries the concrete type, and the coercion is made automatically. In other cases, LOOPHOLE should be used as a work-around.
Some safe expressions are not yet supported.
SELECT expressions are not supported. Very few expressions involving types are supported, and there may always be a few shortfalls here. Statements are not supported, so catch phrases in expressions will not work.
Variant record constructors are limited to positional notation (keyword notation is not supported).
LIST constructors are only partially implemented, since they ignore the zone option, and only work for LIST OF REF ANY.
Object notation is supported for procedure invocation, but may not do all that the compiler does. In particular, NIL as the first argument in object notation will not work.
Selection from interfaces is only partially implemented. The most likely result of not having the appropriate module loaded or not having the interface exported to the top level is that NIL will be returned. It is also the result for INLINE procedures.
There are no plans for BugBane to interpret more than expressions.
Some type constructors are not supported.
AMTypes does not allow the construction of types on the fly, so BugBane does not support type constructors. This means that type constructors such as POINTER TO Foo cannot be interpreted. BugBane does treat types as expressions where possible, so type constructors such as FooDefs.FooPointer are legal (assuming that the symbols are available to BugBane). The difference is that with FooDefs.FooPointer sufficient information is passed from the compiler to the runtime to allow interpretation of the type.
Some unsafe constructs are not supported.
In particular: DESCRIPTOR constructors and overlaid record constructors. UNSPECIFIED and LONG UNSPECIFIED are discouraged, since they are both obsolete and buggy (CODE[LONG UNSPECIFIED] will crash the compiler, for example).
Although LOOPHOLE is supported, no checking for lengths is provided, so you can really do terrible things by typing the wrong thing. It is, of course, your machine.
Procedure type equivalence is only partially implemented.
While this is essentially an AMTypes problem, it does impact BugBane users. Procedure types must match exactly in order for a procedure to be an argument. If you can't get the interpreter to understand, use LOOPHOLE (sigh).
Remote debugging is a bit buggy.
We're working on it. It is not possible to pass ROPE or ATOM constants to remote procedures, for example. LIST, CONS, and NEW do not work for the remote world.
Context reporting is unreliable.
There are several parts to this problem.
1: The compiler performs certain optimizations, such as cross-jumping and constant folding, that keep the object code from being linearly related to the source code. This drawback will not be overcome for some time.
2: There is a long-standing bug in reporting locations inside of catch phrases.
3: Context reporting involving INLINE procedure and cross-jumped code is unreliable.
4: Due to a long-standing bug in the format of fine-grain tables, the source position of the last statement in a procedure is not known. Therefore, when setting breakpoints on the last statement, make sure that the selection points to the first character of the last statement.
The abstract machine has some rough spots.
This is a subset of the know problems.
1: The eval stack is not always empty between statements. If the value of a variable has been placed on the stack in one statement, it may be left on the stack for the next statement. Attempts to set that variable may not work for the latter statement.
2: It may not be possible to form the address of a variable that does not occupy a whole word.
3: The program counter used to report breakpoints may be wrong by 1, which may cause the previous statement to be reported as the location of the breakpoint.
VI. Recent changes
for Cedar 4.2
Remote debugging
Various bug fixes should improve remote debugging.
Bug fixes
Minor bug fixes only (particularly to octal commands).
Structural merge
The octal commands mentioned above are now a standard part of InterpreterPackage, which is a part of the boot file.
Additional features
Expressions of the form v[tag], where v is an overlaid or computed variant record and tag is the name of one of the variants, now coerce the record to be of the specified variant type.
for Cedar 4.1
Remote debugging
Remote debugging is supported through the use of DebugTool, a program by Andrew Birrell. Since this tool is in the boot file, previous methods of remote debugging are now inoperative. There have been significant bug fixes in this area, especially to remove problems when the remote world has been booted, and the use of interfaces.
Structural split
BugBane.bcd and BBV.bcd have been rearranged into BugBaneBelow (lower-level modules) and BugBaneAbove (higher-level modules). BugBaneBelow exports everything that BugBane used to export except BBObjectLocation, BBDisableBreaks, BBAction, BBBreak, BBFocus, and BBNub. BugBaneAbove exports everything that BBV used to export, plus the former BugBane interfaces not exported by BugBaneBelow. Most clients should not notice the difference.
Bug fixes
Performance has improved somewhat. A few minor bugs have been repaired. Error messages have been slightly improved.
Additional features
Array constructors, including ALL[expr], are supported. NEW[typeexpr] is supported. MAX[expr, ...] and MIN[expr, ...] are supported.
for Cedar 4.0
Remote debugging
Remote debugging is supported through the use of DebugTest, a program by Andrew Birrell. The Cedar debugger will be automatically set up if Cedar is installed on the CoPilot volume. To run the remote debugger in the Client volume, perform:
run AMProcessBasicImpl; run AMProcessImpl; run DebugTest
DebugTest RemoteMachineName
Bug fixes
Minor bug fixes only.
Additional features
Variant record constructors now work (positional notation only).
for Cedar 3.5
Remote debugging
Remote debugging is now supported, although the user interface is quite incomplete. Actions may now come from any enabled world. To start listening to a remote machine, evaluate BBNubImpl.FindWorld[name: name, new: TRUE], which will return a world (WorldVM.World) for the named machine. A new action should appear from that machine (if it is set up for remote debugging). Please note that invocation of remote procedures and some remote assignments (especially those involving allocation and reference-counting) are not yet allowed.
Bug fixes
Minor bug fixes only.
Restructuring
BBObjectLocation is now implemented through the AMModel. This interface will probably disappear completely in Cedar 4.0.
for Cedar 3.4
New approach to read-eval-print
Removing the default read-eval-print loop and the default error reporting provides greater separation between BugBane facilities and BugBane clients (the UserExec & BBV). The choice of whether to make a UserExec "stall" if it gets an error, to make it look at the new error, or to provide some other service is no longer dictated by the code of BugBane.
BBV provides default reporting of new actions (breakpoints & uncaught signals). The user is able to select the "current" action through the current menu interface. Facilities for displaying the current stack and actions are also provided.
The UserExec provides an work area (evaluator) for each action. A work area is a read-eval-print loop in the classic style. However, when a breakpoint or uncaught signal occurs for that evaluator other work areas may be spawned in response.
All of these user interfaces should be regarded as experimental.
Separation of printing
Printing of TVs and types has been unified under the control of the IO package maintainer (Warren Teitelman). The implementation no longer appears in BugBane. Russ Atkinson will assist in maintaining this package during the life of Cedar 3.4. However, Warren should be consulted about formatting.
New features
LOOPHOLE is now better supported. An implicit LOOPHOLE with a blank target now defaults to LONG CARDINAL as the target.
BBV provides better error messages. It now reports the source version its wanted if it can't get the right one.
Parsing has become a little faster. This is due to more cases handled by the quick-kill parser, and caching of intermediate storage by the long-winded parser.
The load state is used instead of the GFT to establish global frame search order. This provides true last-loaded-first-found search order. Caching of global frame searching is now substantially improved as well.
Non-started global frames can be found and manipulated much like started global frames.
It should now be possible to set breakpoints in viewers that view remote sources.
Coercion of REF opaque to REF concrete at procedure boundaries has been improved. Coercion of REF ANY variables to REF something values has also been improved. Coercion between opaque and concrete types is not otherwise supported.
Remote debugging
Most users should not see any changes from the BugBane changes in support of remote debugging. Remote debugging is still not supported in Cedar 3.4.
for Cedar 3.2
New features
LOOPHOLE is somewhat supported. Non-RC (reference containing) values of less than 3 words in length can be freely LOOPHOLEd based on the target type. Therefore, LOOPHOLE is only useful when constructing a procedure argument or assigning to a variable in either a global or local frame (not a debugger variable). Explicit types for LOOPHOLE are not yet supported..
Some octal debugging features have been added. In particular, Octal Read and Ascii Read are useful in attempting to examine variables..
BugBane now can access (through RTTypes) symbols files in the Cedar release that are not on the local disk. This access should only be noticable if the server is down or especially slow.
Bug fixes
Improvements have been made (and bugs fixed) in signal handling and reporting. In particular, features regarding catch frames should now work.
The infamous doubled breakpoint problem (where a breakpoint would immediately recur upon proceeding it) will not entirely disappear until the Trinity release of Pilot. The problem lies in the interaction between breakpoints and page faults. In the meantime, the code is touched immediately before proceeding the breakpoint to force it in.