X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fdebug-int.lisp;h=4021963a518168cb3edb5d719637ef3ffda2425a;hb=17ae4361ba5f4c1062d510f3951b0cc10e0bcd8e;hp=2dfd05d95f612e47bca5c21f410a786750ab9907;hpb=b66385e2031fc2cac17dd129df0af400beb48a22;p=sbcl.git diff --git a/src/code/debug-int.lisp b/src/code/debug-int.lisp index 2dfd05d..4021963 100644 --- a/src/code/debug-int.lisp +++ b/src/code/debug-int.lisp @@ -532,9 +532,11 @@ (sap> control-stack-end x) (zerop (logand (sap-int x) #b11))))) +(declaim (inline component-ptr-from-pc)) (sb!alien:define-alien-routine component-ptr-from-pc (system-area-pointer) (pc system-area-pointer)) +(declaim (inline component-from-component-ptr)) (defun component-from-component-ptr (component-ptr) (declare (type system-area-pointer component-ptr)) (make-lisp-obj (logior (sap-int component-ptr) @@ -585,74 +587,64 @@ ;;; ;;; XXX Should handle interrupted frames, both Lisp and C. At present ;;; it manages to find a fp trail, see linux hack below. -(defun x86-call-context (fp &key (depth 0)) - (declare (type system-area-pointer fp) - (fixnum depth)) -;; (format t "*CC ~S ~S~%" fp depth) - (cond - ((not (control-stack-pointer-valid-p fp)) - #+nil (format t "debug invalid fp ~S~%" fp) - nil) - (t - ;; Check the two possible frame pointers. - (let ((lisp-ocfp (sap-ref-sap fp (- (* (1+ ocfp-save-offset) - sb!vm::n-word-bytes)))) - (lisp-ra (sap-ref-sap fp (- (* (1+ return-pc-save-offset) - sb!vm::n-word-bytes)))) - (c-ocfp (sap-ref-sap fp (* 0 sb!vm:n-word-bytes))) - (c-ra (sap-ref-sap fp (* 1 sb!vm:n-word-bytes)))) - #+nil (format t " lisp-ocfp=~S~% lisp-ra=~S~% c-ocfp=~S~% c-ra=~S~%" - lisp-ocfp lisp-ra c-ocfp c-ra) - (cond ((and (sap> lisp-ocfp fp) (control-stack-pointer-valid-p lisp-ocfp) - (ra-pointer-valid-p lisp-ra) - (sap> c-ocfp fp) (control-stack-pointer-valid-p c-ocfp) - (ra-pointer-valid-p c-ra)) - #+nil (format t - "*C Both valid ~S ~S ~S ~S~%" - lisp-ocfp lisp-ra c-ocfp c-ra) - ;; Look forward another step to check their validity. - (let ((lisp-path-fp (x86-call-context lisp-ocfp - :depth (1+ depth))) - (c-path-fp (x86-call-context c-ocfp :depth (1+ depth)))) - (cond ((and lisp-path-fp c-path-fp) - ;; Both still seem valid - choose the lisp frame. - #+nil (when (zerop depth) - (format t - "debug: both still valid ~S ~S ~S ~S~%" - lisp-ocfp lisp-ra c-ocfp c-ra)) - #!+freebsd - (if (sap> lisp-ocfp c-ocfp) - (values lisp-ra lisp-ocfp) - (values c-ra c-ocfp)) - #!-freebsd - (values lisp-ra lisp-ocfp)) - (lisp-path-fp - ;; The lisp convention is looking good. - #+nil (format t "*C lisp-ocfp ~S ~S~%" lisp-ocfp lisp-ra) - (values lisp-ra lisp-ocfp)) - (c-path-fp - ;; The C convention is looking good. - #+nil (format t "*C c-ocfp ~S ~S~%" c-ocfp c-ra) - (values c-ra c-ocfp)) - (t - ;; Neither seems right? - #+nil (format t "debug: no valid2 fp found ~S ~S~%" - lisp-ocfp c-ocfp) - nil)))) - ((and (sap> lisp-ocfp fp) (control-stack-pointer-valid-p lisp-ocfp) - (ra-pointer-valid-p lisp-ra)) - ;; The lisp convention is looking good. - #+nil (format t "*C lisp-ocfp ~S ~S~%" lisp-ocfp lisp-ra) - (values lisp-ra lisp-ocfp)) - ((and (sap> c-ocfp fp) (control-stack-pointer-valid-p c-ocfp) - #!-linux (ra-pointer-valid-p c-ra)) - ;; The C convention is looking good. - #+nil (format t "*C c-ocfp ~S ~S~%" c-ocfp c-ra) - (values c-ra c-ocfp)) - (t - #+nil (format t "debug: no valid fp found ~S ~S~%" - lisp-ocfp c-ocfp) - nil)))))) +(declaim (maybe-inline x86-call-context)) +(defun x86-call-context (fp) + (declare (type system-area-pointer fp)) + (labels ((fail () + (values nil + (int-sap 0) + (int-sap 0))) + (handle (fp) + (cond + ((not (control-stack-pointer-valid-p fp)) + (fail)) + (t + ;; Check the two possible frame pointers. + (let ((lisp-ocfp (sap-ref-sap fp (- (* (1+ ocfp-save-offset) + sb!vm::n-word-bytes)))) + (lisp-ra (sap-ref-sap fp (- (* (1+ return-pc-save-offset) + sb!vm::n-word-bytes)))) + (c-ocfp (sap-ref-sap fp (* 0 sb!vm:n-word-bytes))) + (c-ra (sap-ref-sap fp (* 1 sb!vm:n-word-bytes)))) + (cond ((and (sap> lisp-ocfp fp) + (control-stack-pointer-valid-p lisp-ocfp) + (ra-pointer-valid-p lisp-ra) + (sap> c-ocfp fp) + (control-stack-pointer-valid-p c-ocfp) + (ra-pointer-valid-p c-ra)) + ;; Look forward another step to check their validity. + (let ((lisp-ok (handle lisp-ocfp)) + (c-ok (handle c-ocfp))) + (cond ((and lisp-ok c-ok) + ;; Both still seem valid - choose the lisp frame. + #!+freebsd + (if (sap> lisp-ocfp c-ocfp) + (values t lisp-ra lisp-ocfp) + (values t c-ra c-ocfp)) + #!-freebsd + (values t lisp-ra lisp-ocfp)) + (lisp-ok + ;; The lisp convention is looking good. + (values t lisp-ra lisp-ocfp)) + (c-ok + ;; The C convention is looking good. + (values t c-ra c-ocfp)) + (t + ;; Neither seems right? + (fail))))) + ((and (sap> lisp-ocfp fp) + (control-stack-pointer-valid-p lisp-ocfp) + (ra-pointer-valid-p lisp-ra)) + ;; The lisp convention is looking good. + (values t lisp-ra lisp-ocfp)) + ((and (sap> c-ocfp fp) + (control-stack-pointer-valid-p c-ocfp) + #!-linux (ra-pointer-valid-p c-ra)) + ;; The C convention is looking good. + (values t c-ra c-ocfp)) + (t + (fail)))))))) + (handle fp))) ) ; #+x86 PROGN @@ -706,8 +698,9 @@ (let ((fp (frame-pointer frame))) (when (control-stack-pointer-valid-p fp) #!+(or x86 x86-64) - (multiple-value-bind (ra ofp) (x86-call-context fp) - (and ra (compute-calling-frame ofp ra frame))) + (multiple-value-bind (ok ra ofp) (x86-call-context fp) + (and ok + (compute-calling-frame ofp ra frame))) #!-(or x86 x86-64) (compute-calling-frame #!-alpha @@ -3317,10 +3310,9 @@ register." ;;; which will signal the condition. (defun handle-single-step-trap (context-sap kind callee-register-offset) - (let ((context (sb!alien:sap-alien context-sap - (* os-context-t)))) + (let ((context (sb!alien:sap-alien context-sap (* os-context-t)))) ;; The following calls must get tail-call eliminated for - ;; *STEP-FRAME* to get set correctly. + ;; *STEP-FRAME* to get set correctly on non-x86. (if (= kind single-step-before-trap) (handle-single-step-before-trap context) (handle-single-step-around-trap context callee-register-offset)))) @@ -3332,16 +3324,21 @@ register." ;; If there was not enough debug information available, there's no ;; sense in signaling the condition. (when step-info - (let ((*step-frame* (frame-down (top-frame)))) - ;; KLUDGE: Use the first non-foreign frame as the - ;; *STACK-TOP-HINT*. Getting the frame from the signal context - ;; would be cleaner, but SIGNAL-CONTEXT-FRAME doesn't seem - ;; seem to work very well currently. - (loop while *step-frame* - for dfun = (frame-debug-fun *step-frame*) - do (when (typep dfun 'compiled-debug-fun) - (return)) - do (setf *step-frame* (frame-down *step-frame*))) + (let ((*step-frame* + #+(or x86 x86-64) + (signal-context-frame (sb!alien::alien-sap context)) + #-(or x86 x86-64) + ;; KLUDGE: Use the first non-foreign frame as the + ;; *STACK-TOP-HINT*. Getting the frame from the signal + ;; context as on x86 would be cleaner, but + ;; SIGNAL-CONTEXT-FRAME doesn't seem seem to work at all + ;; on non-x86. + (loop with frame = (frame-down (top-frame)) + while frame + for dfun = (frame-debug-fun frame) + do (when (typep dfun 'compiled-debug-fun) + (return frame)) + do (setf frame (frame-down frame))))) (sb!impl::step-form step-info ;; We could theoretically store information in ;; the debug-info about to determine the @@ -3370,29 +3367,33 @@ register." (fdefn (fdefn-fun callee)) (function callee)) args))) - (let ((sb!impl::*step-out* :maybe)) - (unwind-protect - ;; Signal a step condition - (let* ((step-in - (let ((*step-frame* (frame-down (top-frame)))) - (sb!impl::step-form step-info args)))) - ;; And proceed based on its return value. - (if step-in - ;; If STEP-INTO was selected we pass - ;; the return values to STEP-VALUES which - ;; will show the return value. + ;; Signal a step condition + (let* ((step-in + (let ((*step-frame* (frame-down (top-frame)))) + (sb!impl::step-form step-info args)))) + ;; And proceed based on its return value. + (if step-in + ;; STEP-INTO was selected. Use *STEP-OUT* to + ;; let the stepper know that selecting the + ;; STEP-OUT restart is valid inside this + (let ((sb!impl::*step-out* :maybe)) + ;; Pass the return values of the call to + ;; STEP-VALUES, which will signal a + ;; condition with them in the VALUES slot. + (unwind-protect (multiple-value-call #'sb!impl::step-values step-info (call)) - ;; If STEP-NEXT or STEP-CONTINUE was - ;; selected we disable the stepper for - ;; the duration of the call. - (sb!impl::with-stepping-disabled - (call)))) - ;; If the use selected the STEP-OUT restart - ;; somewhere during the call, resume stepping - (when (eq sb!impl::*step-out* t) - (sb!impl::enable-stepping))))))) + ;; If the user selected the STEP-OUT + ;; restart during the call, resume + ;; stepping + (when (eq sb!impl::*step-out* t) + (sb!impl::enable-stepping)))) + ;; STEP-NEXT / CONTINUE / OUT selected: + ;; Disable the stepper for the duration of + ;; the call. + (sb!impl::with-stepping-disabled + (call))))))) (new-callee (etypecase callee (fdefn (let ((fdefn (make-fdefn (gensym))))