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 <sys/user.h> 77 78 #include <ddb/db_access.h> 79 #include <ddb/db_sym.h> 80 #include <ddb/db_variables.h> 81 82 db_varfcn_t db_dr0; 83 db_varfcn_t db_dr1; 84 db_varfcn_t db_dr2; 85 db_varfcn_t db_dr3; 86 db_varfcn_t db_dr4; 87 db_varfcn_t db_dr5; 88 db_varfcn_t db_dr6; 89 db_varfcn_t db_dr7; 90 91 /* 92 * Machine register set. 93 */ 94 struct db_variable db_regs[] = { 95 { "cs", &ddb_regs.tf_cs, NULL }, 96 /* { "ds", &ddb_regs.tf_ds, NULL }, 97 { "es", &ddb_regs.tf_es, NULL }, 98 { "fs", &ddb_regs.tf_fs, NULL }, 99 { "gs", &ddb_regs.tf_gs, NULL }, */ 100 { "ss", &ddb_regs.tf_ss, NULL }, 101 { "rax", &ddb_regs.tf_rax, NULL }, 102 { "rcx", &ddb_regs.tf_rcx, NULL }, 103 { "rdx", &ddb_regs.tf_rdx, NULL }, 104 { "rbx", &ddb_regs.tf_rbx, NULL }, 105 { "rsp", &ddb_regs.tf_rsp, NULL }, 106 { "rbp", &ddb_regs.tf_rbp, NULL }, 107 { "rsi", &ddb_regs.tf_rsi, NULL }, 108 { "rdi", &ddb_regs.tf_rdi, NULL }, 109 { "rip", &ddb_regs.tf_rip, NULL }, 110 { "rfl", &ddb_regs.tf_rflags, NULL }, 111 { "r8", &ddb_regs.tf_r8, NULL }, 112 { "r9", &ddb_regs.tf_r9, NULL }, 113 { "r10", &ddb_regs.tf_r10, NULL }, 114 { "r11", &ddb_regs.tf_r11, NULL }, 115 { "r12", &ddb_regs.tf_r12, NULL }, 116 { "r13", &ddb_regs.tf_r13, NULL }, 117 { "r14", &ddb_regs.tf_r14, NULL }, 118 { "r15", &ddb_regs.tf_r15, NULL }, 119 { "dr0", NULL, db_dr0 }, 120 { "dr1", NULL, db_dr1 }, 121 { "dr2", NULL, db_dr2 }, 122 { "dr3", NULL, db_dr3 }, 123 { "dr4", NULL, db_dr4 }, 124 { "dr5", NULL, db_dr5 }, 125 { "dr6", NULL, db_dr6 }, 126 { "dr7", NULL, db_dr7 }, 127 }; 128 struct db_variable *db_eregs = db_regs + NELEM(db_regs); 129 130 /* 131 * Stack trace. 132 */ 133 #define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK) 134 135 struct x86_64_frame { 136 struct x86_64_frame *f_frame; 137 long f_retaddr; 138 long f_arg0; 139 }; 140 141 #define NORMAL 0 142 #define TRAP 1 143 #define INTERRUPT 2 144 #define SYSCALL 3 145 146 static void db_nextframe(struct x86_64_frame **, db_addr_t *); 147 static int db_numargs(struct x86_64_frame *); 148 static void db_print_stack_entry(const char *, int, char **, long *, db_addr_t); 149 static void dl_symbol_values(long callpc, const char **name); 150 151 152 static char *watchtype_str(int type); 153 static int kx86_64_set_watch(int watchnum, unsigned int watchaddr, 154 int size, int access, struct dbreg * d); 155 static int kx86_64_clr_watch(int watchnum, struct dbreg * d); 156 int db_md_set_watchpoint(db_expr_t addr, db_expr_t size); 157 int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size); 158 void db_md_list_watchpoints(void); 159 160 161 /* 162 * Figure out how many arguments were passed into the frame at "fp". 163 */ 164 static int 165 db_numargs(struct x86_64_frame *fp) 166 { 167 #if 1 168 return (0); /* regparm, needs dwarf2 info */ 169 #else 170 int args; 171 #if 0 172 int *argp; 173 int inst; 174 175 argp = (int *)db_get_value((int)&fp->f_retaddr, 4, FALSE); 176 /* 177 * XXX etext is wrong for LKMs. We should attempt to interpret 178 * the instruction at the return address in all cases. This 179 * may require better fault handling. 180 */ 181 if (argp < (int *)btext || argp >= (int *)etext) { 182 args = 5; 183 } else { 184 inst = db_get_value((int)argp, 4, FALSE); 185 if ((inst & 0xff) == 0x59) /* popl %ecx */ 186 args = 1; 187 else if ((inst & 0xffff) == 0xc483) /* addl $Ibs, %esp */ 188 args = ((inst >> 16) & 0xff) / 4; 189 else 190 args = 5; 191 } 192 #endif 193 args = 5; 194 return(args); 195 #endif 196 } 197 198 static void 199 db_print_stack_entry(const char *name, int narg, char **argnp, long *argp, 200 db_addr_t callpc) 201 { 202 db_printf("%s(", name); 203 while (narg) { 204 if (argnp) 205 db_printf("%s=", *argnp++); 206 db_printf("%ld", (long)db_get_value((long)argp, 8, FALSE)); 207 argp++; 208 if (--narg != 0) 209 db_printf(","); 210 } 211 db_printf(") at "); 212 db_printsym(callpc, DB_STGY_PROC); 213 db_printf(" %p ", (void*) callpc); 214 db_printf("\n"); 215 } 216 217 /* 218 * Figure out the next frame up in the call stack. 219 */ 220 static void 221 db_nextframe(struct x86_64_frame **fp, db_addr_t *ip) 222 { 223 struct trapframe *tf; 224 int frame_type; 225 long rip, rsp, rbp; 226 db_expr_t offset; 227 const char *sym, *name; 228 229 if ((unsigned long)*fp < PAGE_SIZE) { 230 *fp = NULL; 231 return; 232 } 233 rip = db_get_value((long) &(*fp)->f_retaddr, 8, FALSE); 234 rbp = db_get_value((long) &(*fp)->f_frame, 8, FALSE); 235 236 /* 237 * Figure out frame type. 238 */ 239 240 frame_type = NORMAL; 241 242 sym = db_search_symbol(rip, DB_STGY_ANY, &offset); 243 db_symbol_values(sym, &name, NULL); 244 dl_symbol_values(rip, &name); 245 if (name != NULL) { 246 if (!strcmp(name, "calltrap")) { 247 frame_type = TRAP; 248 } else if (!strncmp(name, "Xresume", 7)) { 249 frame_type = INTERRUPT; 250 } else if (!strcmp(name, "_Xsyscall")) { 251 frame_type = SYSCALL; 252 } 253 } 254 255 /* 256 * Normal frames need no special processing. 257 */ 258 if (frame_type == NORMAL) { 259 *ip = (db_addr_t) rip; 260 *fp = (struct x86_64_frame *) rbp; 261 return; 262 } 263 264 db_print_stack_entry(name, 0, 0, 0, rip); 265 266 /* 267 * Point to base of trapframe which is just above the 268 * current frame. 269 */ 270 tf = (struct trapframe *)((long)*fp + 16); 271 272 #if 0 273 rsp = (ISPL(tf->tf_cs) == SEL_UPL) ? tf->tf_rsp : (long)&tf->tf_rsp; 274 #endif 275 rsp = (long)&tf->tf_rsp; 276 277 switch (frame_type) { 278 case TRAP: 279 { 280 rip = tf->tf_rip; 281 rbp = tf->tf_rbp; 282 db_printf( 283 "--- trap %016lx, rip = %016lx, rsp = %016lx, rbp = %016lx ---\n", 284 tf->tf_trapno, rip, rsp, rbp); 285 } 286 break; 287 case SYSCALL: 288 { 289 rip = tf->tf_rip; 290 rbp = tf->tf_rbp; 291 db_printf( 292 "--- syscall %016lx, rip = %016lx, rsp = %016lx, rbp = %016lx ---\n", 293 tf->tf_rax, rip, rsp, rbp); 294 } 295 break; 296 case INTERRUPT: 297 tf = (struct trapframe *)((long)*fp + 16); 298 { 299 rip = tf->tf_rip; 300 rbp = tf->tf_rbp; 301 db_printf( 302 "--- interrupt, rip = %016lx, rsp = %016lx, rbp = %016lx ---\n", 303 rip, rsp, rbp); 304 } 305 break; 306 default: 307 break; 308 } 309 310 *ip = (db_addr_t) rip; 311 *fp = (struct x86_64_frame *) rbp; 312 } 313 314 void 315 db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, 316 char *modif) 317 { 318 struct x86_64_frame *frame; 319 long *argp; 320 db_addr_t callpc; 321 boolean_t first; 322 int i; 323 324 if (count == -1) 325 count = 1024; 326 327 if (!have_addr) { 328 frame = (struct x86_64_frame *)BP_REGS(&ddb_regs); 329 if (frame == NULL) 330 frame = (struct x86_64_frame *)(SP_REGS(&ddb_regs) - 8); 331 callpc = PC_REGS(&ddb_regs); 332 } else { 333 /* 334 * Look for something that might be a frame pointer, just as 335 * a convenience. 336 */ 337 frame = (struct x86_64_frame *)addr; 338 for (i = 0; i < 4096; i += 8) { 339 struct x86_64_frame *check; 340 341 check = (struct x86_64_frame *)db_get_value((long)((char *)&frame->f_frame + i), 8, FALSE); 342 if ((char *)check - (char *)frame >= 0 && 343 (char *)check - (char *)frame < 4096 344 ) { 345 break; 346 } 347 db_printf("%p does not look like a stack frame, skipping\n", (char *)&frame->f_frame + i); 348 } 349 if (i == 4096) { 350 db_printf("Unable to find anything that looks like a stack frame\n"); 351 return; 352 } 353 frame = (void *)((char *)frame + i); 354 db_printf("Trace beginning at frame %p\n", frame); 355 callpc = (db_addr_t)db_get_value((long)&frame->f_retaddr, 8, FALSE); 356 } 357 358 first = TRUE; 359 while (count--) { 360 struct x86_64_frame *actframe; 361 int narg; 362 const char * name; 363 db_expr_t offset; 364 c_db_sym_t sym; 365 #define MAXNARG 16 366 char *argnames[MAXNARG], **argnp = NULL; 367 368 sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); 369 db_symbol_values(sym, &name, NULL); 370 dl_symbol_values(callpc, &name); 371 372 /* 373 * Attempt to determine a (possibly fake) frame that gives 374 * the caller's pc. It may differ from `frame' if the 375 * current function never sets up a standard frame or hasn't 376 * set one up yet or has just discarded one. The last two 377 * cases can be guessed fairly reliably for code generated 378 * by gcc. The first case is too much trouble to handle in 379 * general because the amount of junk on the stack depends 380 * on the pc (the special handling of "calltrap", etc. in 381 * db_nextframe() works because the `next' pc is special). 382 */ 383 actframe = frame; 384 if (first) { 385 if (!have_addr) { 386 int instr; 387 388 instr = db_get_value(callpc, 4, FALSE); 389 if ((instr & 0xffffffff) == 0xe5894855) { 390 /* pushq %rbp; movq %rsp, %rbp */ 391 actframe = (struct x86_64_frame *) 392 (SP_REGS(&ddb_regs) - 8); 393 } else if ((instr & 0xffffff) == 0xe58948) { 394 /* movq %rsp, %rbp */ 395 actframe = (struct x86_64_frame *) 396 SP_REGS(&ddb_regs); 397 if (ddb_regs.tf_rbp == 0) { 398 /* Fake caller's frame better. */ 399 frame = actframe; 400 } 401 } else if ((instr & 0xff) == 0xc3) { 402 /* ret */ 403 actframe = (struct x86_64_frame *) 404 (SP_REGS(&ddb_regs) - 8); 405 } else if (offset == 0) { 406 /* Probably a symbol in assembler code. */ 407 actframe = (struct x86_64_frame *) 408 (SP_REGS(&ddb_regs) - 8); 409 } 410 } else if (name != NULL && 411 strcmp(name, "fork_trampoline") == 0) { 412 /* 413 * Don't try to walk back on a stack for a 414 * process that hasn't actually been run yet. 415 */ 416 db_print_stack_entry(name, 0, 0, 0, callpc); 417 break; 418 } 419 first = FALSE; 420 } 421 422 argp = &actframe->f_arg0; 423 narg = MAXNARG; 424 if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) { 425 argnp = argnames; 426 } else { 427 narg = db_numargs(frame); 428 } 429 430 db_print_stack_entry(name, narg, argnp, argp, callpc); 431 432 /* 433 * Stop at the system call boundary (else we risk 434 * double-faulting on junk). 435 */ 436 if (name && strcmp(name, "Xfast_syscall") == 0) 437 break; 438 439 if (actframe != frame) { 440 /* `frame' belongs to caller. */ 441 callpc = (db_addr_t) 442 db_get_value((long)&actframe->f_retaddr, 8, FALSE); 443 continue; 444 } 445 446 db_nextframe(&frame, &callpc); 447 if (frame == NULL) 448 break; 449 } 450 } 451 452 void 453 print_backtrace(int count) 454 { 455 register_t rbp; 456 457 __asm __volatile("movq %%rbp, %0" : "=r" (rbp)); 458 db_stack_trace_cmd(rbp, 1, count, NULL); 459 } 460 461 #define DB_DRX_FUNC(reg) \ 462 int \ 463 db_ ## reg (struct db_variable *vp, db_expr_t *valuep, int op) \ 464 { \ 465 if (op == DB_VAR_GET) \ 466 *valuep = r ## reg (); \ 467 else \ 468 load_ ## reg (*valuep); \ 469 \ 470 return(0); \ 471 } 472 473 DB_DRX_FUNC(dr0) 474 DB_DRX_FUNC(dr1) 475 DB_DRX_FUNC(dr2) 476 DB_DRX_FUNC(dr3) 477 DB_DRX_FUNC(dr4) 478 DB_DRX_FUNC(dr5) 479 DB_DRX_FUNC(dr6) 480 DB_DRX_FUNC(dr7) 481 482 static int 483 kx86_64_set_watch(int watchnum, unsigned int watchaddr, int size, int access, 484 struct dbreg *d) 485 { 486 int i; 487 unsigned int mask; 488 489 if (watchnum == -1) { 490 for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2) 491 if ((d->dr[7] & mask) == 0) 492 break; 493 if (i < 4) 494 watchnum = i; 495 else 496 return(-1); 497 } 498 499 switch (access) { 500 case DBREG_DR7_EXEC: 501 size = 1; /* size must be 1 for an execution breakpoint */ 502 /* fall through */ 503 case DBREG_DR7_WRONLY: 504 case DBREG_DR7_RDWR: 505 break; 506 default: 507 return(-1); 508 } 509 510 /* 511 * we can watch a 1, 2, 4, or 8 byte sized location 512 */ 513 switch (size) { 514 case 1: 515 mask = 0x00; 516 break; 517 case 2: 518 mask = 0x01 << 2; 519 break; 520 case 4: 521 mask = 0x03 << 2; 522 break; 523 case 8: 524 mask = 0x02 << 2; 525 break; 526 default: 527 return(-1); 528 } 529 530 mask |= access; 531 532 /* clear the bits we are about to affect */ 533 d->dr[7] &= ~((0x3 << (watchnum * 2)) | (0x0f << (watchnum * 4 + 16))); 534 535 /* set drN register to the address, N=watchnum */ 536 DBREG_DRX(d, watchnum) = watchaddr; 537 538 /* enable the watchpoint */ 539 d->dr[7] |= (0x2 << (watchnum * 2)) | (mask << (watchnum * 4 + 16)); 540 541 return(watchnum); 542 } 543 544 545 int 546 kx86_64_clr_watch(int watchnum, struct dbreg *d) 547 { 548 if (watchnum < 0 || watchnum >= 4) 549 return(-1); 550 551 d->dr[7] &= ~((0x3 << (watchnum * 2)) | (0x0f << (watchnum * 4 + 16))); 552 DBREG_DRX(d, watchnum) = 0; 553 554 return(0); 555 } 556 557 558 int 559 db_md_set_watchpoint(db_expr_t addr, db_expr_t size) 560 { 561 int avail, wsize; 562 int i; 563 struct dbreg d; 564 565 fill_dbregs(NULL, &d); 566 567 avail = 0; 568 for (i = 0; i < 4; i++) { 569 if ((d.dr[7] & (3 << (i * 2))) == 0) 570 avail++; 571 } 572 573 if (avail * 8 < size) 574 return(-1); 575 576 for (i=0; i < 4 && (size != 0); i++) { 577 if ((d.dr[7] & (3 << (i * 2))) == 0) { 578 if (size >= 8 || (avail == 1 && size > 4)) 579 wsize = 8; 580 else if (size > 2) 581 wsize = 4; 582 else 583 wsize = size; 584 if (wsize == 3) 585 wsize++; 586 kx86_64_set_watch(i, addr, wsize, DBREG_DR7_WRONLY, &d); 587 addr += wsize; 588 size -= wsize; 589 } 590 } 591 592 set_dbregs(NULL, &d); 593 594 return(0); 595 } 596 597 int 598 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size) 599 { 600 struct dbreg d; 601 int i; 602 603 fill_dbregs(NULL, &d); 604 605 for(i = 0; i < 4; i++) { 606 if (d.dr[7] & (3 << (i * 2))) { 607 if ((DBREG_DRX((&d), i) >= addr) && 608 (DBREG_DRX((&d), i) < addr + size)) 609 kx86_64_clr_watch(i, &d); 610 } 611 } 612 613 set_dbregs(NULL, &d); 614 615 return(0); 616 } 617 618 static char * 619 watchtype_str(int type) 620 { 621 switch (type) { 622 case DBREG_DR7_EXEC: 623 return "execute"; 624 case DBREG_DR7_RDWR: 625 return "read/write"; 626 case DBREG_DR7_WRONLY: 627 return "write"; 628 default: 629 return "invalid"; 630 } 631 } 632 633 void 634 db_md_list_watchpoints(void) 635 { 636 int i; 637 struct dbreg d; 638 639 fill_dbregs(NULL, &d); 640 641 db_printf("\nhardware watchpoints:\n"); 642 db_printf(" watch status type len address\n" 643 " ----- -------- ---------- --- ----------\n"); 644 for (i = 0; i < 4; i++) { 645 if (d.dr[7] & (0x03 << (i * 2))) { 646 unsigned type, len; 647 type = (d.dr[7] >> (16 + (i * 4))) & 3; 648 len = (d.dr[7] >> (16 + (i * 4) + 2)) & 3; 649 db_printf(" %-5d %-8s %10s %3d 0x%08lx\n", 650 i, "enabled", watchtype_str(type), 651 len + 1, DBREG_DRX((&d), i)); 652 } else { 653 db_printf(" %-5d disabled\n", i); 654 } 655 } 656 657 db_printf("\ndebug register values:\n"); 658 for (i = 0; i < 8; i++) 659 db_printf(" dr%d 0x%08lx\n", i, DBREG_DRX((&d),i)); 660 db_printf("\n"); 661 } 662 663 /* 664 * See if dladdr() can get the symbol name via the standard dynamic loader. 665 */ 666 static 667 void 668 dl_symbol_values(long callpc, const char **name) 669 { 670 #if 0 671 Dl_info info; 672 if (*name == NULL) { 673 if (dladdr((const void *)callpc, &info) != 0) { 674 if (info.dli_saddr <= (const void *)callpc) 675 *name = info.dli_sname; 676 } 677 } 678 #endif 679 } 680 681