Annotation of sys/arch/sh/sh/db_trace.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: db_trace.c,v 1.4 2007/03/17 20:23:05 miod Exp $ */
! 2: /* $NetBSD: db_trace.c,v 1.19 2006/01/21 22:10:59 uwe Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 2000 Tsubai Masanari. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. The name of the author may not be used to endorse or promote products
! 16: * derived from this software without specific prior written permission.
! 17: *
! 18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
! 27: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 28: */
! 29:
! 30: #include <sys/param.h>
! 31: #include <sys/systm.h>
! 32:
! 33: #include <machine/db_machdep.h>
! 34:
! 35: #include <ddb/db_access.h>
! 36: #include <ddb/db_interface.h>
! 37: #include <ddb/db_output.h>
! 38: #include <ddb/db_sym.h>
! 39: #include <ddb/db_variables.h>
! 40:
! 41: #ifdef TRACE_DEBUG
! 42: # define DPRINTF printf
! 43: #else
! 44: # define DPRINTF while (/* CONSTCOND */ 0) printf
! 45: #endif
! 46:
! 47: extern char start[], etext[];
! 48: void db_nextframe(db_addr_t, db_addr_t *, db_addr_t *);
! 49:
! 50: struct db_variable db_regs[] = {
! 51: { "r0", (long *)&ddb_regs.tf_r0, FCN_NULL },
! 52: { "r1", (long *)&ddb_regs.tf_r1, FCN_NULL },
! 53: { "r2", (long *)&ddb_regs.tf_r2, FCN_NULL },
! 54: { "r3", (long *)&ddb_regs.tf_r3, FCN_NULL },
! 55: { "r4", (long *)&ddb_regs.tf_r4, FCN_NULL },
! 56: { "r5", (long *)&ddb_regs.tf_r5, FCN_NULL },
! 57: { "r6", (long *)&ddb_regs.tf_r6, FCN_NULL },
! 58: { "r7", (long *)&ddb_regs.tf_r7, FCN_NULL },
! 59: { "r8", (long *)&ddb_regs.tf_r8, FCN_NULL },
! 60: { "r9", (long *)&ddb_regs.tf_r9, FCN_NULL },
! 61: { "r10", (long *)&ddb_regs.tf_r10, FCN_NULL },
! 62: { "r11", (long *)&ddb_regs.tf_r11, FCN_NULL },
! 63: { "r12", (long *)&ddb_regs.tf_r12, FCN_NULL },
! 64: { "r13", (long *)&ddb_regs.tf_r13, FCN_NULL },
! 65: { "r14", (long *)&ddb_regs.tf_r14, FCN_NULL },
! 66: { "r15", (long *)&ddb_regs.tf_r15, FCN_NULL },
! 67: { "pr", (long *)&ddb_regs.tf_pr, FCN_NULL },
! 68: { "spc", (long *)&ddb_regs.tf_spc, FCN_NULL },
! 69: { "ssr", (long *)&ddb_regs.tf_ssr, FCN_NULL },
! 70: { "mach", (long *)&ddb_regs.tf_mach, FCN_NULL },
! 71: { "macl", (long *)&ddb_regs.tf_macl, FCN_NULL },
! 72: };
! 73:
! 74: struct db_variable *db_eregs =
! 75: db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
! 76:
! 77: void
! 78: db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
! 79: char *modif, int (*print)(const char *, ...))
! 80: {
! 81: db_addr_t callpc, frame, lastframe;
! 82: uint32_t vbr;
! 83:
! 84: __asm volatile("stc vbr, %0" : "=r"(vbr));
! 85:
! 86: frame = ddb_regs.tf_r14;
! 87: callpc = ddb_regs.tf_spc;
! 88:
! 89: if (count == 0 || count == -1)
! 90: count = INT_MAX;
! 91:
! 92: lastframe = 0;
! 93: while (count > 0 && frame != 0) {
! 94: /* Are we crossing a trap frame? */
! 95: if ((callpc & ~PAGE_MASK) == vbr) {
! 96: struct trapframe *tf = (void *)frame;
! 97:
! 98: frame = tf->tf_r14;
! 99: callpc = tf->tf_spc;
! 100:
! 101: (*print)("(EXPEVT %03x; SSR=%08x) at ",
! 102: tf->tf_expevt, tf->tf_ssr);
! 103: db_printsym(callpc, DB_STGY_PROC, print);
! 104: (*print)("\n");
! 105:
! 106: /* XXX: don't venture into the userland yet */
! 107: if ((tf->tf_ssr & PSL_MD) == 0)
! 108: break;
! 109: } else {
! 110: char *name;
! 111: db_expr_t offset;
! 112: db_sym_t sym;
! 113:
! 114:
! 115: DPRINTF(" (1)newpc 0x%lx, newfp 0x%lx\n",
! 116: callpc, frame);
! 117:
! 118: sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
! 119: db_symbol_values(sym, &name, NULL);
! 120:
! 121: (*print)("%s() at ", name ? name : "");
! 122: db_printsym(callpc, DB_STGY_PROC, print);
! 123: (*print)("\n");
! 124:
! 125: if (lastframe == 0 && offset == 0) {
! 126: callpc = ddb_regs.tf_pr;
! 127: continue;
! 128: }
! 129:
! 130: db_nextframe(callpc - offset, &frame, &callpc);
! 131: DPRINTF(" (2)newpc 0x%lx, newfp 0x%lx\n",
! 132: callpc, frame);
! 133:
! 134: if (callpc == 0 && lastframe == 0)
! 135: callpc = (db_addr_t)ddb_regs.tf_pr;
! 136: DPRINTF(" (3)newpc 0x%lx, newfp 0x%lx\n",
! 137: callpc, frame);
! 138: }
! 139:
! 140: count--;
! 141: lastframe = frame;
! 142: }
! 143: }
! 144:
! 145: void
! 146: db_nextframe(
! 147: db_addr_t pc, /* in: entry address of current function */
! 148: db_addr_t *fp, /* in: current fp, out: parent fp */
! 149: db_addr_t *pr) /* out: parent pr */
! 150: {
! 151: int *frame = (void *)*fp;
! 152: int i, inst;
! 153: int depth, prdepth, fpdepth;
! 154:
! 155: depth = 0;
! 156: prdepth = fpdepth = -1;
! 157:
! 158: if (pc < (db_addr_t)start || pc > (db_addr_t)etext)
! 159: goto out;
! 160:
! 161: for (i = 0; i < 30; i++) {
! 162: inst = db_get_value(pc, 2, FALSE);
! 163: pc += 2;
! 164:
! 165: if (inst == 0x6ef3) /* mov r15,r14 -- end of prologue */
! 166: break;
! 167:
! 168: if (inst == 0x4f22) { /* sts.l pr,@-r15 */
! 169: prdepth = depth;
! 170: depth++;
! 171: continue;
! 172: }
! 173: if (inst == 0x2fe6) { /* mov.l r14,@-r15 */
! 174: fpdepth = depth;
! 175: depth++;
! 176: continue;
! 177: }
! 178: if ((inst & 0xff0f) == 0x2f06) { /* mov.l r?,@-r15 */
! 179: depth++;
! 180: continue;
! 181: }
! 182: if ((inst & 0xff00) == 0x7f00) { /* add #n,r15 */
! 183: int8_t n = inst & 0xff;
! 184:
! 185: if (n >= 0) {
! 186: printf("add #n,r15 (n > 0)\n");
! 187: break;
! 188: }
! 189:
! 190: depth += -n/4;
! 191: continue;
! 192: }
! 193: if ((inst & 0xf000) == 0x9000) {
! 194: if (db_get_value(pc, 2, FALSE) == 0x3f38) {
! 195: /* "mov #n,r3; sub r3,r15" */
! 196: unsigned int disp = (int)(inst & 0xff);
! 197: int r3;
! 198:
! 199: r3 = db_get_value(pc + 4 - 2 + (disp << 1),
! 200: 2, FALSE);
! 201: if ((r3 & 0x00008000) == 0)
! 202: r3 &= 0x0000ffff;
! 203: else
! 204: r3 |= 0xffff0000;
! 205: depth += (r3 / 4);
! 206:
! 207: pc += 2;
! 208: continue;
! 209: }
! 210: }
! 211:
! 212: #ifdef TRACE_DEBUG
! 213: printf("unknown instruction in prologue\n");
! 214: db_disasm(pc - 2, 0);
! 215: #endif
! 216: }
! 217:
! 218: out:
! 219: #ifdef TRACE_DEBUG
! 220: printf("depth=%x fpdepth=0x%x prdepth=0x%x\n", depth, fpdepth, prdepth);
! 221: #endif
! 222: if (fpdepth != -1)
! 223: *fp = frame[depth - fpdepth - 1];
! 224: else
! 225: *fp = 0;
! 226:
! 227: if (prdepth != -1)
! 228: *pr = frame[depth - prdepth - 1];
! 229: else
! 230: *pr = 0;
! 231: }
CVSweb