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/5.3/sys/i386/i386/db_trace.c 135309 2004-09-16 17:21:46Z 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
50 static db_varfcn_t db_dr0;
51 static db_varfcn_t db_dr1;
52 static db_varfcn_t db_dr2;
53 static db_varfcn_t db_dr3;
54 static db_varfcn_t db_dr4;
55 static db_varfcn_t db_dr5;
56 static db_varfcn_t db_dr6;
57 static db_varfcn_t db_dr7;
58 static db_varfcn_t db_esp;
59 static db_varfcn_t db_frame;
60 static db_varfcn_t db_ss;
61
62 /*
63 * Machine register set.
64 */
65 #define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
66 struct 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 };
91 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
92
93 #define DB_DRX_FUNC(reg) \
94 static int \
95 db_ ## 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
107 DB_DRX_FUNC(dr0)
108 DB_DRX_FUNC(dr1)
109 DB_DRX_FUNC(dr2)
110 DB_DRX_FUNC(dr3)
111 DB_DRX_FUNC(dr4)
112 DB_DRX_FUNC(dr5)
113 DB_DRX_FUNC(dr6)
114 DB_DRX_FUNC(dr7)
115
116 static __inline int
117 get_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
123 static int
124 db_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
139 static int
140 db_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
153 static int
154 db_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
172 struct 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
184 static void db_nextframe(struct i386_frame **, db_addr_t *, struct thread *);
185 static int db_numargs(struct i386_frame *);
186 static void db_print_stack_entry(const char *, int, char **, int *, db_addr_t);
187 static void decode_syscall(int, struct thread *);
188
189 static char * watchtype_str(int type);
190 int i386_set_watch(int watchnum, unsigned int watchaddr, int size, int access,
191 struct dbreg * d);
192 int i386_clr_watch(int watchnum, struct dbreg * d);
193 int db_md_set_watchpoint(db_expr_t addr, db_expr_t size);
194 int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size);
195 void db_md_list_watchpoints(void);
196
197 /*
198 * Figure out how many arguments were passed into the frame at "fp".
199 */
200 static int
201 db_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
228 static void
229 db_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
250 static void
251 decode_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 */
275 static void
276 db_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
371 static int
372 db_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;
383 boolean_t first;
384
385 if (count == -1)
386 count = 1024;
387
388 first = TRUE;
389 while (count--) {
390 sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
391 db_symbol_values(sym, &name, NULL);
392
393 /*
394 * Attempt to determine a (possibly fake) frame that gives
395 * the caller's pc. It may differ from `frame' if the
396 * current function never sets up a standard frame or hasn't
397 * set one up yet or has just discarded one. The last two
398 * cases can be guessed fairly reliably for code generated
399 * by gcc. The first case is too much trouble to handle in
400 * general because the amount of junk on the stack depends
401 * on the pc (the special handling of "calltrap", etc. in
402 * db_nextframe() works because the `next' pc is special).
403 */
404 actframe = frame;
405 if (first) {
406 if (tf != NULL) {
407 int instr;
408
409 instr = db_get_value(pc, 4, FALSE);
410 if ((instr & 0xffffff) == 0x00e58955) {
411 /* pushl %ebp; movl %esp, %ebp */
412 actframe = (void *)(get_esp(tf) - 4);
413 } else if ((instr & 0xffff) == 0x0000e589) {
414 /* movl %esp, %ebp */
415 actframe = (void *)get_esp(tf);
416 if (tf->tf_ebp == 0) {
417 /* Fake frame better. */
418 frame = actframe;
419 }
420 } else if ((instr & 0xff) == 0x000000c3) {
421 /* ret */
422 actframe = (void *)(get_esp(tf) - 4);
423 } else if (offset == 0) {
424 /* Probably an assembler symbol. */
425 actframe = (void *)(get_esp(tf) - 4);
426 }
427 } else if (strcmp(name, "fork_trampoline") == 0) {
428 /*
429 * Don't try to walk back on a stack for a
430 * process that hasn't actually been run yet.
431 */
432 db_print_stack_entry(name, 0, 0, 0, pc);
433 break;
434 }
435 first = FALSE;
436 }
437
438 argp = &actframe->f_arg0;
439 narg = MAXNARG;
440 if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) {
441 argnp = argnames;
442 } else {
443 narg = db_numargs(frame);
444 }
445
446 db_print_stack_entry(name, narg, argnp, argp, pc);
447
448 if (actframe != frame) {
449 /* `frame' belongs to caller. */
450 pc = (db_addr_t)
451 db_get_value((int)&actframe->f_retaddr, 4, FALSE);
452 continue;
453 }
454
455 db_nextframe(&frame, &pc, td);
456
457 if (INKERNEL((int)pc) && !INKERNEL((int) frame)) {
458 sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
459 db_symbol_values(sym, &name, NULL);
460 db_print_stack_entry(name, 0, 0, 0, pc);
461 break;
462 }
463 if (!INKERNEL((int) frame)) {
464 break;
465 }
466 }
467
468 return (0);
469 }
470
471 void
472 db_trace_self(void)
473 {
474 struct i386_frame *frame;
475 db_addr_t callpc;
476 register_t ebp;
477
478 __asm __volatile("movl %%ebp,%0" : "=r" (ebp));
479 frame = (struct i386_frame *)ebp;
480 callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
481 frame = frame->f_frame;
482 db_backtrace(curthread, NULL, frame, callpc, -1);
483 }
484
485 int
486 db_trace_thread(struct thread *thr, int count)
487 {
488 struct pcb *ctx;
489
490 ctx = kdb_thr_ctx(thr);
491 return (db_backtrace(thr, NULL, (struct i386_frame *)ctx->pcb_ebp,
492 ctx->pcb_eip, count));
493 }
494
495 int
496 i386_set_watch(watchnum, watchaddr, size, access, d)
497 int watchnum;
498 unsigned int watchaddr;
499 int size;
500 int access;
501 struct dbreg * d;
502 {
503 int i;
504 unsigned int mask;
505
506 if (watchnum == -1) {
507 for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2)
508 if ((d->dr[7] & mask) == 0)
509 break;
510 if (i < 4)
511 watchnum = i;
512 else
513 return (-1);
514 }
515
516 switch (access) {
517 case DBREG_DR7_EXEC:
518 size = 1; /* size must be 1 for an execution breakpoint */
519 /* fall through */
520 case DBREG_DR7_WRONLY:
521 case DBREG_DR7_RDWR:
522 break;
523 default : return (-1);
524 }
525
526 /*
527 * we can watch a 1, 2, or 4 byte sized location
528 */
529 switch (size) {
530 case 1 : mask = 0x00; break;
531 case 2 : mask = 0x01 << 2; break;
532 case 4 : mask = 0x03 << 2; break;
533 default : return (-1);
534 }
535
536 mask |= access;
537
538 /* clear the bits we are about to affect */
539 d->dr[7] &= ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
540
541 /* set drN register to the address, N=watchnum */
542 DBREG_DRX(d,watchnum) = watchaddr;
543
544 /* enable the watchpoint */
545 d->dr[7] |= (0x2 << (watchnum*2)) | (mask << (watchnum*4+16));
546
547 return (watchnum);
548 }
549
550
551 int
552 i386_clr_watch(watchnum, d)
553 int watchnum;
554 struct dbreg * d;
555 {
556
557 if (watchnum < 0 || watchnum >= 4)
558 return (-1);
559
560 d->dr[7] = d->dr[7] & ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
561 DBREG_DRX(d,watchnum) = 0;
562
563 return (0);
564 }
565
566
567 int
568 db_md_set_watchpoint(addr, size)
569 db_expr_t addr;
570 db_expr_t size;
571 {
572 int avail, wsize;
573 int i;
574 struct dbreg d;
575
576 fill_dbregs(NULL, &d);
577
578 avail = 0;
579 for(i=0; i<4; i++) {
580 if ((d.dr[7] & (3 << (i*2))) == 0)
581 avail++;
582 }
583
584 if (avail*4 < size)
585 return (-1);
586
587 for (i=0; i<4 && (size != 0); i++) {
588 if ((d.dr[7] & (3<<(i*2))) == 0) {
589 if (size > 4)
590 wsize = 4;
591 else
592 wsize = size;
593 if (wsize == 3)
594 wsize++;
595 i386_set_watch(i, addr, wsize,
596 DBREG_DR7_WRONLY, &d);
597 addr += wsize;
598 size -= wsize;
599 }
600 }
601
602 set_dbregs(NULL, &d);
603
604 return(0);
605 }
606
607
608 int
609 db_md_clr_watchpoint(addr, size)
610 db_expr_t addr;
611 db_expr_t size;
612 {
613 int i;
614 struct dbreg d;
615
616 fill_dbregs(NULL, &d);
617
618 for(i=0; i<4; i++) {
619 if (d.dr[7] & (3 << (i*2))) {
620 if ((DBREG_DRX((&d), i) >= addr) &&
621 (DBREG_DRX((&d), i) < addr+size))
622 i386_clr_watch(i, &d);
623
624 }
625 }
626
627 set_dbregs(NULL, &d);
628
629 return(0);
630 }
631
632
633 static
634 char *
635 watchtype_str(type)
636 int type;
637 {
638 switch (type) {
639 case DBREG_DR7_EXEC : return "execute"; break;
640 case DBREG_DR7_RDWR : return "read/write"; break;
641 case DBREG_DR7_WRONLY : return "write"; break;
642 default : return "invalid"; break;
643 }
644 }
645
646
647 void
648 db_md_list_watchpoints()
649 {
650 int i;
651 struct dbreg d;
652
653 fill_dbregs(NULL, &d);
654
655 db_printf("\nhardware watchpoints:\n");
656 db_printf(" watch status type len address\n");
657 db_printf(" ----- -------- ---------- --- ----------\n");
658 for (i=0; i<4; i++) {
659 if (d.dr[7] & (0x03 << (i*2))) {
660 unsigned type, len;
661 type = (d.dr[7] >> (16+(i*4))) & 3;
662 len = (d.dr[7] >> (16+(i*4)+2)) & 3;
663 db_printf(" %-5d %-8s %10s %3d 0x%08x\n",
664 i, "enabled", watchtype_str(type),
665 len+1, DBREG_DRX((&d),i));
666 }
667 else {
668 db_printf(" %-5d disabled\n", i);
669 }
670 }
671
672 db_printf("\ndebug register values:\n");
673 for (i=0; i<8; i++) {
674 db_printf(" dr%d 0x%08x\n", i, DBREG_DRX((&d),i));
675 }
676 db_printf("\n");
677 }
678
679
Cache object: e67ef1552c8756558b02601d160e3ab6
|