1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-07-03 16:20:39 +02:00

implement a silly debugger

* module/system/vm/debug.scm: Implement the skeleton of a debugger. Not
  very useful yet.

* module/system/repl/repl.scm (call-with-backtrace): Have the pre-unwind
  hook drop the user into the debugger. Hopefully we can have something
  better within a couple weeks.
This commit is contained in:
Andy Wingo 2009-12-22 23:38:06 +01:00
parent 0dfe0e7588
commit 1ad7fef524
2 changed files with 102 additions and 27 deletions

View file

@ -87,7 +87,7 @@
(catch #t (catch #t
(lambda () (%start-stack #t thunk)) (lambda () (%start-stack #t thunk))
default-catch-handler default-catch-handler
default-pre-unwind-handler)) debug-pre-unwind-handler))
(define-macro (with-backtrace form) (define-macro (with-backtrace form)
`(call-with-backtrace (lambda () ,form))) `(call-with-backtrace (lambda () ,form)))

View file

@ -23,39 +23,114 @@
#:use-module (system vm vm) #:use-module (system vm vm)
#:use-module (system vm frame) #:use-module (system vm frame)
#:use-module (ice-9 format) #:use-module (ice-9 format)
#:export (vm-debugger vm-backtrace)) #:export (run-debugger debug-pre-unwind-handler))
;;; ;;;
;;; Debugger ;;; Debugger
;;; ;;;
(define-record/keywords <debugger> vm chain index) (define-record <debugger> vm level breakpoints module)
(define (vm-debugger vm) (define (make-debugger-module)
(let ((chain (vm-last-frame-chain vm))) (let ((m (make-fresh-user-module)))
(if (null? chain) m))
(display "Nothing to debug\n")
(debugger-repl (make-debugger
#:vm vm #:chain chain #:index (length chain))))))
(define (debugger-repl db) (define vm-debugger
(let loop () (let ((prop (make-object-property)))
(display "debug> ") (lambda (vm)
(let ((cmd (read))) (or (prop vm)
(case cmd (let ((debugger (make-debugger vm (make-fluid) '() (make-debugger-module))))
((bt) (vm-backtrace (debugger-vm db))) (set! (prop vm) debugger)
((stack) debugger)))))
(write (vm-fetch-stack (debugger-vm db)))
(newline))
(else
(format #t "Unknown command: ~A" cmd))))))
(define* (run-debugger frame #:optional (vm (the-vm)))
;;; (let* ((db (vm-debugger vm))
;;; Backtrace (level (debugger-level db)))
;;; (with-fluids ((level (or (and=> (fluid-ref level) 1+) 0)))
(debugger-repl db frame))))
(define (vm-backtrace vm) (define (debugger-repl db frame)
(print-frame-chain-as-backtrace (let ((top frame))
(reverse (vm-last-frame-chain vm)))) (define (frame-index frame)
(let lp ((idx 0) (walk top))
(if (= (frame-return-address frame) (frame-return-address walk))
idx
(lp (1+ idx) (frame-previous walk)))))
(let loop ()
(let ((index (frame-index frame))
(level (fluid-ref (debugger-level db))))
(let ((cmd (repl-reader
(lambda ()
(format #f "debug[~a@~a]> " level index))
read)))
(if (not (or (eof-object? cmd)
(memq cmd '(q quit c continue))))
(begin
(case cmd
((bt)
(display-backtrace (make-stack frame) (current-output-port)))
((bindings)
(format #t "~a\n" (frame-bindings frame)))
((frame f)
(format #t "~s\n" frame))
((up)
(let ((prev (frame-previous frame)))
(if prev
(begin
(set! index (1+ index))
(set! frame prev)
(format #t "~s\n" frame))
(format #t "Already at outermost frame.\n"))))
((down)
(if (zero? index)
(format #t "Already at innermost frame.\n")
(begin
(set! frame (let lp ((n (1- index)) (frame top))
(if (zero? n)
frame
(lp (1- n) (frame-previous top)))))
(format #t "~s\n" frame))))
((help ?)
(format #t "Type `c' to continue.\n"))
(else
(format #t "Unknown command: ~A\n" cmd)))
(loop))))))))
;; things this debugger should do:
;;
;; eval expression in context of frame
;; up/down stack for inspecting
;; print procedure and args for frame
;; print local variables for frame
;; set local variable in frame
;; display backtrace
;; display full backtrace
;; 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
;; display a truncated backtrace
;; go to a frame by index
;; (reuse gdb commands perhaps)
;; help
;; disassemble a function
;; disassemble the current function
;; inspect any object
;; hm, trace via reassigning global vars. tricksy.
;; (state associated with vm ?)
(define (debug-pre-unwind-handler key . args)
;; herald
(format #t "Throw to key `~a' with args `~s'.
Entering the debugger. Type `bt' for a backtrace or `c' to continue.
This debugger implementation is temporary. See system/vm/debug.scm for
some ideas on how to make it better.\n" key args)
(run-debugger (stack-ref (make-stack #t) 1))
(save-stack 1)
(apply throw key args))