Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm26/arm26 More informative stack backtrace. Prin...



details:   https://anonhg.NetBSD.org/src/rev/99cf9cb6bc29
branches:  trunk
changeset: 486115:99cf9cb6bc29
user:      bjh21 <bjh21%NetBSD.org@localhost>
date:      Sat May 13 14:43:11 2000 +0000

description:
More informative stack backtrace.  Prints whole stack frames\!

diffstat:

 sys/arch/arm26/arm26/db_trace.c |  102 +++++++++++++++++++++++++++------------
 1 files changed, 71 insertions(+), 31 deletions(-)

diffs (157 lines):

diff -r 9503a58de66f -r 99cf9cb6bc29 sys/arch/arm26/arm26/db_trace.c
--- a/sys/arch/arm26/arm26/db_trace.c   Sat May 13 14:40:10 2000 +0000
+++ b/sys/arch/arm26/arm26/db_trace.c   Sat May 13 14:43:11 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: db_trace.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $       */
+/*     $NetBSD: db_trace.c,v 1.2 2000/05/13 14:43:11 bjh21 Exp $       */
 
 /* 
  * Copyright (c) 1996 Scott K. Stevens
@@ -41,6 +41,39 @@
  
 #define INKERNEL(va)   (((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
 
+/*
+ * APCS stack frames are awkward beasts, so I don't think even trying to use
+ * a structure to represent them is a good idea.
+ *
+ * Here's the diagram from the APCS.  Incresing address is _up_ the page.
+ * 
+ *          save code pointer       [fp]        <- fp points to here
+ *          return link value       [fp, #-4]
+ *          return sp value         [fp, #-8]
+ *          return fp value         [fp, #-12]
+ *          [saved v7 value]
+ *          [saved v6 value]
+ *          [saved v5 value}
+ *          [saved v4 value]
+ *          [saved v3 value]
+ *          [saved v2 value]
+ *          [saved v1 value]
+ *          [saved a4 value]
+ *          [saved a3 value}
+ *          [saved a2 value]
+ *          [saved a1 value]
+ *
+ * The save code pointer points twelve bytes beyond the start of the 
+ * code sequence (usually a single STM) that created the stack frame.  
+ * We have to disassemble it if we want to know which of the optional 
+ * fields are actually present.
+ */
+
+#define FR_SCP (0)
+#define FR_RLV (-1)
+#define FR_RSP (-2)
+#define FR_RFP (-3)
+
 void
 db_stack_trace_cmd(addr, have_addr, count, modif)
        db_expr_t       addr;
@@ -48,7 +81,7 @@
        db_expr_t       count;
        char            *modif;
 {
-       struct frame    *frame, *lastframe;
+       u_int32_t       *frame, *lastframe;
        char c, *cp = modif;
        boolean_t       kernel_only = TRUE;
        boolean_t       trace_thread = FALSE;
@@ -63,15 +96,8 @@
        if (count == -1)
                count = 65535;
 
-       /*
-        * The frame pointer points to the top word of the stack frame so we
-        * need to adjust it by sizeof(struct frame) - sizeof(u_int))
-        * to get the address of the start of the frame structure.
-        */
-
        if (!have_addr)
-               frame = (struct frame *)(DDB_TF->tf_r11
-                   - (sizeof(struct frame) - sizeof(u_int)));
+               frame = (u_int32_t *)(DDB_TF->tf_r11);
        else {
                if (trace_thread) {
                        struct proc *p;
@@ -87,46 +113,60 @@
                                return;
                        }
                        u = p->p_addr;
-                       frame = (struct frame *) (u->u_pcb.pcb_sf->sf_r11
-                           - (sizeof(struct frame) - sizeof(u_int)));
+                       frame = (u_int32_t *)(u->u_pcb.pcb_sf->sf_r11);
                        db_printf("at %p\n", frame);
                } else
-                       frame = (struct frame *)(addr - (sizeof(struct frame)
-                           - sizeof(u_int)));
+                       frame = (u_int32_t *)(addr);
        }
        lastframe = NULL;
 
-       while (count--) {
+       while (count-- && frame != NULL) {
                db_expr_t       offset;
                char            *name;
-               db_addr_t       pc;
-
-/*             db_printf("fp=%08x: fp=%08x sp=%08x lr=%08x pc=%08x\n",
-                   (u_int)frame, frame->fr_fp, frame->fr_sp, frame->fr_lr,
-                   frame->fr_r15);*/
+               db_addr_t       scp;
+               u_int32_t       savecode;
+               int             r;
+               u_int32_t       *rp;
 
-               pc = frame->fr_r15 & R15_PC;
-               if (!INKERNEL(pc))
-                       break;
+               /*
+                * In theory, the SCP isn't guaranteed to be in the function
+                * that generated the stack frame.  We hope for the best.
+                */
+               scp = frame[FR_SCP] & R15_PC;
 
-               db_find_sym_and_offset(pc, &name, &offset);
+               db_find_sym_and_offset(scp, &name, &offset);
                if (name == NULL)
                        name = "?";
 
-               db_printf("%s(", name);
-               db_printsym(pc, DB_STGY_PROC);
-               db_printf(")");
-               db_printf("\n");
+               db_printf("%s", name);
+               db_printf("(scp=0x%x(", frame[FR_SCP]);
+               db_printsym(scp, DB_STGY_PROC);
+               db_printf("), rlv=0x%x(", frame[FR_RLV]);
+               db_printsym(frame[FR_RLV] & R15_PC, DB_STGY_PROC);
+               db_printf("),\n\trsp=0x%x", frame[FR_RSP]);
+               db_printf(", rfp=0x%x", frame[FR_RFP]);
+
+               savecode = ((u_int32_t *)scp)[-3];
+               if ((savecode & 0x0e100000) == 0x08000000) {
+                       /* Looks like an STM */
+                       rp = frame - 4;
+                       for (r = 10; r >= 0; r--)
+                               if (savecode & (1 << r))
+                                       db_printf(",%sr%d=0x%x",
+                                                 (frame - rp) % 4 == 2 ?
+                                                 "\n\t" : " ", r, *rp--);
+               }
+
+               db_printf(")\n");
 
                /*
                 * Switch to next frame up
                 */
-               if (frame->fr_fp == 0)
+               if (frame[FR_RFP] == 0)
                        break; /* Top of stack */
 
                lastframe = frame;
-               frame = (struct frame *)(frame->fr_fp - (sizeof(struct frame)
-                   - sizeof(u_int)));
+               frame = (u_int32_t *)(frame[FR_RFP]);
 
                if (INKERNEL((int)frame)) {
                        /* staying in kernel */



Home | Main Index | Thread Index | Old Index