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