From: Thiemo S. <th...@ne...> - 2005-09-19 20:38:06
|
Hello All, this patch changes (hopefully) all instances of instruction reading/writing in C code to a type of "unsigned int". Currently it is a mixture of "unsigned int" and "unsigned long", seemingly for historical reasons. For mips, it also adds handling for trap_AfterBreakpoint to arch_do_displaced_inst, which gives it at least a chance to work. Without that, handle-breakpoint loses the breakpoint set, because the trap_AfterBreakpoint case in sigtrap is never triggered. Other architectures which seem to have the same bug are ppc and hppa. For sparc, it adds in sigill_handler a missing os_flush_icache call to the trap_AfterBreakpoint case. Tested only on mips, please test this patch also on other architectures, I may have missed some bits. If it holds up intend to commit it shortly after the next release. Thiemo Index: src/code/debug-int.lisp =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/code/debug-int.lisp,v retrieving revision 1.99 diff -u -p -r1.99 debug-int.lisp --- src/code/debug-int.lisp 12 Sep 2005 09:39:31 -0000 1.99 +++ src/code/debug-int.lisp 19 Sep 2005 18:35:19 -0000 @@ -3044,7 +3053,7 @@ register." ;;; returns the overwritten bits. You must call this in a context in ;;; which GC is disabled, so that Lisp doesn't move objects around ;;; that C is pointing to. -(sb!alien:define-alien-routine "breakpoint_install" sb!alien:unsigned-long +(sb!alien:define-alien-routine "breakpoint_install" sb!alien:unsigned-int (code-obj sb!alien:unsigned-long) (pc-offset sb!alien:int)) @@ -3054,11 +3063,11 @@ register." (sb!alien:define-alien-routine "breakpoint_remove" sb!alien:void (code-obj sb!alien:unsigned-long) (pc-offset sb!alien:int) - (old-inst sb!alien:unsigned-long)) + (old-inst sb!alien:unsigned-int)) (sb!alien:define-alien-routine "breakpoint_do_displaced_inst" sb!alien:void (scp (* os-context-t)) - (orig-inst sb!alien:unsigned-long)) + (orig-inst sb!alien:unsigned-int)) ;;;; breakpoint handlers (layer between C and exported interface) Index: src/runtime/alpha-arch.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/alpha-arch.c,v retrieving revision 1.19 diff -u -p -r1.19 alpha-arch.c --- src/runtime/alpha-arch.c 14 Jul 2005 15:41:11 -0000 1.19 +++ src/runtime/alpha-arch.c 19 Sep 2005 18:35:19 -0000 @@ -115,24 +115,22 @@ void arch_set_pseudo_atomic_interrupted( *os_context_register_addr(context,reg_ALLOC) |= (1L<<63); } -unsigned long arch_install_breakpoint(void *pc) +unsigned int arch_install_breakpoint(void *pc) { unsigned int *ptr = (unsigned int *)pc; - unsigned long result = (unsigned long) *ptr; + unsigned int result = *ptr; *ptr = BREAKPOINT_INST; - os_flush_icache((os_vm_address_t)ptr, sizeof(unsigned long)); + os_flush_icache((os_vm_address_t)ptr, sizeof(unsigned int)); return result; } -void arch_remove_breakpoint(void *pc, unsigned long orig_inst) +void arch_remove_breakpoint(void *pc, unsigned int orig_inst) { - /* was (unsigned int) but gcc complains. Changed to mirror - * install_breakpoint() above */ - unsigned long *ptr=(unsigned long *)pc; + unsigned int *ptr = (unsigned int *)pc; *ptr = orig_inst; - os_flush_icache((os_vm_address_t)pc, sizeof(unsigned long)); + os_flush_icache((os_vm_address_t)pc, sizeof(unsigned int)); } static unsigned int *skipped_break_addr, displaced_after_inst, @@ -142,7 +140,7 @@ static unsigned int *skipped_break_addr, /* This returns a PC value. Lisp code is all in the 32-bit-addressable * space, so we should be ok with an unsigned int. */ unsigned int -emulate_branch(os_context_t *context,unsigned long orig_inst) +emulate_branch(os_context_t *context, unsigned int orig_inst) { int op = orig_inst >> 26; int reg_a = (orig_inst >> 21) & 0x1f; @@ -257,7 +255,7 @@ void arch_do_displaced_inst(os_context_t /* Put the original instruction back. */ *pc = orig_inst; - os_flush_icache((os_vm_address_t)pc, sizeof(unsigned long)); + os_flush_icache((os_vm_address_t)pc, sizeof(unsigned int)); skipped_break_addr = pc; /* Figure out where we will end up after running the displaced @@ -272,7 +270,7 @@ void arch_do_displaced_inst(os_context_t displaced_after_inst = *next_pc; *next_pc = BREAKPOINT_INST; after_breakpoint=1; - os_flush_icache((os_vm_address_t)next_pc, sizeof(unsigned long)); + os_flush_icache((os_vm_address_t)next_pc, sizeof(unsigned int)); } static void @@ -298,11 +296,11 @@ sigtrap_handler(int signal, siginfo_t *s *os_context_pc_addr(context) -=4; *skipped_break_addr = BREAKPOINT_INST; os_flush_icache((os_vm_address_t)skipped_break_addr, - sizeof(unsigned long)); + sizeof(unsigned int)); skipped_break_addr = NULL; *(unsigned int *)*os_context_pc_addr(context) = displaced_after_inst; - os_flush_icache((os_vm_address_t)*os_context_pc_addr(context), sizeof(unsigned long)); + os_flush_icache((os_vm_address_t)*os_context_pc_addr(context), sizeof(unsigned int)); *os_context_sigmask_addr(context)= orig_sigmask; after_breakpoint=0; /* false */ return; Index: src/runtime/arch.h =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/arch.h,v retrieving revision 1.7 diff -u -p -r1.7 arch.h --- src/runtime/arch.h 14 Jul 2005 15:41:11 -0000 1.7 +++ src/runtime/arch.h 19 Sep 2005 18:35:19 -0000 @@ -26,8 +26,8 @@ extern boolean arch_pseudo_atomic_atomic extern void arch_set_pseudo_atomic_interrupted(os_context_t*); extern os_vm_address_t arch_get_bad_addr(int, siginfo_t*, os_context_t*); extern unsigned char *arch_internal_error_arguments(os_context_t*); -extern unsigned long arch_install_breakpoint(void *pc); -extern void arch_remove_breakpoint(void *pc, unsigned long orig_inst); +extern unsigned int arch_install_breakpoint(void *pc); +extern void arch_remove_breakpoint(void *pc, unsigned int orig_inst); extern void arch_install_interrupt_handlers(void); extern void arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst); Index: src/runtime/breakpoint.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/breakpoint.c,v retrieving revision 1.20 diff -u -p -r1.20 breakpoint.c --- src/runtime/breakpoint.c 14 Jul 2005 15:41:11 -0000 1.20 +++ src/runtime/breakpoint.c 19 Sep 2005 18:35:19 -0000 @@ -43,19 +43,19 @@ static void *compute_pc(lispobj code_obj + pc_offset); } -unsigned long breakpoint_install(lispobj code_obj, int pc_offset) +unsigned int breakpoint_install(lispobj code_obj, int pc_offset) { return arch_install_breakpoint(compute_pc(code_obj, pc_offset)); } void breakpoint_remove(lispobj code_obj, int pc_offset, - unsigned long orig_inst) + unsigned int orig_inst) { arch_remove_breakpoint(compute_pc(code_obj, pc_offset), orig_inst); } void breakpoint_do_displaced_inst(os_context_t* context, - unsigned long orig_inst) + unsigned int orig_inst) { /* on platforms with sigreturn(), we go directly back from * arch_do_displaced_inst() to lisp code, so we need to clean up Index: src/runtime/breakpoint.h =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/breakpoint.h,v retrieving revision 1.5 diff -u -p -r1.5 breakpoint.h --- src/runtime/breakpoint.h 14 Jul 2005 15:41:11 -0000 1.5 +++ src/runtime/breakpoint.h 19 Sep 2005 18:35:19 -0000 @@ -12,12 +12,12 @@ #ifndef _BREAKPOINT_H_ #define _BREAKPOINT_H_ -extern unsigned long breakpoint_install(lispobj code_obj, int pc_offset); +extern unsigned int breakpoint_install(lispobj code_obj, int pc_offset); extern void breakpoint_remove(lispobj code_obj, int pc_offset, - unsigned long orig_inst); + unsigned int orig_inst); extern void breakpoint_do_displaced_inst(os_context_t *context, - unsigned long orig_inst); + unsigned int orig_inst); extern void handle_breakpoint(int signal, siginfo_t *info, os_context_t *context); extern void *handle_fun_end_breakpoint(int signal, siginfo_t *info, Index: src/runtime/hppa-arch.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/hppa-arch.c,v retrieving revision 1.6 diff -u -p -r1.6 hppa-arch.c --- src/runtime/hppa-arch.c 14 Jul 2005 15:41:11 -0000 1.6 +++ src/runtime/hppa-arch.c 19 Sep 2005 18:35:19 -0000 @@ -91,19 +91,19 @@ void arch_skip_instruction(os_context_t ((char *) *os_context_npc_addr(context)) += 4; } -unsigned long arch_install_breakpoint(void *pc) +unsigned int arch_install_breakpoint(void *pc) { - unsigned long *ulpc = (unsigned long *)pc; - unsigned long orig_inst = *ulpc; + unsigned int *ulpc = (unsigned int *)pc; + unsigned int orig_inst = *ulpc; *ulpc = trap_Breakpoint; os_flush_icache((os_vm_address_t)pc, sizeof(*ulpc)); return orig_inst; } -void arch_remove_breakpoint(void *pc, unsigned long orig_inst) +void arch_remove_breakpoint(void *pc, unsigned int orig_inst) { - unsigned long *ulpc = (unsigned long *)pc; + unsigned int *ulpc = (unsigned int *)pc; *ulpc = orig_inst; os_flush_icache((os_vm_address_t)pc, sizeof(*ulpc)); @@ -117,14 +117,14 @@ void arch_do_displaced_inst(os_context_t /* We change the next-pc to point to a breakpoint instruction, restore */ /* the original instruction, and exit. We would like to be able to */ /* sigreturn, but we can't, because this is hpux. */ - unsigned long *pc = (unsigned long *)(SC_PC(scp) & ~3); + unsigned int *pc = (unsigned int *)(SC_PC(scp) & ~3); NextPc = SC_NPC(scp); - SC_NPC(scp) = (unsigned)SingleStepTraps | (SC_NPC(scp)&3); + SC_NPC(scp) = (unsigned int)SingleStepTraps | (SC_NPC(scp)&3); BreakpointAddr = pc; *pc = orig_inst; - os_flush_icache((os_vm_address_t)pc, sizeof(unsigned long)); + os_flush_icache((os_vm_address_t)pc, sizeof(unsigned int)); #else /* We set the recovery counter to cover one instruction, put the */ /* original instruction back in, and then resume. We will then trap */ @@ -133,7 +133,7 @@ void arch_do_displaced_inst(os_context_t ((struct hp800_thread_state *)scp->sc_ap)->cr0 = 1; scp->sc_ps |= 0x10; - *(unsigned long *)SC_PC(scp) = orig_inst; + *(unsigned int *)SC_PC(scp) = orig_inst; sigreturn(scp); #endif @@ -150,10 +150,10 @@ static void restore_breakpoint(struct si if (NextPc == NULL) lose("SingleStepBreakpoint trap at strange time."); - if ((SC_PC(scp)&~3) == (unsigned long)SingleStepTraps) { + if ((SC_PC(scp)&~3) == (unsigned int)SingleStepTraps) { /* The next instruction was not nullified. */ SC_PC(scp) = NextPc; - if ((SC_NPC(scp)&~3) == (unsigned long)SingleStepTraps + 4) { + if ((SC_NPC(scp)&~3) == (unsigned int)SingleStepTraps + 4) { /* The instruction we just stepped over was not a branch, so */ /* we need to fix it up. If it was a branch, it will point to */ /* the correct place. */ @@ -170,7 +170,7 @@ static void restore_breakpoint(struct si if (BreakpointAddr) { *BreakpointAddr = trap_Breakpoint; os_flush_icache((os_vm_address_t)BreakpointAddr, - sizeof(unsigned long)); + sizeof(unsigned int)); BreakpointAddr = NULL; } } @@ -179,14 +179,14 @@ static void restore_breakpoint(struct si static void sigtrap_handler(int signal, siginfo_t *siginfo, void *void_context) { os_context_t *context = arch_os_get_context(&void_context); - unsigned long bad_inst; + unsigned int bad_inst; #if 0 printf("sigtrap_handler, pc=0x%08x, alloc=0x%08x\n", scp->sc_pcoqh, SC_REG(scp,reg_ALLOC)); #endif - bad_inst = *(unsigned long *)(*os_context_pc_addr(context) & ~3); + bad_inst = *(unsigned int *)(*os_context_pc_addr(context) & ~3); if (bad_inst & 0xfc001fe0) interrupt_handle_now(signal, siginfo, context); else { @@ -240,7 +240,7 @@ static void sigtrap_handler(int signal, static void sigfpe_handler(int signal, siginfo_t *siginfo, void *void_context) { os_context_t *context = arch_os_get_context(&void_context); - unsigned long badinst; + unsigned int badinst; int opcode, r1, r2, t; long op1, op2, res; @@ -251,7 +251,7 @@ static void sigfpe_handler(int signal, s switch (siginfo->si_code) { case FPE_INTOVF: /*I_OVFLO: */ - badinst = *(unsigned long *)(*os_context_pc_addr(context) & ~3); + badinst = *(unsigned int *)(*os_context_pc_addr(context) & ~3); opcode = badinst >> 26; if (opcode == 2) { @@ -301,7 +301,7 @@ static void sigfpe_handler(int signal, s break; case 0: /* I_COND: ?? Maybe tagged add?? FIXME */ - badinst = *(unsigned long *)(*os_context_pc_addr(context) & ~3); + badinst = *(unsigned int *)(*os_context_pc_addr(context) & ~3); if ((badinst&0xfffff800) == (0xb000e000|reg_ALLOC<<21|reg_ALLOC<<16)) { /* It is an ADDIT,OD i,ALLOC,ALLOC instruction that trapped. */ /* That means that it is the end of a pseudo-atomic. So do the */ @@ -333,11 +333,11 @@ static void sigfpe_handler(int signal, s static void sigbus_handler(int signal, siginfo_t *siginfo, void *void_context) { os_context_t *context = arch_os_get_context(&void_context); - unsigned long badinst; + unsigned int badinst; int opcode, r1, r2, t; long op1, op2, res; - badinst = *(unsigned long *)(*os_context_pc_addr(context) & ~3); + badinst = *(unsigned int *)(*os_context_pc_addr(context) & ~3); /* First, test for the pseudo-atomic instruction */ if ((badinst & 0xfffff800) == (0xb000e000 | reg_ALLOC<<21 | Index: src/runtime/mips-arch.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/mips-arch.c,v retrieving revision 1.16 diff -u -p -r1.16 mips-arch.c --- src/runtime/mips-arch.c 15 Sep 2005 17:42:36 -0000 1.16 +++ src/runtime/mips-arch.c 19 Sep 2005 18:35:19 -0000 @@ -236,33 +236,68 @@ arch_set_pseudo_atomic_interrupted(os_co *os_context_register_addr(context, reg_NL4) |= -1LL<<31; } -unsigned long +unsigned int arch_install_breakpoint(void *pc) { unsigned int *ptr = (unsigned int *)pc; unsigned int insn = *ptr; - unsigned long result; /* Don't install over a branch/jump with delay slot. */ if (arch_insn_with_bdelay_p(insn)) ptr++; - result = (unsigned long)insn; *ptr = (trap_Breakpoint << 6) | 0xd; os_flush_icache((os_vm_address_t)ptr, INSN_LEN); - return result; + return insn; +} + +static inline unsigned int +arch_install_after_breakpoint(void *pc) +{ + unsigned int *ptr = (unsigned int *)pc; + unsigned int insn = *ptr; + + /* Don't install over a branch/jump with delay slot. */ + if (arch_insn_with_bdelay_p(insn)) + ptr++; + + *ptr = (trap_AfterBreakpoint << 6) | 0xd; + os_flush_icache((os_vm_address_t)ptr, INSN_LEN); + + return insn; } void -arch_remove_breakpoint(void *pc, unsigned long orig_inst) +arch_remove_breakpoint(void *pc, unsigned int orig_inst) { unsigned int *ptr = (unsigned int *)pc; - *ptr = (unsigned int) orig_inst; + /* We may remove from a branch delay slot. */ + if (arch_insn_with_bdelay_p(orig_inst)) + ptr++; + + *ptr = orig_inst; os_flush_icache((os_vm_address_t)ptr, INSN_LEN); } +/* + * Perform the instruction that we overwrote with a breakpoint. As we + * don't have a single-step facility, this means we have to: + * - put the instruction back + * - put a second breakpoint at the following instruction, + * set after_breakpoint and continue execution. + * + * When the second breakpoint is hit (very shortly thereafter, we hope) + * sigtrap_handler gets called again, but follows the AfterBreakpoint + * arm, which + * - puts a bpt back in the first breakpoint place (running across a + * breakpoint shouldn't cause it to be uninstalled) + * - replaces the second bpt with the instruction it was meant to be + * - carries on + * + * Clear? + */ static unsigned int *skipped_break_addr, displaced_after_inst; static sigset_t orig_sigmask; @@ -270,29 +305,18 @@ void arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst) { unsigned int *pc = (unsigned int *)os_context_pc(context); - unsigned int *break_pc, *next_pc; - unsigned int next_inst; + unsigned int *next_pc; orig_sigmask = *os_context_sigmask_addr(context); sigaddset_blockable(os_context_sigmask_addr(context)); - /* Figure out where the breakpoint is, and what happens next. */ - if (os_context_bd_cause(context)) { - break_pc = pc+1; - next_inst = *pc; - } else { - break_pc = pc; - next_inst = orig_inst; - } - /* Put the original instruction back. */ - arch_remove_breakpoint(break_pc, orig_inst); - skipped_break_addr = break_pc; + arch_remove_breakpoint(pc, orig_inst); + skipped_break_addr = pc; /* Figure out where it goes. */ - next_pc = (unsigned int *)emulate_branch(context, next_inst); - - displaced_after_inst = arch_install_breakpoint(next_pc); + next_pc = (unsigned int *)emulate_branch(context, *pc); + displaced_after_inst = arch_install_after_breakpoint(next_pc); } static void @@ -328,7 +352,7 @@ sigtrap_handler(int signal, siginfo_t *i case trap_AfterBreakpoint: arch_remove_breakpoint(os_context_pc_addr(context), displaced_after_inst); - displaced_after_inst = arch_install_breakpoint(skipped_break_addr); + arch_install_breakpoint(skipped_break_addr); *os_context_sigmask_addr(context) = orig_sigmask; break; Index: src/runtime/ppc-arch.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/ppc-arch.c,v retrieving revision 1.15 diff -u -p -r1.15 ppc-arch.c --- src/runtime/ppc-arch.c 14 Jul 2005 15:41:20 -0000 1.15 +++ src/runtime/ppc-arch.c 19 Sep 2005 18:35:19 -0000 @@ -86,24 +86,41 @@ arch_set_pseudo_atomic_interrupted(os_co += PSEUDO_ATOMIC_INTERRUPTED_BIAS; } -unsigned long +unsigned int arch_install_breakpoint(void *pc) { - unsigned long *ptr = (unsigned long *)pc; - unsigned long result = *ptr; + unsigned int *ptr = (unsigned int *)pc; + unsigned int result = *ptr; *ptr = (3<<26) | (5 << 21) | trap_Breakpoint; - os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long)); + os_flush_icache((os_vm_address_t) pc, sizeof(unsigned int)); return result; } void -arch_remove_breakpoint(void *pc, unsigned long orig_inst) +arch_remove_breakpoint(void *pc, unsigned int orig_inst) { - *(unsigned long *)pc = orig_inst; - os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long)); + *(unsigned int *)pc = orig_inst; + os_flush_icache((os_vm_address_t) pc, sizeof(unsigned int)); } -static unsigned long *skipped_break_addr, displaced_after_inst; +/* + * Perform the instruction that we overwrote with a breakpoint. As we + * don't have a single-step facility, this means we have to: + * - put the instruction back + * - put a second breakpoint at the following instruction, + * set after_breakpoint and continue execution. + * + * When the second breakpoint is hit (very shortly thereafter, we hope) + * sigtrap_handler gets called again, but follows the AfterBreakpoint + * arm, which + * - puts a bpt back in the first breakpoint place (running across a + * breakpoint shouldn't cause it to be uninstalled) + * - replaces the second bpt with the instruction it was meant to be + * - carries on + * + * Clear? + */ +static unsigned int *skipped_break_addr, displaced_after_inst; static sigset_t orig_sigmask; void @@ -111,20 +128,20 @@ arch_do_displaced_inst(os_context_t *con { /* not sure how we ensure that we get the breakpoint reinstalled * after doing this -dan */ - unsigned long *pc = (unsigned long *)(*os_context_pc_addr(context)); + unsigned int *pc = (unsigned int *)(*os_context_pc_addr(context)); orig_sigmask = *os_context_sigmask_addr(context); sigaddset_blockable(os_context_sigmask_addr(context)); *pc = orig_inst; - os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long)); + os_flush_icache((os_vm_address_t) pc, sizeof(unsigned int)); skipped_break_addr = pc; } static void sigtrap_handler(int signal, siginfo_t *siginfo, os_context_t *context) { - u32 code; + unsigned int code; #ifdef LISP_FEATURE_LINUX os_restore_fp_control(context); #endif @@ -173,12 +190,12 @@ sigtrap_handler(int signal, siginfo_t *s case trap_AfterBreakpoint: *skipped_break_addr = trap_Breakpoint; skipped_break_addr = NULL; - *(unsigned long *)*os_context_pc_addr(context) + *(unsigned int *)*os_context_pc_addr(context) = displaced_after_inst; *os_context_sigmask_addr(context)= orig_sigmask; os_flush_icache((os_vm_address_t) *os_context_pc_addr(context), - sizeof(unsigned long)); + sizeof(unsigned int)); break; default: Index: src/runtime/sparc-arch.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/sparc-arch.c,v retrieving revision 1.14 diff -u -p -r1.14 sparc-arch.c --- src/runtime/sparc-arch.c 14 Jul 2005 15:41:21 -0000 1.14 +++ src/runtime/sparc-arch.c 19 Sep 2005 18:35:19 -0000 @@ -35,11 +35,11 @@ void arch_init(void) os_vm_address_t arch_get_bad_addr(int sig, siginfo_t *code, os_context_t *context) { - unsigned long badinst; - unsigned long *pc; + unsigned int badinst; + unsigned int *pc; int rs1; - pc = (unsigned long *)(*os_context_pc_addr(context)); + pc = (unsigned int *)(*os_context_pc_addr(context)); /* On the sparc, we have to decode the instruction. */ @@ -105,30 +105,47 @@ void arch_set_pseudo_atomic_interrupted( *os_context_register_addr(context,reg_ALLOC) |= 1; } -unsigned long arch_install_breakpoint(void *pc) +unsigned int arch_install_breakpoint(void *pc) { - unsigned long *ptr = (unsigned long *)pc; - unsigned long result = *ptr; + unsigned int *ptr = (unsigned int *)pc; + unsigned int result = *ptr; *ptr = trap_Breakpoint; - os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long)); + os_flush_icache((os_vm_address_t) pc, sizeof(unsigned int)); return result; } -void arch_remove_breakpoint(void *pc, unsigned long orig_inst) +void arch_remove_breakpoint(void *pc, unsigned int orig_inst) { - *(unsigned long *)pc = orig_inst; - os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long)); + *(unsigned int *)pc = orig_inst; + os_flush_icache((os_vm_address_t) pc, sizeof(unsigned int)); } -static unsigned long *skipped_break_addr, displaced_after_inst; +/* + * Perform the instruction that we overwrote with a breakpoint. As we + * don't have a single-step facility, this means we have to: + * - put the instruction back + * - put a second breakpoint at the following instruction, + * set after_breakpoint and continue execution. + * + * When the second breakpoint is hit (very shortly thereafter, we hope) + * sigtrap_handler gets called again, but follows the AfterBreakpoint + * arm, which + * - puts a bpt back in the first breakpoint place (running across a + * breakpoint shouldn't cause it to be uninstalled) + * - replaces the second bpt with the instruction it was meant to be + * - carries on + * + * Clear? + */ +static unsigned int *skipped_break_addr, displaced_after_inst; static sigset_t orig_sigmask; void arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst) { - unsigned long *pc = (unsigned long *)(*os_context_pc_addr(context)); - unsigned long *npc = (unsigned long *)(*os_context_npc_addr(context)); + unsigned int *pc = (unsigned int *)(*os_context_pc_addr(context)); + unsigned int *npc = (unsigned int *)(*os_context_npc_addr(context)); /* orig_sigmask = context->sigmask; sigemptyset(&context->sigmask); */ @@ -136,11 +153,11 @@ void arch_do_displaced_inst(os_context_t /* FILLBLOCKSET(&context->uc_sigmask);*/ *pc = orig_inst; - os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long)); + os_flush_icache((os_vm_address_t) pc, sizeof(unsigned int)); skipped_break_addr = pc; displaced_after_inst = *npc; *npc = trap_AfterBreakpoint; - os_flush_icache((os_vm_address_t) npc, sizeof(unsigned long)); + os_flush_icache((os_vm_address_t) npc, sizeof(unsigned int)); } @@ -227,10 +244,11 @@ static void sigill_handler(int signal, s case trap_AfterBreakpoint: *skipped_break_addr = trap_Breakpoint; + os_flush_icache(skipped_break_addr, sizeof(unsigned int)); skipped_break_addr = NULL; *(unsigned long *) os_context_pc_addr(context) = displaced_after_inst; /* context->sigmask = orig_sigmask; */ - os_flush_icache((os_vm_address_t) os_context_pc_addr(context), sizeof(unsigned long)); + os_flush_icache((os_vm_address_t) os_context_pc_addr(context), sizeof(unsigned int)); break; default: @@ -263,7 +281,7 @@ static void sigill_handler(int signal, s static void sigemt_handler(int signal, siginfo_t *siginfo, void *void_context) { - unsigned long badinst; + unsigned int badinst; boolean subtract, immed; int rd, rs1, op1, rs2, op2, result; os_context_t *context = arch_os_get_context(&void_context); @@ -271,7 +289,7 @@ static void sigemt_handler(int signal, s os_restore_fp_control(context); #endif - badinst = *(unsigned long *)os_context_pc_addr(context); + badinst = *(unsigned int *)os_context_pc_addr(context); if ((badinst >> 30) != 2 || ((badinst >> 20) & 0x1f) != 0x11) { /* It wasn't a tagged add. Pass the signal into lisp. */ interrupt_handle_now(signal, siginfo, context); Index: src/runtime/x86-64-arch.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-64-arch.c,v retrieving revision 1.6 diff -u -p -r1.6 x86-64-arch.c --- src/runtime/x86-64-arch.c 14 Jul 2005 15:41:21 -0000 1.6 +++ src/runtime/x86-64-arch.c 19 Sep 2005 18:35:19 -0000 @@ -130,10 +130,10 @@ arch_set_pseudo_atomic_interrupted(os_co * This stuff seems to get called for TRACE and debug activity. */ -unsigned long +unsigned int arch_install_breakpoint(void *pc) { - unsigned long result = *(unsigned long*)pc; + unsigned int result = *(unsigned int*)pc; *(char*)pc = BREAKPOINT_INST; /* x86 INT3 */ *((char*)pc+1) = trap_Breakpoint; /* Lisp trap code */ @@ -142,7 +142,7 @@ arch_install_breakpoint(void *pc) } void -arch_remove_breakpoint(void *pc, unsigned long orig_inst) +arch_remove_breakpoint(void *pc, unsigned int orig_inst) { *((char *)pc) = orig_inst & 0xff; *((char *)pc + 1) = (orig_inst & 0xff00) >> 8; @@ -150,7 +150,7 @@ arch_remove_breakpoint(void *pc, unsigne /* When single stepping, single_stepping holds the original instruction * PC location. */ -unsigned long *single_stepping = NULL; +unsigned int *single_stepping = NULL; #ifdef CANNOT_GET_TO_SINGLE_STEP_FLAG unsigned long single_step_save1; unsigned long single_step_save2; @@ -160,7 +160,7 @@ unsigned long single_step_save3; void arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst) { - unsigned long *pc = (unsigned long*)(*os_context_pc_addr(context)); + unsigned int *pc = (unsigned int*)(*os_context_pc_addr(context)); /* Put the original instruction back. */ *((char *)pc) = orig_inst & 0xff; @@ -179,7 +179,7 @@ arch_do_displaced_inst(os_context_t *con *context_eflags_addr(context) |= 0x100; #endif - single_stepping = (unsigned int*)pc; + single_stepping = pc; #ifdef CANNOT_GET_TO_SINGLE_STEP_FLAG *os_context_pc_addr(context) = (char *)pc - 9; Index: src/runtime/x86-arch.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-arch.c,v retrieving revision 1.31 diff -u -p -r1.31 x86-arch.c --- src/runtime/x86-arch.c 19 Aug 2005 12:15:16 -0000 1.31 +++ src/runtime/x86-arch.c 19 Sep 2005 18:35:19 -0000 @@ -131,10 +131,10 @@ arch_set_pseudo_atomic_interrupted(os_co * This stuff seems to get called for TRACE and debug activity. */ -unsigned long +unsigned int arch_install_breakpoint(void *pc) { - unsigned long result = *(unsigned long*)pc; + unsigned int result = *(unsigned int*)pc; *(char*)pc = BREAKPOINT_INST; /* x86 INT3 */ *((char*)pc+1) = trap_Breakpoint; /* Lisp trap code */ @@ -143,7 +143,7 @@ arch_install_breakpoint(void *pc) } void -arch_remove_breakpoint(void *pc, unsigned long orig_inst) +arch_remove_breakpoint(void *pc, unsigned int orig_inst) { *((char *)pc) = orig_inst & 0xff; *((char *)pc + 1) = (orig_inst & 0xff00) >> 8; @@ -180,7 +180,7 @@ arch_do_displaced_inst(os_context_t *con *context_eflags_addr(context) |= 0x100; #endif - single_stepping = (unsigned int*)pc; + single_stepping = pc; #ifdef CANNOT_GET_TO_SINGLE_STEP_FLAG *os_context_pc_addr(context) = (char *)pc - 9; |