xref: /openbsd/sys/arch/sparc64/sparc64/db_trace.c (revision 949c1c4e)
1 /*	$OpenBSD: db_trace.c,v 1.28 2024/11/07 16:02:29 miod Exp $	*/
2 /*	$NetBSD: db_trace.c,v 1.23 2001/07/10 06:06:16 eeh Exp $ */
3 
4 /*
5  * Mach Operating System
6  * Copyright (c) 1991,1990 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 the
27  * rights to redistribute these changes.
28  */
29 
30 #include <sys/param.h>
31 #include <sys/proc.h>
32 #include <sys/systm.h>
33 #include <sys/stacktrace.h>
34 #include <sys/user.h>
35 #include <machine/db_machdep.h>
36 #include <machine/ctlreg.h>
37 
38 #include <ddb/db_access.h>
39 #include <ddb/db_sym.h>
40 #include <ddb/db_interface.h>
41 #include <ddb/db_output.h>
42 
43 void db_dump_fpstate(db_expr_t, int, db_expr_t, char *);
44 void db_dump_window(db_expr_t, int, db_expr_t, char *);
45 void db_dump_stack(db_expr_t, int, db_expr_t, char *);
46 void db_dump_trap(db_expr_t, int, db_expr_t, char *);
47 void db_dump_ts(db_expr_t, int, db_expr_t, char *);
48 void db_print_window(u_int64_t);
49 
50 #define	KLOAD(x)	probeget((paddr_t)(u_long)&(x), ASI_PRIMARY, sizeof(x))
51 #define ULOAD(x)	probeget((paddr_t)(u_long)&(x), ASI_AIUS, sizeof(x))
52 
53 void
db_stack_trace_print(db_expr_t addr,int have_addr,db_expr_t count,char * modif,int (* pr)(const char *,...))54 db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
55     char *modif, int (*pr)(const char *, ...))
56 {
57 	vaddr_t		frame;
58 	int		kernel_only = 1;
59 	int		trace_thread = 0;
60 	char		c, *cp = modif;
61 
62 	while ((c = *cp++) != 0) {
63 		if (c == 't')
64 			trace_thread = 1;
65 		if (c == 'u')
66 			kernel_only = 0;
67 	}
68 
69 	if (!have_addr)
70 		frame = (vaddr_t)DDB_TF->tf_out[6];
71 	else {
72 		if (trace_thread) {
73 			struct proc *p;
74 			struct user *u;
75 			(*pr)("trace: pid %d ", (int)addr);
76 			p = tfind(addr);
77 			if (p == NULL) {
78 				(*pr)("not found\n");
79 				return;
80 			}
81 			u = p->p_addr;
82 			frame = (vaddr_t)u->u_pcb.pcb_sp;
83 			(*pr)("at %p\n", frame);
84 		} else {
85 			write_all_windows();
86 
87 			frame = (vaddr_t)addr - BIAS;
88 		}
89 	}
90 
91 	if ((frame & 1) == 0) {
92 		db_printf("WARNING: corrupt frame at %lx\n", frame);
93 		return;
94 	}
95 
96 	while (count--) {
97 		int		i;
98 		db_expr_t	offset;
99 		const char	*name;
100 		vaddr_t		pc;
101 		struct frame	*f64;
102 
103 		/*
104 		 * Switch to frame that contains arguments
105 		 */
106 
107 		f64 = (struct frame *)(frame + BIAS);
108 		pc = (vaddr_t)KLOAD(f64->fr_pc);
109 
110 		frame = KLOAD(f64->fr_fp);
111 
112 		if (kernel_only) {
113 			if (pc < KERNBASE || pc >= KERNEND)
114 				break;
115 			if (frame < KERNBASE)
116 				break;
117 		} else {
118 			if (frame == 0 || frame == (vaddr_t)-1)
119 				break;
120 		}
121 
122 		db_find_sym_and_offset(pc, &name, &offset);
123 
124 		if (name == NULL)
125 			(*pr)("%lx(", pc);
126 		else
127 			(*pr)("%s(", name);
128 
129 		if ((frame & 1) == 0) {
130 			db_printf(")\nWARNING: corrupt frame at %lx\n", frame);
131 			break;
132 		}
133 
134 		/*
135 		 * Print %i0..%i5; hope these still reflect the
136 		 * actual arguments somewhat...
137 		 */
138 		f64 = (struct frame *)(frame + BIAS);
139 		for (i = 0; i < 5; i++)
140 			(*pr)("%lx, ", (long)KLOAD(f64->fr_arg[i]));
141 		(*pr)("%lx) at ", (long)KLOAD(f64->fr_arg[i]));
142 		db_printsym(pc, DB_STGY_PROC, pr);
143 		(*pr)("\n");
144 	}
145 }
146 
147 void
stacktrace_save_at(struct stacktrace * st,unsigned int skip)148 stacktrace_save_at(struct stacktrace *st, unsigned int skip)
149 {
150 	struct frame	*f64;
151 	vaddr_t		pc;
152 	vaddr_t		frame;
153 
154 	write_all_windows();
155 
156 	frame = (vaddr_t)__builtin_frame_address(0) - BIAS;
157 	if ((frame & 1) == 0)
158 		return;
159 
160 	st->st_count = 0;
161 	while (st->st_count < STACKTRACE_MAX) {
162 		f64 = (struct frame *)(frame + BIAS);
163 		pc = (vaddr_t)KLOAD(f64->fr_pc);
164 
165 		frame = KLOAD(f64->fr_fp);
166 
167 		if (pc < KERNBASE || pc >= KERNEND)
168 			break;
169 		if (frame < KERNBASE)
170 			break;
171 		if ((frame & 1) == 0)
172 			break;
173 
174 		if (skip == 0)
175 			st->st_pc[st->st_count++] = pc;
176 		else
177 			skip--;
178 	}
179 }
180 
181 void
stacktrace_save_utrace(struct stacktrace * st)182 stacktrace_save_utrace(struct stacktrace *st)
183 {
184 	st->st_count = 0;
185 }
186 
187 void
db_dump_window(db_expr_t addr,int have_addr,db_expr_t count,char * modif)188 db_dump_window(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
189 {
190 	int i;
191 	u_int64_t frame = DDB_TF->tf_out[6];
192 
193 	/* Addr is really window number */
194 	if (!have_addr)
195 		addr = 0;
196 
197 	/* Traverse window stack */
198 	for (i = 0; i < addr && frame; i++) {
199 		if ((frame & 1) == 0)
200 			break;
201 		frame = ((struct frame *)(frame + BIAS))->fr_fp;
202 	}
203 
204 	if ((frame & 1) == 0) {
205 		db_printf("WARNING: corrupt frame at %llx\n", frame);
206 		return;
207 	}
208 
209 	db_printf("Window %lx ", addr);
210 	db_print_window(frame);
211 }
212 
213 void
db_print_window(u_int64_t frame)214 db_print_window(u_int64_t frame)
215 {
216 	struct frame *f = (struct frame *)(frame + BIAS);
217 
218 	db_printf("frame %p locals, ins:\n", f);
219 	db_printf("%llx %llx %llx %llx ",
220 		  (unsigned long long)f->fr_local[0],
221 		  (unsigned long long)f->fr_local[1],
222 		  (unsigned long long)f->fr_local[2],
223 		  (unsigned long long)f->fr_local[3]);
224 	db_printf("%llx %llx %llx %llx\n",
225 		  (unsigned long long)f->fr_local[4],
226 		  (unsigned long long)f->fr_local[5],
227 		  (unsigned long long)f->fr_local[6],
228 		  (unsigned long long)f->fr_local[7]);
229 	db_printf("%llx %llx %llx %llx ",
230 		  (unsigned long long)f->fr_arg[0],
231 		  (unsigned long long)f->fr_arg[1],
232 		  (unsigned long long)f->fr_arg[2],
233 		  (unsigned long long)f->fr_arg[3]);
234 	db_printf("%llx %llx %llx=sp %llx=pc:",
235 		  (unsigned long long)f->fr_arg[4],
236 		  (unsigned long long)f->fr_arg[5],
237 		  (unsigned long long)f->fr_fp,
238 		  (unsigned long long)f->fr_pc);
239 	/* Sometimes this don't work.  Dunno why. */
240 	db_printsym(f->fr_pc, DB_STGY_PROC, db_printf);
241 	db_printf("\n");
242 }
243 
244 void
db_dump_stack(db_expr_t addr,int have_addr,db_expr_t count,char * modif)245 db_dump_stack(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
246 {
247 	int		i;
248 	u_int64_t	frame, oldframe;
249 
250 	if (count == -1)
251 		count = 65535;
252 
253 	if (!have_addr)
254 		frame = DDB_TF->tf_out[6];
255 	else
256 		frame = addr;
257 
258 	/* Traverse window stack */
259 	oldframe = 0;
260 	for (i = 0; i < count && frame; i++) {
261 		if (oldframe == frame) {
262 			db_printf("WARNING: stack loop at %llx\n", frame);
263 			break;
264 		}
265 		oldframe = frame;
266 
267 		if ((frame & 1) == 0) {
268 			db_printf("WARNING: corrupt stack at %llx\n", frame);
269 			break;
270 		}
271 
272 		frame += BIAS;
273 		db_printf("Window %x ", i);
274 		db_print_window(frame - BIAS);
275 		frame = ((struct frame *)frame)->fr_fp;
276 	}
277 }
278 
279 
280 void
db_dump_trap(db_expr_t addr,int have_addr,db_expr_t count,char * modif)281 db_dump_trap(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
282 {
283 	struct trapframe *tf;
284 
285 	/* Use our last trapframe? */
286 	tf = &ddb_regs.ddb_tf;
287 	{
288 		/* Or the user trapframe? */
289 		register char c, *cp = modif;
290 		while ((c = *cp++) != 0)
291 			if (c == 'u')
292 				tf = curproc->p_md.md_tf;
293 	}
294 	/* Or an arbitrary trapframe */
295 	if (have_addr)
296 		tf = (struct trapframe *)addr;
297 
298 	db_printf("Trapframe %p:\ttstate: %llx\tpc: %llx\tnpc: %llx\n",
299 		  tf, (unsigned long long)tf->tf_tstate,
300 		  (unsigned long long)tf->tf_pc,
301 		  (unsigned long long)tf->tf_npc);
302 	db_printf("y: %x\tpil: %d\toldpil: %d\ttt: %x\nGlobals:\n",
303 		  (int)tf->tf_y, (int)tf->tf_pil, (int)tf->tf_oldpil,
304 		  (int)tf->tf_tt);
305 	db_printf("%016llx %016llx %016llx %016llx\n",
306 		  (unsigned long long)tf->tf_global[0],
307 		  (unsigned long long)tf->tf_global[1],
308 		  (unsigned long long)tf->tf_global[2],
309 		  (unsigned long long)tf->tf_global[3]);
310 	db_printf("%016llx %016llx %016llx %016llx\nouts:\n",
311 		  (unsigned long long)tf->tf_global[4],
312 		  (unsigned long long)tf->tf_global[5],
313 		  (unsigned long long)tf->tf_global[6],
314 		  (unsigned long long)tf->tf_global[7]);
315 	db_printf("%016llx %016llx %016llx %016llx\n",
316 		  (unsigned long long)tf->tf_out[0],
317 		  (unsigned long long)tf->tf_out[1],
318 		  (unsigned long long)tf->tf_out[2],
319 		  (unsigned long long)tf->tf_out[3]);
320 	db_printf("%016llx %016llx %016llx %016llx\nlocals:\n",
321 		  (unsigned long long)tf->tf_out[4],
322 		  (unsigned long long)tf->tf_out[5],
323 		  (unsigned long long)tf->tf_out[6],
324 		  (unsigned long long)tf->tf_out[7]);
325 	db_printf("%016llx %016llx %016llx %016llx\n",
326 		  (unsigned long long)tf->tf_local[0],
327 		  (unsigned long long)tf->tf_local[1],
328 		  (unsigned long long)tf->tf_local[2],
329 		  (unsigned long long)tf->tf_local[3]);
330 	db_printf("%016llx %016llx %016llx %016llx\nins:\n",
331 		  (unsigned long long)tf->tf_local[4],
332 		  (unsigned long long)tf->tf_local[5],
333 		  (unsigned long long)tf->tf_local[6],
334 		  (unsigned long long)tf->tf_local[7]);
335 	db_printf("%016llx %016llx %016llx %016llx\n",
336 		  (unsigned long long)tf->tf_in[0],
337 		  (unsigned long long)tf->tf_in[1],
338 		  (unsigned long long)tf->tf_in[2],
339 		  (unsigned long long)tf->tf_in[3]);
340 	db_printf("%016llx %016llx %016llx %016llx\n",
341 		  (unsigned long long)tf->tf_in[4],
342 		  (unsigned long long)tf->tf_in[5],
343 		  (unsigned long long)tf->tf_in[6],
344 		  (unsigned long long)tf->tf_in[7]);
345 }
346 
347 void
db_dump_fpstate(db_expr_t addr,int have_addr,db_expr_t count,char * modif)348 db_dump_fpstate(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
349 {
350 	struct fpstate *fpstate;
351 
352 	/* Use our last trapframe? */
353 	fpstate = &ddb_regs.ddb_fpstate;
354 	/* Or an arbitrary trapframe */
355 	if (have_addr)
356 		fpstate = (struct fpstate *)addr;
357 
358 	db_printf("fpstate %p: fsr = %llx gsr = %lx\nfpregs:\n",
359 		fpstate, (unsigned long long)fpstate->fs_fsr,
360 		(unsigned long)fpstate->fs_gsr);
361 	db_printf(" 0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
362 		(unsigned int)fpstate->fs_regs[0],
363 		(unsigned int)fpstate->fs_regs[1],
364 		(unsigned int)fpstate->fs_regs[2],
365 		(unsigned int)fpstate->fs_regs[3],
366 		(unsigned int)fpstate->fs_regs[4],
367 		(unsigned int)fpstate->fs_regs[5],
368 		(unsigned int)fpstate->fs_regs[6],
369 		(unsigned int)fpstate->fs_regs[7]);
370 	db_printf(" 8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
371 		(unsigned int)fpstate->fs_regs[8],
372 		(unsigned int)fpstate->fs_regs[9],
373 		(unsigned int)fpstate->fs_regs[10],
374 		(unsigned int)fpstate->fs_regs[11],
375 		(unsigned int)fpstate->fs_regs[12],
376 		(unsigned int)fpstate->fs_regs[13],
377 		(unsigned int)fpstate->fs_regs[14],
378 		(unsigned int)fpstate->fs_regs[15]);
379 	db_printf("16: %08x %08x %08x %08x %08x %08x %08x %08x\n",
380 		(unsigned int)fpstate->fs_regs[16],
381 		(unsigned int)fpstate->fs_regs[17],
382 		(unsigned int)fpstate->fs_regs[18],
383 		(unsigned int)fpstate->fs_regs[19],
384 		(unsigned int)fpstate->fs_regs[20],
385 		(unsigned int)fpstate->fs_regs[21],
386 		(unsigned int)fpstate->fs_regs[22],
387 		(unsigned int)fpstate->fs_regs[23]);
388 	db_printf("24: %08x %08x %08x %08x %08x %08x %08x %08x\n",
389 		(unsigned int)fpstate->fs_regs[24],
390 		(unsigned int)fpstate->fs_regs[25],
391 		(unsigned int)fpstate->fs_regs[26],
392 		(unsigned int)fpstate->fs_regs[27],
393 		(unsigned int)fpstate->fs_regs[28],
394 		(unsigned int)fpstate->fs_regs[29],
395 		(unsigned int)fpstate->fs_regs[30],
396 		(unsigned int)fpstate->fs_regs[31]);
397 	db_printf("32: %08x%08x %08x%08x %08x%08x %08x%08x\n",
398 		(unsigned int)fpstate->fs_regs[32],
399 		(unsigned int)fpstate->fs_regs[33],
400 		(unsigned int)fpstate->fs_regs[34],
401 		(unsigned int)fpstate->fs_regs[35],
402 		(unsigned int)fpstate->fs_regs[36],
403 		(unsigned int)fpstate->fs_regs[37],
404 		(unsigned int)fpstate->fs_regs[38],
405 		(unsigned int)fpstate->fs_regs[39]);
406 	db_printf("40: %08x%08x %08x%08x %08x%08x %08x%08x\n",
407 		(unsigned int)fpstate->fs_regs[40],
408 		(unsigned int)fpstate->fs_regs[41],
409 		(unsigned int)fpstate->fs_regs[42],
410 		(unsigned int)fpstate->fs_regs[43],
411 		(unsigned int)fpstate->fs_regs[44],
412 		(unsigned int)fpstate->fs_regs[45],
413 		(unsigned int)fpstate->fs_regs[46],
414 		(unsigned int)fpstate->fs_regs[47]);
415 	db_printf("48: %08x%08x %08x%08x %08x%08x %08x%08x\n",
416 		(unsigned int)fpstate->fs_regs[48],
417 		(unsigned int)fpstate->fs_regs[49],
418 		(unsigned int)fpstate->fs_regs[50],
419 		(unsigned int)fpstate->fs_regs[51],
420 		(unsigned int)fpstate->fs_regs[52],
421 		(unsigned int)fpstate->fs_regs[53],
422 		(unsigned int)fpstate->fs_regs[54],
423 		(unsigned int)fpstate->fs_regs[55]);
424 	db_printf("56: %08x%08x %08x%08x %08x%08x %08x%08x\n",
425 		(unsigned int)fpstate->fs_regs[56],
426 		(unsigned int)fpstate->fs_regs[57],
427 		(unsigned int)fpstate->fs_regs[58],
428 		(unsigned int)fpstate->fs_regs[59],
429 		(unsigned int)fpstate->fs_regs[60],
430 		(unsigned int)fpstate->fs_regs[61],
431 		(unsigned int)fpstate->fs_regs[62],
432 		(unsigned int)fpstate->fs_regs[63]);
433 }
434 
435 void
db_dump_ts(db_expr_t addr,int have_addr,db_expr_t count,char * modif)436 db_dump_ts(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
437 {
438 	struct trapstate	*ts;
439 	int			i, tl;
440 
441 	/* Use our last trapframe? */
442 	ts = &ddb_regs.ddb_ts[0];
443 	tl = ddb_regs.ddb_tl;
444 	for (i = 0; i < tl; i++) {
445 		printf("%d tt=%lx tstate=%lx tpc=%p tnpc=%p\n",
446 		       i+1, (long)ts[i].tt, (u_long)ts[i].tstate,
447 		       (void *)(u_long)ts[i].tpc, (void *)(u_long)ts[i].tnpc);
448 	}
449 
450 }
451