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