The Debugger API

The index for the Allegro CL Documentation is in index.htm. The documentation is described in introduction.htm.

This document contains the following sections:

1.0 Introduction
2.0 The dynamic interface specification
   2.1 Stack frames
   2.2 Stack frame filter
   2.3 Frame references
   2.4 Frame variables
   2.5 Distinguished values: unknown-p and none-p
   2.6 Transferring Control to the debugger: break-hook
   2.7 Frame interface functions
   2.8 Top-level and debugger interface
   2.9 Environment objects

1.0 Introduction

This document is based on a design document prepared by Hans Muller, Cris Perdue, Dave Morein, all (at the time they wrote it) of Sun Microsystems. Many of their suggestions have been included in the Allegro CL debugger.

This document describes many of the internals of the Allegro CL debugger. (The standard interface to the debugger is described in debugging.htm.) While most users will have no need to concern themselves with debugger internals, certain application writers may wish to make use of the information in this document to facilitate error handling and debugging in applictaions.

Note that the symbols naming functions, variables, etc. in this document do not have their own description pages. All relevant documentation is in this document. All symbols are in the debugger package (nicknamed debug. Some are present in any image that contains the debugger. Other are only present when (require :sundebug) is evaluated (loading the sundebug module). If you intend to use these functions, be sure to evaluate

>(require :sundebug)

If you are building an applictaion using these function, be sure the :sundebug is included.

2.0 The dynamic interface specification

This document specifies a set of functions that form the foundation for the debugger and inspector.

2.1 Stack frames

A frame in this specification represents an event in Lisp execution which is recorded on the stack. The function frame-type permits testing as to what a frame represents. The types of frames include

Binding frames corresponding to binding events which are not associated directly with function invocation. For example, interpretation of LET and LET* forms would be represented as binding frames. In-line lambda expressions, such as

((let ((x 2) (y 3)) (foo x y)))

are represented as as :binding frames.

The following frame interface functions apply to both compiled and interpreted function frames:

When a frame is passed in as an argument to one of these functions, the interpreted lexical environment of the frame is accessed if the frame represents the interpretation of an s-expression; otherwise, the compiled lexical environment of the frame is accessed.

2.2 Stack frame filter

The stack frame filter is a mechanism that can be used by the programmer to customize the presentation of the stack backtrace. The filter will elide frames based on frame type and, if the frame represents a function application, the function package or function name. Sometimes it is desirable to hide all of the functions in some package except a few important ones. An exception can be created by unhiding a function whose home package is hidden.

The top-level commands :hide and :unhide provide the user interface to frame filtering and use these functions.

The function frame-visible-p is used to determine if a frame is to be displayed or not.

hide-packages

Function

Package: debugger

Arguments: &rest package-names

This function makes the specified packages (the names are typically keywords) invisible, meaning they will not be displayed in stack backtraces (unless all frames are displayed, see the :all argument to :zoom). If no arguments are supplied then this function returns a list of all of the hidden packages.

hide-package-internals

Function

Package: debugger

Arguments: &rest package-names

Similar to hide-packages except this function makes internal symbols the specified packages (the names are typically keywords) invisible, rather than all symbols. If no arguments are supplied then this function returns a list of all of the hidden packages where internals are hidden.

hide-functions

Function

Package: debugger

Arguments: &rest functions

This function makes the specified functions invisible, meaning they will not be displayed in stack backtraces (unless all frames are displayed, see the :all argument to :zoom). If no arguments are supplied then this function returns a list of all of the hidden functions.

hide-frames

Function

Package: debugger

Arguments: &rest frame-types

This function makes the specified frame types invisible, meaning they will not be displayed in stack backtraces (unless all frames are displayed, see the :all argument to :zoom). See frame-type for a list of frame types. If no arguments are supplied then this function returns a list of all of the hidden frame-types.

unhide-packages

Function

Package: debugger

Arguments: &rest package-names

This function makes the specified packages visible, meaning they will be displayed in a backtrace even when it is not displaying all frames (see the :all argument to :zoom). If no arguments are supplied then this function makes all packages visible.

unhide-package-internals

Function

Package: debugger

Arguments: &rest package-names

Similar to unhide-packages except this function makes internal symbols the specified packages (the names are typically keywords) visible, rather than all symbols. If no arguments are supplied then this function make the internals of all packages visible.

unhide-functions

Function

Package: debugger

Arguments: &rest functions

This function makes the specified functions visible, meaning they will be displayed in a backtrace even when it is not displaying all frames (see the :all argument to :zoom). If no arguments are supplied then this function makes all functions visible.

unhide-frame-types

Function

Package: debugger

Arguments: &rest functions

This function makes the specified types of stack frames visible, meaning they will be displayed in a backtrace even when it is not displaying all frames (see the :all argument to :zoom). If no arguments are supplied then this function makes all types of stack frames. See frame-type for a list of frame types.

frame-visible-p

Function

Package: debugger

Arguments: frame

Returns true or nil as frame is visible (i.e. not hidden) or not (i.e. hidden). This function tests a frame with the following algorithm:

- If the frame-type for this frame is hidden then return NIL.
- If the frame-type for this frame is :function then
        - If this function has been hidden then return NIL
        - If (this function's package has been hidden AND
             this function has NOT been :unhidden) then return NIL
- Otherwise return T

frame-filter-hook

Function

Package: debugger

Arguments:

The window debugger must be informed whenever the filter (i.e. what is and is not hidden) parameters are changed so that it can update the backtrace display. This function returns the the function that is called after any change has been made to the frame filter parameters, i.e. when one of the hide- and unhide- (i.e hide-packages, hide-functions, hide-frames, unhide-packages, unhide-functions, and unhide-frames) functions has been called. The value returned by this function can can be changed with setf. The function returned by this function could be defined like this:

(my-frame-filter-hook name args)

Where name is a keyword that represents the hide/unhide filter function that was called and args is the list of arguments passed to the filter function.

2.3 Frame references

Stack frames are referred to by "frame references", which are implemented as structs. Reference may be compared with frame-reference-eq. References must not be modified or generated inside of these functions. For all practical purposes, frame references behave like pointers. A frame reference contains information identifying the stack group or thread it is referring to.

2.4 Frame variables

The term "variables" in this document includes both parameters and other local variables. Where an index argument is specified in frame variable access primitives, it is assumed to be zero-based. It is permissible to change the order by which parameters and other locals are accessed by frame-var-value. Frame variables are enumerated starting with with requireds, then optionals, then extra-args, then the rest arg, then keywords, then locals, which may also include closed-over variables. Whether a keyword is supplied or not depends on whether it was given as an argument.

Note that some variables may be shown but not bound, and the values of some variables may out of date because of compiler optimizations.

2.5 Distinguished values: unknown-p and none-p

unknown-p

Function

Package: debugger

Arguments: value

Some functions which return LISP values can possibly fail in such a way that it is known that the information requested is not retrievable. To cover this eventuality, this predicate and and none-p have been defined. In this document UNKNOWN refers to an implementation-specific value which indicates that the answer to a query made through one of the functions in this interface is unknown, but that it may exist. NONE refers to an implementation-specific value which indicates that the answer to a particular query does not exist. The actual values of UNKNOWN and NONE are never directly accessed or manipulated by debugger tools. Instead, their presence is detected using this predicate and none-p.

The functions which may return these values include:

none-p

Function

Package: debugger

Arguments: value

Some functions which return LISP values can possibly fail in such a way that it is known that the information requested is not retrievable. To cover this eventuality, this predicate and and unknown-p have been defined. In this document UNKNOWN refers to an implementation-specific value which indicates that the answer to a query made through one of the functions in this interface is unknown, but that it may exist. NONE refers to an implementation-specific value which indicates that the answer to a particular query does not exist. The actual values of UNKNOWN and NONE are never directly accessed or manipulated by debugger tools. Instead, their presence is detected using this predicate and unknown-p.

The functions which may return these values include:

2.6 Transferring Control to the debugger: break-hook

break-hook

Function

Package: debugger

Arguments:

The function break-hook returns the current value of the break hook variable (excl::*break-hook*), and (setf (break-hook) value) sets the break hook to value. The semantics of the break hook variable are:

The arguments of the function are as follows:

After gaining control, the debugger will adjust the state of its screen display, output the error message, output the continue message (for continuable errors), and then call excl::read-eval-print-loop (an internal function that implements the standard read-eval-print-loop) or read-eval-in-context-print-loop if it's available.

2.7 Frame interface functions

frame-reference-p

Function

Package: debugger

Arguments: r

This function allows easy identification of "bogus" frame references. It returns a non-nil value if and only if r refers to a LISP stack frame. If possible, this is an exact answer. If not possible, then this function at least performs some rudimentary range checking on r to reject pointers which are clearly wrong.

frame-reference-eq

Function

Package: debugger

Arguments: r1 r2

Returns non-nil if and only if the stack frame corresponding to r1 is the same as the stack frame corresponding to r2.

oldest-frame

Function

Package: debugger

Arguments: &optional stack-group&key visible-only-p

Returns a reference to the oldest frame on the stack corresponding to stack-group. If stack-group is not supplied, then it defaults to the stack group of the caller. If visible-only-p is true, the oldest frame that is not hidden is found.

newest-break-frame

Function

Package: debugger

Arguments: &optional stack-group

Returns a reference to the most recent break frame, that is, the frame which called the current invocation of the debugger in the stack corresponding to stack-group. If stack-group is not supplied, then it defaults to the stack group of the caller. This function, as well as oldest-frame, return valid results at any time after the break hook function object gains control.

next-newer-frame

Function

Package: debugger

Arguments: r

This function returns the reference of frame called from frame r.

next-older-frame

Function

Package: debugger

Arguments: r

This function returns the reference of frame which called frame r.

frame-name

Function

Package: debugger

Arguments: r

This function return the function name corresponding to frame r or NONE in the case of an anonymous lambda. If r is a binding frame, and a special form can be associated with the frame (e.g. let, let*), then this function returns the name of the special form. If r is an :eval frame, then if the expression being evaluated is a function application, then this function returns the name of the function (if any), or NONE in the case of an anonymous lambda. If the expression being evaluated is atomic, then return NONE.

If the function represents a runtime-system operation (an operation in the core or kernel of the lisp) then the name returned will be one of sys::..context-saving-runtime-operation, sys::..lisp-breakpoint-runtime-handler, or sys::..runtime-operation.

frame-type

Function

Package: debugger

Arguments: r

This function returns the type of the frame r. The types of frames are:

frame-interpreter-p

Function

Package: debugger

Arguments: r

Returns non-nil if and only if the frame referred to by r corresponds to part of the internal mechanism of the interpreter.

frame-interp-env-p

Function

Package: debugger

Arguments: r

Returns a non-nil value if and only if there exists an interpreted environment corresponding to r. This would normally be true for those :function frames which represent applications of interpreted functions, and for :binding frames which represent interpretation of let and similar forms.

frame-number-vars

Function

Package: debugger

Arguments: r

Returns the total number of variables in the frame referred to by r, including all parameters and other local variables. This function is used by the debugger to obtain a legal bound for parameter n in its calls to frame-get-var, frame-set-var, frame-var-name, and frame-var-type.

frame-var-value

Function

Package: debugger

Arguments: r n

Gets or sets with setf the value of variable number n in stack frame r. n refers to the variable number and could refer either to a parameter or to another local variable.

frame-var-name

Function

Package: debugger

Arguments: r n

Returns the name of variable n in stack frame r. If variable n has no name, then a value which satisfies NONE-P is returned. If variable n is known to have a name, but it cannot be retrieved, then a value which satisfies UNKNOWN-P is returned.

frame-var-type

Function

Package: debugger

Arguments: r n

Returns the "type" of a variable n in stack frame r. The set of variable types expected, with associated meanings is:

If the type cannot be determined, then a value of NONE is returned.

eval-frame-expr

Function

Package: debugger

Arguments: r

This function returns the expression being evaluated by the interpreter in the frame corresponding to r, which must be an :eval frame.

frame-retry

Function

Package: debugger

Arguments: r function &optional actuals

Retries the frame referred to by r by using either supplied function and the frame's existing actual arguments, or, if actuals is supplied, by using actuals as the actual arguments. If unable to retry the frame, then a value of nil is returned. Note that the function referenced in the frame is not looked at.

frame-return

Function

Package: debugger

Arguments: r &rest values

This function returns one or more values from the frame referred to by r. The form of the command is

(frame-return frame value1 value2 ... valuen)

If function A calls B with args C and D,

(defun A (x y) ... (B C D) ...)

and breaks, we would like to say

(frame-return "B" 'E))

This cuts the stack back to "B" and return 'E to the caller of "B" [in this case, to "A"] If this function fails, it returns 2 values: nil and an error message which explains why it failed. Note: the error message is not output, just returned.

frame-returnable-p

Function

Package: debugger

Arguments: r

Returns non-nil if frame-return will succeed if applied to r.

frame-retryable-p

Function

Package: debugger

Arguments: r

Returns non-nil if frame-retry will succeed if applied to r.

frame-context-p

Function

Package: debugger

Arguments: r

Returns non-nil if and only if the frame referred to by r is a valid context for eval-form-in-context.

frame-arglist

Function

Package: debugger

Arguments: r

Returns the formal parameter list for the frame corresponding to r, or :unknown if this cannot be determined.

frame-number-actuals

Function

Package: debugger

Arguments: r

Returns a best-guess at the list of actual arguments to the function frame corresponding to r. It may be wrong in that optional arguments which weren't passed in by the user will be returned.

frame-source-code

Function

Package: debugger

Arguments: r

This function tries to find the source for the function for the frame r, reading the source file and returning a copy of the source as its value. If source-file recording is not turned on (see source-file-recording.htm), or if the source cannot otherwise be determined, nil is returned.

2.8 Top-level and debugger interface

debug-break-level

Function

Package: debugger

Arguments: &optional process

Returns the current debugger break level of process (the current process, which is the value of *current-process*, if unsupplied). Break level 0 corresponds to normal operation (no break).

debug-pop

Function

Package: debugger

Arguments: &optional p n break-level

Pops control to the previous break or the top level of process p (the current process, which is the value of *current-process*, if unsupplied). If n is specified and greater than 1, then multiple levels are popped. In case of an error, this routine returns nil, although, if it returns at all, something has to be wrong. This function returns nil if an attempt was made to pop past the top-level.

break-level is the number of break-levels in the process to be popped from. If not given, it is calculated. When break-level is one (the target process is at break-level 0) a process-reset is done instead of a debug-pop on that process.

debug-reset

Function

Package: debugger

Arguments: &optional p

Unwinds the stack of process p (the current process, which is the value of *current-process*, if unsupplied) to top-level. Returns nil and an error message string in the case of an unrecoverable error.

debug-continue

Function

Package: debugger

Arguments: &optional p &rest args

Continues from the most recent error (which must be continuable) of process p (the current process, which is the value of *current-process*, if unsupplied). Returns the values nil and an error message string if the error cannot be continued.

most-recent-error-string

Function

Package: debugger

Arguments: &optional p

Returns a string that corresponds to the message output by error. p is the process where the error occured (the current process, which is the value of *current-process*, if unsupplied).

most-recent-continuable-error-string

Function

Package: debugger

Arguments: &optional p

returns the message that was generated from the continue-format-string to cerror argument (if any). p is the process where the error occured (the current process, which is the value of *current-process*, if unsupplied).

error-continuable-p

Function

Package: debugger

Arguments: &optional process

Returns non-nil if and only if there is a "most recent error", and it is continuable. This function could be defined like this:

(defun error-continuable-p () 
   (most-recent-continuable-error-string))

process is the process where the error occured (the current process, which is the value of *current-process*, if unsupplied).

read-eval-in-context-print-loop

Function

Package: debugger

Arguments:

Similar to excl::read-eval-print-loop, this function evaluates with respect to an environment. The environment is set separately via the set-context function.

frame-function

Function

Package: debugger

Arguments: r

Returns the function object associated with frame r.

frame-expression

Function

Package: debugger

Arguments: r &key function

Returns a form that attempts to reproduce the call to frame r, if possible. Some of the elements of the form may contain unknowns if argument saving is turned off. If function is true, then a funcall-style form is returned, using the actual function object instead of trying to use its name in a normal lisp function call.

output-frame

Function

Package: debugger

Arguments: dest r &optional mode func-style&key output-function

The return value is undefined; this function is called for its side effects. Prints a description of frame r in the desired mode to the stream dest. dest is a stream suitable as the :stream argument to write.

mode may be :brief, :moderate, or :verbose (see :brief, :moderate, and :verbose modes of :zoom in debugging.htm).

If output-function is supplied, it must be a function of two arguments; the object that is being written, and the destination. The output-function is used only for brief or moderate modes; it is not used for verbose mode.

If func-style is non-nil, then the function object is used instead of the name of the function.

2.9 Environment objects

Where environment structs are returned by dynamic interface functions, the bindings shown are the current value of the bindings established by the frame which was passed in as an argument. An environment struct contains all necessary information to identify these bindings, possibly including CLtL2-style augmentable environment objects. An environment struct is denoted by e in the descriptions below.

eval-form-in-context

Function

Package: debugger

Arguments: form &optional e

Evaluates form from within the context of environment e.

If the environment struct includes a compiled function's frame, then the compiled environment includes bindings for any variables whose names can be determined from local name info, or else dummy names are generated to identify each variable in the compiled function. An attempt is made to match the variable names within a compiled function to the names given to those variables by the disassembler.

If the environment struct contains an interpreted environment, then its bindings are used as well. If the form performs a setf or setq, the environment is changed if possible to reflect the setf or setq.

After the form is evaluated, the environments are restored, and the return from the form is returned.

environment-of-frame

Function

Package: debugger

Arguments: r

Returns an environment struct as seen for frame reference r.

environment-p

Function

Package: debugger

Arguments: e

Returns a non-nil value if and only if e is an environment struct.

set-context

Function

Package: debugger

Arguments: e

Set the context for read-eval-in-context-print-loop. e must be an environment struct. See get-context.

get-context

Function

Package: debugger

Arguments: e

Get the context for read-eval-in-context-print-loop. e must be an environment struct. See set-context.

Copyright (c) 1998-2000, Franz Inc. Berkeley, CA., USA. All rights reserved. Created 2000.10.5.