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 <ddb/db_access.h> 78 #include <ddb/db_sym.h> 79 #include <ddb/db_variables.h> 80 81 db_varfcn_t db_dr0; 82 db_varfcn_t db_dr1; 83 db_varfcn_t db_dr2; 84 db_varfcn_t db_dr3; 85 db_varfcn_t db_dr4; 86 db_varfcn_t db_dr5; 87 db_varfcn_t db_dr6; 88 db_varfcn_t db_dr7; 89 90 /* 91 * Machine register set. 92 */ 93 struct db_variable db_regs[] = { 94 { "cs", &ddb_regs.tf_cs, NULL }, 95 /* { "ds", &ddb_regs.tf_ds, NULL }, 96 { "es", &ddb_regs.tf_es, NULL }, 97 { "fs", &ddb_regs.tf_fs, NULL }, 98 { "gs", &ddb_regs.tf_gs, NULL }, */ 99 { "ss", &ddb_regs.tf_ss, NULL }, 100 { "rax", &ddb_regs.tf_rax, NULL }, 101 { "rcx", &ddb_regs.tf_rcx, NULL }, 102 { "rdx", &ddb_regs.tf_rdx, NULL }, 103 { "rbx", &ddb_regs.tf_rbx, NULL }, 104 { "rsp", &ddb_regs.tf_rsp, NULL }, 105 { "rbp", &ddb_regs.tf_rbp, NULL }, 106 { "rsi", &ddb_regs.tf_rsi, NULL }, 107 { "rdi", &ddb_regs.tf_rdi, NULL }, 108 { "rip", &ddb_regs.tf_rip, NULL }, 109 { "rfl", &ddb_regs.tf_rflags, NULL }, 110 { "r8", &ddb_regs.tf_r8, NULL }, 111 { "r9", &ddb_regs.tf_r9, NULL }, 112 { "r10", &ddb_regs.tf_r10, NULL }, 113 { "r11", &ddb_regs.tf_r11, NULL }, 114 { "r12", &ddb_regs.tf_r12, NULL }, 115 { "r13", &ddb_regs.tf_r13, NULL }, 116 { "r14", &ddb_regs.tf_r14, NULL }, 117 { "r15", &ddb_regs.tf_r15, NULL }, 118 { "dr0", NULL, db_dr0 }, 119 { "dr1", NULL, db_dr1 }, 120 { "dr2", NULL, db_dr2 }, 121 { "dr3", NULL, db_dr3 }, 122 { "dr4", NULL, db_dr4 }, 123 { "dr5", NULL, db_dr5 }, 124 { "dr6", NULL, db_dr6 }, 125 { "dr7", NULL, db_dr7 }, 126 }; 127 struct db_variable *db_eregs = db_regs + NELEM(db_regs); 128 129 /* 130 * Stack trace. 131 */ 132 #define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK) 133 134 struct x86_64_frame { 135 struct x86_64_frame *f_frame; 136 long f_retaddr; 137 long f_arg0; 138 }; 139 140 #define NORMAL 0 141 #define TRAP 1 142 #define INTERRUPT 2 143 #define SYSCALL 3 144 145 static void db_nextframe(struct x86_64_frame **, db_addr_t *); 146 static int db_numargs(struct x86_64_frame *); 147 static void db_print_stack_entry(const char *, int, char **, long *, db_addr_t); 148 static void dl_symbol_values(long callpc, const char **name); 149 150 151 static char *watchtype_str(int type); 152 static int kx86_64_set_watch(int watchnum, unsigned int watchaddr, 153 int size, int access, struct dbreg * d); 154 static int kx86_64_clr_watch(int watchnum, struct dbreg * d); 155 int db_md_set_watchpoint(db_expr_t addr, db_expr_t size); 156 int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size); 157 void db_md_list_watchpoints(void); 158 159 160 /* 161 * Figure out how many arguments were passed into the frame at "fp". 162 */ 163 static int 164 db_numargs(struct x86_64_frame *fp) 165 { 166 #if 1 167 return (0); /* regparm, needs dwarf2 info */ 168 #else 169 int args; 170 #if 0 171 int *argp; 172 int inst; 173 174 argp = (int *)db_get_value((int)&fp->f_retaddr, 4, FALSE); 175 /* 176 * XXX etext is wrong for LKMs. We should attempt to interpret 177 * the instruction at the return address in all cases. This 178 * may require better fault handling. 179 */ 180 if (argp < (int *)btext || argp >= (int *)etext) { 181 args = 5; 182 } else { 183 inst = db_get_value((int)argp, 4, FALSE); 184 if ((inst & 0xff) == 0x59) /* popl %ecx */ 185 args = 1; 186 else if ((inst & 0xffff) == 0xc483) /* addl $Ibs, %esp */ 187 args = ((inst >> 16) & 0xff) / 4; 188 else 189 args = 5; 190 } 191 #endif 192 args = 5; 193 return(args); 194 #endif 195 } 196 197 static void 198 db_print_stack_entry(const char *name, int narg, char **argnp, long *argp, 199 db_addr_t callpc) 200 { 201 db_printf("%s(", name); 202 while (narg) { 203 if (argnp) 204 db_printf("%s=", *argnp++); 205 db_printf("%ld", (long)db_get_value((long)argp, 8, FALSE)); 206 argp++; 207 if (--narg != 0) 208 db_printf(","); 209 } 210 db_printf(") at "); 211 db_printsym(callpc, DB_STGY_PROC); 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 if (actframe != frame) { 431 /* `frame' belongs to caller. */ 432 callpc = (db_addr_t) 433 db_get_value((long)&actframe->f_retaddr, 8, FALSE); 434 continue; 435 } 436 437 db_nextframe(&frame, &callpc); 438 if (frame == NULL) 439 break; 440 } 441 } 442 443 void 444 print_backtrace(int count) 445 { 446 register_t rbp; 447 448 __asm __volatile("movq %%rbp, %0" : "=r" (rbp)); 449 db_stack_trace_cmd(rbp, 1, count, NULL); 450 } 451 452 #define DB_DRX_FUNC(reg) \ 453 int \ 454 db_ ## reg (struct db_variable *vp, db_expr_t *valuep, int op) \ 455 { \ 456 if (op == DB_VAR_GET) \ 457 *valuep = r ## reg (); \ 458 else \ 459 load_ ## reg (*valuep); \ 460 \ 461 return(0); \ 462 } 463 464 DB_DRX_FUNC(dr0) 465 DB_DRX_FUNC(dr1) 466 DB_DRX_FUNC(dr2) 467 DB_DRX_FUNC(dr3) 468 DB_DRX_FUNC(dr4) 469 DB_DRX_FUNC(dr5) 470 DB_DRX_FUNC(dr6) 471 DB_DRX_FUNC(dr7) 472 473 static int 474 kx86_64_set_watch(int watchnum, unsigned int watchaddr, int size, int access, 475 struct dbreg *d) 476 { 477 int i; 478 unsigned int mask; 479 480 if (watchnum == -1) { 481 for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2) 482 if ((d->dr[7] & mask) == 0) 483 break; 484 if (i < 4) 485 watchnum = i; 486 else 487 return(-1); 488 } 489 490 switch (access) { 491 case DBREG_DR7_EXEC: 492 size = 1; /* size must be 1 for an execution breakpoint */ 493 /* fall through */ 494 case DBREG_DR7_WRONLY: 495 case DBREG_DR7_RDWR: 496 break; 497 default: 498 return(-1); 499 } 500 501 /* 502 * we can watch a 1, 2, 4, or 8 byte sized location 503 */ 504 switch (size) { 505 case 1: 506 mask = 0x00; 507 break; 508 case 2: 509 mask = 0x01 << 2; 510 break; 511 case 4: 512 mask = 0x03 << 2; 513 break; 514 case 8: 515 mask = 0x02 << 2; 516 break; 517 default: 518 return(-1); 519 } 520 521 mask |= access; 522 523 /* clear the bits we are about to affect */ 524 d->dr[7] &= ~((0x3 << (watchnum * 2)) | (0x0f << (watchnum * 4 + 16))); 525 526 /* set drN register to the address, N=watchnum */ 527 DBREG_DRX(d, watchnum) = watchaddr; 528 529 /* enable the watchpoint */ 530 d->dr[7] |= (0x2 << (watchnum * 2)) | (mask << (watchnum * 4 + 16)); 531 532 return(watchnum); 533 } 534 535 536 int 537 kx86_64_clr_watch(int watchnum, struct dbreg *d) 538 { 539 if (watchnum < 0 || watchnum >= 4) 540 return(-1); 541 542 d->dr[7] &= ~((0x3 << (watchnum * 2)) | (0x0f << (watchnum * 4 + 16))); 543 DBREG_DRX(d, watchnum) = 0; 544 545 return(0); 546 } 547 548 549 int 550 db_md_set_watchpoint(db_expr_t addr, db_expr_t size) 551 { 552 int avail, wsize; 553 int i; 554 struct dbreg d; 555 556 fill_dbregs(NULL, &d); 557 558 avail = 0; 559 for (i = 0; i < 4; i++) { 560 if ((d.dr[7] & (3 << (i * 2))) == 0) 561 avail++; 562 } 563 564 if (avail * 8 < size) 565 return(-1); 566 567 for (i=0; i < 4 && (size != 0); i++) { 568 if ((d.dr[7] & (3 << (i * 2))) == 0) { 569 if (size >= 8 || (avail == 1 && size > 4)) 570 wsize = 8; 571 else if (size > 2) 572 wsize = 4; 573 else 574 wsize = size; 575 if (wsize == 3) 576 wsize++; 577 kx86_64_set_watch(i, addr, wsize, DBREG_DR7_WRONLY, &d); 578 addr += wsize; 579 size -= wsize; 580 } 581 } 582 583 set_dbregs(NULL, &d); 584 585 return(0); 586 } 587 588 int 589 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size) 590 { 591 struct dbreg d; 592 int i; 593 594 fill_dbregs(NULL, &d); 595 596 for(i = 0; i < 4; i++) { 597 if (d.dr[7] & (3 << (i * 2))) { 598 if ((DBREG_DRX((&d), i) >= addr) && 599 (DBREG_DRX((&d), i) < addr + size)) 600 kx86_64_clr_watch(i, &d); 601 } 602 } 603 604 set_dbregs(NULL, &d); 605 606 return(0); 607 } 608 609 static char * 610 watchtype_str(int type) 611 { 612 switch (type) { 613 case DBREG_DR7_EXEC: 614 return "execute"; 615 case DBREG_DR7_RDWR: 616 return "read/write"; 617 case DBREG_DR7_WRONLY: 618 return "write"; 619 default: 620 return "invalid"; 621 } 622 } 623 624 void 625 db_md_list_watchpoints(void) 626 { 627 int i; 628 struct dbreg d; 629 630 fill_dbregs(NULL, &d); 631 632 db_printf("\nhardware watchpoints:\n"); 633 db_printf(" watch status type len address\n" 634 " ----- -------- ---------- --- ----------\n"); 635 for (i = 0; i < 4; i++) { 636 if (d.dr[7] & (0x03 << (i * 2))) { 637 unsigned type, len; 638 type = (d.dr[7] >> (16 + (i * 4))) & 3; 639 len = (d.dr[7] >> (16 + (i * 4) + 2)) & 3; 640 db_printf(" %-5d %-8s %10s %3d 0x%08lx\n", 641 i, "enabled", watchtype_str(type), 642 len + 1, DBREG_DRX((&d), i)); 643 } else { 644 db_printf(" %-5d disabled\n", i); 645 } 646 } 647 648 db_printf("\ndebug register values:\n"); 649 for (i = 0; i < 8; i++) 650 db_printf(" dr%d 0x%08lx\n", i, DBREG_DRX((&d),i)); 651 db_printf("\n"); 652 } 653 654 /* 655 * See if dladdr() can get the symbol name via the standard dynamic loader. 656 */ 657 static 658 void 659 dl_symbol_values(long callpc, const char **name) 660 { 661 Dl_info info; 662 663 if (*name == NULL) { 664 if (dladdr((const void *)callpc, &info) != 0) { 665 if (info.dli_saddr <= (const void *)callpc) 666 *name = info.dli_sname; 667 } 668 } 669 } 670