From 485053aa46c262f9c357cf5cf48d8f6c3f6e8223 Mon Sep 17 00:00:00 2001 From: Alastair Bridgewater Date: Sun, 6 Jun 2010 19:51:18 +0000 Subject: [PATCH] 1.0.39.7: Make TRACE :ENCAPSULATE NIL work on PPC. * SIGNAL-CONTEXT-FRAME (debug-int.lisp) was passing a bogus parameter to COMPUTE-CALLING-FRAME on non-x86oids, causing an unknown immediate object to be constructed. Fixed, and KLUDGEd to still work on x86oids. * fun_end_breakpoint_guts (ppc-assem.S) wasn't implemented at all, just stubbed out to provide the symbols that the core looks for when compiling MAKE-BOGUS-LRA (debug-int.lisp). * The implementation of fun_end_breakpoint_guts on non-PPC is sparsely explained at best. Addressed in the new PPC version. * The usual implementation of fun_end_breakpoint_guts leaves setting the LRA header data to MAKE-BOGUS-LRA but this is done after attempting to create the LRA object, which fails on GENCGC systems due to the sanity checking of the pointer. On PPC, this is addressed by setting the LRA header data by dead reckoning in ppc-assem.S. * In MAKE-BOGUS-LRA, don't bother setting the LRA header data if it is known to already be correct. --- NEWS | 1 + src/code/debug-int.lisp | 25 +++++++++++---- src/runtime/ppc-assem.S | 82 ++++++++++++++++++++++++++++++++++++++--------- tests/debug.impure.lisp | 4 +-- version.lisp-expr | 2 +- 5 files changed, 90 insertions(+), 24 deletions(-) diff --git a/NEWS b/NEWS index 87c8c0e..02c97ab 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ single call to IMPORT no longer add multiple symbols with the same name to the package (detectable via DO-SYMBOLS). * bug fix: support building without the dlshim on darwin x86 and x86-64 (lp#533470). + * bug fix: TRACE :ENCAPSULATE NIL now works on ppc/linux. changes in sbcl-1.0.39 relative to sbcl-1.0.38: * bug fix: Backtrace from undefined function on x86 and x86-64 now show diff --git a/src/code/debug-int.lisp b/src/code/debug-int.lisp index 9554efe..89d1b7a 100644 --- a/src/code/debug-int.lisp +++ b/src/code/debug-int.lisp @@ -3018,7 +3018,11 @@ register." (sb!alien:sap-alien signal-context (* os-context-t)))) (cfp (int-sap (sb!vm:context-register scp sb!vm::cfp-offset)))) (compute-calling-frame cfp - (sb!vm:context-pc scp) + ;; KLUDGE: This argument is ignored on + ;; x86oids in this scenario, but is + ;; declared to be a SAP. + #!+(or x86 x86-64) (sb!vm:context-pc scp) + #!-(or x86 x86-64) nil nil))) (defun handle-fun-end-breakpoint (offset component context) @@ -3115,11 +3119,20 @@ register." #!-(or x86 x86-64) (let ((new-lra (make-lisp-obj (+ (sap-int dst-start) sb!vm:other-pointer-lowtag)))) - (set-header-data - new-lra - (logandc2 (+ sb!vm:code-constants-offset bogus-lra-constants 1) - 1)) - (sb!vm:sanctify-for-execution code-object) + #!-(or gencgc ppc) + (progn + ;; Set the offset from the LRA to the enclosing component. + ;; This does not need to be done on GENCGC targets, as the + ;; pointer validation done in MAKE-LISP-OBJ requires that it + ;; already have been set before we get here. It does not + ;; need to be done on CHENEYGC PPC as it's easier to use the + ;; same fun_end_breakpoint_guts on both, including the LRA + ;; header. + (set-header-data + new-lra + (logandc2 (+ sb!vm:code-constants-offset bogus-lra-constants 1) + 1)) + (sb!vm:sanctify-for-execution code-object)) (values new-lra code-object (sap- trap-loc src-start)))))) ;;;; miscellaneous diff --git a/src/runtime/ppc-assem.S b/src/runtime/ppc-assem.S index c95fa0e..13175df 100644 --- a/src/runtime/ppc-assem.S +++ b/src/runtime/ppc-assem.S @@ -574,23 +574,75 @@ CSYMBOL(funcallable_instance_tramp) = . + 1 mtctr reg_LIP bctr SET_SIZE(funcallable_instance_tramp) - - GFUNCDEF(fun_end_breakpoint_trap) - .long 0 - SET_SIZE(fun_end_breakpoint_trap) - - GFUNCDEF(fun_end_breakpoint) - .long 0 - SET_SIZE(fun_end_breakpoint) - + + /* The fun_end_breakpoint support here is considered by the + authors of the other $ARCH-assem.S files to be magic, and it + is. It is a small fragment of code that is copied into a heap + code-object when needed, and contains an LRA object, code to + convert a single-value return to unknown-values format, and a + trap_FunEndBreakpoint. */ GFUNCDEF(fun_end_breakpoint_guts) - .long 0 - SET_SIZE(fun_end_breakpoint_guts) - - GFUNCDEF(fun_end_breakpoint_end) - .long 0 - SET_SIZE(fun_end_breakpoint_end) + .globl CSYMBOL(fun_end_breakpoint_trap) + .globl CSYMBOL(fun_end_breakpoint_end) + + /* Due to pointer verification in MAKE-LISP-OBJ on GENCGC + targets, which includes PPC, this must include its header data + (the offset from the start of the code-object to the LRA). + The code-object header is five words, there are two words of + constants, and the instruction space is doubleword-aligned, + making an offset of eight. This is header data for a widetag, + so shift left eight bits and add. */ + .long RETURN_PC_HEADER_WIDETAG + 0x800 + + /* We are receiving unknown multiple values, thus must deal + with the single-value and multiple-value cases separately. */ + b fun_end_breakpoint_multiple_values + nop + /* Compute the correct value for reg_CODE based on the LRA. + This is a "simple" matter of subtracting a constant from + reg_CODE (where the LRA is stored by the return sequence) to + obtain a tagged pointer to the enclosing code component. Both + values are tagged OTHER_POINTER_LOWTAG, so we just have to + account for the eight words (see calculation for + RETURN_PC_HEADER_WIDETAG, above) between the two addresses. + Restoring reg_CODE doesn't appear to be strictly necessary + here, but let's observe the niceties.*/ + addi reg_CODE, reg_CODE, -32 + + /* Multiple values are stored relative to reg_OCFP, which we + set to be the current top-of-stack. */ + mr reg_OCFP, reg_CSP + + /* Reserve a save location for the one value we have. */ + addi reg_CSP, reg_CSP, 4 + + /* Record the number of values we have as a FIXNUM. */ + li reg_NARGS, 4 + + /* Blank the remaining arg-passing registers. */ + mr reg_A1, reg_NULL + mr reg_A2, reg_NULL + mr reg_A3, reg_NULL + + /* And branch to our trap. */ + b CSYMBOL(fun_end_breakpoint_trap) + +fun_end_breakpoint_multiple_values: + /* Compute the correct value for reg_CODE. See the + explanation for the single-value case, above. */ + addi reg_CODE, reg_CODE, -32 + + /* The actual magic trap. */ +CSYMBOL(fun_end_breakpoint_trap): + twllei reg_ZERO, trap_FunEndBreakpoint + + /* Finally, the debugger needs to know where the end of the + fun_end_breakpoint_guts are, so that it may calculate its size + in order to populate out a suitably-sized code object. */ +CSYMBOL(fun_end_breakpoint_end): + SET_SIZE(fun_end_breakpoint_guts) + GFUNCDEF(ppc_flush_cache_line) dcbf 0,REG(3) diff --git a/tests/debug.impure.lisp b/tests/debug.impure.lisp index 67303cc..27283ae 100644 --- a/tests/debug.impure.lisp +++ b/tests/debug.impure.lisp @@ -389,7 +389,7 @@ ;;; on that platform. #-(and (or ppc x86 x86-64) darwin) (with-test (:name (trace :encapsulate nil) - :fails-on '(or :ppc :sparc :mips)) + :fails-on '(or (and :ppc (not :linux)) :sparc :mips)) (let ((out (with-output-to-string (*trace-output*) (trace trace-this :encapsulate nil) (assert (eq 'ok (trace-this))) @@ -399,7 +399,7 @@ #-(and (or ppc x86 x86-64) darwin) (with-test (:name (trace-recursive :encapsulate nil) - :fails-on '(or :ppc :sparc :mips)) + :fails-on '(or (and :ppc (not :linux)) :sparc :mips)) (let ((out (with-output-to-string (*trace-output*) (trace trace-fact :encapsulate nil) (assert (= 120 (trace-fact 5))) diff --git a/version.lisp-expr b/version.lisp-expr index 4b1d5b8..268032b 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".) -"1.0.39.6" +"1.0.39.7" -- 1.7.10.4