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