diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2014-09-06 09:42:24 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2014-09-06 09:42:24 +0000 |
commit | 80c4a5e6590c3c153d2c40af7a931c334687251d (patch) | |
tree | 0b6e2b8c412de0865e66e9ed57847b8873173fe1 | |
parent | fc67eaa624ebcad11d73e46f431c766a22204e49 (diff) |
Rewrite the PowerPC stack dump routine to delimit the trap & interrupt
contexts with markers (---like on x86---) and print the associated type
or number when available.
While here, gyp' the support for process tracing (tr /p).
ok miod@
-rw-r--r-- | sys/arch/macppc/macppc/locore.S | 6 | ||||
-rw-r--r-- | sys/arch/powerpc/ddb/db_trace.c | 148 | ||||
-rw-r--r-- | sys/arch/powerpc/powerpc/trap.c | 17 | ||||
-rw-r--r-- | sys/arch/socppc/socppc/locore.S | 6 |
4 files changed, 109 insertions, 68 deletions
diff --git a/sys/arch/macppc/macppc/locore.S b/sys/arch/macppc/macppc/locore.S index b315f42a0c0..5c3717ebb9d 100644 --- a/sys/arch/macppc/macppc/locore.S +++ b/sys/arch/macppc/macppc/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.42 2013/12/29 21:06:37 miod Exp $ */ +/* $OpenBSD: locore.S,v 1.43 2014/09/06 09:42:22 mpi Exp $ */ /* $NetBSD: locore.S,v 1.2 1996/10/16 19:33:09 ws Exp $ */ /* @@ -887,6 +887,7 @@ realtrap: /* * Now the common trap catching code. */ + .globl s_trap s_trap: FRAME_SETUP(CI_TEMPSAVE) /* Now we can recover interrupts again: */ @@ -901,6 +902,8 @@ s_trap: trapagain: addi %r3,%r1,8 bl _C_LABEL(trap) + + .globl trapexit trapexit: /* Disable interrupts: */ mfmsr %r3 @@ -1180,6 +1183,7 @@ rfi3: rfi /* * Decrementer interrupt second level handler */ + .globl decrintr decrintr: INTRENTER addi %r3,%r1,8 /* intr frame */ diff --git a/sys/arch/powerpc/ddb/db_trace.c b/sys/arch/powerpc/ddb/db_trace.c index e233eca7c0f..95db2e870f6 100644 --- a/sys/arch/powerpc/ddb/db_trace.c +++ b/sys/arch/powerpc/ddb/db_trace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_trace.c,v 1.5 2014/07/13 12:11:01 jasper Exp $ */ +/* $OpenBSD: db_trace.c,v 1.6 2014/09/06 09:42:23 mpi Exp $ */ /* $NetBSD: db_trace.c,v 1.15 1996/02/22 23:23:41 gwr Exp $ */ /* @@ -30,10 +30,14 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> +#include <sys/user.h> + +#include <uvm/uvm_extern.h> #include <machine/db_machdep.h> #include <machine/signal.h> #include <machine/pcb.h> +#include <machine/pmap.h> #include <ddb/db_access.h> #include <ddb/db_sym.h> @@ -41,8 +45,6 @@ #include <ddb/db_interface.h> #include <ddb/db_output.h> -int db_read32(u_int32_t paddr, u_int32_t *value); - db_regs_t ddb_regs; struct db_variable db_regs[] = { @@ -88,8 +90,6 @@ struct db_variable db_regs[] = { struct db_variable *db_eregs = db_regs + nitems(db_regs); -extern label_t *db_recover; - /* * this is probably hackery. */ @@ -99,46 +99,16 @@ db_save_regs(struct trapframe *frame) bcopy(frame, &(ddb_regs.tf), sizeof (struct trapframe)); } -int -db_read32(u_int32_t paddr, u_int32_t *value) -{ - faultbuf env; - faultbuf *old_onfault = curpcb->pcb_onfault; - if (setfault(&env)) { - curpcb->pcb_onfault = old_onfault; - return EFAULT; - } - *value = *(u_int32_t *)paddr; - curpcb->pcb_onfault = old_onfault; - return 0; -} - -db_expr_t -db_dumpframe(u_int32_t pframe, int (*pr)(const char *, ...)) -{ - u_int32_t nextframe; - u_int32_t lr; - char *name; - db_expr_t offset; - - if (db_read32(pframe, &nextframe) == EFAULT) { - return 0; - } - - if (db_read32(pframe+4, &lr) == EFAULT) { - return 0; - } +/* from locore.S */ +extern db_addr_t trapexit; +extern db_addr_t esym; +#define INTSTK (8*1024) /* 8K interrupt stack */ - db_find_sym_and_offset(lr-4, &name, &offset); - if (!name) { - name = "0"; - offset = lr-4; - } - (*pr)("%08x: %s+0x%x fp %x nfp %x\n", - lr-4, name, offset, pframe, nextframe); +#define INKERNEL(va) (((vaddr_t)(va)) >= VM_MIN_KERNEL_ADDRESS && \ + ((vaddr_t)(va)) < VM_MAX_KERNEL_ADDRESS) - return nextframe; -} +#define ININTSTK(va) (((vaddr_t)(va)) >= round_page(esym) && \ + ((vaddr_t)(va)) < (round_page(esym) + INTSTK)) /* * Frame tracing. @@ -147,14 +117,92 @@ void db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count, char *modif, int (*pr)(const char *, ...)) { + db_addr_t lr, sp, lastsp; + db_expr_t offset; + db_sym_t sym; + char *name; + char c, *cp = modif; + int trace_proc = 0; + + while ((c = *cp++) != 0) { + if (c == 'p') + trace_proc = 1; + } - if (count == 0 || count == -1) - count = INT_MAX; - if (have_addr == 0){ - addr = ddb_regs.tf.fixreg[1]; + if (!have_addr) { + sp = ddb_regs.tf.fixreg[1]; + lr = ddb_regs.tf.srr0; + } else { + if (trace_proc) { + struct proc *p = pfind((pid_t)addr); + if (p == NULL) { + (*pr) ("db_trace.c: process not found\n"); + return; + } + addr = p->p_addr->u_pcb.pcb_sp; + } + sp = addr; + db_read_bytes(sp + 4, sizeof(db_addr_t), (char *)&lr); } - while (addr != 0 && count > 0) { - addr = db_dumpframe(addr, pr); - count --; + + while (count && sp != 0) { + /* + * lr contains the return address, so adjust its value + * to display the offset of the calling address. + */ + sym = db_search_symbol(lr - 4, DB_STGY_ANY, &offset); + db_symbol_values(sym, &name, NULL); + + if (name == NULL || strcmp(name, "end") == 0) { + (*pr)("at 0x%lx", lr - 4); + } else { + (*pr)("%s() at ", name); + db_printsym(lr - 4, DB_STGY_PROC, pr); + } + (*pr)("\n"); + + lastsp = sp; + + /* + * Abuse the fact that the return address of the trap() + * function is always 'trapexit'. + */ + if (lr == (db_addr_t)&trapexit) { + struct trapframe *tf = (struct trapframe *)(sp + 8); + uint32_t code = tf->fixreg[0]; + uint32_t type = tf->exc; + + if (tf->srr1 & PSL_PR) + type |= EXC_USER; + + if (type == (EXC_SC|EXC_USER)) + (*pr)("--- syscall (number %d) ---\n", code); + else + (*pr)("--- trap (type 0x%x) ---\n", type); + } + + db_read_bytes(sp, sizeof(db_addr_t), (char *)&sp); + if (sp == 0) + break; + + db_read_bytes(sp + 4, sizeof(db_addr_t), (char *)&lr); + + if (INKERNEL(sp)) { + if (sp <= lastsp) { + (*pr)("Bad frame pointer: 0x%lx\n", sp); + break; + } + + if (ININTSTK(lastsp)) + (*pr)("--- interrupt ---\n"); + + } else { + if (!ININTSTK(sp)) { + (*pr)("End of kernel: 0x%lx\n", sp); + break; + } + } + --count; } + (*pr)("end trace frame: 0x%lx, count: %d\n", sp, count); } diff --git a/sys/arch/powerpc/powerpc/trap.c b/sys/arch/powerpc/powerpc/trap.c index df85ef245be..6915c9c6121 100644 --- a/sys/arch/powerpc/powerpc/trap.c +++ b/sys/arch/powerpc/powerpc/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.101 2014/07/09 08:32:57 deraadt Exp $ */ +/* $OpenBSD: trap.c,v 1.102 2014/09/06 09:42:23 mpi Exp $ */ /* $NetBSD: trap.c,v 1.3 1996/10/13 03:31:37 christos Exp $ */ /* @@ -66,21 +66,6 @@ void trap(struct trapframe *frame); #define NARGREG 8 /* 8 args are in registers */ #define MOREARGS(sp) ((caddr_t)((int)(sp) + 8)) /* more args go here */ -#ifdef DDB -void ppc_dumpbt(struct trapframe *frame); - -void -ppc_dumpbt(struct trapframe *frame) -{ - u_int32_t addr; - /* dumpframe is defined in db_trace.c */ - addr=frame->fixreg[1]; - while (addr != 0) - addr = db_dumpframe(addr, db_printf); - return; -} -#endif - #ifdef ALTIVEC /* * Save state of the vector processor, This is done lazily in the hope diff --git a/sys/arch/socppc/socppc/locore.S b/sys/arch/socppc/socppc/locore.S index d73fd2f5eda..b686a50f90c 100644 --- a/sys/arch/socppc/socppc/locore.S +++ b/sys/arch/socppc/socppc/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.9 2013/12/29 21:06:37 miod Exp $ */ +/* $OpenBSD: locore.S,v 1.10 2014/09/06 09:42:23 mpi Exp $ */ /* $NetBSD: locore.S,v 1.2 1996/10/16 19:33:09 ws Exp $ */ /* @@ -906,6 +906,7 @@ realtrap: /* * Now the common trap catching code. */ + .globl s_trap s_trap: FRAME_SETUP(CI_TEMPSAVE) /* Now we can recover interrupts again: */ @@ -920,6 +921,8 @@ s_trap: trapagain: addi %r3,%r1,8 bl _C_LABEL(trap) + + .globl trapexit trapexit: /* Disable interrupts: */ mfmsr %r3 @@ -1199,6 +1202,7 @@ rfi3: rfi /* * Decrementer interrupt second level handler */ + .globl decrintr decrintr: INTRENTER addi %r3,%r1,8 /* intr frame */ |