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("\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 if (actframe != frame) { 433 /* `frame' belongs to caller. */ 434 callpc = (db_addr_t) 435 db_get_value((long)&actframe->f_retaddr, 8, FALSE); 436 continue; 437 } 438 439 db_nextframe(&frame, &callpc); 440 if (frame == NULL) 441 break; 442 } 443 } 444 445 void 446 print_backtrace(int count) 447 { 448 register_t rbp; 449 450 __asm __volatile("movq %%rbp, %0" : "=r" (rbp)); 451 db_stack_trace_cmd(rbp, 1, count, NULL); 452 } 453 454 #define DB_DRX_FUNC(reg) \ 455 int \ 456 db_ ## reg (struct db_variable *vp, db_expr_t *valuep, int op) \ 457 { \ 458 if (op == DB_VAR_GET) \ 459 *valuep = r ## reg (); \ 460 else \ 461 load_ ## reg (*valuep); \ 462 \ 463 return(0); \ 464 } 465 466 DB_DRX_FUNC(dr0) 467 DB_DRX_FUNC(dr1) 468 DB_DRX_FUNC(dr2) 469 DB_DRX_FUNC(dr3) 470 DB_DRX_FUNC(dr4) 471 DB_DRX_FUNC(dr5) 472 DB_DRX_FUNC(dr6) 473 DB_DRX_FUNC(dr7) 474 475 static int 476 kx86_64_set_watch(int watchnum, unsigned int watchaddr, int size, int access, 477 struct dbreg *d) 478 { 479 int i; 480 unsigned int mask; 481 482 if (watchnum == -1) { 483 for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2) 484 if ((d->dr[7] & mask) == 0) 485 break; 486 if (i < 4) 487 watchnum = i; 488 else 489 return(-1); 490 } 491 492 switch (access) { 493 case DBREG_DR7_EXEC: 494 size = 1; /* size must be 1 for an execution breakpoint */ 495 /* fall through */ 496 case DBREG_DR7_WRONLY: 497 case DBREG_DR7_RDWR: 498 break; 499 default: 500 return(-1); 501 } 502 503 /* 504 * we can watch a 1, 2, 4, or 8 byte sized location 505 */ 506 switch (size) { 507 case 1: 508 mask = 0x00; 509 break; 510 case 2: 511 mask = 0x01 << 2; 512 break; 513 case 4: 514 mask = 0x03 << 2; 515 break; 516 case 8: 517 mask = 0x02 << 2; 518 break; 519 default: 520 return(-1); 521 } 522 523 mask |= access; 524 525 /* clear the bits we are about to affect */ 526 d->dr[7] &= ~((0x3 << (watchnum * 2)) | (0x0f << (watchnum * 4 + 16))); 527 528 /* set drN register to the address, N=watchnum */ 529 DBREG_DRX(d, watchnum) = watchaddr; 530 531 /* enable the watchpoint */ 532 d->dr[7] |= (0x2 << (watchnum * 2)) | (mask << (watchnum * 4 + 16)); 533 534 return(watchnum); 535 } 536 537 538 int 539 kx86_64_clr_watch(int watchnum, struct dbreg *d) 540 { 541 if (watchnum < 0 || watchnum >= 4) 542 return(-1); 543 544 d->dr[7] &= ~((0x3 << (watchnum * 2)) | (0x0f << (watchnum * 4 + 16))); 545 DBREG_DRX(d, watchnum) = 0; 546 547 return(0); 548 } 549 550 551 int 552 db_md_set_watchpoint(db_expr_t addr, db_expr_t size) 553 { 554 int avail, wsize; 555 int i; 556 struct dbreg d; 557 558 fill_dbregs(NULL, &d); 559 560 avail = 0; 561 for (i = 0; i < 4; i++) { 562 if ((d.dr[7] & (3 << (i * 2))) == 0) 563 avail++; 564 } 565 566 if (avail * 8 < size) 567 return(-1); 568 569 for (i=0; i < 4 && (size != 0); i++) { 570 if ((d.dr[7] & (3 << (i * 2))) == 0) { 571 if (size >= 8 || (avail == 1 && size > 4)) 572 wsize = 8; 573 else if (size > 2) 574 wsize = 4; 575 else 576 wsize = size; 577 if (wsize == 3) 578 wsize++; 579 kx86_64_set_watch(i, addr, wsize, DBREG_DR7_WRONLY, &d); 580 addr += wsize; 581 size -= wsize; 582 } 583 } 584 585 set_dbregs(NULL, &d); 586 587 return(0); 588 } 589 590 int 591 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size) 592 { 593 struct dbreg d; 594 int i; 595 596 fill_dbregs(NULL, &d); 597 598 for(i = 0; i < 4; i++) { 599 if (d.dr[7] & (3 << (i * 2))) { 600 if ((DBREG_DRX((&d), i) >= addr) && 601 (DBREG_DRX((&d), i) < addr + size)) 602 kx86_64_clr_watch(i, &d); 603 } 604 } 605 606 set_dbregs(NULL, &d); 607 608 return(0); 609 } 610 611 static char * 612 watchtype_str(int type) 613 { 614 switch (type) { 615 case DBREG_DR7_EXEC: 616 return "execute"; 617 case DBREG_DR7_RDWR: 618 return "read/write"; 619 case DBREG_DR7_WRONLY: 620 return "write"; 621 default: 622 return "invalid"; 623 } 624 } 625 626 void 627 db_md_list_watchpoints(void) 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.dr[7] & (0x03 << (i * 2))) { 639 unsigned type, len; 640 type = (d.dr[7] >> (16 + (i * 4))) & 3; 641 len = (d.dr[7] >> (16 + (i * 4) + 2)) & 3; 642 db_printf(" %-5d %-8s %10s %3d 0x%08lx\n", 643 i, "enabled", watchtype_str(type), 644 len + 1, DBREG_DRX((&d), i)); 645 } else { 646 db_printf(" %-5d disabled\n", i); 647 } 648 } 649 650 db_printf("\ndebug register values:\n"); 651 for (i = 0; i < 8; i++) 652 db_printf(" dr%d 0x%08lx\n", i, DBREG_DRX((&d),i)); 653 db_printf("\n"); 654 } 655 656 /* 657 * See if dladdr() can get the symbol name via the standard dynamic loader. 658 */ 659 static 660 void 661 dl_symbol_values(long callpc, const char **name) 662 { 663 Dl_info info; 664 665 if (*name == NULL) { 666 if (dladdr((const void *)callpc, &info) != 0) { 667 if (info.dli_saddr <= (const void *)callpc) 668 *name = info.dli_sname; 669 } 670 } 671 } 672