guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

New debugger


From: Andy Wingo
Subject: New debugger
Date: Tue, 29 Dec 2009 21:45:24 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.92 (gnu/linux)

Hey folks,

First off, happy solstice :) Hope all are well.

If you're following git, you might have noticed that if you get an
error, you're now dropped into a debugger, instead of getting a
backtrace at the console.

I don't know if this is the right default, but it sure is useful to have
a more hands-on treatment of the stack when you error. Currently you
can't do much -- only go up and down in the stack, print backtraces, and
local variables. But already this is better than a backtrace that always
abbreviates in the wrong place (Murphy's law and all) -- because you can
pass #:width to most of the commands to change the width at which
printouts are abbreviated.

Of course, we're still seeing the entire stack here, and subrs are not
on that stack. I hope to fix this next week. But given that, here's a
little tour...

    scheme@(guile-user)> (let ((a 10)) (/ a 0))
    Throw to key `numerical-overflow' with args `("/" "Numerical overflow" #f 
#f)'.
    Entering the debugger. Type `bt' for a backtrace or `c' to continue.

Here we do something that causes an error, and we're dropped into the
debugger. Pressing "c" continues, allowing the error to propagate as usual.

    0 debug> c
    ERROR: In procedure /:
    ERROR: Numerical overflow

OK let's do it again.

    scheme@(guile-user)> (let ((a 10)) (/ a 0))
    Throw to key `numerical-overflow' with args `("/" "Numerical overflow" #f 
#f)'.
    Entering the debugger. Type `bt' for a backtrace or `c' to continue.

Let's ask for a backtrace.

    0 debug> bt
    In ice-9/boot-9.scm:
     3496:  8 (top-repl)
     3519:  7 (#<program 94e97e0 at ice-9/boot-9.scm:3518:10 ()>)
    In system/repl/repl.scm:
      111:  6 (start-repl scheme)
       86:  5 (call-with-backtrace #<program 979b740 ()>)
       87:  4 (#<program 979b720 at system/repl/repl.scm:87:9 ()>)
      112:  3 (#<program 979b740 ()>)
      117:  2 (#<program 979b6f0 at system/repl/repl.scm:113:18 ()>)
    In system/vm/vm.scm:
       39:  1 (vm-load #<vm 93b3668> #<objcode 97a2fd0>)
    In current input:
        2:  0 (#<program 97a2fc0 at <unknown port>:2:0 ()>)

Of course as I mentioned about make-stack not doing anything, we get
loads of extraneous frames, but hey.

Incidentally, this backtrace implementation is written in Scheme :)

You can limit the backtrace length:

    0 debug> bt 1
    In current input:
        2:  0 (#<program 97a2fc0 at <unknown port>:2:0 ()>)

Or show your current frame, like in GDB:

    0 debug> frame
    #0  0x0000000e in (#<program 97a2fc0 at <unknown port>:2:0 ()>)

I wrote this format to look like GDB's, but in retrospect that's a
little silly. We should probably change it to look like a one-frame
backtrace.

You can ask for the local variables for any frame:

    0 debug> locals
    Local variables:
       0 a = 10

You can get help on any command, or on all commands:

    0 debug> help bt
    backtrace #:OPTIONAL COUNT #:KEY WIDTH FULL?(aliases: bt)
    Print a backtrace of all stack frames, or innermost COUNT frames.

Climbing up the stack...

    0 debug> up
    #1  0x00000011 in (vm-load #<vm 93b3668> #<objcode 97a2fd0>)
    1 debug> up
    #2  0x0000002d in (#<program 979b6f0 at system/repl/repl.scm:113:18 ()>)
    2 debug> locals
    No local variables.
    2 debug> up
    #3  0x0000001e in (#<program 979b740 ()>)
    3 debug> locals
    No local variables.
    3 debug> up
    #4  0x0000000d in (#<program 979b720 at system/repl/repl.scm:87:9 ()>)
    4 debug> locals
    No local variables.
    4 debug> up
    #5  0x00000017 in (call-with-backtrace #<program 979b740 ()>)
    5 debug> locals
    Local variables:
       0 thunk = #<program 979b740 ()>
    5 debug> up
    #6  0x000000bb in (start-repl scheme)
    6 debug> locals
    Local variables:
       0 lang = scheme
       1 repl = #<<repl> vm: #<vm 93b3668> language: #<<language> name: ...>
       2 status (boxed) = #f
       3 exp = (let ((a 10)) (/ a 0))
       4 t = #f

You can select frames by index as well.

    6 debug> 2
    #2  0x0000002d in (#<program 979b6f0 at system/repl/repl.scm:113:18 ()>)
    2 debug> 6
    #6  0x000000bb in (start-repl scheme)

That's pretty much all you can do at this point. It's still pretty weak,
but being able to do bt #:full? #t #:width 1000 is already quite useful.
Here's my TODO list regarding the debugger:

;; eval expression in context of frame
;; set local variable in frame
;; step until next instruction
;; step until next function call/return
;; step until return from frame
;; step until different source line
;; step until greater source line
;; watch expression
;; break on a function
;; remove breakpoints
;; set printing width
;; (reuse gdb commands perhaps)
;; disassemble a function
;; disassemble the current function
;; inspect any object

Thoughts? Should this thing be on by default? There should certainly be
a way to turn it off...

Cheers,

Andy
-- 
http://wingolog.org/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]