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