From 55ba706ac509b215da17b3b0ce775795e5b5ed62 Mon Sep 17 00:00:00 2001 From: Nikodemus Siivola Date: Wed, 1 Dec 2004 14:14:23 +0000 Subject: [PATCH] 0.8.17.8: x86 backtraces * fixed bug #345: don't set the escaped flag to NIL on x86 in COMPUTE-CALLING FRAME if we have no code from FIND-ESCAPED-FRAME. Add tag-bytes to undefined_tramp and closure_tramp on x86 like others. * partial fix for #61: instead of throwing no-debug-info conditions, return a "no debug information for frame" bogus-debug-fun from debug-fun-from-pc. * Two new BUGS entries about backtraces. * Tests. (debug.impure.lisp now passes on sparc as well, but only because one test now axxepts the XEP in lieu of the function on sparc and x86. --- BUGS | 36 +++++++++++++++++++++------------- NEWS | 3 +++ src/code/debug-int.lisp | 27 +++++++------------------- src/runtime/x86-assem.S | 2 ++ tests/debug.impure.lisp | 49 ++++++++++++++++++++++++++++++----------------- version.lisp-expr | 2 +- 6 files changed, 67 insertions(+), 52 deletions(-) diff --git a/BUGS b/BUGS index 729da42..d5271f0 100644 --- a/BUGS +++ b/BUGS @@ -167,11 +167,11 @@ WORKAROUND: then requesting a BACKTRACE at the debugger prompt gives no information about where in the user program the problem occurred. - (this is apparently mostly fixed on the SPARC and PPC architectures: - while giving the backtrace the system complains about "unknown + (this is apparently mostly fixed on the SPARC, PPC, and x86 architectures: + while giving the backtrace the non-x86 systems complains about "unknown source location: using block start", but apart from that the - backtrace seems reasonable. See tests/debug.impure.lisp for a test - case) + backtrace seems reasonable. On x86 this is masked by bug 353. See + tests/debug.impure.lisp for a test case) 64: Using the pretty-printer from the command prompt gives funny @@ -1529,15 +1529,6 @@ WORKAROUND: (Note: there's at least one dubious thing in room.lisp: see the comment in VALID-OBJ) -345: backtrace on x86 undefined function - In sbcl-0.8.13 (and probably earlier versions), code of the form - (flet ((test () (#:undefined-fun 42))) - (funcall #'test)) - yields the debugger with a poorly-functioning backtrace. Brian - Downing fixed most of the problems on non-x86 architectures, but on - the x86 the backtrace from this evaluation does not reveal anything - about the problem. (See tests in debug.impure.lisp) - 346: alpha backtrace In sbcl-0.8.13, all backtraces from errors caused by internal errors on the alpha seem to have a "bogus stack frame". @@ -1578,3 +1569,22 @@ WORKAROUND: While computing the class precedence list of the class named C. The class named B is a forward referenced class. The class named B is a direct superclass of the class named C. + +353: debugger suboptimalities on x86 + On x86 backtraces for undefined functions start with a bogus stack + frame, and backtraces for throws to unknown catch tags with a "no + debug information" frame. These are both due to CODE-COMPONENT-FROM-BITS + (used on non-x86 platforms) being a more complete solution then what + is done on x86. + + More generally, the debugger internals suffer from excessive x86/non-x86 + conditionalization and OAOOMization: refactoring the common parts would + be good. + +354: XEPs in backtraces + Under default compilation policy + (defun test () + (throw :unknown t)) + (test) + Has the XEP for TEST in the backtrace, not the TEST frame itself. + (sparc and x86 at least) diff --git a/NEWS b/NEWS index bdc5339..3aabb52 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ changes in sbcl-0.8.18 relative to sbcl-0.8.17: supported. (thanks to Dan Debertin) * fixed bug #331: structure-class instances corresponding to DEFSTRUCT forms are now created eagerly. + * fixed bug #345: backtraces from calls to undefined functions work + on x86 as well. Related bug #61 is now also partially fixed on x86 + (backtraces from throws to unknown catch tags.) * bug fix: lambda-list parsing is now stricter vrt. order and number of lambda-list keywords. * fixed some bugs revealed by Paul Dietz' test suite: diff --git a/src/code/debug-int.lisp b/src/code/debug-int.lisp index 67d0a59..9964063 100644 --- a/src/code/debug-int.lisp +++ b/src/code/debug-int.lisp @@ -41,17 +41,6 @@ "All DEBUG-CONDITIONs inherit from this type. These are serious conditions that must be handled, but they are not programmer errors.")) -(define-condition no-debug-info (debug-condition) - ((code-component :reader no-debug-info-code-component - :initarg :code-component)) - #!+sb-doc - (:documentation "There is no usable debugging information available.") - (:report (lambda (condition stream) - (fresh-line stream) - (format stream - "no debug information available for ~S~%" - (no-debug-info-code-component condition))))) - (define-condition no-debug-fun-returns (debug-condition) ((debug-fun :reader no-debug-fun-returns-debug-fun :initarg :debug-fun)) @@ -854,7 +843,6 @@ (multiple-value-bind (code pc-offset escaped) (find-escaped-frame caller) (/noshow0 "at COND") (cond (code - (/noshow0 "in CODE clause") ;; If it's escaped it may be a function end breakpoint trap. (when (and (code-component-p code) (eq (%code-debug-info code) :bogus-lra)) @@ -863,16 +851,12 @@ code (1+ real-lra-slot))) (setq code (code-header-ref code real-lra-slot)) (aver code))) - (t - (/noshow0 "in T clause") - ;; not escaped + ((not escaped) (multiple-value-setq (pc-offset code) (compute-lra-data-from-pc ra)) (unless code (setf code :foreign-function - pc-offset 0 - escaped nil)))) - + pc-offset 0)))) (let ((d-fun (case code (:undefined-function (make-bogus-debug-fun @@ -1041,8 +1025,11 @@ register." (defun debug-fun-from-pc (component pc) (let ((info (%code-debug-info component))) (cond - ((not info) - (debug-signal 'no-debug-info :code-component component)) + ((not info) + ;; FIXME: It seems that most of these (at least on x86) are + ;; actually assembler routines, and could be named by looking + ;; at the sb-fasl:*assembler-routines*. + (make-bogus-debug-fun "no debug information for frame")) ((eq info :bogus-lra) (make-bogus-debug-fun "function end breakpoint")) (t diff --git a/src/runtime/x86-assem.S b/src/runtime/x86-assem.S index 3dfb53b..d512676 100644 --- a/src/runtime/x86-assem.S +++ b/src/runtime/x86-assem.S @@ -286,6 +286,7 @@ GNAME(fpu_restore): .align align_4byte,0x90 .global GNAME(undefined_tramp) .type GNAME(undefined_tramp),@function + .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG GNAME(undefined_tramp): int3 .byte trap_Error @@ -302,6 +303,7 @@ GNAME(undefined_tramp): .align align_4byte,0x90 .global GNAME(closure_tramp) .type GNAME(closure_tramp),@function + .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG GNAME(closure_tramp): movl FDEFN_FUN_OFFSET(%eax),%eax /* FIXME: The '*' after "jmp" in the next line is from PVE's diff --git a/tests/debug.impure.lisp b/tests/debug.impure.lisp index a1d1e19..5301d5a 100644 --- a/tests/debug.impure.lisp +++ b/tests/debug.impure.lisp @@ -74,20 +74,22 @@ (let ((backtrace (ignore-errors (sb-debug:backtrace-as-list)))) ;; Make sure we find what we're looking for. - (when (member frame-name backtrace - :key key :test test) - (setf result (list :error condition))) + (if (member frame-name backtrace :key key :test test) + (setf result (list :error condition)) + (print (list :failed :frame frame-name :backtrace backtrace))) ;; Make sure there's no bogus stack frames ;; unless they're explicitly allowed. (when (and (not allow-bogus-frames) (member "bogus stack frame" backtrace :key #'first :test #'equal)) + (print 'verify-backtrace-bogus) (setf result nil)) ;; Make sure the backtrace isn't stunted in ;; any way. (Depends on running in the main ;; thread.) (unless (member 'sb-impl::toplevel-init backtrace :key #'first :test #'equal) + (print 'verify-backtrace-stunted) (setf result nil))) (return-from outer-handler)))) (funcall test-function))) @@ -97,19 +99,27 @@ ;;; Try it with and without tail call elimination, since they can have ;;; different effects. (Specifically, if undefined_tramp is incorrect ;;; a stunted stack can result from the tail call variant.) -#-(or alpha x86) ; bug 345 -(progn - (flet ((test-function () - (declare (optimize (speed 2) (debug 1))) ; tail call elimination - (#:undefined-function 42))) - (assert (verify-backtrace #'test-function "undefined function" - :test #'equal))) - - (flet ((test-function () - (declare (optimize (speed 1) (debug 2))) ; no tail call elimination - (#:undefined-function 42))) - (assert (verify-backtrace #'test-function "undefined function" - :test #'equal)))) +#-(or alpha) ; bug 346 +(flet ((optimized () + (declare (optimize (speed 2) (debug 1))) ; tail call elimination + (#:undefined-function 42)) + (not-optimized () + (declare (optimize (speed 1) (debug 2))) ; no tail call elimination + (#:undefined-function 42)) + (test (fun) + (declare (optimize (speed 1) (debug 2))) ; no tail call elimination + (funcall fun))) + (dolist (frame '(#-x86 "undefined function" ; bug 353 + "FLET COMMON-LISP-USER::TEST")) + (assert (verify-backtrace (lambda () (test #'optimized)) frame + :test #'equal + :allow-bogus-frames (or #+x86 t)))) + (dolist (frame '(#-x86 "undefined function" ; bug 353 + "FLET COMMON-LISP-USER::NOT-OPTIMIZED" + "FLET COMMON-LISP-USER::TEST")) + (assert (verify-backtrace (lambda () (test #'not-optimized)) frame + :test #'equal + :allow-bogus-frames (or #+x86 t))))) ;;; Division by zero was a common error on PPC. It depended on the ;;; return function either being before INTEGER-/-INTEGER in memory, @@ -135,11 +145,14 @@ (/ 42 0))) (assert (verify-backtrace #'test-function '/)))) -#-(or x86 alpha) ; bug 61 +#-(or alpha) ; bug 61 (progn (defun throw-test () (throw 'no-such-tag t)) - (assert (verify-backtrace #'throw-test 'throw-test))) + (assert (verify-backtrace #'throw-test + #-(or x86 sparc) 'throw-test + #+(or x86 sparc) "XEP for COMMON-LISP-USER::THROW-TEST" ; bug 354 + :test #'equal))) ;;; success (quit :unix-status 104) diff --git a/version.lisp-expr b/version.lisp-expr index 349c154..7c55463 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"0.8.17.7" +"0.8.17.8" -- 1.7.10.4