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