BugBane - the Cedar Debugger Russ Atkinson January 26, 1983 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 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 may be more than the compiled langauge provides. constants -- fixed, float, rope, char, bool, atom 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 P[args] -- P is a procedure taking given arguments RT[args] -- a record constructor where RT is a record type LIST[exprs] -- only LIST OF REF ANY is supported X _ Y -- 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. Currently, the only way to stop a runaway process is to plant a breakpoint in it. The difficulty with simply stopping the process in its tracks 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 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: 1: 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. 2: 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). 3: 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. 4: the 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. 5: the current global frame The current 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 current global frame for each work area. IV. Current built-in procedures for debugging &ar[ptr,len] Ascii Read &fm[name] Find Matching (procs matching name) &or[ptr,len] Octal Read &orc[ptr,len] Octal Read Code &sob[gf,pc] Set Octal Break &soc[lf] Set Octal Context (to local frame) V. Shortfalls Performance is only moderately acceptable. Although there is substantial caching of results in RTTypes 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. Some constructs are particularly slow, selection from interface names being one of the most egregious. 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. Source to object mapping vs. fine-grain tables. 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. 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. This search is described in more detail in BugBane.doc. Opaque types are not well 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 routine that expects a REF concrete is to be passed a REF opaque. 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. Array constructors and SELECT expressions are not yet 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 not yet implemented, although record constructors are. LIST constructors are implemented, although 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. This should become better sometime around Cedar 3.5. Besides being slow, the most likely result of not having the appropriate module loaded is that NIL will be returned. This is also the symptom when the interface in question is not exported from a loaded configuration. It is also the result from other, less frequent, causes. There are no plans for BugBane to interpret more than expressions. Some type constructors are not supported. RTTypes 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" can not 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. Multiple processes are only lightly supported. There is no way to list the current processes, since they are not stopped in general. There is no way to stop a process or set of processes except by manually planting breakpoints. There is a strawman design to attack some of these issues, but there is no timetable yet for implementation. The general idea is to automatically plant breakpoints and wait for appropriate processes to stop. At least, that's the idea. There is a hack available for people who really need the equivalent of the CoPilot List Processes command. It is often unreliable, but could be useful. See Russ Atkinson for details. Procedure type equivalence is only partially implemented. While this is essentially an RTTypes 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 not yet implemented. We're working on it. The first release that supports remote debugging will probably be Cedar 4.0. Context reporting is unreliable. There are several parts to this problem. First, 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. Second, the program counter used in frames refers to where execution will proceed, not where the execution left the frame. Consider the following example: Example: PROC = { x: INT _ 1; {y: INT _ 2; Q[]}; x _ 2; }; If you have a breakpoint or error in Q when called from P, then during a backtrace of the stack you may be able to see the variable x, but not the variable y. This is because the program counter has advanced to the beginning of "x _ 2", and there is no variable y in that context. BugBane attempts to back up the program counter heuristically, but the heuristic used may fail for a number of reasons. VI. Recent user changes 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.