The debugger programmers interface is exported from from the
DEBUG-INTERNALS or DI package. This is a CMU
extension that allows debugging tools to be written without detailed
knowledge of the compiler or run-time system.
Some of the interface routines take a code-location as an argument. As
described in the section on code-locations, some code-locations are
unknown. When a function calls for a basic-code-location, it
takes either type, but when it specifically names the argument
code-location, the routine will signal an error if you give it an
unknown code-location.
11.1 |
DI Exceptional Conditions |
|
Some of these operations fail depending on the availability debugging
information. In the most severe case, when someone saved a Lisp image
stripping all debugging data structures, no operations are valid. In
this case, even backtracing and finding frames is impossible. Some
interfaces can simply return values indicating the lack of information,
or their return values are naturally meaningful in light missing data.
Other routines, as documented below, will signal
serious-conditions when they discover awkward situations. This
interface does not provide for programs to detect these situations other
than by calling a routine that detects them and signals a condition.
These are serious-conditions because the program using the interface
must handle them before it can correctly continue execution. These
debugging conditions are not errors since it is no fault of the
programmers that the conditions occur.
The debug internals interface signals conditions when it can't adhere
to its contract. These are serious-conditions because the program
using the interface must handle them before it can correctly continue
execution. These debugging conditions are not errors since it is no
fault of the programmers that the conditions occur. The interface
does not provide for programs to detect these situations other than
calling a routine that detects them and signals a condition.
[Condition]
debug-condition
This condition inherits from serious-condition, and all debug-conditions
inherit from this. These must be handled, but they are not programmer errors.
[Condition]
no-debug-info
This condition indicates there is absolutely no debugging information
available.
[Condition]
no-debug-function-returns
This condition indicates the system cannot return values from a frame since
its debug-function lacks debug information details about returning values.
[Condition]
no-debug-blocks
This condition indicates that a function was not compiled with debug-block
information, but this information is necessary necessary for some requested
operation.
[Condition]
no-debug-variables
Similar to no-debug-blocks, except that variable information was
requested.
[Condition]
lambda-list-unavailable
Similar to no-debug-blocks, except that lambda list information was
requested.
[Condition]
invalid-value
This condition indicates a debug-variable has :invalid or :unknown
value in a particular frame.
[Condition]
ambiguous-variable-name
This condition indicates a user supplied debug-variable name identifies more
than one valid variable in a particular frame.
These are programmer errors resulting from misuse of the debugging tools'
programmers' interface. You could have avoided an occurrence of one of these
by using some routine to check the use of the routine generating the error.
[Condition]
debug-error
This condition inherits from error, and all user programming errors inherit
from this condition.
[Condition]
unhandled-condition
This error results from a signalled debug-condition occurring
without anyone handling it.
[Condition]
unknown-code-location
This error indicates the invalid use of an unknown-code-location.
[Condition]
unknown-debug-variable
This error indicates an attempt to use a debug-variable in conjunction with an
inappropriate debug-function; for example, checking the variable's validity
using a code-location in the wrong debug-function will signal this error.
[Condition]
frame-function-mismatch
This error indicates you called a function returned by
preprocess-for-eval
on a frame other than the one for which the function had been prepared.
Debug-variables represent the constant information about where the system
stores argument and local variable values. The system uniquely identifies with
an integer every instance of a variable with a particular name and package. To
access a value, you must supply the frame along with the debug-variable since
these are particular to a function, not every instance of a variable on the
stack.
[Function]
debug-variable-name debug-variable
This function returns the name of the debug-variable. The
name is the name of the symbol used as an identifier when writing
the code.
[Function]
debug-variable-package debug-variable
This function returns the package name of the debug-variable.
This is the package name of the symbol used as an identifier when
writing the code.
[Function]
debug-variable-symbol debug-variable
This function returns the symbol from interning
debug-variable-name in the package named by
debug-variable-package.
[Function]
debug-variable-id debug-variable
This function returns the integer that makes debug-variable's
name and package name unique with respect to other
debug-variable's in the same function.
[Function]
debug-variable-validity debug-variable basic-code-location
This function returns three values reflecting the validity of
debug-variable's value at basic-code-location:
-
:valid
- The value is known to be available.
- :invalid
- The value is known to be unavailable.
- :unknown
- The value's availability is unknown.
[Function]
debug-variable-value debug-variable
frame
This function returns the value stored for debug-variable in
frame. The value may be invalid. This is SETF'able.
[Function]
debug-variable-valid-value debug-variable frame
This function returns the value stored for debug-variable in
frame. If the value is not :valid, then this signals an
invalid-value error.
Frames describe a particular call on the stack for a particular thread. This
is the environment for name resolution, getting arguments and locals, and
returning values. The stack conceptually grows up, so the top of the stack is
the most recently called function.
top-frame, frame-down, frame-up, and
frame-debug-function can only fail when there is absolutely no
debug information available. This can only happen when someone saved a
Lisp image specifying that the system dump all debugging data.
[Function]
top-frame
This function never returns the frame for itself, always the frame
before calling top-frame.
[Function]
frame-down frame
This returns the frame immediately below frame on the stack.
When frame is the bottom of the stack, this returns nil.
[Function]
frame-up frame
This returns the frame immediately above frame on the stack.
When frame is the top of the stack, this returns nil.
[Function]
frame-debug-function frame
This function returns the debug-function for the function whose call
frame represents.
[Function]
frame-code-location frame
This function returns the code-location where frame's
debug-function will continue running when program execution returns
to frame. If someone interrupted this frame, the result could
be an unknown code-location.
[Function]
frame-catches frame
This function returns an a-list for all active catches in
frame mapping catch tags to the code-locations at which the
catch re-enters.
[Function]
eval-in-frame frame form
This evaluates form in frame's environment. This can
signal several different debug-conditions since its success relies
on a variety of inexact debug information: invalid-value,
ambiguous-variable-name, frame-function-mismatch. See
also preprocess-for-eval.
Debug-functions represent the static information about a function determined at
compile time---argument and variable storage, their lifetime information,
etc. The debug-function also contains all the debug-blocks representing
basic-blocks of code, and these contains information about specific
code-locations in a debug-function.
[Macro]
do-debug-function-blocks (block-var debug-function {result-form})
{form}*
This executes the forms in a context with block-var bound to
each debug-block in debug-function successively.
Result-form is an optional form to execute for a return value,
and do-debug-function-blocks returns nilif there is no
result-form. This signals a no-debug-blocks condition
when the debug-function lacks debug-block information.
[Function]
debug-function-lambda-list debug-function
This function returns a list representing the lambda-list for
debug-function. The list has the following structure:
(required-var1 required-var2
...
(:optional var3 suppliedp-var4)
(:optional var5)
...
(:rest var6) (:rest var7)
...
(:keyword keyword-symbol var8 suppliedp-var9)
(:keyword keyword-symbol var10)
...
)
Each varn is a debug-variable; however, the symbol
:deleted appears instead whenever the argument remains
unreferenced throughout debug-function.
If there is no lambda-list information, this signals a
lambda-list-unavailable condition.
[Macro]
do-debug-function-variables (var debug-function {result})
{form}*
This macro executes each form in a context with var
bound to each debug-variable in debug-function. This returns
the value of executing result (defaults to nil). This may
iterate over only some of debug-function's variables or none
depending on debug policy; for example, possibly the compilation
only preserved argument information.
[Function]
debug-variable-info-available debug-function
This function returns whether there is any variable information for
debug-function. This is useful for distinguishing whether
there were no locals in a function or whether there was no variable
information. For example, if do-debug-function-variables
executes its forms zero times, then you can use this function to
determine the reason.
[Function]
debug-function-symbol-variables debug-function symbol
This function returns a list of debug-variables in
debug-function having the same name and package as
symbol. If symbol is uninterned, then this returns a
list of debug-variables without package names and with the same name
as symbol. The result of this function is limited to the
availability of variable information in debug-function; for
example, possibly debug-function only knows about its
arguments.
[Function]
ambiguous-debug-variables debug-function name-prefix-string
This function returns a list of debug-variables in
debug-function whose names contain name-prefix-string as
an initial substring. The result of this function is limited to the
availability of variable information in debug-function; for
example, possibly debug-function only knows about its
arguments.
[Function]
preprocess-for-eval form basic-code-location
This function returns a function of one argument that evaluates
form in the lexical context of basic-code-location.
This allows efficient repeated evaluation of form at a certain
place in a function which could be useful for conditional breaking.
This signals a no-debug-variables condition when the
code-location's debug-function has no debug-variable information
available. The returned function takes a frame as an argument. See
also eval-in-frame.
[Function]
function-debug-function function
This function returns a debug-function that represents debug
information for function.
[Function]
debug-function-kind debug-function
This function returns the kind of function debug-function
represents. The value is one of the following:
-
:optional
- This kind of function is an entry point to an
ordinary function. It handles optional defaulting, parsing
keywords, etc.
- :external
- This kind of function is an entry point to an
ordinary function. It checks argument values and count and calls
the defined function.
- :top-level
- This kind of function executes one or more
random top-level forms from a file.
- :cleanup
- This kind of function represents the cleanup
forms in an unwind-protect.
- nil
- This kind of function is not one of the above; that is,
it is not specially marked in any way.
[Function]
debug-function-function debug-function
This function returns the Common Lisp function associated with the
debug-function. This returns nil if the function is
unavailable or is non-existent as a user callable function object.
[Function]
debug-function-name debug-function
This function returns the name of the function represented by
debug-function. This may be a string or a cons; do not assume
it is a symbol.
Debug-blocks contain information pertinent to a specific range of code in a
debug-function.
[Macro]
do-debug-block-locations (code-var debug-block {result})
{form}*
This macro executes each form in a context with code-var
bound to each code-location in debug-block. This returns the
value of executing result (defaults to nil).
[Function]
debug-block-successors debug-block
This function returns the list of possible code-locations where
execution may continue when the basic-block represented by
debug-block completes its execution.
[Function]
debug-block-elsewhere-p debug-block
This function returns whether debug-block represents elsewhere
code. This is code the compiler has moved out of a function's code
sequence for optimization reasons. Code-locations in these blocks
are unsuitable for stepping tools, and the first code-location has
nothing to do with a normal starting location for the block.
A breakpoint represents a function the system calls with the current frame when
execution passes a certain code-location. A break point is active or inactive
independent of its existence. They also have an extra slot for users to tag
the breakpoint with information.
[Function]
make-breakpoint hook-function what &key :kind :info
:function-end-cookie
This function creates and returns a breakpoint. When program
execution encounters the breakpoint, the system calls
hook-function. hook-function takes the current frame
for the function in which the program is running and the breakpoint
object.
what and kind determine where in a function the system
invokes hook-function. what is either a code-location
or a debug-function. kind is one of :code-location,
:function-start, or :function-end. Since the starts and
ends of functions may not have code-locations representing them,
designate these places by supplying what as a debug-function
and kind indicating the :function-start or
:function-end. When what is a debug-function and
kind is :function-end, then hook-function must take two
additional arguments, a list of values returned by the function and
a function-end-cookie.
info is information supplied by and used by the user.
function-end-cookie is a function. To implement function-end
breakpoints, the system uses starter breakpoints to establish the
function-end breakpoint for each invocation of the function. Upon
each entry, the system creates a unique cookie to identify the
invocation, and when the user supplies a function for this argument,
the system invokes it on the cookie. The system later invokes the
function-end breakpoint hook on the same cookie. The user may save
the cookie when passed to the function-end-cookie function for later
comparison in the hook function.
This signals an error if what is an unknown code-location.
Note: Breakpoints in interpreted code or byte-compiled code are
not implemented. Function-end breakpoints are not implemented for
compiled functions that use the known local return convention
(e.g. for block-compiled or self-recursive functions.)
[Function]
activate-breakpoint breakpoint
This function causes the system to invoke the breakpoint's
hook-function until the next call to deactivate-breakpoint or
delete-breakpoint. The system invokes breakpoint hook
functions in the opposite order that you activate them.
[Function]
deactivate-breakpoint breakpoint
This function stops the system from invoking the breakpoint's
hook-function.
[Function]
breakpoint-active-p breakpoint
This returns whether breakpoint is currently active.
[Function]
breakpoint-hook-function breakpoint
This function returns the breakpoint's function the system
calls when execution encounters breakpoint, and it is active.
This is SETF'able.
[Function]
breakpoint-info breakpoint
This function returns breakpoint's information supplied by the
user. This is SETF'able.
[Function]
breakpoint-kind breakpoint
This function returns the breakpoint's kind specification.
[Function]
breakpoint-what breakpoint
This function returns the breakpoint's what specification.
[Function]
delete-breakpoint breakpoint
This function frees system storage and removes computational
overhead associated with breakpoint. After calling this,
breakpoint is useless and can never become active again.
Code-locations represent places in functions where the system has correct
information about the function's environment and where interesting operations
can occur---asking for a local variable's value, setting breakpoints,
evaluating forms within the function's environment, etc.
Sometimes the interface returns unknown code-locations. These
represent places in functions, but there is no debug information
associated with them. Some operations accept these since they may
succeed even with missing debug data. These operations' argument is
named basic-code-location indicating they take known and unknown
code-locations. If an operation names its argument
code-location, and you supply an unknown one, it will signal an
error. For example, frame-code-location may return an unknown
code-location if someone interrupted Lisp in the given frame. The
system knows where execution will continue, but this place in the code
may not be a place for which the compiler dumped debug information.
[Function]
code-location-debug-function basic-code-location
This function returns the debug-function representing information
about the function corresponding to the code-location.
[Function]
code-location-debug-block basic-code-location
This function returns the debug-block containing code-location if it
is available. Some debug policies inhibit debug-block information,
and if none is available, then this signals a no-debug-blocks
condition.
[Function]
code-location-top-level-form-offset code-location
This function returns the number of top-level forms before the one
containing code-location as seen by the compiler in some
compilation unit. A compilation unit is not necessarily a single
file, see the section on debug-sources.
[Function]
code-location-form-number code-location
This function returns the number of the form corresponding to
code-location. The form number is derived by walking the
subforms of a top-level form in depth-first order. While walking
the top-level form, count one in depth-first order for each subform
that is a cons. See form-number-translations.
[Function]
code-location-debug-source code-location
This function returns code-location's debug-source.
[Function]
code-location-unknown-p basic-code-location
This function returns whether basic-code-location is unknown.
It returns nil when the code-location is known.
[Function]
code-location= code-location1
code-location2
This function returns whether the two code-locations are the same.
Debug-sources represent how to get back the source for some code. The
source is either a file (compile-file or load), a
lambda-expression (compile, defun, defmacro), or
a stream (something particular to CMUCL, compile-from-stream).
When compiling a source, the compiler counts each top-level form it
processes, but when the compiler handles multiple files as one block
compilation, the top-level form count continues past file boundaries.
Therefore code-location-top-level-form-offset returns an offset
that does not always start at zero for the code-location's
debug-source. The offset into a particular source is
code-location-top-level-form-offset minus
debug-source-root-number.
Inside a top-level form, a code-location's form number indicates the
subform corresponding to the code-location.
[Function]
debug-source-from debug-source
This function returns an indication of the type of source. The
following are the possible values:
-
:file
- from a file (obtained by compile-file if
compiled).
- :lisp
- from Lisp (obtained by compile if
compiled).
- :stream
- from a non-file stream (CMUCL supports
compile-from-stream).
[Function]
debug-source-name debug-source
This function returns the actual source in some sense represented by
debug-source, which is related to debug-source-from:
-
:file
- the pathname of the file.
- :lisp
- a lambda-expression.
- :stream
- some descriptive string that's otherwise
useless.
[Function]
debug-source-created debug-source
This function returns the universal time someone created the source.
This may be nil if it is unavailable.
[Function]
debug-source-compiled debug-source
This function returns the time someone compiled the source. This is
nil if the source is uncompiled.
[Function]
debug-source-root-number debug-source
This returns the number of top-level forms processed by the compiler
before compiling this source. If this source is uncompiled, this is
zero. This may be zero even if the source is compiled since the
first form in the first file compiled in one compilation, for
example, must have a root number of zero---the compiler saw no other
top-level forms before it.
11.9 |
Source Translation Utilities |
|
These two functions provide a mechanism for converting the rather
obscure (but highly compact) representation of source locations into an
actual source form:
[Function]
debug-source-start-positions debug-source
This function returns the file position of each top-level form as a
vector if debug-source is from a :file. If
debug-source-from is :lisp or :stream, or the file
is byte-compiled, then the result is nil.
[Function]
form-number-translations form
tlf-number
This function returns a table mapping form numbers (see
code-location-form-number) to source-paths. A source-path
indicates a descent into the top-level-form form, going
directly to the subform corresponding to a form number.
tlf-number is the top-level-form number of form.
[Function]
source-path-context form path context
This function returns the subform of form indicated by the
source-path. Form is a top-level form, and path is a
source-path into it. Context is the number of enclosing forms
to return instead of directly returning the source-path form. When
context is non-zero, the form returned contains a marker,
#:****HERE****, immediately before the form indicated by
path.