ToC DocOverview CGDoc RelNotes FAQ Index PermutedIndex
Allegro CL version 11.0

The Debugger API


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.html.) 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 applications.

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. Others 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 application using these functions, 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.

Many of the functions in this module take a frame-descriptor as an argument. For a variety of reasons, not everything that looks like a frame descriptor is actually valid. You can use frame-reference-eq. to test the validity of a frame descriptor. It is recommended you validate frame desciptors with that function prior to passing them to the various other functions.


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 :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: debug

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: debug

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: debug

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: debug

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: debug

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: debug

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 makes the internals of all packages visible.


unhide-functions

function, package: debug

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-frames

function, package: debug

Arguments: &rest types

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: debug

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: debug

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 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 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 descriptors

Stack frames are referred to by "frame descriptors" (also known as "frame references"), which are implemented as structs. Descriptors may be compared with frame-reference-eq. Descriptors must not be modified or generated inside of these functions. For all practical purposes, frame descriptors behave like pointers. A frame descriptor contains information identifying the process 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 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 be out of date because of compiler optimizations.


2.5 Distinguished values: unknown-p and none-p


unknown-p

function, package: debug

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 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: debug

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 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: debug

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: debug

Arguments: frame-descriptor

This function allows easy identification of "bogus" frame references. It returns a non-nil value if and only if frame-descriptor 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 frame-descriptor to reject pointers which are clearly wrong.


frame-reference-eq

function, package: debug

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: debug

Arguments: &optional process visible-only-p

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


newest-frame

function, package: debug

Arguments: &optional process visible-only-p

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


newest-break-frame

function, package: debug

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: debug

Arguments: frame-descriptor

This function returns the reference of frame called from frame frame-descriptor.


next-older-frame

function, package: debug

Arguments: frame-descriptor

This function returns the reference of frame which called frame frame-descriptor.


frame-name

function, package: debug

Arguments: frame-descriptor

This function returns the function name corresponding to frame frame-descriptor or NONE in the case of an anonymous lambda. If frame-descriptor is a binding frame, and a special operator can be associated with the frame (e.g. let, let*), then this function returns the name of the special operator. If frame-descriptor 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 returns 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.

If frame-descriptor points to an invalid frame, this function signals an error. You can check whether a frame is valid with frame-reference-p.


frame-type

function, package: debug

Arguments: frame-descriptor

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


frame-interpreter-p

function, package: debug

Arguments: frame-descriptor

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


frame-interp-env-p

function, package: debug

Arguments: frame-descriptor

Returns a non-nil value if and only if there exists an interpreted environment corresponding to frame-descriptor. 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: debug

Arguments: frame-descriptor

Returns the total number of variables in the frame referred to by frame-descriptor, 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-var-name, and frame-var-type.


frame-var-value

function, package: debug

Arguments: frame-descriptor n

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


frame-var-name

function, package: debug

Arguments: frame-descriptor n

Returns the name of variable n in stack frame frame-descriptor. 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: debug

Arguments: frame-descriptor n

Returns the "type" of a variable n in stack frame frame-descriptor. 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: debug

Arguments: frame-descriptor

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

If frame-descriptor points to an invalid frame, this function signals an error. You can check whether a frame is valid with frame-reference-p.


frame-get-actuals

function, package: debug

Arguments: frame-descriptor

Returns the actual arguments passed the frame referred to by frame-descriptor.

If frame-descriptor points to an invalid frame, this function signals an error. You can check whether a frame is valid with frame-reference-p.


frame-retry

function, package: debug

Arguments: frame-descriptor function &rest actuals

Retries the frame referred to by frame-descriptor, invoking the supplied function and using actuals as arguments. There is no default way to use the frame's existing arguments; to use the existing arguments, use frame-get-actuals to supply the current 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: debug

Arguments: frame-descriptor &rest values

This function returns one or more values from the frame referred to by frame-descriptor. 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 returns '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.

If frame-descriptor points to an invalid frame, this function signals an error. You can check whether a frame is valid with frame-reference-p.


frame-returnable-p

function, package: debug

Arguments: frame-descriptor

Returns non-nil if frame-return will succeed if applied to frame-descriptor. nil is returned if the frame is not valid (see frame-reference-p).


frame-retryable-p

function, package: debug

Arguments: frame-descriptor

Returns non-nil if frame-retry will succeed if applied to frame-descriptor. nil is returned if the frame is not valid (see frame-reference-p).


frame-context-p

function, package: debug

Arguments: frame-descriptor

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


frame-arglist

function, package: debug

Arguments: frame-descriptor

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


frame-number-actuals

function, package: debug

Arguments: frame-descriptor

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

If frame-descriptor points to an invalid frame, this function signals an error. You can check whether a frame is valid with frame-reference-p.


frame-source-code

function, package: debug

Arguments: frame-descriptor

This function tries to find the source for the function for the frame frame-descriptor, 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.html), or if the source cannot otherwise be determined, nil is returned.

If frame-descriptor points to an invalid frame, this function signals an error. You can check whether a frame is valid with frame-reference-p.


2.8 Top-level and debugger interface


debug-break-level

function, package: debug

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: debug

Arguments: &optional process n break-level

Pops control to the previous break or the top level of process process (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: debug

Arguments: &optional process

Unwinds the stack of process process (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: debug

Arguments: &optional process &rest args

Continues from the most recent error (which must be continuable) of process process (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: debug

Arguments: &optional process

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


most-recent-continuable-error-string

function, package: debug

Arguments: &optional process

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


error-continuable-p

function, package: debug

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 occurred (the current process, which is the value of *current-process*, if unsupplied).


read-eval-in-context-print-loop

function, package: debug

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: debug

Arguments: frame-descriptor

Returns the function object associated with frame frame-descriptor.

If frame-descriptor points to an invalid frame, this function signals an error. You can check whether a frame is valid with frame-reference-p.


frame-expression

function, package: debug

Arguments: frame-descriptor &key function

Returns a form that attempts to reproduce the call to frame frame-descriptor, 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.

If frame-descriptor points to an invalid frame, this function signals an error. You can check whether a frame is valid with frame-reference-p.


output-frame

function, package: debug

Arguments: dest frame-descriptor &optional mode func-style output-function

The return value is undefined; this function is called for its side effects. Prints a description of frame frame-descriptor 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.html).

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.

If frame-descriptor points to an invalid frame, this function signals an error. You can check whether a frame is valid with frame-reference-p.


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 environment in the descriptions below.


eval-form-in-context

function, package: debug

Arguments: form &optional environment

Evaluates form from within the context of environment environment.

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 value returned from the form is returned.


environment-of-frame

function, package: debug

Arguments: frame-descriptor

Returns an environment struct as seen for frame reference frame-descriptor.

If frame-descriptor points to an invalid frame, this function signals an error. You can check whether a frame is valid with frame-reference-p.


environment-p

function, package: debug

Arguments: environment

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


set-context

function, package: debug

Arguments: environment

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


get-context

function, package: debug

Arguments: environment

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



Copyright (c) Franz Inc. Lafayette, CA., USA. All rights reserved.

ToC DocOverview CGDoc RelNotes FAQ Index PermutedIndex
Allegro CL version 11.0