From 1a13dcc2ab127a947b3ef36eaa865655ef21b4c7 Mon Sep 17 00:00:00 2001 From: wlott <wlott> Date: Mon, 8 Nov 1993 00:07:29 +0000 Subject: [PATCH] HP breakpoint support. --- lisp/breakpoint.c | 11 +++++- lisp/hppa-arch.c | 94 +++++++++++++++++++++++++++++++++++------------ lisp/hppa-assem.S | 33 +++++++++++++++++ lisp/hppa-assem.s | 33 +++++++++++++++++ 4 files changed, 146 insertions(+), 25 deletions(-) diff --git a/lisp/breakpoint.c b/lisp/breakpoint.c index d57d80d98..1e3979ff4 100644 --- a/lisp/breakpoint.c +++ b/lisp/breakpoint.c @@ -37,7 +37,9 @@ void breakpoint_remove(lispobj code_obj, int pc_offset, void breakpoint_do_displaced_inst(struct sigcontext *scp, unsigned long orig_inst) { +#ifndef hpux undo_fake_foreign_function_call(scp); +#endif arch_do_displaced_inst(scp, orig_inst); } @@ -67,13 +69,18 @@ static int compute_offset(struct sigcontext *scp, lispobj code) else { unsigned long code_start; struct code *codeptr = (struct code *)PTR(code); +#ifdef parisc + unsigned long pc = SC_PC(scp) & ~3; +#else + unsigned long pc = SC_PC(scp); +#endif code_start = (unsigned long)codeptr + HeaderValue(codeptr->header)*sizeof(lispobj); - if (SC_PC(scp) < code_start) + if (pc < code_start) return 0; else { - int offset = SC_PC(scp) - code_start; + int offset = pc - code_start; if (offset >= codeptr->code_size) return 0; else diff --git a/lisp/hppa-arch.c b/lisp/hppa-arch.c index 4937317c9..137fe0419 100644 --- a/lisp/hppa-arch.c +++ b/lisp/hppa-arch.c @@ -30,12 +30,12 @@ os_vm_address_t arch_get_bad_addr(int signal, return NULL; /* Check the instruction address first. */ - addr = scp->sc_pcoq_head & ~3; - if (addr < 0x1000) + addr = (os_vm_address_t)((unsigned long)scp->sc_pcoq_head & ~3); + if (addr < (os_vm_address_t)0x1000) return addr; /* Otherwise, it must have been a data fault. */ - return state->ss_cr21; + return (os_vm_address_t)state->ss_cr21; #else struct hp800_thread_state *state; os_vm_address_t addr; @@ -99,6 +99,7 @@ unsigned long arch_install_breakpoint(void *pc) unsigned long orig_inst = *ulpc; *ulpc = trap_Breakpoint; + os_flush_icache((os_vm_address_t)pc, sizeof(*ulpc)); return orig_inst; } @@ -107,33 +108,79 @@ void arch_remove_breakpoint(void *pc, unsigned long orig_inst) unsigned long *ulpc = (unsigned long *)pc; *ulpc = orig_inst; + os_flush_icache((os_vm_address_t)pc, sizeof(*ulpc)); } +#ifdef hpux +extern void SingleStepTraps(); +static unsigned long *BreakpointAddr = NULL; +static unsigned long NextPc = NULL; +#endif + void arch_do_displaced_inst(struct sigcontext *scp, unsigned long orig_inst) { +#ifdef hpux + /* 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); + + NextPc = SC_NPC(scp); + SC_NPC(scp) = (unsigned)SingleStepTraps | (SC_NPC(scp)&3); + + BreakpointAddr = pc; + *pc = orig_inst; + os_flush_icache((os_vm_address_t)pc, sizeof(unsigned long)); +#else /* We set the recovery counter to cover one instruction, put the */ /* original instruction back in, and then resume. We will then trap */ /* after executing that one instruction, at which time we can put */ /* the breakpoint back in. */ -#ifdef hpux - scp->sc_sl.sl_ss.ss_cr0 = 1; - scp->sc_flags |= 0x10; -#else ((struct hp800_thread_state *)scp->sc_ap)->cr0 = 1; scp->sc_ps |= 0x10; -#endif *(unsigned long *)SC_PC(scp) = orig_inst; - undo_fake_foreign_function_call(scp); - -#ifdef hpux - printf("ERROR: arch_do_displaced_inst doesn't work because no sigreturn\n"); -#else sigreturn(scp); #endif } +#ifdef hpux +static void restore_breakpoint(struct sigcontext *scp) +{ + /* We just single-stepped over an instruction that we want to replace */ + /* with a breakpoint. So we put the breakpoint back in, and tweek the */ + /* state so that we will continue as if nothing happened. */ + + if (NextPc == NULL) + lose("SingleStepBreakpoint trap at strange time."); + + if ((SC_PC(scp)&~3) == (unsigned long)SingleStepTraps) { + /* The next instruction was not nullified. */ + SC_PC(scp) = NextPc; + if ((SC_NPC(scp)&~3) == (unsigned long)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. */ + SC_NPC(scp) = NextPc + 4; + } + } + else { + /* The next instruction was nullified, so we want to skip it. */ + SC_PC(scp) = NextPc + 4; + SC_NPC(scp) = NextPc + 8; + } + NextPc = NULL; + + if (BreakpointAddr) { + *BreakpointAddr = trap_Breakpoint; + os_flush_icache((os_vm_address_t)BreakpointAddr, + sizeof(unsigned long)); + BreakpointAddr = NULL; + } +} +#endif + static void sigtrap_handler(int signal, int code, struct sigcontext *scp) { unsigned long bad_inst; @@ -173,26 +220,27 @@ static void sigtrap_handler(int signal, int code, struct sigcontext *scp) case trap_Breakpoint: sigsetmask(scp->sc_mask); - fake_foreign_function_call(scp); handle_breakpoint(signal, code, scp); - undo_fake_foreign_function_call(scp); break; case trap_FunctionEndBreakpoint: sigsetmask(scp->sc_mask); - fake_foreign_function_call(scp); { - void *pc; - pc = handle_function_end_breakpoint(signal, code, scp); + unsigned long pc; + pc = (unsigned long) + handle_function_end_breakpoint(signal, code, scp); #ifdef hpux - scp->sc_pcoq_head = (unsigned long)pc; - scp->sc_pcoq_tail = (unsigned long)pc + 4; + scp->sc_pcoq_head = pc; + scp->sc_pcoq_tail = pc + 4; #else - scp->sc_pcoqh = (unsigned long)pc; - scp->sc_pcoqt = (unsigned long)pc + 4; + scp->sc_pcoqh = pc; + scp->sc_pcoqt = pc + 4; #endif } - undo_fake_foreign_function_call(scp); + break; + + case trap_SingleStepBreakpoint: + restore_breakpoint(scp); break; default: diff --git a/lisp/hppa-assem.S b/lisp/hppa-assem.S index b71977f2b..2770bc528 100644 --- a/lisp/hppa-assem.S +++ b/lisp/hppa-assem.S @@ -334,3 +334,36 @@ restore_state b _restore_state copy arg1,ret0 .procend + + + + .export SingleStepTraps +SingleStepTraps + break trap_SingleStepBreakpoint,0 + break trap_SingleStepBreakpoint,0 + + + + .align 8 + .export function_end_breakpoint_guts +function_end_breakpoint_guts + .word type_ReturnPcHeader + /* multiple value return point -- just jump to trap. */ + b,n function_end_breakpoint_trap + /* single value return point -- convert to multiple w/ n=1 */ + copy reg_CSP, reg_OCFP + addi 4, reg_CSP, reg_CSP + addi 4, r0, reg_NARGS + copy reg_NULL, reg_A1 + copy reg_NULL, reg_A2 + copy reg_NULL, reg_A3 + copy reg_NULL, reg_A4 + copy reg_NULL, reg_A5 + + .export function_end_breakpoint_trap +function_end_breakpoint_trap + break trap_FunctionEndBreakpoint,0 + b,n function_end_breakpoint_trap + + .export function_end_breakpoint_end +function_end_breakpoint_end diff --git a/lisp/hppa-assem.s b/lisp/hppa-assem.s index b71977f2b..2770bc528 100644 --- a/lisp/hppa-assem.s +++ b/lisp/hppa-assem.s @@ -334,3 +334,36 @@ restore_state b _restore_state copy arg1,ret0 .procend + + + + .export SingleStepTraps +SingleStepTraps + break trap_SingleStepBreakpoint,0 + break trap_SingleStepBreakpoint,0 + + + + .align 8 + .export function_end_breakpoint_guts +function_end_breakpoint_guts + .word type_ReturnPcHeader + /* multiple value return point -- just jump to trap. */ + b,n function_end_breakpoint_trap + /* single value return point -- convert to multiple w/ n=1 */ + copy reg_CSP, reg_OCFP + addi 4, reg_CSP, reg_CSP + addi 4, r0, reg_NARGS + copy reg_NULL, reg_A1 + copy reg_NULL, reg_A2 + copy reg_NULL, reg_A3 + copy reg_NULL, reg_A4 + copy reg_NULL, reg_A5 + + .export function_end_breakpoint_trap +function_end_breakpoint_trap + break trap_FunctionEndBreakpoint,0 + b,n function_end_breakpoint_trap + + .export function_end_breakpoint_end +function_end_breakpoint_end -- GitLab