| Allegro CL version 9.0 Significantly revised from 8.2. 8.2 version |
This document contains the following sections:
1.0 IntroductionThis 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 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.
This document specifies a set of functions that form the foundation for the debugger and inspector.
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
:function
: A compiled or
interpreted function application.
:eval
: The frame where evaluation of an
s-expression starts.
:interpreter
: An interpreter frame (for which
frame-interpreter-p is
true).
:binding
: The frame where
variable binding starts.
:catch
: Either an
interpreted or compiled catch frame.
:special-form
: The frame where
evaluation of a special operator starts (the frame name comes from the
old term for special operators).
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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.
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.
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.
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:
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:
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:
Arguments: frame-descriptor source continue-format-string args condition
The arguments of the function are as follows:
:break
, :error
,
:warn
, etc., depending upon where the break
originated.
nil
. If it is not null, then the rest of the arguments
to the break hook function are assumed to have the same meaning which
they would have to cerror. If
continue-format-string is nil
, then the error is not assumed to be continuable,
and args are processed as if they were passed in
from a break, error, or
warn. condition is the condition signaled.
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.
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.
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.
Arguments: &optional process visible-only-p
Compartibility note: in versions of this function prior to 9.0, visible-only-p was a keyword rather than an optional argument. Mixing optional and keyword arguments is a bad design choice which was not caught when this function was first implemented. For code specifying a value for that argument to run in both versions prior to 9.0 and in 9.0 and after, you can conditionalize the code s follows:
(db:oldest-frame process #-(version>= 9 0) :visible-only-p t)
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.
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.
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.
Arguments: frame-descriptor
This function returns the reference of frame called from frame frame-descriptor.
Arguments: frame-descriptor
This function returns the reference of frame which called frame frame-descriptor.
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
.
Arguments: frame-descriptor
This function returns the type of the frame frame-descriptor. The types of frames are:
:function
: A compiled or
interpreted function application.
:eval
: The frame where evaluation of an
s-expression starts.
:interpreter
: An interpreter frame (for which
frame-interpreter-p is
true).
:binding
: The frame where
variable binding starts.
:special-form
: The frame where
evaluation of a special operator starts (the frame name comes from the
old term for special operators).
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.
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.
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.
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.
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.
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:
:required
: a required parameter.:optional
: an optional parameter.:keyword
: a keyword parameter.:local
: a local variable allocated on
the frame.:rest
: a rest parameter.:extra-arg
: an argument in excess of the number
of allowed arguments (improperly) supplied to a function which does no
argument count checking.If the type cannot be determined, then a value of NONE is returned.
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.
Arguments: frame-descriptor
Returns the actual arguments passed the frame referred to by frame-descriptor.
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.
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.
Arguments: frame-descriptor
Returns non-nil
if frame-return will succeed if
applied to frame-descriptor.
Arguments: frame-descriptor
Returns non-nil
if frame-retry will succeed if
applied
to frame-descriptor.
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.
Arguments: frame-descriptor
Returns the formal parameter list for the frame corresponding to
frame-descriptor, or :unknown
if this cannot
be determined.
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.
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.htm), or if the source
cannot otherwise be determined, nil
is
returned.
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).
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.
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.
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.
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).
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).
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).
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.
Arguments: frame-descriptor
Returns the function object associated with frame frame-descriptor.
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.
Arguments: dest frame-descriptor &optional mode func-style output-function
Compartibility note: in versions of this function prior to 9.0, output-function was a keyword rather than an optional argument. Mixing optional and keyword arguments is a bad design choice which was not caught when this function was first implemented. For code specifying a value for that argument to run in both versions prior to 9.0 and in 9.0 and after, you can conditionalize the code s follows:
(db:output-frame dest frame-descriptor mode func-style #-(version>= 9 0) :output-function t)
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.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.
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.
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.
Arguments: frame-descriptor
Returns an environment struct as seen for frame reference frame-descriptor.
Arguments: environment
Returns a non-nil
value if and only if
environment is an environment struct.
Arguments: environment
Set the context for read-eval-in-context-print-loop. environment must be an environment struct. See get-context.
Arguments: environment
Get the context for read-eval-in-context-print-loop. environment must be an environment struct. See set-context.
Copyright (c) 1998-2019, Franz Inc. Oakland, CA., USA. All rights reserved.
This page has had significant revisions compared to the 8.2 page.
Created 2019.8.20.
| Allegro CL version 9.0 Significantly revised from 8.2. 8.2 version |