diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2001-08-19 16:05:13 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2001-08-19 16:05:13 +0000 |
commit | 12f4b98746a067f0fd2a2a3c31a7bee6c0a3676a (patch) | |
tree | 952b089508c14afd9973168c3f454f5a320d454f /sys | |
parent | 3f6b211612007bd74d9e379c6b50ab9dc6cf2d9d (diff) |
db_trace from NetBSD.
minimal mods to fit our ddb.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc64/sparc64/db_trace.c | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/sys/arch/sparc64/sparc64/db_trace.c b/sys/arch/sparc64/sparc64/db_trace.c new file mode 100644 index 00000000000..404da7b7c1e --- /dev/null +++ b/sys/arch/sparc64/sparc64/db_trace.c @@ -0,0 +1,533 @@ +/* $NetBSD: db_trace.c,v 1.23 2001/07/10 06:06:16 eeh Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/user.h> +#include <machine/db_machdep.h> +#include <machine/ctlreg.h> + +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_interface.h> +#include <ddb/db_output.h> + +void db_dump_fpstate __P((db_expr_t, int, db_expr_t, char *)); +void db_dump_window __P((db_expr_t, int, db_expr_t, char *)); +void db_dump_stack __P((db_expr_t, int, db_expr_t, char *)); +void db_dump_trap __P((db_expr_t, int, db_expr_t, char *)); +void db_dump_ts __P((db_expr_t, int, db_expr_t, char *)); +void db_print_window __P((u_int64_t)); + +#if 0 +#define INKERNEL(va) (((vaddr_t)(va)) >= USRSTACK) /* Not really true, y'know */ +#else +#define INKERNEL(va) 1 /* Everything's in the kernel now. 8^) */ +#endif + +#define KLOAD(x) probeget((paddr_t)(u_long)&(x), ASI_PRIMARY, sizeof(x)) +#define ULOAD(x) probeget((paddr_t)(u_long)&(x), ASI_AIUS, sizeof(x)) + +void +db_stack_trace_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + vaddr_t frame; + boolean_t kernel_only = TRUE; + boolean_t trace_thread = FALSE; + char c, *cp = modif; + int (*pr) __P((const char *, ...)); + + pr = db_printf; + + while ((c = *cp++) != 0) { + if (c == 't') + trace_thread = TRUE; + if (c == 'u') + kernel_only = FALSE; + } + + if (!have_addr) + frame = (vaddr_t)DDB_TF->tf_out[6]; + else { + if (trace_thread) { + struct proc *p; + struct user *u; + (*pr)("trace: pid %d ", (int)addr); + p = pfind(addr); + if (p == NULL) { + (*pr)("not found\n"); + return; + } + if ((p->p_flag & P_INMEM) == 0) { + (*pr)("swapped out\n"); + return; + } + u = p->p_addr; + frame = (vaddr_t)u->u_pcb.pcb_sp; + (*pr)("at %p\n", frame); + } else { + frame = (vaddr_t)addr; + } + } + + while (count--) { + int i; + db_expr_t offset; + char *name; + db_addr_t pc; + struct frame64 *f64; + struct frame32 *f32; + + /* + * Switch to frame that contains arguments + */ + if (frame & 1) { + f64 = (struct frame64 *)(frame + BIAS); + pc = (db_addr_t)KLOAD(f64->fr_pc); + + frame = KLOAD(f64->fr_fp); + } else { + f32 = (struct frame32 *)(frame); + pc = (db_addr_t)KLOAD(f32->fr_pc); + + frame = (long)KLOAD(f32->fr_fp); + } + + if (kernel_only) { + if (pc < KERNBASE || pc >= KERNEND) + break; + if (frame < KERNBASE || frame >= EINTSTACK) + break; + } else { + if (frame == 0 || frame == (vaddr_t)-1) + break; + } +#if 0 + if (!INKERNEL(frame)) + break; +#endif + + db_find_sym_and_offset(pc, &name, &offset); + if (name == NULL) + name = "?"; + + (*pr)("%s(", name); + + /* + * Print %i0..%i5; hope these still reflect the + * actual arguments somewhat... + */ + if (frame & 1) { + f64 = (struct frame64 *)(frame + BIAS); + for (i = 0; i < 5; i++) + (*pr)("%lx, ", (long)KLOAD(f64->fr_arg[i])); + (*pr)("%lx) at ", (long)KLOAD(f64->fr_arg[i])); + } else { + f32 = (struct frame32 *)(frame); + for (i = 0; i < 5; i++) + (*pr)("%x, ", (u_int)KLOAD(f32->fr_arg[i])); + (*pr)("%x) at ", (u_int)KLOAD(f32->fr_arg[i])); + } + db_printsym(pc, DB_STGY_PROC); + (*pr)("\n"); + } +} + + +void +db_dump_window(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + int i; + u_int64_t frame = DDB_TF->tf_out[6]; + + /* Addr is really window number */ + if (!have_addr) + addr = 0; + + /* Traverse window stack */ + for (i=0; i<addr && frame; i++) { + if (frame & 1) + frame = (u_int64_t)((struct frame64 *)(u_long)(frame + BIAS))->fr_fp; + else frame = (u_int64_t)((struct frame32 *)(u_long)frame)->fr_fp; + } + + db_printf("Window %lx ", addr); + db_print_window(frame); +} + +void +db_print_window(frame) +u_int64_t frame; +{ + if (frame & 1) { + struct frame64* f = (struct frame64*)(u_long)(frame + BIAS); + + db_printf("frame64 %p locals, ins:\n", f); + if (INKERNEL(f)) { + db_printf("%llx %llx %llx %llx ", + (unsigned long long)f->fr_local[0], + (unsigned long long)f->fr_local[1], + (unsigned long long)f->fr_local[2], + (unsigned long long)f->fr_local[3]); + db_printf("%llx %llx %llx %llx\n", + (unsigned long long)f->fr_local[4], + (unsigned long long)f->fr_local[5], + (unsigned long long)f->fr_local[6], + (unsigned long long)f->fr_local[7]); + db_printf("%llx %llx %llx %llx ", + (unsigned long long)f->fr_arg[0], + (unsigned long long)f->fr_arg[1], + (unsigned long long)f->fr_arg[2], + (unsigned long long)f->fr_arg[3]); + db_printf("%llx %llx %llx=sp %llx=pc:", + (unsigned long long)f->fr_arg[4], + (unsigned long long)f->fr_arg[5], + (unsigned long long)f->fr_fp, + (unsigned long long)f->fr_pc); + /* Sometimes this don't work. Dunno why. */ + db_printsym(f->fr_pc, DB_STGY_PROC); + db_printf("\n"); + } else { + struct frame64 fr; + + if (copyin(f, &fr, sizeof(fr))) return; + f = &fr; + db_printf("%llx %llx %llx %llx ", + (unsigned long long)f->fr_local[0], (unsigned long long)f->fr_local[1], (unsigned long long)f->fr_local[2], (unsigned long long)f->fr_local[3]); + db_printf("%llx %llx %llx %llx\n", + (unsigned long long)f->fr_local[4], (unsigned long long)f->fr_local[5], (unsigned long long)f->fr_local[6], (unsigned long long)f->fr_local[7]); + db_printf("%llx %llx %llx %llx ", + (unsigned long long)f->fr_arg[0], + (unsigned long long)f->fr_arg[1], + (unsigned long long)f->fr_arg[2], + (unsigned long long)f->fr_arg[3]); + db_printf("%llx %llx %llx=sp %llx=pc", + (unsigned long long)f->fr_arg[4], + (unsigned long long)f->fr_arg[5], + (unsigned long long)f->fr_fp, + (unsigned long long)f->fr_pc); + db_printf("\n"); + } + } else { + struct frame32* f = (struct frame32*)(u_long)frame; + + db_printf("frame %p locals, ins:\n", f); + if (INKERNEL(f)) { + db_printf("%8x %8x %8x %8x %8x %8x %8x %8x\n", + f->fr_local[0], f->fr_local[1], f->fr_local[2], f->fr_local[3], + f->fr_local[4], f->fr_local[5], f->fr_local[6], f->fr_local[7]); + db_printf("%8x %8x %8x %8x %8x %8x %8x=sp %8x=pc:", + f->fr_arg[0], f->fr_arg[1], f->fr_arg[2], f->fr_arg[3], + f->fr_arg[4], f->fr_arg[5], f->fr_fp, f->fr_pc); + db_printsym(f->fr_pc, DB_STGY_PROC); + db_printf("\n"); + } else { + struct frame32 fr; + + if (copyin(f, &fr, sizeof(fr))) return; + f = &fr; + db_printf("%8x %8x %8x %8x %8x %8x %8x %8x\n", + f->fr_local[0], f->fr_local[1], + f->fr_local[2], f->fr_local[3], + f->fr_local[4], f->fr_local[5], + f->fr_local[6], f->fr_local[7]); + db_printf("%8x %8x %8x %8x %8x %8x %8x=sp %8x=pc\n", + f->fr_arg[0], f->fr_arg[1], + f->fr_arg[2], f->fr_arg[3], + f->fr_arg[4], f->fr_arg[5], + f->fr_fp, f->fr_pc); + } + } +} + +void +db_dump_stack(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + int i; + u_int64_t frame, oldframe; + boolean_t kernel_only = TRUE; + char c, *cp = modif; + + while ((c = *cp++) != 0) + if (c == 'u') + kernel_only = FALSE; + + if (count == -1) + count = 65535; + + if (!have_addr) + frame = DDB_TF->tf_out[6]; + else + frame = addr; + + /* Traverse window stack */ + oldframe = 0; + for (i=0; i<count && frame; i++) { + if (oldframe == frame) { + db_printf("WARNING: stack loop at %llx\n", + (unsigned long long) frame); + break; + } + oldframe = frame; + if (frame & 1) { + frame += BIAS; + if (!INKERNEL(((struct frame64 *)(u_long)(frame))) + && kernel_only) break; + db_printf("Window %x ", i); + db_print_window(frame - BIAS); + if (!INKERNEL(((struct frame64 *)(u_long)(frame)))) + copyin(((caddr_t)&((struct frame64 *)(u_long)frame)->fr_fp), &frame, sizeof(frame)); + else + frame = ((struct frame64 *)(u_long)frame)->fr_fp; + } else { + u_int32_t tmp; + if (!INKERNEL(((struct frame32 *)(u_long)frame)) + && kernel_only) break; + db_printf("Window %x ", i); + db_print_window(frame); + if (!INKERNEL(((struct frame32 *)(u_long)frame))) { + copyin(&((struct frame32 *)(u_long)frame)->fr_fp, &tmp, sizeof(tmp)); + frame = (u_int64_t)tmp; + } else + frame = (u_int64_t)((struct frame32 *)(u_long)frame)->fr_fp; + } + } + +} + + +void +db_dump_trap(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + struct trapframe64 *tf; + + /* Use our last trapframe? */ + tf = &ddb_regs.ddb_tf; + { + /* Or the user trapframe? */ + register char c, *cp = modif; + while ((c = *cp++) != 0) + if (c == 'u') + tf = curproc->p_md.md_tf; + } + /* Or an arbitrary trapframe */ + if (have_addr) + tf = (struct trapframe64 *)addr; + + db_printf("Trapframe %p:\ttstate: %llx\tpc: %llx\tnpc: %llx\n", + tf, (unsigned long long)tf->tf_tstate, + (unsigned long long)tf->tf_pc, + (unsigned long long)tf->tf_npc); + db_printf("y: %x\tpil: %d\toldpil: %d\tfault: %llx\tkstack: %llx\ttt: %x\tGlobals:\n", + (int)tf->tf_y, (int)tf->tf_pil, (int)tf->tf_oldpil, + (unsigned long long)tf->tf_fault, + (unsigned long long)tf->tf_kstack, (int)tf->tf_tt); + db_printf("%016llx %016llx %016llx %016llx\n", + (unsigned long long)tf->tf_global[0], + (unsigned long long)tf->tf_global[1], + (unsigned long long)tf->tf_global[2], + (unsigned long long)tf->tf_global[3]); + db_printf("%016llx %016llx %016llx %016llx\nouts:\n", + (unsigned long long)tf->tf_global[4], + (unsigned long long)tf->tf_global[5], + (unsigned long long)tf->tf_global[6], + (unsigned long long)tf->tf_global[7]); + db_printf("%016llx %016llx %016llx %016llx\n", + (unsigned long long)tf->tf_out[0], + (unsigned long long)tf->tf_out[1], + (unsigned long long)tf->tf_out[2], + (unsigned long long)tf->tf_out[3]); + db_printf("%016llx %016llx %016llx %016llx\nlocals:\n", + (unsigned long long)tf->tf_out[4], + (unsigned long long)tf->tf_out[5], + (unsigned long long)tf->tf_out[6], + (unsigned long long)tf->tf_out[7]); + db_printf("%016llx %016llx %016llx %016llx\n", + (unsigned long long)tf->tf_local[0], + (unsigned long long)tf->tf_local[1], + (unsigned long long)tf->tf_local[2], + (unsigned long long)tf->tf_local[3]); + db_printf("%016llx %016llx %016llx %016llx\nins:\n", + (unsigned long long)tf->tf_local[4], + (unsigned long long)tf->tf_local[5], + (unsigned long long)tf->tf_local[6], + (unsigned long long)tf->tf_local[7]); + db_printf("%016llx %016llx %016llx %016llx\n", + (unsigned long long)tf->tf_in[0], + (unsigned long long)tf->tf_in[1], + (unsigned long long)tf->tf_in[2], + (unsigned long long)tf->tf_in[3]); + db_printf("%016llx %016llx %016llx %016llx\n", + (unsigned long long)tf->tf_in[4], + (unsigned long long)tf->tf_in[5], + (unsigned long long)tf->tf_in[6], + (unsigned long long)tf->tf_in[7]); +#if 0 + if (tf == curproc->p_md.md_tf) { + struct rwindow32 *kstack = (struct rwindow32 *)(((caddr_t)tf)+CCFSZ); + db_printf("ins (from stack):\n%016llx %016llx %016llx %016llx\n", + (int64_t)kstack->rw_local[0], (int64_t)kstack->rw_local[1], + (int64_t)kstack->rw_local[2], (int64_t)kstack->rw_local[3]); + db_printf("%016llx %016llx %016llx %016llx\n", + (int64_t)kstack->rw_local[4], (int64_t)kstack->rw_local[5], + (int64_t)kstack->rw_local[6], (int64_t)kstack->rw_local[7]); + } +#endif +} + +void +db_dump_fpstate(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + struct fpstate64 *fpstate; + + /* Use our last trapframe? */ + fpstate = &ddb_regs.ddb_fpstate; + /* Or an arbitrary trapframe */ + if (have_addr) + fpstate = (struct fpstate64 *)addr; + + db_printf("fpstate %p: fsr = %llx gsr = %lx\nfpregs:\n", + fpstate, (unsigned long long)fpstate->fs_fsr, + (unsigned long)fpstate->fs_gsr); + db_printf(" 0: %08x %08x %08x %08x %08x %08x %08x %08x\n", + (unsigned int)fpstate->fs_regs[0], + (unsigned int)fpstate->fs_regs[1], + (unsigned int)fpstate->fs_regs[2], + (unsigned int)fpstate->fs_regs[3], + (unsigned int)fpstate->fs_regs[4], + (unsigned int)fpstate->fs_regs[5], + (unsigned int)fpstate->fs_regs[6], + (unsigned int)fpstate->fs_regs[7]); + db_printf(" 8: %08x %08x %08x %08x %08x %08x %08x %08x\n", + (unsigned int)fpstate->fs_regs[8], + (unsigned int)fpstate->fs_regs[9], + (unsigned int)fpstate->fs_regs[10], + (unsigned int)fpstate->fs_regs[11], + (unsigned int)fpstate->fs_regs[12], + (unsigned int)fpstate->fs_regs[13], + (unsigned int)fpstate->fs_regs[14], + (unsigned int)fpstate->fs_regs[15]); + db_printf("16: %08x %08x %08x %08x %08x %08x %08x %08x\n", + (unsigned int)fpstate->fs_regs[16], + (unsigned int)fpstate->fs_regs[17], + (unsigned int)fpstate->fs_regs[18], + (unsigned int)fpstate->fs_regs[19], + (unsigned int)fpstate->fs_regs[20], + (unsigned int)fpstate->fs_regs[21], + (unsigned int)fpstate->fs_regs[22], + (unsigned int)fpstate->fs_regs[23]); + db_printf("24: %08x %08x %08x %08x %08x %08x %08x %08x\n", + (unsigned int)fpstate->fs_regs[24], + (unsigned int)fpstate->fs_regs[25], + (unsigned int)fpstate->fs_regs[26], + (unsigned int)fpstate->fs_regs[27], + (unsigned int)fpstate->fs_regs[28], + (unsigned int)fpstate->fs_regs[29], + (unsigned int)fpstate->fs_regs[30], + (unsigned int)fpstate->fs_regs[31]); + db_printf("32: %08x%08x %08x%08x %08x%08x %08x%08x\n", + (unsigned int)fpstate->fs_regs[32], + (unsigned int)fpstate->fs_regs[33], + (unsigned int)fpstate->fs_regs[34], + (unsigned int)fpstate->fs_regs[35], + (unsigned int)fpstate->fs_regs[36], + (unsigned int)fpstate->fs_regs[37], + (unsigned int)fpstate->fs_regs[38], + (unsigned int)fpstate->fs_regs[39]); + db_printf("40: %08x%08x %08x%08x %08x%08x %08x%08x\n", + (unsigned int)fpstate->fs_regs[40], + (unsigned int)fpstate->fs_regs[41], + (unsigned int)fpstate->fs_regs[42], + (unsigned int)fpstate->fs_regs[43], + (unsigned int)fpstate->fs_regs[44], + (unsigned int)fpstate->fs_regs[45], + (unsigned int)fpstate->fs_regs[46], + (unsigned int)fpstate->fs_regs[47]); + db_printf("48: %08x%08x %08x%08x %08x%08x %08x%08x\n", + (unsigned int)fpstate->fs_regs[48], + (unsigned int)fpstate->fs_regs[49], + (unsigned int)fpstate->fs_regs[50], + (unsigned int)fpstate->fs_regs[51], + (unsigned int)fpstate->fs_regs[52], + (unsigned int)fpstate->fs_regs[53], + (unsigned int)fpstate->fs_regs[54], + (unsigned int)fpstate->fs_regs[55]); + db_printf("56: %08x%08x %08x%08x %08x%08x %08x%08x\n", + (unsigned int)fpstate->fs_regs[56], + (unsigned int)fpstate->fs_regs[57], + (unsigned int)fpstate->fs_regs[58], + (unsigned int)fpstate->fs_regs[59], + (unsigned int)fpstate->fs_regs[60], + (unsigned int)fpstate->fs_regs[61], + (unsigned int)fpstate->fs_regs[62], + (unsigned int)fpstate->fs_regs[63]); +} + +void +db_dump_ts(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + struct trapstate *ts; + int i, tl; + + /* Use our last trapframe? */ + ts = &ddb_regs.ddb_ts[0]; + tl = ddb_regs.ddb_tl; + for (i=0; i<tl; i++) { + printf("%d tt=%lx tstate=%lx tpc=%p tnpc=%p\n", + i+1, (long)ts[i].tt, (u_long)ts[i].tstate, + (void*)(u_long)ts[i].tpc, (void*)(u_long)ts[i].tnpc); + } + +} + + |