1 /* 2 * Copyright (c) 2008 The DragonFly Project. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 3. Neither the name of The DragonFly Project nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific, prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * -- 32 * 33 * Mach Operating System 34 * Copyright (c) 1991,1990 Carnegie Mellon University 35 * All Rights Reserved. 36 * 37 * Permission to use, copy, modify and distribute this software and its 38 * documentation is hereby granted, provided that both the copyright 39 * notice and this permission notice appear in all copies of the 40 * software, derivative works or modified versions, and any portions 41 * thereof, and that both notices appear in supporting documentation. 42 * 43 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 44 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 45 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 46 * 47 * Carnegie Mellon requests users of this software to return to 48 * 49 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 50 * School of Computer Science 51 * Carnegie Mellon University 52 * Pittsburgh PA 15213-3890 53 * 54 * any improvements or extensions that they make and grant Carnegie the 55 * rights to redistribute these changes. 56 * 57 * $FreeBSD: src/sys/i386/i386/db_trace.c,v 1.35.2.3 2002/02/21 22:31:25 silby Exp $ 58 */ 59 60 #include <sys/param.h> 61 #include <sys/systm.h> 62 #include <sys/linker_set.h> 63 #include <sys/lock.h> 64 #include <sys/proc.h> 65 #include <sys/reg.h> 66 67 #include <machine/cpu.h> 68 #include <machine/md_var.h> 69 70 #include <vm/vm.h> 71 #include <vm/vm_param.h> 72 #include <vm/pmap.h> 73 #include <vm/vm_map.h> 74 #include <ddb/ddb.h> 75 76 #include <ddb/db_access.h> 77 #include <ddb/db_sym.h> 78 #include <ddb/db_variables.h> 79 80 db_varfcn_t db_dr0; 81 db_varfcn_t db_dr1; 82 db_varfcn_t db_dr2; 83 db_varfcn_t db_dr3; 84 db_varfcn_t db_dr4; 85 db_varfcn_t db_dr5; 86 db_varfcn_t db_dr6; 87 db_varfcn_t db_dr7; 88 89 /* 90 * Machine register set. 91 */ 92 struct db_variable db_regs[] = { 93 { "cs", &ddb_regs.tf_cs, NULL }, 94 /* { "ds", &ddb_regs.tf_ds, NULL }, 95 { "es", &ddb_regs.tf_es, NULL }, 96 { "fs", &ddb_regs.tf_fs, NULL }, 97 { "gs", &ddb_regs.tf_gs, NULL }, */ 98 { "ss", &ddb_regs.tf_ss, NULL }, 99 { "rax", &ddb_regs.tf_rax, NULL }, 100 { "rcx", &ddb_regs.tf_rcx, NULL }, 101 { "rdx", &ddb_regs.tf_rdx, NULL }, 102 { "rbx", &ddb_regs.tf_rbx, NULL }, 103 { "rsp", &ddb_regs.tf_rsp, NULL }, 104 { "rbp", &ddb_regs.tf_rbp, NULL }, 105 { "rsi", &ddb_regs.tf_rsi, NULL }, 106 { "rdi", &ddb_regs.tf_rdi, NULL }, 107 { "rip", &ddb_regs.tf_rip, NULL }, 108 { "rfl", &ddb_regs.tf_rflags, NULL }, 109 { "r8", &ddb_regs.tf_r8, NULL }, 110 { "r9", &ddb_regs.tf_r9, NULL }, 111 { "r10", &ddb_regs.tf_r10, NULL }, 112 { "r11", &ddb_regs.tf_r11, NULL }, 113 { "r12", &ddb_regs.tf_r12, NULL }, 114 { "r13", &ddb_regs.tf_r13, NULL }, 115 { "r14", &ddb_regs.tf_r14, NULL }, 116 { "r15", &ddb_regs.tf_r15, NULL }, 117 { "dr0", NULL, db_dr0 }, 118 { "dr1", NULL, db_dr1 }, 119 { "dr2", NULL, db_dr2 }, 120 { "dr3", NULL, db_dr3 }, 121 { "dr4", NULL, db_dr4 }, 122 { "dr5", NULL, db_dr5 }, 123 { "dr6", NULL, db_dr6 }, 124 { "dr7", NULL, db_dr7 }, 125 }; 126 struct db_variable *db_eregs = db_regs + NELEM(db_regs); 127 128 /* 129 * Stack trace. 130 */ 131 #define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK) 132 133 struct x86_64_frame { 134 struct x86_64_frame *f_frame; 135 long f_retaddr; 136 long f_arg0; 137 }; 138 139 #define NORMAL 0 140 #define TRAP 1 141 #define INTERRUPT 2 142 #define SYSCALL 3 143 144 static void db_nextframe(struct x86_64_frame **, db_addr_t *); 145 static int db_numargs(struct x86_64_frame *); 146 static void db_print_stack_entry(const char *, int, char **, long *, db_addr_t); 147 static void dl_symbol_values(long callpc, const char **name); 148 149 150 static char *watchtype_str(int type); 151 static int kx86_64_set_watch(int watchnum, unsigned int watchaddr, 152 int size, int access, struct dbreg * d); 153 static int kx86_64_clr_watch(int watchnum, struct dbreg * d); 154 int db_md_set_watchpoint(db_expr_t addr, db_expr_t size); 155 int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size); 156 void db_md_list_watchpoints(void); 157 158 159 /* 160 * Figure out how many arguments were passed into the frame at "fp". 161 */ 162 static int 163 db_numargs(struct x86_64_frame *fp) 164 { 165 #if 1 166 return (0); /* regparm, needs dwarf2 info */ 167 #else 168 int args; 169 #if 0 170 int *argp; 171 int inst; 172 173 argp = (int *)db_get_value((int)&fp->f_retaddr, 4, FALSE); 174 /* 175 * XXX etext is wrong for LKMs. We should attempt to interpret 176 * the instruction at the return address in all cases. This 177 * may require better fault handling. 178 */ 179 if (argp < (int *)btext || argp >= (int *)etext) { 180 args = 5; 181 } else { 182 inst = db_get_value((int)argp, 4, FALSE); 183 if ((inst & 0xff) == 0x59) /* popl %ecx */ 184 args = 1; 185 else if ((inst & 0xffff) == 0xc483) /* addl $Ibs, %esp */ 186 args = ((inst >> 16) & 0xff) / 4; 187 else 188 args = 5; 189 } 190 #endif 191 args = 5; 192 return(args); 193 #endif 194 } 195 196 static void 197 db_print_stack_entry(const char *name, int narg, char **argnp, long *argp, 198 db_addr_t callpc) 199 { 200 db_printf("%s(", name); 201 while (narg) { 202 if (argnp) 203 db_printf("%s=", *argnp++); 204 db_printf("%ld", (long)db_get_value((long)argp, 8, FALSE)); 205 argp++; 206 if (--narg != 0) 207 db_printf(","); 208 } 209 db_printf(") at "); 210 db_printsym(callpc, DB_STGY_PROC); 211 db_printf(" %p ", (void*) callpc); 212 db_printf("\n"); 213 } 214 215 /* 216 * Figure out the next frame up in the call stack. 217 */ 218 static void 219 db_nextframe(struct x86_64_frame **fp, db_addr_t *ip) 220 { 221 struct trapframe *tf; 222 int frame_type; 223 long rip, rsp, rbp; 224 db_expr_t offset; 225 const char *sym, *name; 226 227 if ((unsigned long)*fp < PAGE_SIZE) { 228 *fp = NULL; 229 return; 230 } 231 rip = db_get_value((long) &(*fp)->f_retaddr, 8, FALSE); 232 rbp = db_get_value((long) &(*fp)->f_frame, 8, FALSE); 233 234 /* 235 * Figure out frame type. 236 */ 237 238 frame_type = NORMAL; 239 240 sym = db_search_symbol(rip, DB_STGY_ANY, &offset); 241 db_symbol_values(sym, &name, NULL); 242 dl_symbol_values(rip, &name); 243 if (name != NULL) { 244 if (!strcmp(name, "calltrap")) { 245 frame_type = TRAP; 246 } else if (!strncmp(name, "Xresume", 7)) { 247 frame_type = INTERRUPT; 248 } else if (!strcmp(name, "_Xsyscall")) { 249 frame_type = SYSCALL; 250 } 251 } 252 253 /* 254 * Normal frames need no special processing. 255 */ 256 if (frame_type == NORMAL) { 257 *ip = (db_addr_t) rip; 258 *fp = (struct x86_64_frame *) rbp; 259 return; 260 } 261 262 db_print_stack_entry(name, 0, 0, 0, rip); 263 264 /* 265 * Point to base of trapframe which is just above the 266 * current frame. 267 */ 268 tf = (struct trapframe *)((long)*fp + 16); 269 270 #if 0 271 rsp = (ISPL(tf->tf_cs) == SEL_UPL) ? tf->tf_rsp : (long)&tf->tf_rsp; 272 #endif 273 rsp = (long)&tf->tf_rsp; 274 275 switch (frame_type) { 276 case TRAP: 277 { 278 rip = tf->tf_rip; 279 rbp = tf->tf_rbp; 280 db_printf( 281 "--- trap %016lx, rip = %016lx, rsp = %016lx, rbp = %016lx ---\n", 282 tf->tf_trapno, rip, rsp, rbp); 283 } 284 break; 285 case SYSCALL: 286 { 287 rip = tf->tf_rip; 288 rbp = tf->tf_rbp; 289 db_printf( 290 "--- syscall %016lx, rip = %016lx, rsp = %016lx, rbp = %016lx ---\n", 291 tf->tf_rax, rip, rsp, rbp); 292 } 293 break; 294 case INTERRUPT: 295 tf = (struct trapframe *)((long)*fp + 16); 296 { 297 rip = tf->tf_rip; 298 rbp = tf->tf_rbp; 299 db_printf( 300 "--- interrupt, rip = %016lx, rsp = %016lx, rbp = %016lx ---\n", 301 rip, rsp, rbp); 302 } 303 break; 304 default: 305 break; 306 } 307 308 *ip = (db_addr_t) rip; 309 *fp = (struct x86_64_frame *) rbp; 310 } 311 312 void 313 db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, 314 char *modif) 315 { 316 struct x86_64_frame *frame; 317 long *argp; 318 db_addr_t callpc; 319 boolean_t first; 320 int i; 321 322 if (count == -1) 323 count = 1024; 324 325 if (!have_addr) { 326 frame = (struct x86_64_frame *)BP_REGS(&ddb_regs); 327 if (frame == NULL) 328 frame = (struct x86_64_frame *)(SP_REGS(&ddb_regs) - 8); 329 callpc = PC_REGS(&ddb_regs); 330 } else { 331 /* 332 * Look for something that might be a frame pointer, just as 333 * a convenience. 334 */ 335 frame = (struct x86_64_frame *)addr; 336 for (i = 0; i < 4096; i += 8) { 337 struct x86_64_frame *check; 338 339 check = (struct x86_64_frame *)db_get_value((long)((char *)&frame->f_frame + i), 8, FALSE); 340 if ((char *)check - (char *)frame >= 0 && 341 (char *)check - (char *)frame < 4096 342 ) { 343 break; 344 } 345 db_printf("%p does not look like a stack frame, skipping\n", (char *)&frame->f_frame + i); 346 } 347 if (i == 4096) { 348 db_printf("Unable to find anything that looks like a stack frame\n"); 349 return; 350 } 351 frame = (void *)((char *)frame + i); 352 db_printf("Trace beginning at frame %p\n", frame); 353 callpc = (db_addr_t)db_get_value((long)&frame->f_retaddr, 8, FALSE); 354 } 355 356 first = TRUE; 357 while (count--) { 358 struct x86_64_frame *actframe; 359 int narg; 360 const char * name; 361 db_expr_t offset; 362 c_db_sym_t sym; 363 #define MAXNARG 16 364 char *argnames[MAXNARG], **argnp = NULL; 365 366 sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); 367 db_symbol_values(sym, &name, NULL); 368 dl_symbol_values(callpc, &name); 369 370 /* 371 * Attempt to determine a (possibly fake) frame that gives 372 * the caller's pc. It may differ from `frame' if the 373 * current function never sets up a standard frame or hasn't 374 * set one up yet or has just discarded one. The last two 375 * cases can be guessed fairly reliably for code generated 376 * by gcc. The first case is too much trouble to handle in 377 * general because the amount of junk on the stack depends 378 * on the pc (the special handling of "calltrap", etc. in 379 * db_nextframe() works because the `next' pc is special). 380 */ 381 actframe = frame; 382 if (first) { 383 if (!have_addr) { 384 int instr; 385 386 instr = db_get_value(callpc, 4, FALSE); 387 if ((instr & 0xffffffff) == 0xe5894855) { 388 /* pushq %rbp; movq %rsp, %rbp */ 389 actframe = (struct x86_64_frame *) 390 (SP_REGS(&ddb_regs) - 8); 391 } else if ((instr & 0xffffff) == 0xe58948) { 392 /* movq %rsp, %rbp */ 393 actframe = (struct x86_64_frame *) 394 SP_REGS(&ddb_regs); 395 if (ddb_regs.tf_rbp == 0) { 396 /* Fake caller's frame better. */ 397 frame = actframe; 398 } 399 } else if ((instr & 0xff) == 0xc3) { 400 /* ret */ 401 actframe = (struct x86_64_frame *) 402 (SP_REGS(&ddb_regs) - 8); 403 } else if (offset == 0) { 404 /* Probably a symbol in assembler code. */ 405 actframe = (struct x86_64_frame *) 406 (SP_REGS(&ddb_regs) - 8); 407 } 408 } else if (name != NULL && 409 strcmp(name, "fork_trampoline") == 0) { 410 /* 411 * Don't try to walk back on a stack for a 412 * process that hasn't actually been run yet. 413 */ 414 db_print_stack_entry(name, 0, 0, 0, callpc); 415 break; 416 } 417 first = FALSE; 418 } 419 420 argp = &actframe->f_arg0; 421 narg = MAXNARG; 422 if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) { 423 argnp = argnames; 424 } else { 425 narg = db_numargs(frame); 426 } 427 428 db_print_stack_entry(name, narg, argnp, argp, callpc); 429 430 /* 431 * Stop at the system call boundary (else we risk 432 * double-faulting on junk). 433 */ 434 if (name && strcmp(name, "Xfast_syscall") == 0) 435 break; 436 437 if (actframe != frame) { 438 /* `frame' belongs to caller. */ 439 callpc = (db_addr_t) 440 db_get_value((long)&actframe->f_retaddr, 8, FALSE); 441 continue; 442 } 443 444 db_nextframe(&frame, &callpc); 445 if (frame == NULL) 446 break; 447 } 448 } 449 450 void 451 print_backtrace(int count) 452 { 453 register_t rbp; 454 455 __asm __volatile("movq %%rbp, %0" : "=r" (rbp)); 456 db_stack_trace_cmd(rbp, 1, count, NULL); 457 } 458 459 #define DB_DRX_FUNC(reg) \ 460 int \ 461 db_ ## reg (struct db_variable *vp, db_expr_t *valuep, int op) \ 462 { \ 463 if (op == DB_VAR_GET) \ 464 *valuep = r ## reg (); \ 465 else \ 466 load_ ## reg (*valuep); \ 467 \ 468 return(0); \ 469 } 470 471 DB_DRX_FUNC(dr0) 472 DB_DRX_FUNC(dr1) 473 DB_DRX_FUNC(dr2) 474 DB_DRX_FUNC(dr3) 475 DB_DRX_FUNC(dr4) 476 DB_DRX_FUNC(dr5) 477 DB_DRX_FUNC(dr6) 478 DB_DRX_FUNC(dr7) 479 480 static int 481 kx86_64_set_watch(int watchnum, unsigned int watchaddr, int size, int access, 482 struct dbreg *d) 483 { 484 int i; 485 unsigned int mask; 486 487 if (watchnum == -1) { 488 for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2) 489 if ((d->dr[7] & mask) == 0) 490 break; 491 if (i < 4) 492 watchnum = i; 493 else 494 return(-1); 495 } 496 497 switch (access) { 498 case DBREG_DR7_EXEC: 499 size = 1; /* size must be 1 for an execution breakpoint */ 500 /* fall through */ 501 case DBREG_DR7_WRONLY: 502 case DBREG_DR7_RDWR: 503 break; 504 default: 505 return(-1); 506 } 507 508 /* 509 * we can watch a 1, 2, 4, or 8 byte sized location 510 */ 511 switch (size) { 512 case 1: 513 mask = 0x00; 514 break; 515 case 2: 516 mask = 0x01 << 2; 517 break; 518 case 4: 519 mask = 0x03 << 2; 520 break; 521 case 8: 522 mask = 0x02 << 2; 523 break; 524 default: 525 return(-1); 526 } 527 528 mask |= access; 529 530 /* clear the bits we are about to affect */ 531 d->dr[7] &= ~((0x3 << (watchnum * 2)) | (0x0f << (watchnum * 4 + 16))); 532 533 /* set drN register to the address, N=watchnum */ 534 DBREG_DRX(d, watchnum) = watchaddr; 535 536 /* enable the watchpoint */ 537 d->dr[7] |= (0x2 << (watchnum * 2)) | (mask << (watchnum * 4 + 16)); 538 539 return(watchnum); 540 } 541 542 543 int 544 kx86_64_clr_watch(int watchnum, struct dbreg *d) 545 { 546 if (watchnum < 0 || watchnum >= 4) 547 return(-1); 548 549 d->dr[7] &= ~((0x3 << (watchnum * 2)) | (0x0f << (watchnum * 4 + 16))); 550 DBREG_DRX(d, watchnum) = 0; 551 552 return(0); 553 } 554 555 556 int 557 db_md_set_watchpoint(db_expr_t addr, db_expr_t size) 558 { 559 int avail, wsize; 560 int i; 561 struct dbreg d; 562 563 fill_dbregs(NULL, &d); 564 565 avail = 0; 566 for (i = 0; i < 4; i++) { 567 if ((d.dr[7] & (3 << (i * 2))) == 0) 568 avail++; 569 } 570 571 if (avail * 8 < size) 572 return(-1); 573 574 for (i=0; i < 4 && (size != 0); i++) { 575 if ((d.dr[7] & (3 << (i * 2))) == 0) { 576 if (size >= 8 || (avail == 1 && size > 4)) 577 wsize = 8; 578 else if (size > 2) 579 wsize = 4; 580 else 581 wsize = size; 582 if (wsize == 3) 583 wsize++; 584 kx86_64_set_watch(i, addr, wsize, DBREG_DR7_WRONLY, &d); 585 addr += wsize; 586 size -= wsize; 587 } 588 } 589 590 set_dbregs(NULL, &d); 591 592 return(0); 593 } 594 595 int 596 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size) 597 { 598 struct dbreg d; 599 int i; 600 601 fill_dbregs(NULL, &d); 602 603 for(i = 0; i < 4; i++) { 604 if (d.dr[7] & (3 << (i * 2))) { 605 if ((DBREG_DRX((&d), i) >= addr) && 606 (DBREG_DRX((&d), i) < addr + size)) 607 kx86_64_clr_watch(i, &d); 608 } 609 } 610 611 set_dbregs(NULL, &d); 612 613 return(0); 614 } 615 616 static char * 617 watchtype_str(int type) 618 { 619 switch (type) { 620 case DBREG_DR7_EXEC: 621 return "execute"; 622 case DBREG_DR7_RDWR: 623 return "read/write"; 624 case DBREG_DR7_WRONLY: 625 return "write"; 626 default: 627 return "invalid"; 628 } 629 } 630 631 void 632 db_md_list_watchpoints(void) 633 { 634 int i; 635 struct dbreg d; 636 637 fill_dbregs(NULL, &d); 638 639 db_printf("\nhardware watchpoints:\n"); 640 db_printf(" watch status type len address\n" 641 " ----- -------- ---------- --- ----------\n"); 642 for (i = 0; i < 4; i++) { 643 if (d.dr[7] & (0x03 << (i * 2))) { 644 unsigned type, len; 645 type = (d.dr[7] >> (16 + (i * 4))) & 3; 646 len = (d.dr[7] >> (16 + (i * 4) + 2)) & 3; 647 db_printf(" %-5d %-8s %10s %3d 0x%08lx\n", 648 i, "enabled", watchtype_str(type), 649 len + 1, DBREG_DRX((&d), i)); 650 } else { 651 db_printf(" %-5d disabled\n", i); 652 } 653 } 654 655 db_printf("\ndebug register values:\n"); 656 for (i = 0; i < 8; i++) 657 db_printf(" dr%d 0x%08lx\n", i, DBREG_DRX((&d),i)); 658 db_printf("\n"); 659 } 660 661 /* 662 * See if dladdr() can get the symbol name via the standard dynamic loader. 663 */ 664 static 665 void 666 dl_symbol_values(long callpc, const char **name) 667 { 668 #if 0 669 Dl_info info; 670 if (*name == NULL) { 671 if (dladdr((const void *)callpc, &info) != 0) { 672 if (info.dli_saddr <= (const void *)callpc) 673 *name = info.dli_sname; 674 } 675 } 676 #endif 677 } 678 679