[Openmcl-devel] debugger internals

Gary Byers gb at clozure.com
Fri Feb 13 12:18:27 UTC 2004

On Fri, 13 Feb 2004, Marco Baringer wrote:

> i'm trying to get the slime commands return-from-frame and
> restart-frame to work and i'm not understanding certain things about
> openmcl's debugger.

Much of the code in "ccl:lib;backtrace-lds.lisp" was originally
tied to MCL's GUI backtrace dialog (or at least was only called
from there), and the GUI backtrace dialog wasn't/isn't LLGPL'ed.

> 1) does anybody set *backtrace-dialogs*? (to my eyes it seems that
> unless someone somewhere sets this apply-in-nth-frame will never do
> anything)

It's never set.  If it were, it'd be be set on entry to a break loop
to indicate the range of stack frames that are valid as long as
control doesn't exit that context.

> 2) is the return value of ccl::%current-frame-ptr a valid value for
> FRAME in the various apply-in-frame, return-from-frame, etc. functions?

Yes.  Any stack address is word-aligned (on a byte address whose
low 2 bits are clear.)  It just so happens tha fixnums always
have their low 2 bits clear, so any stack address (including
those addresses that mark frame boundaries) can be represented
as fixnums.

> 3) if so, what needs to be done to make a frame restartable?

To "restart" a frame involves exiting it (unwinding all stacks until
they're at the point where the call ocurred) and returning to some
(magic) code which invokes a function in that dynamic context.

Exiting from an arbitrary point in a function is hard (for several
reasons); you basically want to pretend that the function returns
to a CATCH (that probably isn't really there) and THROW to that
CATCH's tag.  In order to simulate that, you have to "know" what
the dynamic state of the thread would look like at the point where
the frame was entered: what values were in non-volatile registers
at that time, what CATCH/UNWIND-PROTECTs were pending, what special
bindings were in effect, where all of the stack pointers pointed ...

Some of that information can be determined by walking around in
the stack.  CCL::%APPLY-IN-FRAME and friends tried to deduce the rest
of it by partially disassembling the machine code of the intervening
function(s).  If its model of what compiled code looked like was
entirely accurate, that might work.  I would be surprised if that
model is entirely accurate (and don't think that it ever was), but
a slightly inaccurate model wouldd work some (perhaps even most) of
the time.

I can understand how people might find APPLY-IN-FRAME and
RETURN-FROM-FRAME useful (the canonical case is to sort of fix &
continue a computation that'd take a long time to set up.); I hope
that people also understand that it's a brutal hack that's very hard
to maintain or reason about.  Native threads complicate things
still further: a function can be interrupted at basically any
instruction boundary, and that almost certainly violates some of
the assumptions that the function-analyzing code might be making
(i.e, special bindings may be half-made when the user hits ^C
and decides that it's time to exit from/re-execte some frame.

That makes me think that APPLY-IN-FRAME/RETURN-FROM-FRAME should
be viewed (if they worked) as last-resort things to try when
he alternative is less desirable than a possible crash (unless
this stuff its -very- accurate, crashing because of misinformation
is a strong possibility.)

> 4) how should i prepare the arguments for apply-in-frame? in other
> words, what functions do i need to call in order to be able to get a
> valid frame, fn, arglist values for that call? i'm assuming frame
> should be a value returned by %get-frame-ptr (or maybe
> %current-frame-ptr), fn can just be a regular function object, and
> arglist should be a list, however under these assumptions i get an
> error about ppc::opcode being on unknown type specifier (backtrace
> follows).
This is more mundane: the code should refer to ARCH::OPCODE instead

More information about the Openmcl-devel mailing list