db_trace.c revision 135529
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: head/sys/i386/i386/db_trace.c 135529 2004-09-20 19:05:32Z jhb $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/kdb.h>
33#include <sys/proc.h>
34#include <sys/sysent.h>
35
36#include <machine/cpu.h>
37#include <machine/md_var.h>
38#include <machine/pcb.h>
39#include <machine/reg.h>
40
41#include <vm/vm.h>
42#include <vm/vm_param.h>
43#include <vm/pmap.h>
44
45#include <ddb/ddb.h>
46#include <ddb/db_access.h>
47#include <ddb/db_sym.h>
48#include <ddb/db_variables.h>
49
50static db_varfcn_t db_dr0;
51static db_varfcn_t db_dr1;
52static db_varfcn_t db_dr2;
53static db_varfcn_t db_dr3;
54static db_varfcn_t db_dr4;
55static db_varfcn_t db_dr5;
56static db_varfcn_t db_dr6;
57static db_varfcn_t db_dr7;
58static db_varfcn_t db_esp;
59static db_varfcn_t db_frame;
60static db_varfcn_t db_ss;
61
62/*
63 * Machine register set.
64 */
65#define	DB_OFFSET(x)	(db_expr_t *)offsetof(struct trapframe, x)
66struct db_variable db_regs[] = {
67	{ "cs",		DB_OFFSET(tf_cs),	db_frame },
68	{ "ds",		DB_OFFSET(tf_ds),	db_frame },
69	{ "es",		DB_OFFSET(tf_es),	db_frame },
70	{ "fs",		DB_OFFSET(tf_fs),	db_frame },
71	{ "ss",		NULL,			db_ss },
72	{ "eax",	DB_OFFSET(tf_eax),	db_frame },
73	{ "ecx",	DB_OFFSET(tf_ecx),	db_frame },
74	{ "edx",	DB_OFFSET(tf_edx),	db_frame },
75	{ "ebx",	DB_OFFSET(tf_ebx),	db_frame },
76	{ "esp",	NULL,			db_esp },
77	{ "ebp",	DB_OFFSET(tf_ebp),	db_frame },
78	{ "esi",	DB_OFFSET(tf_esi),	db_frame },
79	{ "edi",	DB_OFFSET(tf_edi),	db_frame },
80	{ "eip",	DB_OFFSET(tf_eip),	db_frame },
81	{ "efl",	DB_OFFSET(tf_eflags),	db_frame },
82	{ "dr0",	NULL,			db_dr0 },
83	{ "dr1",	NULL,			db_dr1 },
84	{ "dr2",	NULL,			db_dr2 },
85	{ "dr3",	NULL,			db_dr3 },
86	{ "dr4",	NULL,			db_dr4 },
87	{ "dr5",	NULL,			db_dr5 },
88	{ "dr6",	NULL,			db_dr6 },
89	{ "dr7",	NULL,			db_dr7 },
90};
91struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
92
93#define DB_DRX_FUNC(reg)		\
94static int				\
95db_ ## reg (vp, valuep, op)		\
96	struct db_variable *vp;		\
97	db_expr_t * valuep;		\
98	int op;				\
99{					\
100	if (op == DB_VAR_GET)		\
101		*valuep = r ## reg ();	\
102	else				\
103		load_ ## reg (*valuep); \
104	return (1);			\
105}
106
107DB_DRX_FUNC(dr0)
108DB_DRX_FUNC(dr1)
109DB_DRX_FUNC(dr2)
110DB_DRX_FUNC(dr3)
111DB_DRX_FUNC(dr4)
112DB_DRX_FUNC(dr5)
113DB_DRX_FUNC(dr6)
114DB_DRX_FUNC(dr7)
115
116static __inline int
117get_esp(struct trapframe *tf)
118{
119	return ((ISPL(tf->tf_cs)) ? tf->tf_esp :
120	    (db_expr_t)tf + (uintptr_t)DB_OFFSET(tf_esp));
121}
122
123static int
124db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
125{
126	int *reg;
127
128	if (kdb_frame == NULL)
129		return (0);
130
131	reg = (int *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
132	if (op == DB_VAR_GET)
133		*valuep = *reg;
134	else
135		*reg = *valuep;
136	return (1);
137}
138
139static int
140db_esp(struct db_variable *vp, db_expr_t *valuep, int op)
141{
142
143	if (kdb_frame == NULL)
144		return (0);
145
146	if (op == DB_VAR_GET)
147		*valuep = get_esp(kdb_frame);
148	else if (ISPL(kdb_frame->tf_cs))
149		kdb_frame->tf_esp = *valuep;
150	return (1);
151}
152
153static int
154db_ss(struct db_variable *vp, db_expr_t *valuep, int op)
155{
156
157	if (kdb_frame == NULL)
158		return (0);
159
160	if (op == DB_VAR_GET)
161		*valuep = (ISPL(kdb_frame->tf_cs)) ? kdb_frame->tf_ss : rss();
162	else if (ISPL(kdb_frame->tf_cs))
163		kdb_frame->tf_ss = *valuep;
164	return (1);
165}
166
167/*
168 * Stack trace.
169 */
170#define	INKERNEL(va)	(((vm_offset_t)(va)) >= USRSTACK)
171
172struct i386_frame {
173	struct i386_frame	*f_frame;
174	int			f_retaddr;
175	int			f_arg0;
176};
177
178#define NORMAL		0
179#define	TRAP		1
180#define	INTERRUPT	2
181#define	SYSCALL		3
182#define	DOUBLE_FAULT	4
183
184static void db_nextframe(struct i386_frame **, db_addr_t *, struct thread *);
185static int db_numargs(struct i386_frame *);
186static void db_print_stack_entry(const char *, int, char **, int *, db_addr_t);
187static void decode_syscall(int, struct thread *);
188
189static char * watchtype_str(int type);
190int  i386_set_watch(int watchnum, unsigned int watchaddr, int size, int access,
191		    struct dbreg * d);
192int  i386_clr_watch(int watchnum, struct dbreg * d);
193int  db_md_set_watchpoint(db_expr_t addr, db_expr_t size);
194int  db_md_clr_watchpoint(db_expr_t addr, db_expr_t size);
195void db_md_list_watchpoints(void);
196
197/*
198 * Figure out how many arguments were passed into the frame at "fp".
199 */
200static int
201db_numargs(fp)
202	struct i386_frame *fp;
203{
204	int	*argp;
205	int	inst;
206	int	args;
207
208	argp = (int *)db_get_value((int)&fp->f_retaddr, 4, FALSE);
209	/*
210	 * XXX etext is wrong for LKMs.  We should attempt to interpret
211	 * the instruction at the return address in all cases.  This
212	 * may require better fault handling.
213	 */
214	if (argp < (int *)btext || argp >= (int *)etext) {
215		args = 5;
216	} else {
217		inst = db_get_value((int)argp, 4, FALSE);
218		if ((inst & 0xff) == 0x59)	/* popl %ecx */
219			args = 1;
220		else if ((inst & 0xffff) == 0xc483)	/* addl $Ibs, %esp */
221			args = ((inst >> 16) & 0xff) / 4;
222		else
223			args = 5;
224	}
225	return (args);
226}
227
228static void
229db_print_stack_entry(name, narg, argnp, argp, callpc)
230	const char *name;
231	int narg;
232	char **argnp;
233	int *argp;
234	db_addr_t callpc;
235{
236	db_printf("%s(", name);
237	while (narg) {
238		if (argnp)
239			db_printf("%s=", *argnp++);
240		db_printf("%r", db_get_value((int)argp, 4, FALSE));
241		argp++;
242		if (--narg != 0)
243			db_printf(",");
244	}
245	db_printf(") at ");
246	db_printsym(callpc, DB_STGY_PROC);
247	db_printf("\n");
248}
249
250static void
251decode_syscall(int number, struct thread *td)
252{
253	struct proc *p;
254	c_db_sym_t sym;
255	db_expr_t diff;
256	sy_call_t *f;
257	const char *symname;
258
259	db_printf(" (%d", number);
260	p = (td != NULL) ? td->td_proc : NULL;
261	if (p != NULL && 0 <= number && number < p->p_sysent->sv_size) {
262		f = p->p_sysent->sv_table[number].sy_call;
263		sym = db_search_symbol((db_addr_t)f, DB_STGY_ANY, &diff);
264		if (sym != DB_SYM_NULL && diff == 0) {
265			db_symbol_values(sym, &symname, NULL);
266			db_printf(", %s, %s", p->p_sysent->sv_name, symname);
267		}
268	}
269	db_printf(")");
270}
271
272/*
273 * Figure out the next frame up in the call stack.
274 */
275static void
276db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td)
277{
278	struct trapframe *tf;
279	int frame_type;
280	int eip, esp, ebp;
281	db_expr_t offset;
282	c_db_sym_t sym;
283	const char *name;
284
285	eip = db_get_value((int) &(*fp)->f_retaddr, 4, FALSE);
286	ebp = db_get_value((int) &(*fp)->f_frame, 4, FALSE);
287
288	/*
289	 * Figure out frame type.
290	 */
291	frame_type = NORMAL;
292	sym = db_search_symbol(eip, DB_STGY_ANY, &offset);
293	db_symbol_values(sym, &name, NULL);
294	if (name != NULL) {
295		if (strcmp(name, "calltrap") == 0 ||
296		    strcmp(name, "fork_trampoline") == 0)
297			frame_type = TRAP;
298		else if (strncmp(name, "Xatpic_intr", 11) == 0 ||
299		    strncmp(name, "Xapic_isr", 9) == 0)
300			frame_type = INTERRUPT;
301		else if (strcmp(name, "Xlcall_syscall") == 0 ||
302		    strcmp(name, "Xint0x80_syscall") == 0)
303			frame_type = SYSCALL;
304		else if (strcmp(name, "dblfault_handler") == 0)
305			frame_type = DOUBLE_FAULT;
306	}
307
308	/*
309	 * Normal frames need no special processing.
310	 */
311	if (frame_type == NORMAL) {
312		*ip = (db_addr_t) eip;
313		*fp = (struct i386_frame *) ebp;
314		return;
315	}
316
317	db_print_stack_entry(name, 0, 0, 0, eip);
318
319	/*
320	 * For a double fault, we have to snag the values from the
321	 * previous TSS since a double fault uses a task gate to
322	 * switch to a known good state.
323	 */
324	if (frame_type == DOUBLE_FAULT) {
325		esp = PCPU_GET(common_tss.tss_esp);
326		eip = PCPU_GET(common_tss.tss_eip);
327		ebp = PCPU_GET(common_tss.tss_ebp);
328		db_printf(
329		    "--- trap 0x17, eip = %#r, esp = %#r, ebp = %#r ---\n",
330		    eip, esp, ebp);
331		*ip = (db_addr_t) eip;
332		*fp = (struct i386_frame *) ebp;
333		return;
334	}
335
336	/*
337	 * Point to base of trapframe which is just above the
338	 * current frame.
339	 */
340	if (frame_type == INTERRUPT)
341		tf = (struct trapframe *)((int)*fp + 12);
342	else
343		tf = (struct trapframe *)((int)*fp + 8);
344
345	if (INKERNEL((int) tf)) {
346		esp = get_esp(tf);
347		eip = tf->tf_eip;
348		ebp = tf->tf_ebp;
349		switch (frame_type) {
350		case TRAP:
351			db_printf("--- trap %#r", tf->tf_trapno);
352			break;
353		case SYSCALL:
354			db_printf("--- syscall");
355			decode_syscall(tf->tf_eax, td);
356			break;
357		case INTERRUPT:
358			db_printf("--- interrupt");
359			break;
360		default:
361			panic("The moon has moved again.");
362		}
363		db_printf(", eip = %#r, esp = %#r, ebp = %#r ---\n", eip,
364		    esp, ebp);
365	}
366
367	*ip = (db_addr_t) eip;
368	*fp = (struct i386_frame *) ebp;
369}
370
371static int
372db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame,
373    db_addr_t pc, int count)
374{
375	struct i386_frame *actframe;
376#define MAXNARG	16
377	char *argnames[MAXNARG], **argnp = NULL;
378	const char *name;
379	int *argp;
380	db_expr_t offset;
381	c_db_sym_t sym;
382	int narg, quit;
383	boolean_t first;
384
385	if (count == -1)
386		count = 1024;
387
388	first = TRUE;
389	quit = 0;
390	db_setup_paging(db_simple_pager, &quit, DB_LINES_PER_PAGE);
391	while (count-- && !quit) {
392		sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
393		db_symbol_values(sym, &name, NULL);
394
395		/*
396		 * Attempt to determine a (possibly fake) frame that gives
397		 * the caller's pc.  It may differ from `frame' if the
398		 * current function never sets up a standard frame or hasn't
399		 * set one up yet or has just discarded one.  The last two
400		 * cases can be guessed fairly reliably for code generated
401		 * by gcc.  The first case is too much trouble to handle in
402		 * general because the amount of junk on the stack depends
403		 * on the pc (the special handling of "calltrap", etc. in
404		 * db_nextframe() works because the `next' pc is special).
405		 */
406		actframe = frame;
407		if (first) {
408			if (tf != NULL) {
409				int instr;
410
411				instr = db_get_value(pc, 4, FALSE);
412				if ((instr & 0xffffff) == 0x00e58955) {
413					/* pushl %ebp; movl %esp, %ebp */
414					actframe = (void *)(get_esp(tf) - 4);
415				} else if ((instr & 0xffff) == 0x0000e589) {
416					/* movl %esp, %ebp */
417					actframe = (void *)get_esp(tf);
418					if (tf->tf_ebp == 0) {
419						/* Fake frame better. */
420						frame = actframe;
421					}
422				} else if ((instr & 0xff) == 0x000000c3) {
423					/* ret */
424					actframe = (void *)(get_esp(tf) - 4);
425				} else if (offset == 0) {
426					/* Probably an assembler symbol. */
427					actframe = (void *)(get_esp(tf) - 4);
428				}
429			} else if (strcmp(name, "fork_trampoline") == 0) {
430				/*
431				 * Don't try to walk back on a stack for a
432				 * process that hasn't actually been run yet.
433				 */
434				db_print_stack_entry(name, 0, 0, 0, pc);
435				break;
436			}
437			first = FALSE;
438		}
439
440		argp = &actframe->f_arg0;
441		narg = MAXNARG;
442		if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) {
443			argnp = argnames;
444		} else {
445			narg = db_numargs(frame);
446		}
447
448		db_print_stack_entry(name, narg, argnp, argp, pc);
449
450		if (actframe != frame) {
451			/* `frame' belongs to caller. */
452			pc = (db_addr_t)
453			    db_get_value((int)&actframe->f_retaddr, 4, FALSE);
454			continue;
455		}
456
457		db_nextframe(&frame, &pc, td);
458
459		if (INKERNEL((int)pc) && !INKERNEL((int) frame)) {
460			sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
461			db_symbol_values(sym, &name, NULL);
462			db_print_stack_entry(name, 0, 0, 0, pc);
463			break;
464		}
465		if (!INKERNEL((int) frame)) {
466			break;
467		}
468	}
469
470	return (0);
471}
472
473void
474db_trace_self(void)
475{
476	struct i386_frame *frame;
477	db_addr_t callpc;
478	register_t ebp;
479
480	__asm __volatile("movl %%ebp,%0" : "=r" (ebp));
481	frame = (struct i386_frame *)ebp;
482	callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
483	frame = frame->f_frame;
484	db_backtrace(curthread, NULL, frame, callpc, -1);
485}
486
487int
488db_trace_thread(struct thread *thr, int count)
489{
490	struct pcb *ctx;
491
492	ctx = kdb_thr_ctx(thr);
493	return (db_backtrace(thr, NULL, (struct i386_frame *)ctx->pcb_ebp,
494		    ctx->pcb_eip, count));
495}
496
497int
498i386_set_watch(watchnum, watchaddr, size, access, d)
499	int watchnum;
500	unsigned int watchaddr;
501	int size;
502	int access;
503	struct dbreg * d;
504{
505	int i;
506	unsigned int mask;
507
508	if (watchnum == -1) {
509		for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2)
510			if ((d->dr[7] & mask) == 0)
511				break;
512		if (i < 4)
513			watchnum = i;
514		else
515			return (-1);
516	}
517
518	switch (access) {
519	case DBREG_DR7_EXEC:
520		size = 1; /* size must be 1 for an execution breakpoint */
521		/* fall through */
522	case DBREG_DR7_WRONLY:
523	case DBREG_DR7_RDWR:
524		break;
525	default : return (-1);
526	}
527
528	/*
529	 * we can watch a 1, 2, or 4 byte sized location
530	 */
531	switch (size) {
532	case 1	: mask = 0x00; break;
533	case 2	: mask = 0x01 << 2; break;
534	case 4	: mask = 0x03 << 2; break;
535	default : return (-1);
536	}
537
538	mask |= access;
539
540	/* clear the bits we are about to affect */
541	d->dr[7] &= ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
542
543	/* set drN register to the address, N=watchnum */
544	DBREG_DRX(d,watchnum) = watchaddr;
545
546	/* enable the watchpoint */
547	d->dr[7] |= (0x2 << (watchnum*2)) | (mask << (watchnum*4+16));
548
549	return (watchnum);
550}
551
552
553int
554i386_clr_watch(watchnum, d)
555	int watchnum;
556	struct dbreg * d;
557{
558
559	if (watchnum < 0 || watchnum >= 4)
560		return (-1);
561
562	d->dr[7] = d->dr[7] & ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
563	DBREG_DRX(d,watchnum) = 0;
564
565	return (0);
566}
567
568
569int
570db_md_set_watchpoint(addr, size)
571	db_expr_t addr;
572	db_expr_t size;
573{
574	int avail, wsize;
575	int i;
576	struct dbreg d;
577
578	fill_dbregs(NULL, &d);
579
580	avail = 0;
581	for(i=0; i<4; i++) {
582		if ((d.dr[7] & (3 << (i*2))) == 0)
583			avail++;
584	}
585
586	if (avail*4 < size)
587		return (-1);
588
589	for (i=0; i<4 && (size != 0); i++) {
590		if ((d.dr[7] & (3<<(i*2))) == 0) {
591			if (size > 4)
592				wsize = 4;
593			else
594				wsize = size;
595			if (wsize == 3)
596				wsize++;
597			i386_set_watch(i, addr, wsize,
598				       DBREG_DR7_WRONLY, &d);
599			addr += wsize;
600			size -= wsize;
601		}
602	}
603
604	set_dbregs(NULL, &d);
605
606	return(0);
607}
608
609
610int
611db_md_clr_watchpoint(addr, size)
612	db_expr_t addr;
613	db_expr_t size;
614{
615	int i;
616	struct dbreg d;
617
618	fill_dbregs(NULL, &d);
619
620	for(i=0; i<4; i++) {
621		if (d.dr[7] & (3 << (i*2))) {
622			if ((DBREG_DRX((&d), i) >= addr) &&
623			    (DBREG_DRX((&d), i) < addr+size))
624				i386_clr_watch(i, &d);
625
626		}
627	}
628
629	set_dbregs(NULL, &d);
630
631	return(0);
632}
633
634
635static
636char *
637watchtype_str(type)
638	int type;
639{
640	switch (type) {
641		case DBREG_DR7_EXEC   : return "execute";    break;
642		case DBREG_DR7_RDWR   : return "read/write"; break;
643		case DBREG_DR7_WRONLY : return "write";	     break;
644		default		      : return "invalid";    break;
645	}
646}
647
648
649void
650db_md_list_watchpoints()
651{
652	int i;
653	struct dbreg d;
654
655	fill_dbregs(NULL, &d);
656
657	db_printf("\nhardware watchpoints:\n");
658	db_printf("  watch    status        type  len     address\n");
659	db_printf("  -----  --------  ----------  ---  ----------\n");
660	for (i=0; i<4; i++) {
661		if (d.dr[7] & (0x03 << (i*2))) {
662			unsigned type, len;
663			type = (d.dr[7] >> (16+(i*4))) & 3;
664			len =  (d.dr[7] >> (16+(i*4)+2)) & 3;
665			db_printf("  %-5d  %-8s  %10s  %3d  0x%08x\n",
666				  i, "enabled", watchtype_str(type),
667				  len+1, DBREG_DRX((&d),i));
668		}
669		else {
670			db_printf("  %-5d  disabled\n", i);
671		}
672	}
673
674	db_printf("\ndebug register values:\n");
675	for (i=0; i<8; i++) {
676		db_printf("  dr%d 0x%08x\n", i, DBREG_DRX((&d),i));
677	}
678	db_printf("\n");
679}
680
681
682