Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/vax/vax Better support for tracing stacks. From Chu...
details: https://anonhg.NetBSD.org/src/rev/b4f8d1ae7101
branches: trunk
changeset: 473806:b4f8d1ae7101
user: ragge <ragge%NetBSD.org@localhost>
date: Sun Jun 20 00:58:23 1999 +0000
description:
Better support for tracing stacks. From Chuck McManis.
diffstat:
sys/arch/vax/vax/db_machdep.c | 329 ++++++++++++++++++++++++++++++++++++-----
1 files changed, 286 insertions(+), 43 deletions(-)
diffs (truncated from 406 to 300 lines):
diff -r 40eb22eb8894 -r b4f8d1ae7101 sys/arch/vax/vax/db_machdep.c
--- a/sys/arch/vax/vax/db_machdep.c Sun Jun 20 00:53:58 1999 +0000
+++ b/sys/arch/vax/vax/db_machdep.c Sun Jun 20 00:58:23 1999 +0000
@@ -1,6 +1,8 @@
-/* $NetBSD: db_machdep.c,v 1.16 1999/04/12 20:38:20 pk Exp $ */
+/* $NetBSD: db_machdep.c,v 1.17 1999/06/20 00:58:23 ragge Exp $ */
/*
+ * :set tabs=4
+ *
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
@@ -26,6 +28,9 @@
* rights to redistribute these changes.
*
* db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
+ *
+ * VAX enhancements by cmcmanis%mcmanis.com@localhost no rights reserved :-)
+ *
*/
/*
@@ -36,6 +41,7 @@
#include <sys/param.h>
#include <sys/proc.h>
+#include <sys/user.h>
#include <sys/reboot.h>
#include <sys/systm.h> /* just for boothowto --eichin */
@@ -46,6 +52,7 @@
#include <machine/db_machdep.h>
#include <machine/trap.h>
#include <machine/frame.h>
+#include <machine/pcb.h>
#include <machine/cpu.h>
#include <machine/../vax/gencons.h>
@@ -67,6 +74,25 @@
static int splsave; /* IPL before entering debugger */
/*
+ * VAX Call frame on the stack, this from
+ * "Computer Programming and Architecture, The VAX-11"
+ * Henry Levy & Richard Eckhouse Jr.
+ * ISBN 0-932376-07-X
+ */
+typedef struct __vax_frame {
+ u_int vax_cond; /* condition handler */
+ u_int vax_psw:16; /* 16 bit processor status word */
+ u_int vax_regs:12; /* Register save mask. */
+ u_int vax_zero:1; /* Always zero */
+ u_int vax_calls:1; /* True if CALLS, false if CALLG */
+ u_int vax_spa:2; /* Stack pointer alignment */
+ u_int *vax_ap; /* argument pointer */
+ struct __vax_frame *vax_fp; /* frame pointer of previous frame */
+ u_int vax_pc; /* program counter */
+ u_int vax_args[1]; /* 0 or more arguments */
+} VAX_CALLFRAME;
+
+/*
* DDB is called by either <ESC> - D on keyboard, via a TRACE or
* BPT trap or from kernel, normally as a result of a panic.
* If it is the result of a panic, set the ddb register frame to
@@ -83,6 +109,7 @@
case T_TRCTRAP: /* single_step */
break;
+ /* XXX todo: should be migrated to use VAX_CALLFRAME at some point */
case T_KDBTRAP:
if (panicstr) {
struct callsframe *pf, *df;
@@ -116,12 +143,12 @@
/* XXX Should switch to interrupt stack here, if needed. */
- s = splddb();
+ s = splimp();
db_active++;
- cnpollc(TRUE);
- db_trap(frame->trap, frame->code);
- cnpollc(FALSE);
- db_active--;
+ cnpollc(TRUE);
+ db_trap(frame->trap, frame->code);
+ cnpollc(FALSE);
+ db_active--;
splx(s);
if (!panicstr)
@@ -207,56 +234,273 @@
};
struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+#define IN_USERLAND(x) (((u_int)(x) & 0x80000000) == 0)
+
+/*
+ * Dump a stack traceback. Takes two arguments:
+ * fp - CALL FRAME pointer
+ * stackbase - Lowest stack value
+ */
+static void
+db_dump_stack(VAX_CALLFRAME *fp, u_int stackbase) {
+ u_int nargs, arg_base, regs;
+ VAX_CALLFRAME *tmp_frame;
+ db_expr_t diff;
+ db_sym_t sym;
+ char *symname;
+
+ db_printf("Stack traceback : \n");
+ if (IN_USERLAND(fp)) {
+ db_printf(" Process is executing in user space.\n");
+ return;
+ }
+
+ while (((u_int)(fp->vax_fp) > stackbase) &&
+ ((u_int)(fp->vax_fp) < (stackbase + USPACE))) {
+
+ diff = INT_MAX;
+ symname = NULL;
+ sym = db_search_symbol(fp->vax_pc, DB_STGY_ANY, &diff);
+ db_symbol_values(sym, &symname, 0);
+ db_printf("%s+0x%lx(", symname, diff);
+
+ /*
+ * Figure out the arguments by using a bit of subtlety.
+ * As the argument pointer may have been used as a temporary
+ * by the callee ... recreate what it would have pointed to
+ * as follows:
+ * The vax_regs value has a 12 bit bitmask of the registers
+ * that were saved on the stack.
+ * Store that in 'regs' and then for every bit that is
+ * on (indicates the register contents are on the stack)
+ * increment the argument base (arg_base) by one.
+ * When that is done, args[arg_base] points to the longword
+ * that identifies the number of arguments.
+ * arg_base+1 - arg_base+n are the argument pointers/contents.
+ */
+
+ /* First get the frame that called this function ... */
+ tmp_frame = fp->vax_fp;
+
+ /* Isolate the saved register bits, and count them */
+ regs = tmp_frame->vax_regs;
+ for (arg_base = 0; regs != 0; regs >>= 1) {
+ if (regs & 1)
+ arg_base++;
+ }
+
+ /* number of arguments is then pointed to by vax_args[arg_base] */
+ nargs = tmp_frame->vax_args[arg_base];
+ if (nargs) {
+ nargs--; /* reduce by one for formatting niceties */
+ arg_base++; /* skip past the actual number of arguments */
+ while (nargs--)
+ db_printf("0x%x,", tmp_frame->vax_args[arg_base++]);
+
+ /* now print out the last arg with closing brace and \n */
+ db_printf("0x%x)\n", tmp_frame->vax_args[++arg_base]);
+ } else
+ db_printf("void)\n");
+ /* move to the next frame */
+ fp = fp->vax_fp;
+ }
+}
+
+/*
+ * Implement the trace command which has the form:
+ *
+ * trace <-- Trace panic (same as before)
+ * trace 0x88888 <-- Trace process whose address is 888888
+ * trace/t <-- Trace current process (0 if no current proc)
+ * trace/t 0tnn <-- Trace process nn (0t for decimal)
+ */
void
db_stack_trace_cmd(addr, have_addr, count, modif)
- db_expr_t addr;
- boolean_t have_addr;
- db_expr_t count;
- char *modif;
+ db_expr_t addr; /* Address parameter */
+ boolean_t have_addr; /* True if addr is valid */
+ db_expr_t count; /* Optional count */
+ char *modif; /* pointer to flag modifier 't' */
{
- extern vaddr_t proc0paddr, istack;
+ extern vaddr_t proc0paddr;
struct proc *p = curproc;
- db_expr_t diff;
- db_sym_t sym;
- vaddr_t paddr;
- u_int *cf, *tcf, abase, loop, i, stackbase;
- char *symname;
+ struct user *uarea;
+ int trace_proc;
+ pid_t curpid;
+ char *s;
- if (panicstr) {
- cf = (int *)ddb_regs.sp;
- } else {
- printf("Don't know what to do without panic\n");
- cf = (int *)ddb_regs.fp; /* XXX */
+ /* Check to see if we're tracing a process */
+ trace_proc = 0;
+ s = modif;
+ while (!trace_proc && *s) {
+ if (*s++ == 't')
+ trace_proc++; /* why yes we are */
+ }
+
+ /* Trace a panic */
+ if (! trace_proc) {
+ if (! panicstr) {
+ db_printf("Not a panic, use trace/t to trace a process.\n");
+ return;
+ }
+ db_printf("panic: %s\n", panicstr);
+ /* xxx ? where did we panic and whose stack are we using? */
+ db_dump_stack((VAX_CALLFRAME *)(ddb_regs.sp), ddb_regs.ap);
+ return;
}
- if (p)
- paddr = (u_int)p->p_addr;
- else
- paddr = proc0paddr;
- stackbase = (ddb_regs.psl & PSL_IS ? istack : paddr);
- while ((cf[3] > stackbase) && (cf[3] < (stackbase + USPACE))) {
+
+ /*
+ * If user typed an address its either a PID, or a Frame
+ * if no address then either current proc or panic
+ */
+ if (have_addr) {
+ if (trace_proc) {
+ p = pfind((int)addr);
+ /* Try to be helpful by looking at it as if it were decimal */
+ if (p == NULL) {
+ u_int tpid = 0;
+ u_int foo = addr;
+
+ while (foo != 0) {
+ int digit = (foo >> 28) & 0xf;
+ if (digit > 9) {
+ db_printf(" No such process.\n");
+ return;
+ }
+ tpid = tpid * 10 + digit;
+ foo = foo << 4;
+ }
+ p = pfind(tpid);
+ if (p == NULL) {
+ db_printf(" No such process.\n");
+ return;
+ }
+ }
+ } else {
+ p = (struct proc *)(addr);
+ if (pfind(p->p_pid) != p) {
+ db_printf(" This address does not point to a valid process.\n");
+ return;
+ }
+ }
+ } else {
+ if (trace_proc) {
+ p = curproc;
+ if (p == NULL) {
+ db_printf("trace: no current process! (ignored)\n");
+ return;
+ }
+ } else {
+ if (! panicstr) {
+ db_printf("Not a panic, no active process, ignored.\n");
+ return;
+ }
+ }
+ }
+ if (p == NULL) {
+ uarea = (struct user *)proc0paddr;
+ curpid = 0;
+ } else {
+ uarea = p->p_addr;
+ curpid = p->p_pid;
+ }
+ db_printf("Process %d\n", curpid);
+ db_printf(" PCB contents:\n");
+ db_printf(" KSP = 0x%x\n", (unsigned int)(uarea->u_pcb.KSP));
+ db_printf(" ESP = 0x%x\n", (unsigned int)(uarea->u_pcb.ESP));
+ db_printf(" SSP = 0x%x\n", (unsigned int)(uarea->u_pcb.SSP));
+ db_printf(" USP = 0x%x\n", (unsigned int)(uarea->u_pcb.USP));
+ db_printf(" R[00] = 0x%08x R[06] = 0x%08x\n",
+ (unsigned int)(uarea->u_pcb.R[0]), (unsigned int)(uarea->u_pcb.R[6]));
+ db_printf(" R[01] = 0x%08x R[07] = 0x%08x\n",
+ (unsigned int)(uarea->u_pcb.R[1]), (unsigned int)(uarea->u_pcb.R[7]));
+ db_printf(" R[02] = 0x%08x R[08] = 0x%08x\n",
+ (unsigned int)(uarea->u_pcb.R[2]), (unsigned int)(uarea->u_pcb.R[8]));
+ db_printf(" R[03] = 0x%08x R[09] = 0x%08x\n",
+ (unsigned int)(uarea->u_pcb.R[3]), (unsigned int)(uarea->u_pcb.R[9]));
+ db_printf(" R[04] = 0x%08x R[10] = 0x%08x\n",
Home |
Main Index |
Thread Index |
Old Index