db_trace.c revision 103646
199730Sbenno/*	$FreeBSD: head/sys/powerpc/powerpc/db_trace.c 103646 2002-09-19 18:46:29Z jhb $ */
299730Sbenno/*	$NetBSD: db_trace.c,v 1.20 2002/05/13 20:30:09 matt Exp $	*/
399730Sbenno/*	$OpenBSD: db_trace.c,v 1.3 1997/03/21 02:10:48 niklas Exp $	*/
499730Sbenno
599730Sbenno/*
699730Sbenno * Mach Operating System
799730Sbenno * Copyright (c) 1992 Carnegie Mellon University
899730Sbenno * All Rights Reserved.
999730Sbenno *
1099730Sbenno * Permission to use, copy, modify and distribute this software and its
1199730Sbenno * documentation is hereby granted, provided that both the copyright
1299730Sbenno * notice and this permission notice appear in all copies of the
1399730Sbenno * software, derivative works or modified versions, and any portions
1499730Sbenno * thereof, and that both notices appear in supporting documentation.
1599730Sbenno *
1699730Sbenno * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
1799730Sbenno * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
1899730Sbenno * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1999730Sbenno *
2099730Sbenno * Carnegie Mellon requests users of this software to return to
2199730Sbenno *
2299730Sbenno *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
2399730Sbenno *  School of Computer Science
2499730Sbenno *  Carnegie Mellon University
2599730Sbenno *  Pittsburgh PA 15213-3890
2699730Sbenno *
2799730Sbenno * any improvements or extensions that they make and grant Carnegie Mellon
2899730Sbenno * the rights to redistribute these changes.
2999730Sbenno */
3099730Sbenno
3199730Sbenno#include <sys/param.h>
3299730Sbenno#include <sys/proc.h>
3399730Sbenno#include <sys/user.h>
3499730Sbenno
3599730Sbenno#include <vm/vm.h>
3699730Sbenno#include <vm/pmap.h>
3799730Sbenno#include <vm/vm_extern.h>
3899730Sbenno
3999730Sbenno#include <machine/db_machdep.h>
4099730Sbenno#include <machine/spr.h>
4199730Sbenno#include <machine/trap.h>
4299730Sbenno
4399730Sbenno#include <ddb/ddb.h>
4499730Sbenno#include <ddb/db_access.h>
4599730Sbenno#include <ddb/db_sym.h>
4699730Sbenno#include <ddb/db_variables.h>
4799730Sbenno
4899730Sbennostruct db_variable db_regs[] = {
4999730Sbenno	{ "r0",  (long *)&ddb_regs.r[0],  FCN_NULL },
5099730Sbenno	{ "r1",  (long *)&ddb_regs.r[1],  FCN_NULL },
5199730Sbenno	{ "r2",  (long *)&ddb_regs.r[2],  FCN_NULL },
5299730Sbenno	{ "r3",  (long *)&ddb_regs.r[3],  FCN_NULL },
5399730Sbenno	{ "r4",  (long *)&ddb_regs.r[4],  FCN_NULL },
5499730Sbenno	{ "r5",  (long *)&ddb_regs.r[5],  FCN_NULL },
5599730Sbenno	{ "r6",  (long *)&ddb_regs.r[6],  FCN_NULL },
5699730Sbenno	{ "r7",  (long *)&ddb_regs.r[7],  FCN_NULL },
5799730Sbenno	{ "r8",  (long *)&ddb_regs.r[8],  FCN_NULL },
5899730Sbenno	{ "r9",  (long *)&ddb_regs.r[9],  FCN_NULL },
5999730Sbenno	{ "r10", (long *)&ddb_regs.r[10], FCN_NULL },
6099730Sbenno	{ "r11", (long *)&ddb_regs.r[11], FCN_NULL },
6199730Sbenno	{ "r12", (long *)&ddb_regs.r[12], FCN_NULL },
6299730Sbenno	{ "r13", (long *)&ddb_regs.r[13], FCN_NULL },
6399730Sbenno	{ "r14", (long *)&ddb_regs.r[14], FCN_NULL },
6499730Sbenno	{ "r15", (long *)&ddb_regs.r[15], FCN_NULL },
6599730Sbenno	{ "r16", (long *)&ddb_regs.r[16], FCN_NULL },
6699730Sbenno	{ "r17", (long *)&ddb_regs.r[17], FCN_NULL },
6799730Sbenno	{ "r18", (long *)&ddb_regs.r[18], FCN_NULL },
6899730Sbenno	{ "r19", (long *)&ddb_regs.r[19], FCN_NULL },
6999730Sbenno	{ "r20", (long *)&ddb_regs.r[20], FCN_NULL },
7099730Sbenno	{ "r21", (long *)&ddb_regs.r[21], FCN_NULL },
7199730Sbenno	{ "r22", (long *)&ddb_regs.r[22], FCN_NULL },
7299730Sbenno	{ "r23", (long *)&ddb_regs.r[23], FCN_NULL },
7399730Sbenno	{ "r24", (long *)&ddb_regs.r[24], FCN_NULL },
7499730Sbenno	{ "r25", (long *)&ddb_regs.r[25], FCN_NULL },
7599730Sbenno	{ "r26", (long *)&ddb_regs.r[26], FCN_NULL },
7699730Sbenno	{ "r27", (long *)&ddb_regs.r[27], FCN_NULL },
7799730Sbenno	{ "r28", (long *)&ddb_regs.r[28], FCN_NULL },
7899730Sbenno	{ "r29", (long *)&ddb_regs.r[29], FCN_NULL },
7999730Sbenno	{ "r30", (long *)&ddb_regs.r[30], FCN_NULL },
8099730Sbenno	{ "r31", (long *)&ddb_regs.r[31], FCN_NULL },
8199730Sbenno	{ "iar", (long *)&ddb_regs.iar,   FCN_NULL },
8299730Sbenno	{ "msr", (long *)&ddb_regs.msr,   FCN_NULL },
8399730Sbenno	{ "lr",  (long *)&ddb_regs.lr,    FCN_NULL },
8499730Sbenno	{ "ctr", (long *)&ddb_regs.ctr,   FCN_NULL },
8599730Sbenno	{ "cr",  (long *)&ddb_regs.cr,    FCN_NULL },
8699730Sbenno	{ "xer", (long *)&ddb_regs.xer,   FCN_NULL },
8799730Sbenno#ifdef PPC_IBM4XX
8899730Sbenno	{ "dear", (long *)&ddb_regs.dear, FCN_NULL },
8999730Sbenno	{ "esr", (long *)&ddb_regs.esr,   FCN_NULL },
9099730Sbenno	{ "pid", (long *)&ddb_regs.pid,   FCN_NULL },
9199730Sbenno#endif
9299730Sbenno};
9399730Sbennostruct db_variable *db_eregs = db_regs + sizeof (db_regs)/sizeof (db_regs[0]);
9499730Sbenno
9599730Sbennoextern int trapexit[];
9699730Sbennoextern int end[];
9799730Sbenno
9899730Sbenno/*
9999730Sbenno *	Frame tracing.
10099730Sbenno */
10199730Sbennovoid
10299730Sbennodb_stack_trace_print(addr, have_addr, count, modif, pr)
10399730Sbenno	db_expr_t addr;
10499730Sbenno	int have_addr;
10599730Sbenno	db_expr_t count;
10699730Sbenno	char *modif;
10799730Sbenno	void (*pr) __P((const char *, ...));
10899730Sbenno{
10999730Sbenno	db_addr_t frame, lr, caller, *args;
11099730Sbenno	db_addr_t fakeframe[2];
11199730Sbenno	db_expr_t diff;
11299730Sbenno	db_sym_t sym;
11399730Sbenno	char *symname;
11499730Sbenno	boolean_t kernel_only = TRUE;
11599730Sbenno	boolean_t trace_thread = FALSE;
11699730Sbenno	boolean_t full = FALSE;
11799730Sbenno
11899730Sbenno	{
11999730Sbenno		register char *cp = modif;
12099730Sbenno		register char c;
12199730Sbenno
12299730Sbenno		while ((c = *cp++) != 0) {
12399730Sbenno			if (c == 't')
12499730Sbenno				trace_thread = TRUE;
12599730Sbenno			if (c == 'u')
12699730Sbenno				kernel_only = FALSE;
12799730Sbenno			if (c == 'f')
12899730Sbenno				full = TRUE;
12999730Sbenno		}
13099730Sbenno	}
13199730Sbenno
13299730Sbenno	if (have_addr) {
13399730Sbenno#if 0
13499730Sbenno		if (trace_thread) {
13599730Sbenno			struct proc *p;
13699730Sbenno			struct user *u;
13799730Sbenno
13899730Sbenno			(*pr)("trace: pid %d ", (int)addr);
13999730Sbenno			p = pfind(addr);
14099730Sbenno			if (p == NULL) {
14199730Sbenno				(*pr)("not found\n");
14299730Sbenno				return;
14399730Sbenno			}
14499730Sbenno			if (!(p->p_flag&P_INMEM)) {
14599730Sbenno				(*pr)("swapped out\n");
14699730Sbenno				return;
14799730Sbenno			}
14899730Sbenno			u = p->p_addr;
14999730Sbenno			frame = (db_addr_t)u->u_pcb.pcb_sp;
15099730Sbenno			(*pr)("at %p\n", frame);
15199730Sbenno		} else
15299730Sbenno#endif
15399730Sbenno			frame = (db_addr_t)addr;
15499730Sbenno	} else {
15599730Sbenno		frame = (db_addr_t)ddb_regs.r[1];
15699730Sbenno	}
15799730Sbenno	for (;;) {
15899730Sbenno		if (frame < PAGE_SIZE)
15999730Sbenno			break;
16099730Sbenno#ifdef PPC_MPC6XX
16199730Sbenno		if (kernel_only &&
16299730Sbenno		    ((frame > (db_addr_t) end &&
16399730Sbenno		      frame < VM_MIN_KERNEL_ADDRESS) ||
16499730Sbenno		     frame >= VM_MAX_KERNEL_ADDRESS))
16599730Sbenno			break;
16699730Sbenno#endif
16799730Sbenno		frame = *(db_addr_t *)frame;
16899730Sbenno	    next_frame:
16999730Sbenno		args = (db_addr_t *)(frame + 8);
17099730Sbenno		if (frame < PAGE_SIZE)
17199730Sbenno			break;
17299730Sbenno#ifdef PPC_MPC6XX
17399730Sbenno		if (kernel_only &&
17499730Sbenno		    ((frame > (db_addr_t) end &&
17599730Sbenno		      frame < VM_MIN_KERNEL_ADDRESS) ||
17699730Sbenno		     frame >= VM_MAX_KERNEL_ADDRESS))
17799730Sbenno			break;
17899730Sbenno#endif
17999730Sbenno	        if (count-- == 0)
18099730Sbenno			break;
18199730Sbenno
18299730Sbenno		lr = *(db_addr_t *)(frame + 4) - 4;
18399730Sbenno		if ((lr & 3) || (lr < 0x100)) {
18499730Sbenno			(*pr)("saved LR(0x%x) is invalid.", lr);
18599730Sbenno			break;
18699730Sbenno		}
18799730Sbenno		if ((caller = (db_addr_t)vtophys(lr)) == 0)
18899730Sbenno			caller = lr;
18999730Sbenno
19099730Sbenno		if (frame != (db_addr_t) fakeframe) {
19199730Sbenno			(*pr)("0x%08lx: ", frame);
19299730Sbenno		} else {
19399730Sbenno			(*pr)("     <?>  : ");
19499730Sbenno		}
19599730Sbenno		if (caller + 4 == (db_addr_t) &trapexit) {
19699730Sbenno			const char *trapstr;
19799730Sbenno			struct trapframe *tf = (struct trapframe *) (frame+8);
19899730Sbenno			(*pr)("%s ", tf->srr1 & PSL_PR ? "user" : "kernel");
19999730Sbenno			switch (tf->exc) {
20099730Sbenno			case EXC_DSI:
20199730Sbenno#ifdef PPC_MPC6XX
20299730Sbenno				(*pr)("DSI %s trap @ %#x by ",
20399730Sbenno				    tf->dsisr & DSISR_STORE ? "write" : "read",
20499730Sbenno				    tf->dar);
20599730Sbenno#endif
20699730Sbenno#ifdef PPC_IBM4XX
20799730Sbenno				(*pr)("DSI %s trap @ %#x by ",
20899730Sbenno				    tf->esr & ESR_DST ? "write" : "read",
20999730Sbenno				    tf->dear);
21099730Sbenno#endif
21199730Sbenno				goto print_trap;
21299730Sbenno			case EXC_ISI: trapstr = "ISI"; break;
21399730Sbenno			case EXC_PGM: trapstr = "PGM"; break;
21499730Sbenno			case EXC_SC: trapstr = "SC"; break;
21599730Sbenno			case EXC_EXI: trapstr = "EXI"; break;
21699730Sbenno			case EXC_MCHK: trapstr = "MCHK"; break;
21799730Sbenno			case EXC_VEC: trapstr = "VEC"; break;
21899730Sbenno			case EXC_FPU: trapstr = "FPU"; break;
21999730Sbenno			case EXC_FPA: trapstr = "FPA"; break;
22099730Sbenno			case EXC_DECR: trapstr = "DECR"; break;
22199730Sbenno			case EXC_ALI: trapstr = "ALI"; break;
22299730Sbenno			case EXC_BPT: trapstr = "BPT"; break;
22399730Sbenno			case EXC_TRC: trapstr = "TRC"; break;
22499730Sbenno			case EXC_RUNMODETRC: trapstr = "RUNMODETRC"; break;
22599730Sbenno			case EXC_PERF: trapstr = "PERF"; break;
22699730Sbenno			case EXC_SMI: trapstr = "SMI"; break;
22799730Sbenno			case EXC_RST: trapstr = "RST"; break;
22899730Sbenno			default: trapstr = NULL; break;
22999730Sbenno			}
23099730Sbenno			if (trapstr != NULL) {
23199730Sbenno				(*pr)("%s trap by ", trapstr);
23299730Sbenno			} else {
23399730Sbenno				(*pr)("trap %#x by ", tf->exc);
23499730Sbenno			}
23599730Sbenno		   print_trap:
23699730Sbenno			lr = (db_addr_t) tf->srr0;
23799730Sbenno			if ((caller = (db_addr_t)vtophys(lr)) == 0)
23899730Sbenno				caller = lr;
23999730Sbenno			diff = 0;
24099730Sbenno			symname = NULL;
24199730Sbenno			sym = db_search_symbol(caller, DB_STGY_ANY, &diff);
24299730Sbenno			db_symbol_values(sym, &symname, 0);
24399730Sbenno			if (symname == NULL || !strcmp(symname, "end")) {
24499730Sbenno				(*pr)("%p: srr1=%#x\n", caller, tf->srr1);
24599730Sbenno			} else {
24699730Sbenno				(*pr)("%s+%x: srr1=%#x\n", symname, diff,
24799730Sbenno				    tf->srr1);
24899730Sbenno			}
24999730Sbenno			(*pr)("%-10s  r1=%#x cr=%#x xer=%#x ctr=%#x",
25099730Sbenno			    "", tf->fixreg[1], tf->cr, tf->xer, tf->ctr);
25199730Sbenno#ifdef PPC_MPC6XX
25299730Sbenno			if (tf->exc == EXC_DSI)
25399730Sbenno				(*pr)(" dsisr=%#x", tf->dsisr);
25499730Sbenno#endif
25599730Sbenno#ifdef PPC_IBM4XX
25699730Sbenno			if (tf->exc == EXC_DSI)
25799730Sbenno				(*pr)(" dear=%#x", tf->dear);
25899730Sbenno			(*pr)(" esr=%#x pid=%#x", tf->esr, tf->pid);
25999730Sbenno#endif
26099730Sbenno			(*pr)("\n");
26199730Sbenno			fakeframe[0] = (db_addr_t) tf->fixreg[1];
26299730Sbenno			fakeframe[1] = (db_addr_t) tf->lr;
26399730Sbenno			frame = (db_addr_t) fakeframe;
26499730Sbenno			if (kernel_only && (tf->srr1 & PSL_PR))
26599730Sbenno				break;
26699730Sbenno			goto next_frame;
26799730Sbenno		}
26899730Sbenno
26999730Sbenno		diff = 0;
27099730Sbenno		symname = NULL;
27199730Sbenno		sym = db_search_symbol(caller, DB_STGY_ANY, &diff);
27299730Sbenno		db_symbol_values(sym, &symname, 0);
27399730Sbenno		if (symname == NULL || !strcmp(symname, "end"))
27499730Sbenno			(*pr)("at %p", caller);
27599730Sbenno		else
27699730Sbenno			(*pr)("at %s+%#x", symname, diff);
27799730Sbenno		if (full)
27899730Sbenno			/* Print all the args stored in that stackframe. */
27999730Sbenno			(*pr)("(%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx)",
28099730Sbenno				args[0], args[1], args[2], args[3],
28199730Sbenno				args[4], args[5], args[6], args[7]);
28299730Sbenno		(*pr)("\n");
28399730Sbenno	}
28499730Sbenno}
28599730Sbenno
28699730Sbennovoid
28799730Sbennodb_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
28899730Sbenno    char *modif)
28999730Sbenno{
29099730Sbenno
29199730Sbenno	db_stack_trace_print(addr, have_addr, count, modif, db_printf);
29299730Sbenno}
29399730Sbenno
294103646Sjhbvoid
295103646Sjhbdb_print_backtrace(void)
296103646Sjhb{
297103646Sjhb}
298