Next: , Up: The Debug-Info Structure   [Contents]


39.1.1 Debugger Interface

How does the debugger interface to the “evaluator” (where the evaluator means all of native code, byte-code and interpreted IR1)? It seems that it would be much more straightforward to have a consistent user interface to debugging all code representations if there was a uniform debugger interface to the underlying stuff, and vice-versa.

Of course, some operations might not be supported by some representations, etc. For example, fine-control stepping might not be available in native code. In other cases, we might reduce an operation to the lowest common denominator, for example fetching lexical variables by string and admitting the possibility of ambiguous matches. [Actually, it would probably be a good idea to store the package if we are going to allow variables to be closed over.]

Some objects we would need:

Location:
	The constant information about the place where a value is stored,
        everything but which particular frame it is in.  Operations:
        location name, type, etc.
        location-value frame location (setf'able)
	monitor-location location function
            Function is called whenever location is set with the location,
            frame and old value.  If active values aren't supported, then we
            dummy the effect using breakpoints, in which case the change won't
            be noticed until the end of the block (and intermediate changes
            will be lost.)
debug info:
        All the debug information for a component.
Frame:
	frame-changed-locations frame => location*
            Return a list of the locations in frame that were changed since the
            last time this function was called.  Or something.  This is for
            displaying interesting state changes at breakpoints.
	save-frame-state frame => frame-state
	restore-frame-state frame frame-state
	    These operations allow the debugger to back up evaluation, modulo
	    side-effects and non-local control transfers.  This copies and
	    restores all variables, temporaries, etc, local to the frame, and
	    also the current PC and dynamic environment (current catch, etc.)

	    At the time of the save, the frame must be for the running function
	    (not waiting for a call to return.)  When we restore, the frame
	    becomes current again, effectively exiting from any frames on top.
	    (Of course, frame must not already be exited.)
       
Thread:
        Representation of which stack to use, etc.
Block:
        What successors the block has, what calls there are in the block.
        (Don't need to know where calls are as long as we know called function,
        since can breakpoint at the function.)  Whether code in this block is
        wildly out of order due to being the result of loop-invariant
        optimization, etc.  Operations:
        block-successors block => code-location*
        block-forms block => (source-location code-location)*
            Return the corresponding source locations and code locations for
            all forms (and form fragments) in the block.

Next: Variable maps, Up: The Debug-Info Structure   [Contents]