xref: /freebsd/sys/amd64/amd64/db_trace.c (revision c697fb7f)
1 /*-
2  * Mach Operating System
3  * Copyright (c) 1991,1990 Carnegie Mellon University
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify and distribute this software and its
7  * documentation is hereby granted, provided that both the copyright
8  * notice and this permission notice appear in all copies of the
9  * software, derivative works or modified versions, and any portions
10  * thereof, and that both notices appear in supporting documentation.
11  *
12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15  *
16  * Carnegie Mellon requests users of this software to return to
17  *
18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19  *  School of Computer Science
20  *  Carnegie Mellon University
21  *  Pittsburgh PA 15213-3890
22  *
23  * any improvements or extensions that they make and grant Carnegie the
24  * rights to redistribute these changes.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kdb.h>
33 #include <sys/proc.h>
34 #include <sys/smp.h>
35 #include <sys/stack.h>
36 #include <sys/sysent.h>
37 
38 #include <machine/cpu.h>
39 #include <machine/md_var.h>
40 #include <machine/pcb.h>
41 #include <machine/reg.h>
42 #include <machine/stack.h>
43 
44 #include <vm/vm.h>
45 #include <vm/vm_param.h>
46 #include <vm/pmap.h>
47 
48 #include <ddb/ddb.h>
49 #include <ddb/db_access.h>
50 #include <ddb/db_sym.h>
51 #include <ddb/db_variables.h>
52 
53 static db_varfcn_t db_frame;
54 static db_varfcn_t db_frame_seg;
55 
56 CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg));
57 
58 /*
59  * Machine register set.
60  */
61 #define	DB_OFFSET(x)	(db_expr_t *)offsetof(struct trapframe, x)
62 struct db_variable db_regs[] = {
63 	{ "cs",		DB_OFFSET(tf_cs),	db_frame_seg },
64 	{ "ds",		DB_OFFSET(tf_ds),	db_frame_seg },
65 	{ "es",		DB_OFFSET(tf_es),	db_frame_seg },
66 	{ "fs",		DB_OFFSET(tf_fs),	db_frame_seg },
67 	{ "gs",		DB_OFFSET(tf_gs),	db_frame_seg },
68 	{ "ss",		DB_OFFSET(tf_ss),	db_frame_seg },
69 	{ "rax",	DB_OFFSET(tf_rax),	db_frame },
70 	{ "rcx",        DB_OFFSET(tf_rcx),	db_frame },
71 	{ "rdx",	DB_OFFSET(tf_rdx),	db_frame },
72 	{ "rbx",	DB_OFFSET(tf_rbx),	db_frame },
73 	{ "rsp",	DB_OFFSET(tf_rsp),	db_frame },
74 	{ "rbp",	DB_OFFSET(tf_rbp),	db_frame },
75 	{ "rsi",	DB_OFFSET(tf_rsi),	db_frame },
76 	{ "rdi",	DB_OFFSET(tf_rdi),	db_frame },
77 	{ "r8",		DB_OFFSET(tf_r8),	db_frame },
78 	{ "r9",		DB_OFFSET(tf_r9),	db_frame },
79 	{ "r10",	DB_OFFSET(tf_r10),	db_frame },
80 	{ "r11",	DB_OFFSET(tf_r11),	db_frame },
81 	{ "r12",	DB_OFFSET(tf_r12),	db_frame },
82 	{ "r13",	DB_OFFSET(tf_r13),	db_frame },
83 	{ "r14",	DB_OFFSET(tf_r14),	db_frame },
84 	{ "r15",	DB_OFFSET(tf_r15),	db_frame },
85 	{ "rip",	DB_OFFSET(tf_rip),	db_frame },
86 	{ "rflags",	DB_OFFSET(tf_rflags),	db_frame },
87 };
88 struct db_variable *db_eregs = db_regs + nitems(db_regs);
89 
90 static int
91 db_frame_seg(struct db_variable *vp, db_expr_t *valuep, int op)
92 {
93 	uint16_t *reg;
94 
95 	if (kdb_frame == NULL)
96 		return (0);
97 
98 	reg = (uint16_t *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
99 	if (op == DB_VAR_GET)
100 		*valuep = *reg;
101 	else
102 		*reg = *valuep;
103 	return (1);
104 }
105 
106 static int
107 db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
108 {
109 	long *reg;
110 
111 	if (kdb_frame == NULL)
112 		return (0);
113 
114 	reg = (long *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
115 	if (op == DB_VAR_GET)
116 		*valuep = *reg;
117 	else
118 		*reg = *valuep;
119 	return (1);
120 }
121 
122 #define NORMAL		0
123 #define	TRAP		1
124 #define	INTERRUPT	2
125 #define	SYSCALL		3
126 
127 static void db_nextframe(struct amd64_frame **, db_addr_t *, struct thread *);
128 static void db_print_stack_entry(const char *, db_addr_t, void *);
129 static void decode_syscall(int, struct thread *);
130 
131 static const char * watchtype_str(int type);
132 int  amd64_set_watch(int watchnum, unsigned long watchaddr, int size,
133 		    int access, struct dbreg *d);
134 int  amd64_clr_watch(int watchnum, struct dbreg *d);
135 
136 static void
137 db_print_stack_entry(const char *name, db_addr_t callpc, void *frame)
138 {
139 
140 	db_printf("%s() at ", name != NULL ? name : "??");
141 	db_printsym(callpc, DB_STGY_PROC);
142 	if (frame != NULL)
143 		db_printf("/frame 0x%lx", (register_t)frame);
144 	db_printf("\n");
145 }
146 
147 static void
148 decode_syscall(int number, struct thread *td)
149 {
150 	struct proc *p;
151 	c_db_sym_t sym;
152 	db_expr_t diff;
153 	sy_call_t *f;
154 	const char *symname;
155 
156 	db_printf(" (%d", number);
157 	p = (td != NULL) ? td->td_proc : NULL;
158 	if (p != NULL && 0 <= number && number < p->p_sysent->sv_size) {
159 		f = p->p_sysent->sv_table[number].sy_call;
160 		sym = db_search_symbol((db_addr_t)f, DB_STGY_ANY, &diff);
161 		if (sym != DB_SYM_NULL && diff == 0) {
162 			db_symbol_values(sym, &symname, NULL);
163 			db_printf(", %s, %s", p->p_sysent->sv_name, symname);
164 		}
165 	}
166 	db_printf(")");
167 }
168 
169 /*
170  * Figure out the next frame up in the call stack.
171  */
172 static void
173 db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td)
174 {
175 	struct trapframe *tf;
176 	int frame_type;
177 	long rip, rsp, rbp;
178 	db_expr_t offset;
179 	c_db_sym_t sym;
180 	const char *name;
181 
182 	rip = db_get_value((long) &(*fp)->f_retaddr, 8, FALSE);
183 	rbp = db_get_value((long) &(*fp)->f_frame, 8, FALSE);
184 
185 	/*
186 	 * Figure out frame type.  We look at the address just before
187 	 * the saved instruction pointer as the saved EIP is after the
188 	 * call function, and if the function being called is marked as
189 	 * dead (such as panic() at the end of dblfault_handler()), then
190 	 * the instruction at the saved EIP will be part of a different
191 	 * function (syscall() in this example) rather than the one that
192 	 * actually made the call.
193 	 */
194 	frame_type = NORMAL;
195 	sym = db_search_symbol(rip - 1, DB_STGY_ANY, &offset);
196 	db_symbol_values(sym, &name, NULL);
197 	if (name != NULL) {
198 		if (strcmp(name, "calltrap") == 0 ||
199 		    strcmp(name, "fork_trampoline") == 0 ||
200 		    strcmp(name, "mchk_calltrap") == 0 ||
201 		    strcmp(name, "nmi_calltrap") == 0 ||
202 		    strcmp(name, "Xdblfault") == 0)
203 			frame_type = TRAP;
204 		else if (strncmp(name, "Xatpic_intr", 11) == 0 ||
205 		    strncmp(name, "Xapic_isr", 9) == 0 ||
206 		    strcmp(name, "Xxen_intr_upcall") == 0 ||
207 		    strcmp(name, "Xtimerint") == 0 ||
208 		    strcmp(name, "Xipi_intr_bitmap_handler") == 0 ||
209 		    strcmp(name, "Xcpustop") == 0 ||
210 		    strcmp(name, "Xcpususpend") == 0 ||
211 		    strcmp(name, "Xrendezvous") == 0)
212 			frame_type = INTERRUPT;
213 		else if (strcmp(name, "Xfast_syscall") == 0 ||
214 		    strcmp(name, "Xfast_syscall_pti") == 0 ||
215 		    strcmp(name, "fast_syscall_common") == 0)
216 			frame_type = SYSCALL;
217 #ifdef COMPAT_FREEBSD32
218 		else if (strcmp(name, "Xint0x80_syscall") == 0)
219 			frame_type = SYSCALL;
220 #endif
221 	}
222 
223 	/*
224 	 * Normal frames need no special processing.
225 	 */
226 	if (frame_type == NORMAL) {
227 		*ip = (db_addr_t) rip;
228 		*fp = (struct amd64_frame *) rbp;
229 		return;
230 	}
231 
232 	db_print_stack_entry(name, rip, &(*fp)->f_frame);
233 
234 	/*
235 	 * Point to base of trapframe which is just above the
236 	 * current frame.
237 	 */
238 	tf = (struct trapframe *)((long)*fp + 16);
239 
240 	if (INKERNEL((long) tf)) {
241 		rsp = tf->tf_rsp;
242 		rip = tf->tf_rip;
243 		rbp = tf->tf_rbp;
244 		switch (frame_type) {
245 		case TRAP:
246 			db_printf("--- trap %#r", tf->tf_trapno);
247 			break;
248 		case SYSCALL:
249 			db_printf("--- syscall");
250 			decode_syscall(tf->tf_rax, td);
251 			break;
252 		case INTERRUPT:
253 			db_printf("--- interrupt");
254 			break;
255 		default:
256 			panic("The moon has moved again.");
257 		}
258 		db_printf(", rip = %#lr, rsp = %#lr, rbp = %#lr ---\n", rip,
259 		    rsp, rbp);
260 	}
261 
262 	*ip = (db_addr_t) rip;
263 	*fp = (struct amd64_frame *) rbp;
264 }
265 
266 static int
267 db_backtrace(struct thread *td, struct trapframe *tf, struct amd64_frame *frame,
268     db_addr_t pc, register_t sp, int count)
269 {
270 	struct amd64_frame *actframe;
271 	const char *name;
272 	db_expr_t offset;
273 	c_db_sym_t sym;
274 	boolean_t first;
275 
276 	if (count == -1)
277 		count = 1024;
278 
279 	first = TRUE;
280 	while (count-- && !db_pager_quit) {
281 		sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
282 		db_symbol_values(sym, &name, NULL);
283 
284 		/*
285 		 * Attempt to determine a (possibly fake) frame that gives
286 		 * the caller's pc.  It may differ from `frame' if the
287 		 * current function never sets up a standard frame or hasn't
288 		 * set one up yet or has just discarded one.  The last two
289 		 * cases can be guessed fairly reliably for code generated
290 		 * by gcc.  The first case is too much trouble to handle in
291 		 * general because the amount of junk on the stack depends
292 		 * on the pc (the special handling of "calltrap", etc. in
293 		 * db_nextframe() works because the `next' pc is special).
294 		 */
295 		actframe = frame;
296 		if (first) {
297 			first = FALSE;
298 			if (sym == C_DB_SYM_NULL && sp != 0) {
299 				/*
300 				 * If a symbol couldn't be found, we've probably
301 				 * jumped to a bogus location, so try and use
302 				 * the return address to find our caller.
303 				 */
304 				db_print_stack_entry(name, pc, NULL);
305 				pc = db_get_value(sp, 8, FALSE);
306 				if (db_search_symbol(pc, DB_STGY_PROC,
307 				    &offset) == C_DB_SYM_NULL)
308 					break;
309 				continue;
310 			} else if (tf != NULL) {
311 				int instr;
312 
313 				instr = db_get_value(pc, 4, FALSE);
314 				if ((instr & 0xffffffff) == 0xe5894855) {
315 					/* pushq %rbp; movq %rsp, %rbp */
316 					actframe = (void *)(tf->tf_rsp - 8);
317 				} else if ((instr & 0xffffff) == 0xe58948) {
318 					/* movq %rsp, %rbp */
319 					actframe = (void *)tf->tf_rsp;
320 					if (tf->tf_rbp == 0) {
321 						/* Fake frame better. */
322 						frame = actframe;
323 					}
324 				} else if ((instr & 0xff) == 0xc3) {
325 					/* ret */
326 					actframe = (void *)(tf->tf_rsp - 8);
327 				} else if (offset == 0) {
328 					/* Probably an assembler symbol. */
329 					actframe = (void *)(tf->tf_rsp - 8);
330 				}
331 			} else if (name != NULL &&
332 			    strcmp(name, "fork_trampoline") == 0) {
333 				/*
334 				 * Don't try to walk back on a stack for a
335 				 * process that hasn't actually been run yet.
336 				 */
337 				db_print_stack_entry(name, pc, actframe);
338 				break;
339 			}
340 		}
341 
342 		db_print_stack_entry(name, pc, actframe);
343 
344 		if (actframe != frame) {
345 			/* `frame' belongs to caller. */
346 			pc = (db_addr_t)
347 			    db_get_value((long)&actframe->f_retaddr, 8, FALSE);
348 			continue;
349 		}
350 
351 		db_nextframe(&frame, &pc, td);
352 
353 		if (INKERNEL((long)pc) && !INKERNEL((long)frame)) {
354 			sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
355 			db_symbol_values(sym, &name, NULL);
356 			db_print_stack_entry(name, pc, frame);
357 			break;
358 		}
359 		if (!INKERNEL((long) frame)) {
360 			break;
361 		}
362 	}
363 
364 	return (0);
365 }
366 
367 void
368 db_trace_self(void)
369 {
370 	struct amd64_frame *frame;
371 	db_addr_t callpc;
372 	register_t rbp;
373 
374 	__asm __volatile("movq %%rbp,%0" : "=r" (rbp));
375 	frame = (struct amd64_frame *)rbp;
376 	callpc = (db_addr_t)db_get_value((long)&frame->f_retaddr, 8, FALSE);
377 	frame = frame->f_frame;
378 	db_backtrace(curthread, NULL, frame, callpc, 0, -1);
379 }
380 
381 int
382 db_trace_thread(struct thread *thr, int count)
383 {
384 	struct pcb *ctx;
385 	struct trapframe *tf;
386 
387 	ctx = kdb_thr_ctx(thr);
388 	tf = thr == kdb_thread ? kdb_frame : NULL;
389 	return (db_backtrace(thr, tf, (struct amd64_frame *)ctx->pcb_rbp,
390 	    ctx->pcb_rip, ctx->pcb_rsp, count));
391 }
392 
393 int
394 amd64_set_watch(watchnum, watchaddr, size, access, d)
395 	int watchnum;
396 	unsigned long watchaddr;
397 	int size;
398 	int access;
399 	struct dbreg *d;
400 {
401 	int i, len;
402 
403 	if (watchnum == -1) {
404 		for (i = 0; i < 4; i++)
405 			if (!DBREG_DR7_ENABLED(d->dr[7], i))
406 				break;
407 		if (i < 4)
408 			watchnum = i;
409 		else
410 			return (-1);
411 	}
412 
413 	switch (access) {
414 	case DBREG_DR7_EXEC:
415 		size = 1; /* size must be 1 for an execution breakpoint */
416 		/* fall through */
417 	case DBREG_DR7_WRONLY:
418 	case DBREG_DR7_RDWR:
419 		break;
420 	default:
421 		return (-1);
422 	}
423 
424 	/*
425 	 * we can watch a 1, 2, 4, or 8 byte sized location
426 	 */
427 	switch (size) {
428 	case 1:
429 		len = DBREG_DR7_LEN_1;
430 		break;
431 	case 2:
432 		len = DBREG_DR7_LEN_2;
433 		break;
434 	case 4:
435 		len = DBREG_DR7_LEN_4;
436 		break;
437 	case 8:
438 		len = DBREG_DR7_LEN_8;
439 		break;
440 	default:
441 		return (-1);
442 	}
443 
444 	/* clear the bits we are about to affect */
445 	d->dr[7] &= ~DBREG_DR7_MASK(watchnum);
446 
447 	/* set drN register to the address, N=watchnum */
448 	DBREG_DRX(d, watchnum) = watchaddr;
449 
450 	/* enable the watchpoint */
451 	d->dr[7] |= DBREG_DR7_SET(watchnum, len, access,
452 	    DBREG_DR7_GLOBAL_ENABLE);
453 
454 	return (watchnum);
455 }
456 
457 
458 int
459 amd64_clr_watch(watchnum, d)
460 	int watchnum;
461 	struct dbreg *d;
462 {
463 
464 	if (watchnum < 0 || watchnum >= 4)
465 		return (-1);
466 
467 	d->dr[7] &= ~DBREG_DR7_MASK(watchnum);
468 	DBREG_DRX(d, watchnum) = 0;
469 
470 	return (0);
471 }
472 
473 
474 int
475 db_md_set_watchpoint(addr, size)
476 	db_expr_t addr;
477 	db_expr_t size;
478 {
479 	struct dbreg *d;
480 	struct pcpu *pc;
481 	int avail, c, cpu, i, wsize;
482 
483 	d = (struct dbreg *)PCPU_PTR(dbreg);
484 	cpu = PCPU_GET(cpuid);
485 	fill_dbregs(NULL, d);
486 
487 	avail = 0;
488 	for (i = 0; i < 4; i++) {
489 		if (!DBREG_DR7_ENABLED(d->dr[7], i))
490 			avail++;
491 	}
492 
493 	if (avail * 8 < size)
494 		return (-1);
495 
496 	for (i = 0; i < 4 && size > 0; i++) {
497 		if (!DBREG_DR7_ENABLED(d->dr[7], i)) {
498 			if (size >= 8 || (avail == 1 && size > 4))
499 				wsize = 8;
500 			else if (size > 2)
501 				wsize = 4;
502 			else
503 				wsize = size;
504 			amd64_set_watch(i, addr, wsize, DBREG_DR7_WRONLY, d);
505 			addr += wsize;
506 			size -= wsize;
507 			avail--;
508 		}
509 	}
510 
511 	set_dbregs(NULL, d);
512 	CPU_FOREACH(c) {
513 		if (c == cpu)
514 			continue;
515 		pc = pcpu_find(c);
516 		memcpy(pc->pc_dbreg, d, sizeof(*d));
517 		pc->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
518 	}
519 
520 	return (0);
521 }
522 
523 int
524 db_md_clr_watchpoint(addr, size)
525 	db_expr_t addr;
526 	db_expr_t size;
527 {
528 	struct dbreg *d;
529 	struct pcpu *pc;
530 	int i, c, cpu;
531 
532 	d = (struct dbreg *)PCPU_PTR(dbreg);
533 	cpu = PCPU_GET(cpuid);
534 	fill_dbregs(NULL, d);
535 
536 	for (i = 0; i < 4; i++) {
537 		if (DBREG_DR7_ENABLED(d->dr[7], i)) {
538 			if (DBREG_DRX((d), i) >= addr &&
539 			    DBREG_DRX((d), i) < addr + size)
540 				amd64_clr_watch(i, d);
541 
542 		}
543 	}
544 
545 	set_dbregs(NULL, d);
546 	CPU_FOREACH(c) {
547 		if (c == cpu)
548 			continue;
549 		pc = pcpu_find(c);
550 		memcpy(pc->pc_dbreg, d, sizeof(*d));
551 		pc->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
552 	}
553 
554 	return (0);
555 }
556 
557 
558 static const char *
559 watchtype_str(type)
560 	int type;
561 {
562 	switch (type) {
563 		case DBREG_DR7_EXEC   : return "execute";    break;
564 		case DBREG_DR7_RDWR   : return "read/write"; break;
565 		case DBREG_DR7_WRONLY : return "write";	     break;
566 		default		      : return "invalid";    break;
567 	}
568 }
569 
570 
571 void
572 db_md_list_watchpoints(void)
573 {
574 	struct dbreg d;
575 	int i, len, type;
576 
577 	fill_dbregs(NULL, &d);
578 
579 	db_printf("\nhardware watchpoints:\n");
580 	db_printf("  watch    status        type  len             address\n");
581 	db_printf("  -----  --------  ----------  ---  ------------------\n");
582 	for (i = 0; i < 4; i++) {
583 		if (DBREG_DR7_ENABLED(d.dr[7], i)) {
584 			type = DBREG_DR7_ACCESS(d.dr[7], i);
585 			len = DBREG_DR7_LEN(d.dr[7], i);
586 			if (len == DBREG_DR7_LEN_8)
587 				len = 8;
588 			else
589 				len++;
590 			db_printf("  %-5d  %-8s  %10s  %3d  ",
591 			    i, "enabled", watchtype_str(type), len);
592 			db_printsym((db_addr_t)DBREG_DRX(&d, i), DB_STGY_ANY);
593 			db_printf("\n");
594 		} else {
595 			db_printf("  %-5d  disabled\n", i);
596 		}
597 	}
598 
599 	db_printf("\ndebug register values:\n");
600 	for (i = 0; i < 8; i++)
601 		if (i != 4 && i != 5)
602 			db_printf("  dr%d 0x%016lx\n", i, DBREG_DRX(&d, i));
603 	db_printf("\n");
604 }
605 
606 void
607 amd64_db_resume_dbreg(void)
608 {
609 	struct dbreg *d;
610 
611 	switch (PCPU_GET(dbreg_cmd)) {
612 	case PC_DBREG_CMD_LOAD:
613 		d = (struct dbreg *)PCPU_PTR(dbreg);
614 		set_dbregs(NULL, d);
615 		PCPU_SET(dbreg_cmd, PC_DBREG_CMD_NONE);
616 		break;
617 	}
618 }
619