diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2005-12-04 12:14:11 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2005-12-04 12:14:11 +0000 |
commit | 1a6b6052298833348054d8c0369aa3625e92782a (patch) | |
tree | fb419b7c5f6d4642f9a5ed077eec8390bdff3dd4 | |
parent | 94996bfa764162035342c47b5c50a43f25ba97e7 (diff) |
Simplify ptrace branch handling code.
-rw-r--r-- | sys/arch/m88k/m88k/trap.c | 148 |
1 files changed, 41 insertions, 107 deletions
diff --git a/sys/arch/m88k/m88k/trap.c b/sys/arch/m88k/m88k/trap.c index bfcda591eb7..9919a23355b 100644 --- a/sys/arch/m88k/m88k/trap.c +++ b/sys/arch/m88k/m88k/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.25 2005/12/03 14:30:06 miod Exp $ */ +/* $OpenBSD: trap.c,v 1.26 2005/12/04 12:14:10 miod Exp $ */ /* * Copyright (c) 2004, Miodrag Vallat. * Copyright (c) 1998 Steve Murphree, Jr. @@ -107,6 +107,7 @@ const char *trap_type[] = { }; const int trap_types = sizeof trap_type / sizeof trap_type[0]; +#ifdef M88100 const char *pbus_exception_type[] = { "Success (No Fault)", "unknown 1", @@ -117,6 +118,7 @@ const char *pbus_exception_type[] = { "Supervisor Violation", "Write Violation", }; +#endif static inline void userret(struct proc *p, struct trapframe *frame, u_quad_t oticks) @@ -258,9 +260,6 @@ m88100_trap(unsigned type, struct trapframe *frame) break; case T_INT: case T_INT+T_USER: - /* This function pointer is set in machdep.c - It calls m188_ext_int or sbc_ext_int depending - on the value of brdtyp - smurph */ curcpu()->ci_intrdepth++; md_interrupt_func(T_INT, frame); curcpu()->ci_intrdepth--; @@ -1111,15 +1110,6 @@ m88100_syscall(register_t code, struct trapframe *tf) callp = p->p_emul->e_sysent; nsys = p->p_emul->e_nsysent; -#ifdef DIAGNOSTIC - if (USERMODE(tf->tf_epsr) == 0) - panic("syscall"); - if (curpcb != &p->p_addr->u_pcb) - panic("syscall curpcb/ppcb"); - if (tf != (struct trapframe *)&curpcb->user_state) - panic("syscall trapframe"); -#endif - sticks = p->p_sticks; p->p_md.md_tf = tf; @@ -1269,15 +1259,6 @@ m88110_syscall(register_t code, struct trapframe *tf) callp = p->p_emul->e_sysent; nsys = p->p_emul->e_nsysent; -#ifdef DIAGNOSTIC - if (USERMODE(tf->tf_epsr) == 0) - panic("syscall"); - if (curpcb != &p->p_addr->u_pcb) - panic("syscall curpcb/ppcb"); - if (tf != (struct trapframe *)&curpcb->user_state) - panic("syscall trapframe"); -#endif - sticks = p->p_sticks; p->p_md.md_tf = tf; @@ -1363,13 +1344,6 @@ m88110_syscall(register_t code, struct trapframe *tf) switch (error) { case 0: - /* - * If fork succeeded and we are the child, our stack - * has moved and the pointer tf is no longer valid, - * and p is wrong. Compute the new trapframe pointer. - * (The trap frame invariably resides at the - * tippity-top of the u. area.) - */ tf->tf_r[2] = rval[0]; tf->tf_r[3] = rval[1]; tf->tf_epsr &= ~PSR_C; @@ -1467,12 +1441,9 @@ child_return(arg) #include <sys/ptrace.h> -vaddr_t ss_branch_taken(u_int, vaddr_t, u_int (*func)(u_int, struct reg *), - struct reg *); -u_int ss_getreg_val(u_int, struct reg *); +vaddr_t ss_branch_taken(u_int, vaddr_t, struct reg *); int ss_get_value(struct proc *, vaddr_t, u_int *); -int ss_inst_branch(unsigned); -int ss_inst_delayed(unsigned); +int ss_inst_branch_or_call(u_int); int ss_put_breakpoint(struct proc *, vaddr_t, vaddr_t *, u_int *); #define SYSCALL_INSTR 0xf000d080 /* tb0 0,r0,128 */ @@ -1514,114 +1485,78 @@ ss_put_value(struct proc *p, vaddr_t addr, u_int value) } /* - * ss_branch_taken(instruction, program counter, func, func_data) + * ss_branch_taken(instruction, pc, regs) * * instruction will be a control flow instruction location at address pc. * Branch taken is supposed to return the address to which the instruction - * would jump if the branch is taken. Func can be used to get the current - * register values when invoked with a register number and func_data as - * arguments. + * would jump if the branch is taken. * - * If the instruction is not a control flow instruction, panic. + * This is different from branch_taken() in ddb, as we also need to process + * system calls. */ vaddr_t -ss_branch_taken(u_int inst, vaddr_t pc, u_int (*func)(u_int, struct reg *), - struct reg *func_data) +ss_branch_taken(u_int inst, vaddr_t pc, struct reg *regs) { - /* check for system call */ - if (inst == SYSCALL_INSTR) { - /* - * The regular (pc + 4) breakpoint will match the error - * return. Successfull system calls return at (pc + 8), - * so we'll set up a branch breakpoint there. - */ - return (pc + 8); - } + u_int regno; - /* check if br/bsr */ - if ((inst & 0xf0000000) == 0xc0000000) { - /* signed 26 bit pc relative displacement, shift left two bits */ + /* + * Quick check of the instruction. Note that we know we are only + * invoked if ss_inst_branch_or_call() returns TRUE, so we do not + * need to repeat the jpm, jsr and syscall stricter checks here. + */ + switch (inst >> (32 - 5)) { + case 0x18: /* br */ + case 0x19: /* bsr */ + /* signed 26 bit pc relative displacement, shift left 2 bits */ inst = (inst & 0x03ffffff) << 2; /* check if sign extension is needed */ if (inst & 0x08000000) inst |= 0xf0000000; return (pc + inst); - } - /* check if bb0/bb1/bcnd case */ - switch (inst & 0xf8000000) { - case 0xd0000000: /* bb0 */ - case 0xd8000000: /* bb1 */ - case 0xe8000000: /* bcnd */ - /* signed 16 bit pc relative displacement, shift left two bits */ + case 0x1a: /* bb0 */ + case 0x1b: /* bb1 */ + case 0x1d: /* bcnd */ + /* signed 16 bit pc relative displacement, shift left 2 bits */ inst = (inst & 0x0000ffff) << 2; /* check if sign extension is needed */ if (inst & 0x00020000) inst |= 0xfffc0000; return (pc + inst); - } - - /* check jmp/jsr case */ - /* check bits 5-31, skipping 10 & 11 */ - if ((inst & 0xfffff3e0) == 0xf400c000) - return (*func)(inst & 0x1f, func_data); /* the register value */ - /* can't happen */ - return (0); -} + case 0x1e: /* jmp or jsr */ + regno = inst & 0x1f; /* get the register value */ + return (regno == 0 ? 0 : regs->r[regno]); -/* - * ss_getreg_val - handed a register number and an exception frame. - * Returns the value of the register in the specified - * frame. Only makes sense for general registers. - */ -u_int -ss_getreg_val(u_int regno, struct reg *regs) -{ - return (regno == 0 ? 0 : regs->r[regno]); + default: /* system call */ + /* + * The regular (pc + 4) breakpoint will match the error + * return. Successfull system calls return at (pc + 8), + * so we'll set up a branch breakpoint there. + */ + return (pc + 8); + } } int -ss_inst_branch(u_int ins) +ss_inst_branch_or_call(u_int ins) { /* check high five bits */ - switch (ins >> (32 - 5)) { case 0x18: /* br */ + case 0x19: /* bsr */ case 0x1a: /* bb0 */ case 0x1b: /* bb1 */ case 0x1d: /* bcnd */ return (TRUE); - break; - case 0x1e: /* could be jmp */ - if ((ins & 0xfffffbe0) == 0xf400c000) + case 0x1e: /* could be jmp or jsr */ + if ((ins & 0xfffff3e0) == 0xf400c000) return (TRUE); } return (FALSE); } -/* ss_inst_delayed - this instruction is followed by a delay slot. Could be - br.n, bsr.n bb0.n, bb1.n, bcnd.n or jmp.n or jsr.n */ - -int -ss_inst_delayed(u_int ins) -{ - /* check the br, bsr, bb0, bb1, bcnd cases */ - switch ((ins & 0xfc000000) >> (32 - 6)) { - case 0x31: /* br */ - case 0x33: /* bsr */ - case 0x35: /* bb0 */ - case 0x37: /* bb1 */ - case 0x3b: /* bcnd */ - return (TRUE); - } - - /* check the jmp, jsr cases */ - /* mask out bits 0-4, bit 11 */ - return (((ins & 0xfffff7e0) == 0xf400c400) ? TRUE : FALSE); -} - int ss_put_breakpoint(struct proc *p, vaddr_t va, vaddr_t *bpva, u_int *bpsave) { @@ -1676,9 +1611,8 @@ process_sstep(struct proc *p, int sstep) * Find if this instruction may cause a branch, and set up a breakpoint * at the branch location. */ - if (ss_inst_branch(instr) || inst_call(instr) || inst_return(instr) || - instr == SYSCALL_INSTR) { - brpc = ss_branch_taken(instr, pc, ss_getreg_val, sstf); + if (ss_inst_branch_or_call(instr) || instr == SYSCALL_INSTR) { + brpc = ss_branch_taken(instr, pc, sstf); /* self-branches are hopeless */ if (brpc != pc && brpc != 0) { |