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