xref: /openbsd-src/sys/arch/powerpc/ddb/db_trace.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: db_trace.c,v 1.4 2003/10/15 01:06:13 drahn Exp $	*/
2 /*	$NetBSD: db_trace.c,v 1.15 1996/02/22 23:23:41 gwr Exp $	*/
3 
4 /*
5  * Mach Operating System
6  * Copyright (c) 1992 Carnegie Mellon University
7  * All Rights Reserved.
8  *
9  * Permission to use, copy, modify and distribute this software and its
10  * documentation is hereby granted, provided that both the copyright
11  * notice and this permission notice appear in all copies of the
12  * software, derivative works or modified versions, and any portions
13  * thereof, and that both notices appear in supporting documentation.
14  *
15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18  *
19  * Carnegie Mellon requests users of this software to return to
20  *
21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22  *  School of Computer Science
23  *  Carnegie Mellon University
24  *  Pittsburgh PA 15213-3890
25  *
26  * any improvements or extensions that they make and grant Carnegie Mellon
27  * the rights to redistribute these changes.
28  */
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/proc.h>
33 
34 #include <machine/db_machdep.h>
35 #include <machine/signal.h>
36 #include <machine/pcb.h>
37 
38 #include <ddb/db_access.h>
39 #include <ddb/db_sym.h>
40 #include <ddb/db_variables.h>
41 #include <ddb/db_interface.h>
42 #include <ddb/db_output.h>
43 
44 int db_read32(u_int32_t paddr, u_int32_t *value);
45 
46 db_regs_t ddb_regs;
47 
48 struct db_variable db_regs[] = {
49 	{ "r0",  (long *)&(DDB_REGS->tf.fixreg[0]),	FCN_NULL },
50 	{ "r1",  (long *)&(DDB_REGS->tf.fixreg[1]),	FCN_NULL },
51 	{ "r2",  (long *)&(DDB_REGS->tf.fixreg[2]),	FCN_NULL },
52 	{ "r3",  (long *)&(DDB_REGS->tf.fixreg[3]),	FCN_NULL },
53 	{ "r4",  (long *)&(DDB_REGS->tf.fixreg[4]),	FCN_NULL },
54 	{ "r5",  (long *)&(DDB_REGS->tf.fixreg[5]),	FCN_NULL },
55 	{ "r6",  (long *)&(DDB_REGS->tf.fixreg[6]),	FCN_NULL },
56 	{ "r7",  (long *)&(DDB_REGS->tf.fixreg[7]),	FCN_NULL },
57 	{ "r8",  (long *)&(DDB_REGS->tf.fixreg[8]),	FCN_NULL },
58 	{ "r9",  (long *)&(DDB_REGS->tf.fixreg[9]),	FCN_NULL },
59 	{ "r10", (long *)&(DDB_REGS->tf.fixreg[10]),	FCN_NULL },
60 	{ "r11", (long *)&(DDB_REGS->tf.fixreg[11]),	FCN_NULL },
61 	{ "r12", (long *)&(DDB_REGS->tf.fixreg[12]),	FCN_NULL },
62 	{ "r13", (long *)&(DDB_REGS->tf.fixreg[13]),	FCN_NULL },
63 	{ "r14", (long *)&(DDB_REGS->tf.fixreg[13]),	FCN_NULL },
64 	{ "r15", (long *)&(DDB_REGS->tf.fixreg[13]),	FCN_NULL },
65 	{ "r16", (long *)&(DDB_REGS->tf.fixreg[13]),	FCN_NULL },
66 	{ "r17", (long *)&(DDB_REGS->tf.fixreg[17]),	FCN_NULL },
67 	{ "r18", (long *)&(DDB_REGS->tf.fixreg[18]),	FCN_NULL },
68 	{ "r19", (long *)&(DDB_REGS->tf.fixreg[19]),	FCN_NULL },
69 	{ "r20", (long *)&(DDB_REGS->tf.fixreg[20]),	FCN_NULL },
70 	{ "r21", (long *)&(DDB_REGS->tf.fixreg[21]),	FCN_NULL },
71 	{ "r22", (long *)&(DDB_REGS->tf.fixreg[22]),	FCN_NULL },
72 	{ "r23", (long *)&(DDB_REGS->tf.fixreg[23]),	FCN_NULL },
73 	{ "r24", (long *)&(DDB_REGS->tf.fixreg[24]),	FCN_NULL },
74 	{ "r25", (long *)&(DDB_REGS->tf.fixreg[25]),	FCN_NULL },
75 	{ "r26", (long *)&(DDB_REGS->tf.fixreg[26]),	FCN_NULL },
76 	{ "r27", (long *)&(DDB_REGS->tf.fixreg[27]),	FCN_NULL },
77 	{ "r28", (long *)&(DDB_REGS->tf.fixreg[28]),	FCN_NULL },
78 	{ "r29", (long *)&(DDB_REGS->tf.fixreg[29]),	FCN_NULL },
79 	{ "r30", (long *)&(DDB_REGS->tf.fixreg[30]),	FCN_NULL },
80 	{ "r31", (long *)&(DDB_REGS->tf.fixreg[31]),	FCN_NULL },
81 	{ "lr", (long *)&(DDB_REGS->tf.lr),	FCN_NULL },
82 	{ "cr", (long *)&(DDB_REGS->tf.cr),	FCN_NULL },
83 	{ "xer", (long *)&(DDB_REGS->tf.xer),	FCN_NULL },
84 	{ "ctr", (long *)&(DDB_REGS->tf.ctr),	FCN_NULL },
85 	{ "iar", (long *)&(DDB_REGS->tf.srr0),	FCN_NULL },
86 	{ "msr", (long *)&(DDB_REGS->tf.srr1),	FCN_NULL },
87 };
88 
89 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
90 
91 extern label_t	*db_recover;
92 
93 /*
94  * this is probably hackery.
95  */
96 void
97 db_save_regs(struct trapframe *frame)
98 {
99 	bcopy(frame, &(ddb_regs.tf), sizeof (struct trapframe));
100 }
101 
102 int
103 db_read32(u_int32_t paddr, u_int32_t *value)
104 {
105 	faultbuf env;
106 	faultbuf *old_onfault = curpcb->pcb_onfault;
107 	if (setfault(&env)) {
108 		curpcb->pcb_onfault = old_onfault;
109 		return EFAULT;
110 	}
111 	*value = *(u_int32_t *)paddr;
112 	curpcb->pcb_onfault = old_onfault;
113 	return 0;
114 }
115 
116 db_expr_t
117 db_dumpframe(u_int32_t pframe, int (*pr)(const char *, ...))
118 {
119 	u_int32_t nextframe;
120 	u_int32_t lr;
121 	char *name;
122 	db_expr_t offset;
123 
124 	if (db_read32(pframe, &nextframe) == EFAULT) {
125 		return 0;
126 	}
127 
128 	if (db_read32(pframe+4, &lr) == EFAULT) {
129 		return 0;
130 	}
131 
132 	db_find_sym_and_offset(lr-4, &name, &offset);
133 	if (!name) {
134 		name = "0";
135 		offset = lr-4;
136 	}
137 	(*pr)("%08x: %s+0x%x fp %x nfp %x\n",
138 		lr-4, name, offset, pframe, nextframe);
139 
140 	return nextframe;
141 }
142 
143 /*
144  *	Frame tracing.
145  */
146 void
147 db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
148     char *modif, int (*pr)(const char *, ...))
149 {
150 
151 	if (count == 0 || count == -1)
152 		count = INT_MAX;
153 	if (have_addr == 0){
154 		addr = ddb_regs.tf.fixreg[1];
155 	}
156 	while (addr != 0 && count > 0) {
157 		addr = db_dumpframe(addr, pr);
158 		count --;
159 	}
160 }
161