1 /* 2 * Copyright 2005-2016, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <arch/user_debugger.h> 8 9 #include <string.h> 10 11 #include <debugger.h> 12 #include <driver_settings.h> 13 #include <int.h> 14 #include <team.h> 15 #include <thread.h> 16 #include <util/AutoLock.h> 17 18 19 //#define TRACE_ARCH_USER_DEBUGGER 20 #ifdef TRACE_ARCH_USER_DEBUGGER 21 # define TRACE(x) dprintf x 22 #else 23 # define TRACE(x) ; 24 #endif 25 26 #define B_NO_MORE_BREAKPOINTS B_BUSY 27 #define B_NO_MORE_WATCHPOINTS B_BUSY 28 #define B_BAD_WATCHPOINT_ALIGNMENT B_BAD_VALUE 29 #define B_WATCHPOINT_TYPE_NOT_SUPPORTED B_NOT_SUPPORTED 30 #define B_WATCHPOINT_LENGTH_NOT_SUPPORTED B_NOT_SUPPORTED 31 #define B_BREAKPOINT_NOT_FOUND B_NAME_NOT_FOUND 32 #define B_WATCHPOINT_NOT_FOUND B_NAME_NOT_FOUND 33 // TODO: Make those real error codes. 34 35 36 #ifdef __x86_64__ 37 extern bool gHasXsave; 38 #else 39 extern bool gHasSSE; 40 #endif 41 42 // The software breakpoint instruction (int3). 43 const uint8 kX86SoftwareBreakpoint[1] = { 0xcc }; 44 45 // maps breakpoint slot index to LEN_i LSB number 46 static const size_t sDR7Len[4] = { 47 X86_DR7_LEN0_LSB, X86_DR7_LEN1_LSB, X86_DR7_LEN2_LSB, X86_DR7_LEN3_LSB 48 }; 49 50 // maps breakpoint slot index to R/W_i LSB number 51 static const size_t sDR7RW[4] = { 52 X86_DR7_RW0_LSB, X86_DR7_RW1_LSB, X86_DR7_RW2_LSB, X86_DR7_RW3_LSB 53 }; 54 55 // maps breakpoint slot index to L_i bit number 56 static const size_t sDR7L[4] = { 57 X86_DR7_L0, X86_DR7_L1, X86_DR7_L2, X86_DR7_L3 58 }; 59 60 // maps breakpoint slot index to G_i bit number 61 static const size_t sDR7G[4] = { 62 X86_DR7_G0, X86_DR7_G1, X86_DR7_G2, X86_DR7_G3 63 }; 64 65 // maps breakpoint slot index to B_i bit number 66 static const size_t sDR6B[4] = { 67 X86_DR6_B0, X86_DR6_B1, X86_DR6_B2, X86_DR6_B3 68 }; 69 70 // Enables a hack to make single stepping work under qemu. Set via kernel 71 // driver settings. 72 static bool sQEmuSingleStepHack = false; 73 74 75 #ifdef __x86_64__ 76 77 78 static void 79 get_iframe_registers(const iframe* frame, debug_cpu_state* cpuState) 80 { 81 // Get general purpose registers. 82 cpuState->r15 = frame->r15; 83 cpuState->r14 = frame->r14; 84 cpuState->r13 = frame->r13; 85 cpuState->r12 = frame->r12; 86 cpuState->r11 = frame->r11; 87 cpuState->r10 = frame->r10; 88 cpuState->r9 = frame->r9; 89 cpuState->r8 = frame->r8; 90 cpuState->rbp = frame->bp; 91 cpuState->rsi = frame->si; 92 cpuState->rdi = frame->di; 93 cpuState->rdx = frame->dx; 94 cpuState->rcx = frame->cx; 95 cpuState->rbx = frame->bx; 96 cpuState->rax = frame->ax; 97 cpuState->vector = frame->vector; 98 cpuState->error_code = frame->error_code; 99 cpuState->rip = frame->ip; 100 cpuState->cs = frame->cs; 101 cpuState->rflags = frame->flags; 102 cpuState->rsp = frame->sp; 103 cpuState->ss = frame->ss; 104 105 // Other segment registers are not saved or changed on interrupts, so 106 // get their value here. 107 uint16 seg; 108 __asm__ volatile ("movw %%ds, %0" : "=r" (seg)); 109 cpuState->ds = seg; 110 __asm__ volatile ("movw %%es, %0" : "=r" (seg)); 111 cpuState->es = seg; 112 __asm__ volatile ("movw %%fs, %0" : "=r" (seg)); 113 cpuState->fs = seg; 114 __asm__ volatile ("movw %%gs, %0" : "=r" (seg)); 115 cpuState->gs = seg; 116 } 117 118 119 static void 120 set_iframe_registers(iframe* frame, const debug_cpu_state* cpuState) 121 { 122 frame->r15 = cpuState->r15; 123 frame->r14 = cpuState->r14; 124 frame->r13 = cpuState->r13; 125 frame->r12 = cpuState->r12; 126 frame->r11 = cpuState->r11; 127 frame->r10 = cpuState->r10; 128 frame->r9 = cpuState->r9; 129 frame->r8 = cpuState->r8; 130 frame->bp = cpuState->rbp; 131 frame->si = cpuState->rsi; 132 frame->di = cpuState->rdi; 133 frame->dx = cpuState->rdx; 134 frame->cx = cpuState->rcx; 135 frame->bx = cpuState->rbx; 136 frame->ax = cpuState->rax; 137 frame->ip = cpuState->rip; 138 frame->flags = (frame->flags & ~X86_EFLAGS_USER_SETTABLE_FLAGS) 139 | (cpuState->rflags & X86_EFLAGS_USER_SETTABLE_FLAGS); 140 frame->sp = cpuState->rsp; 141 } 142 143 144 #else // __x86_64__ 145 146 147 static void 148 get_iframe_registers(const iframe* frame, debug_cpu_state* cpuState) 149 { 150 cpuState->gs = frame->gs; 151 cpuState->fs = frame->fs; 152 cpuState->es = frame->es; 153 cpuState->ds = frame->ds; 154 cpuState->edi = frame->di; 155 cpuState->esi = frame->si; 156 cpuState->ebp = frame->bp; 157 cpuState->esp = frame->sp; 158 cpuState->ebx = frame->bx; 159 cpuState->edx = frame->orig_edx; 160 cpuState->ecx = frame->cx; 161 cpuState->eax = frame->orig_eax; 162 cpuState->vector = frame->vector; 163 cpuState->error_code = frame->error_code; 164 cpuState->eip = frame->ip; 165 cpuState->cs = frame->cs; 166 cpuState->eflags = frame->flags; 167 cpuState->user_esp = frame->user_sp; 168 cpuState->user_ss = frame->user_ss; 169 } 170 171 172 static void 173 set_iframe_registers(iframe* frame, const debug_cpu_state* cpuState) 174 { 175 // frame->gs = cpuState->gs; 176 // frame->fs = cpuState->fs; 177 // frame->es = cpuState->es; 178 // frame->ds = cpuState->ds; 179 frame->di = cpuState->edi; 180 frame->si = cpuState->esi; 181 frame->bp = cpuState->ebp; 182 // frame->esp = cpuState->esp; 183 frame->bx = cpuState->ebx; 184 frame->dx = cpuState->edx; 185 frame->cx = cpuState->ecx; 186 frame->ax = cpuState->eax; 187 // frame->vector = cpuState->vector; 188 // frame->error_code = cpuState->error_code; 189 frame->ip = cpuState->eip; 190 // frame->cs = cpuState->cs; 191 frame->flags = (frame->flags & ~X86_EFLAGS_USER_SETTABLE_FLAGS) 192 | (cpuState->eflags & X86_EFLAGS_USER_SETTABLE_FLAGS); 193 frame->user_sp = cpuState->user_esp; 194 // frame->user_ss = cpuState->user_ss; 195 } 196 197 198 #endif // __x86_64__ 199 200 201 static void 202 get_cpu_state(Thread* thread, iframe* frame, debug_cpu_state* cpuState) 203 { 204 // For the floating point state to be correct the calling function must 205 // not use these registers (not even indirectly). 206 #ifdef __x86_64__ 207 memset(&cpuState->extended_registers, 0, 208 sizeof(cpuState->extended_registers)); 209 210 if (frame->fpu != nullptr) { 211 if (gHasXsave) { 212 // TODO check the xsave header to know the actual size of the 213 // register context depending on what is saved. For now we assume 214 // there is only the YMM AVX registers 215 memcpy(&cpuState->extended_registers, frame->fpu, 216 sizeof(cpuState->extended_registers)); 217 } else { 218 // Only the "legacy area" saved by fxsave is available 219 memcpy(&cpuState->extended_registers, frame->fpu, 220 sizeof(cpuState->extended_registers.fp_fxsave)); 221 } 222 } 223 #else 224 Thread* thisThread = thread_get_current_thread(); 225 if (gHasSSE) { 226 if (thread == thisThread) { 227 // Since fxsave requires 16-byte alignment and this isn't guaranteed 228 // for the passed buffer, we use our thread's fpu_state field as 229 // temporary buffer. We need to disable interrupts to make use of 230 // it. 231 Thread* thread = thread_get_current_thread(); 232 InterruptsLocker locker; 233 x86_fxsave(thread->arch_info.fpu_state); 234 // unlike fnsave, fxsave doesn't reinit the FPU state 235 } 236 memcpy(&cpuState->extended_registers, thread->arch_info.fpu_state, 237 sizeof(cpuState->extended_registers)); 238 } else { 239 if (thread == thisThread) { 240 x86_fnsave(&cpuState->extended_registers); 241 // fnsave reinits the FPU state after saving, so we need to 242 // load it again 243 x86_frstor(&cpuState->extended_registers); 244 } else { 245 memcpy(&cpuState->extended_registers, thread->arch_info.fpu_state, 246 sizeof(cpuState->extended_registers)); 247 } 248 // TODO: Convert to fxsave format! 249 } 250 #endif 251 get_iframe_registers(frame, cpuState); 252 } 253 254 255 static inline void 256 install_breakpoints(const arch_team_debug_info& teamInfo) 257 { 258 // set breakpoints 259 asm("mov %0, %%dr0" : : "r"(teamInfo.breakpoints[0].address)); 260 asm("mov %0, %%dr1" : : "r"(teamInfo.breakpoints[1].address)); 261 asm("mov %0, %%dr2" : : "r"(teamInfo.breakpoints[2].address)); 262 asm("mov %0, %%dr3" : : "r"(teamInfo.breakpoints[3].address)); 263 264 // enable breakpoints 265 asm("mov %0, %%dr7" : : "r"(teamInfo.dr7)); 266 } 267 268 269 static inline void 270 disable_breakpoints() 271 { 272 asm("mov %0, %%dr7" : : "r"((size_t)X86_BREAKPOINTS_DISABLED_DR7)); 273 } 274 275 276 /*! Sets a break-/watchpoint in the given team info. 277 Interrupts must be disabled and the team debug info lock be held. 278 */ 279 static inline status_t 280 set_breakpoint(arch_team_debug_info& info, void* address, size_t type, 281 size_t length, bool setGlobalFlag) 282 { 283 // check, if there is already a breakpoint at that address 284 bool alreadySet = false; 285 for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) { 286 if (info.breakpoints[i].address == address 287 && info.breakpoints[i].type == type) { 288 alreadySet = true; 289 break; 290 } 291 } 292 293 if (!alreadySet) { 294 // find a free slot 295 int32 slot = -1; 296 for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) { 297 if (!info.breakpoints[i].address) { 298 slot = i; 299 break; 300 } 301 } 302 303 // init the breakpoint 304 if (slot >= 0) { 305 info.breakpoints[slot].address = address; 306 info.breakpoints[slot].type = type; 307 info.breakpoints[slot].length = length; 308 309 info.dr7 |= (length << sDR7Len[slot]) 310 | (type << sDR7RW[slot]) 311 | (1 << sDR7L[slot]); 312 if (setGlobalFlag) 313 info.dr7 |= (1 << sDR7G[slot]); 314 } else { 315 if (type == X86_INSTRUCTION_BREAKPOINT) 316 return B_NO_MORE_BREAKPOINTS; 317 else 318 return B_NO_MORE_WATCHPOINTS; 319 } 320 } 321 322 return B_OK; 323 } 324 325 326 /*! Clears a break-/watchpoint in the given team info. 327 Interrupts must be disabled and the team debug info lock be held. 328 */ 329 static inline status_t 330 clear_breakpoint(arch_team_debug_info& info, void* address, bool watchpoint) 331 { 332 // find the breakpoint 333 int32 slot = -1; 334 for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) { 335 if (info.breakpoints[i].address == address 336 && (watchpoint 337 != (info.breakpoints[i].type == X86_INSTRUCTION_BREAKPOINT))) { 338 slot = i; 339 break; 340 } 341 } 342 343 // clear the breakpoint 344 if (slot >= 0) { 345 info.breakpoints[slot].address = NULL; 346 347 info.dr7 &= ~((0x3 << sDR7Len[slot]) 348 | (0x3 << sDR7RW[slot]) 349 | (1 << sDR7L[slot]) 350 | (1 << sDR7G[slot])); 351 } else { 352 if (watchpoint) 353 return B_WATCHPOINT_NOT_FOUND; 354 else 355 return B_BREAKPOINT_NOT_FOUND; 356 } 357 358 return B_OK; 359 } 360 361 362 static status_t 363 set_breakpoint(void* address, size_t type, size_t length) 364 { 365 if (!address) 366 return B_BAD_VALUE; 367 368 Thread* thread = thread_get_current_thread(); 369 370 cpu_status state = disable_interrupts(); 371 GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info); 372 373 status_t error = set_breakpoint(thread->team->debug_info.arch_info, address, 374 type, length, false); 375 376 RELEASE_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info); 377 restore_interrupts(state); 378 379 return error; 380 } 381 382 383 static status_t 384 clear_breakpoint(void* address, bool watchpoint) 385 { 386 if (!address) 387 return B_BAD_VALUE; 388 389 Thread* thread = thread_get_current_thread(); 390 391 cpu_status state = disable_interrupts(); 392 GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info); 393 394 status_t error = clear_breakpoint(thread->team->debug_info.arch_info, 395 address, watchpoint); 396 397 RELEASE_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info); 398 restore_interrupts(state); 399 400 return error; 401 } 402 403 404 #if KERNEL_BREAKPOINTS 405 406 407 static void 408 install_breakpoints_per_cpu(void* /*cookie*/, int cpu) 409 { 410 Team* kernelTeam = team_get_kernel_team(); 411 412 GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info); 413 414 install_breakpoints(kernelTeam->debug_info.arch_info); 415 416 RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info); 417 } 418 419 420 static status_t 421 set_kernel_breakpoint(void* address, size_t type, size_t length) 422 { 423 if (!address) 424 return B_BAD_VALUE; 425 426 Team* kernelTeam = team_get_kernel_team(); 427 428 cpu_status state = disable_interrupts(); 429 GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info); 430 431 status_t error = set_breakpoint(kernelTeam->debug_info.arch_info, address, 432 type, length, true); 433 434 RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info); 435 436 call_all_cpus(install_breakpoints_per_cpu, NULL); 437 438 restore_interrupts(state); 439 440 return error; 441 } 442 443 444 static status_t 445 clear_kernel_breakpoint(void* address, bool watchpoint) 446 { 447 if (!address) 448 return B_BAD_VALUE; 449 450 Team* kernelTeam = team_get_kernel_team(); 451 452 cpu_status state = disable_interrupts(); 453 GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info); 454 455 status_t error = clear_breakpoint(kernelTeam->debug_info.arch_info, 456 address, watchpoint); 457 458 RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info); 459 460 call_all_cpus(install_breakpoints_per_cpu, NULL); 461 462 restore_interrupts(state); 463 464 return error; 465 } 466 467 #endif // KERNEL_BREAKPOINTS 468 469 470 static inline status_t 471 check_watch_point_parameters(void* address, uint32 type, int32 length, 472 size_t& archType, size_t& archLength) 473 { 474 // check type 475 switch (type) { 476 case B_DATA_WRITE_WATCHPOINT: 477 archType = X86_DATA_WRITE_BREAKPOINT; 478 break; 479 case B_DATA_READ_WRITE_WATCHPOINT: 480 archType = X86_DATA_READ_WRITE_BREAKPOINT; 481 break; 482 case B_DATA_READ_WATCHPOINT: 483 default: 484 return B_WATCHPOINT_TYPE_NOT_SUPPORTED; 485 break; 486 } 487 488 // check length and alignment 489 switch (length) { 490 case 1: 491 archLength = X86_BREAKPOINT_LENGTH_1; 492 break; 493 case 2: 494 if ((addr_t)address & 0x1) 495 return B_BAD_WATCHPOINT_ALIGNMENT; 496 archLength = X86_BREAKPOINT_LENGTH_2; 497 break; 498 case 4: 499 if ((addr_t)address & 0x3) 500 return B_BAD_WATCHPOINT_ALIGNMENT; 501 archLength = X86_BREAKPOINT_LENGTH_4; 502 break; 503 default: 504 return B_WATCHPOINT_LENGTH_NOT_SUPPORTED; 505 } 506 507 return B_OK; 508 } 509 510 511 // #pragma mark - kernel debugger commands 512 513 514 #if KERNEL_BREAKPOINTS 515 516 static int 517 debugger_breakpoints(int argc, char** argv) 518 { 519 Team* kernelTeam = team_get_kernel_team(); 520 arch_team_debug_info& info = kernelTeam->debug_info.arch_info; 521 522 for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) { 523 kprintf("breakpoint[%" B_PRId32 "] ", i); 524 525 if (info.breakpoints[i].address != NULL) { 526 kprintf("%p ", info.breakpoints[i].address); 527 switch (info.breakpoints[i].type) { 528 case X86_INSTRUCTION_BREAKPOINT: 529 kprintf("instruction"); 530 break; 531 case X86_IO_READ_WRITE_BREAKPOINT: 532 kprintf("io read/write"); 533 break; 534 case X86_DATA_WRITE_BREAKPOINT: 535 kprintf("data write"); 536 break; 537 case X86_DATA_READ_WRITE_BREAKPOINT: 538 kprintf("data read/write"); 539 break; 540 } 541 542 int length = 1; 543 switch (info.breakpoints[i].length) { 544 case X86_BREAKPOINT_LENGTH_1: 545 length = 1; 546 break; 547 case X86_BREAKPOINT_LENGTH_2: 548 length = 2; 549 break; 550 case X86_BREAKPOINT_LENGTH_4: 551 length = 4; 552 break; 553 } 554 555 if (info.breakpoints[i].type != X86_INSTRUCTION_BREAKPOINT) 556 kprintf(" %d byte%s", length, (length > 1 ? "s" : "")); 557 } else 558 kprintf("unused"); 559 560 kprintf("\n"); 561 } 562 563 return 0; 564 } 565 566 567 static int 568 debugger_breakpoint(int argc, char** argv) 569 { 570 // get arguments 571 572 if (argc < 2 || argc > 3) 573 return print_debugger_command_usage(argv[0]); 574 575 addr_t address = strtoul(argv[1], NULL, 0); 576 if (address == 0) 577 return print_debugger_command_usage(argv[0]); 578 579 bool clear = false; 580 if (argc == 3) { 581 if (strcmp(argv[2], "clear") == 0) 582 clear = true; 583 else 584 return print_debugger_command_usage(argv[0]); 585 } 586 587 // set/clear breakpoint 588 589 arch_team_debug_info& info = team_get_kernel_team()->debug_info.arch_info; 590 591 status_t error; 592 593 if (clear) { 594 error = clear_breakpoint(info, (void*)address, false); 595 } else { 596 error = set_breakpoint(info, (void*)address, X86_INSTRUCTION_BREAKPOINT, 597 X86_BREAKPOINT_LENGTH_1, true); 598 } 599 600 if (error == B_OK) 601 call_all_cpus_sync(install_breakpoints_per_cpu, NULL); 602 else 603 kprintf("Failed to install breakpoint: %s\n", strerror(error)); 604 605 return 0; 606 } 607 608 609 static int 610 debugger_watchpoint(int argc, char** argv) 611 { 612 // get arguments 613 614 if (argc < 2 || argc > 4) 615 return print_debugger_command_usage(argv[0]); 616 617 addr_t address = strtoul(argv[1], NULL, 0); 618 if (address == 0) 619 return print_debugger_command_usage(argv[0]); 620 621 bool clear = false; 622 bool readWrite = false; 623 int argi = 2; 624 int length = 1; 625 if (argc >= 3) { 626 if (strcmp(argv[argi], "clear") == 0) { 627 clear = true; 628 argi++; 629 } else if (strcmp(argv[argi], "rw") == 0) { 630 readWrite = true; 631 argi++; 632 } 633 634 if (!clear && argi < argc) 635 length = strtoul(argv[argi++], NULL, 0); 636 637 if (length == 0 || argi < argc) 638 return print_debugger_command_usage(argv[0]); 639 } 640 641 // set/clear breakpoint 642 643 arch_team_debug_info& info = team_get_kernel_team()->debug_info.arch_info; 644 645 status_t error; 646 647 if (clear) { 648 error = clear_breakpoint(info, (void*)address, true); 649 } else { 650 uint32 type = readWrite ? B_DATA_READ_WRITE_WATCHPOINT 651 : B_DATA_WRITE_WATCHPOINT; 652 653 size_t archType, archLength; 654 error = check_watch_point_parameters((void*)address, type, length, 655 archType, archLength); 656 657 if (error == B_OK) { 658 error = set_breakpoint(info, (void*)address, archType, archLength, 659 true); 660 } 661 } 662 663 if (error == B_OK) 664 call_all_cpus_sync(install_breakpoints_per_cpu, NULL); 665 else 666 kprintf("Failed to install breakpoint: %s\n", strerror(error)); 667 668 return 0; 669 } 670 671 672 static int 673 debugger_single_step(int argc, char** argv) 674 { 675 // TODO: Since we need an iframe, this doesn't work when KDL wasn't entered 676 // via an exception. 677 678 iframe* frame = x86_get_current_iframe(); 679 if (frame == NULL) { 680 kprintf("Failed to get the current iframe!\n"); 681 return 0; 682 } 683 684 frame->flags |= (1 << X86_EFLAGS_TF); 685 686 return B_KDEBUG_QUIT; 687 } 688 689 690 #endif // KERNEL_BREAKPOINTS 691 692 693 // #pragma mark - in-kernel public interface 694 695 696 void 697 arch_clear_team_debug_info(arch_team_debug_info* info) 698 { 699 for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) 700 info->breakpoints[i].address = NULL; 701 702 info->dr7 = X86_BREAKPOINTS_DISABLED_DR7; 703 } 704 705 706 void 707 arch_destroy_team_debug_info(arch_team_debug_info* info) 708 { 709 arch_clear_team_debug_info(info); 710 } 711 712 713 void 714 arch_clear_thread_debug_info(arch_thread_debug_info* info) 715 { 716 info->flags = 0; 717 } 718 719 720 void 721 arch_destroy_thread_debug_info(arch_thread_debug_info* info) 722 { 723 arch_clear_thread_debug_info(info); 724 } 725 726 727 void 728 arch_update_thread_single_step() 729 { 730 if (iframe* frame = x86_get_user_iframe()) { 731 Thread* thread = thread_get_current_thread(); 732 733 // set/clear TF in EFLAGS depending on whether single stepping is 734 // desired 735 if (thread->debug_info.flags & B_THREAD_DEBUG_SINGLE_STEP) 736 frame->flags |= (1 << X86_EFLAGS_TF); 737 else 738 frame->flags &= ~(1 << X86_EFLAGS_TF); 739 } 740 } 741 742 743 void 744 arch_set_debug_cpu_state(const debug_cpu_state* cpuState) 745 { 746 if (iframe* frame = x86_get_user_iframe()) { 747 // For the floating point state to be correct the calling function must 748 // not use these registers (not even indirectly). 749 #ifdef __x86_64__ 750 Thread* thread = thread_get_current_thread(); 751 memcpy(thread->arch_info.fpu_state, &cpuState->extended_registers, 752 sizeof(cpuState->extended_registers)); 753 frame->fpu = &thread->arch_info.fpu_state; 754 #else 755 if (gHasSSE) { 756 // Since fxrstor requires 16-byte alignment and this isn't 757 // guaranteed passed buffer, we use our thread's fpu_state field as 758 // temporary buffer. We need to disable interrupts to make use of 759 // it. 760 Thread* thread = thread_get_current_thread(); 761 InterruptsLocker locker; 762 memcpy(thread->arch_info.fpu_state, &cpuState->extended_registers, 763 sizeof(cpuState->extended_registers)); 764 x86_fxrstor(thread->arch_info.fpu_state); 765 } else { 766 // TODO: Implement! We need to convert the format first. 767 // x86_frstor(&cpuState->extended_registers); 768 } 769 #endif 770 set_iframe_registers(frame, cpuState); 771 } 772 } 773 774 775 void 776 arch_get_debug_cpu_state(debug_cpu_state* cpuState) 777 { 778 if (iframe* frame = x86_get_user_iframe()) 779 get_cpu_state(thread_get_current_thread(), frame, cpuState); 780 } 781 782 783 /*! \brief Retrieves the CPU state for the given thread. 784 The thread must not be running and the thread's scheduler spinlock must be 785 held. 786 \param thread The thread whose CPU state to retrieve. 787 \param cpuState Pointer to pre-allocated storage for the CPU state. 788 \return \c B_OK, if everything goes fine, another error code, if the CPU 789 state could not be retrieved. 790 */ 791 status_t 792 arch_get_thread_debug_cpu_state(Thread* thread, debug_cpu_state* cpuState) 793 { 794 iframe* frame = x86_get_thread_user_iframe(thread); 795 if (frame == NULL) 796 return B_BAD_VALUE; 797 798 get_cpu_state(thread, frame, cpuState); 799 return B_OK; 800 } 801 802 803 status_t 804 arch_set_breakpoint(void* address) 805 { 806 return set_breakpoint(address, X86_INSTRUCTION_BREAKPOINT, 807 X86_BREAKPOINT_LENGTH_1); 808 } 809 810 811 status_t 812 arch_clear_breakpoint(void* address) 813 { 814 return clear_breakpoint(address, false); 815 } 816 817 818 status_t 819 arch_set_watchpoint(void* address, uint32 type, int32 length) 820 { 821 size_t archType, archLength; 822 status_t error = check_watch_point_parameters(address, type, length, 823 archType, archLength); 824 if (error != B_OK) 825 return error; 826 827 return set_breakpoint(address, archType, archLength); 828 } 829 830 831 status_t 832 arch_clear_watchpoint(void* address) 833 { 834 return clear_breakpoint(address, true); 835 } 836 837 838 bool 839 arch_has_breakpoints(arch_team_debug_info* info) 840 { 841 // Reading info->dr7 is atomically, so we don't need to lock. The caller 842 // has to ensure, that the info doesn't go away. 843 return (info->dr7 != X86_BREAKPOINTS_DISABLED_DR7); 844 } 845 846 847 #if KERNEL_BREAKPOINTS 848 849 status_t 850 arch_set_kernel_breakpoint(void* address) 851 { 852 status_t error = set_kernel_breakpoint(address, X86_INSTRUCTION_BREAKPOINT, 853 X86_BREAKPOINT_LENGTH_1); 854 855 if (error != B_OK) { 856 panic("arch_set_kernel_breakpoint() failed to set breakpoint: %s", 857 strerror(error)); 858 } 859 860 return error; 861 } 862 863 864 status_t 865 arch_clear_kernel_breakpoint(void* address) 866 { 867 status_t error = clear_kernel_breakpoint(address, false); 868 869 if (error != B_OK) { 870 panic("arch_clear_kernel_breakpoint() failed to clear breakpoint: %s", 871 strerror(error)); 872 } 873 874 return error; 875 } 876 877 878 status_t 879 arch_set_kernel_watchpoint(void* address, uint32 type, int32 length) 880 { 881 size_t archType, archLength; 882 status_t error = check_watch_point_parameters(address, type, length, 883 archType, archLength); 884 885 if (error == B_OK) 886 error = set_kernel_breakpoint(address, archType, archLength); 887 888 if (error != B_OK) { 889 panic("arch_set_kernel_watchpoint() failed to set watchpoint: %s", 890 strerror(error)); 891 } 892 893 return error; 894 } 895 896 897 status_t 898 arch_clear_kernel_watchpoint(void* address) 899 { 900 status_t error = clear_kernel_breakpoint(address, true); 901 902 if (error != B_OK) { 903 panic("arch_clear_kernel_watchpoint() failed to clear watchpoint: %s", 904 strerror(error)); 905 } 906 907 return error; 908 } 909 910 #endif // KERNEL_BREAKPOINTS 911 912 913 // #pragma mark - x86 implementation interface 914 915 916 /** 917 * Interrupts are disabled. \a frame is unused, i.e. can be \c NULL. 918 */ 919 void 920 x86_init_user_debug_at_kernel_exit(iframe* frame) 921 { 922 Thread* thread = thread_get_current_thread(); 923 924 if (!(thread->flags & THREAD_FLAGS_BREAKPOINTS_DEFINED)) 925 return; 926 927 // disable kernel breakpoints 928 disable_breakpoints(); 929 930 // install the user breakpoints 931 GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info); 932 933 arch_team_debug_info &teamInfo = thread->team->debug_info.arch_info; 934 935 install_breakpoints(teamInfo); 936 937 atomic_or(&thread->flags, THREAD_FLAGS_BREAKPOINTS_INSTALLED); 938 939 RELEASE_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info); 940 } 941 942 943 /** 944 * Interrupts are disabled. 945 */ 946 void 947 x86_exit_user_debug_at_kernel_entry() 948 { 949 Thread* thread = thread_get_current_thread(); 950 951 // We need to save the current values of dr6 and dr7 in the CPU structure, 952 // since in case of a debug exception we might overwrite them before 953 // x86_handle_debug_exception() is called. Debug exceptions occur when 954 // hitting a hardware break/watchpoint or when single-stepping. 955 asm("mov %%dr6, %0" : "=r"(thread->cpu->arch.dr6)); 956 asm("mov %%dr7, %0" : "=r"(thread->cpu->arch.dr7)); 957 958 // The remainder needs only be done, when user breakpoints are installed. 959 if (!(thread->flags & THREAD_FLAGS_BREAKPOINTS_INSTALLED)) 960 return; 961 962 // disable user breakpoints 963 disable_breakpoints(); 964 965 // install kernel breakpoints 966 Team* kernelTeam = team_get_kernel_team(); 967 968 GRAB_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info); 969 970 install_breakpoints(kernelTeam->debug_info.arch_info); 971 972 atomic_and(&thread->flags, ~THREAD_FLAGS_BREAKPOINTS_INSTALLED); 973 974 RELEASE_TEAM_DEBUG_INFO_LOCK(kernelTeam->debug_info); 975 } 976 977 978 /** 979 * Interrupts are disabled and will possibly be enabled by the function. 980 */ 981 void 982 x86_handle_debug_exception(iframe* frame) 983 { 984 Thread* thread = thread_get_current_thread(); 985 986 // Get dr6 and dr7. If the given iframe is a userland frame, the exception 987 // obviously occurred in userland. In that case 988 // x86_exit_user_debug_at_kernel_entry() has already been invoked and dr6 989 // and dr7 are stored in the cpu info. Otherwise we need to fetch the 990 // current values from the registers. 991 size_t dr6; 992 size_t dr7; 993 if (IFRAME_IS_USER(frame)) { 994 dr6 = thread->cpu->arch.dr6; 995 dr7 = thread->cpu->arch.dr7; 996 } else { 997 asm("mov %%dr6, %0" : "=r"(dr6)); 998 asm("mov %%dr7, %0" : "=r"(dr7)); 999 } 1000 1001 TRACE(("x86_handle_debug_exception(): DR6: %lx, DR7: %lx\n", dr6, dr7)); 1002 1003 // check, which exception condition applies 1004 if (dr6 & X86_DR6_BREAKPOINT_MASK) { 1005 // breakpoint 1006 1007 // check which breakpoint was taken 1008 bool watchpoint = true; 1009 for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) { 1010 if (dr6 & (1 << sDR6B[i])) { 1011 size_t type = (dr7 >> sDR7RW[i]) & 0x3; 1012 if (type == X86_INSTRUCTION_BREAKPOINT) 1013 watchpoint = false; 1014 } 1015 } 1016 1017 if (IFRAME_IS_USER(frame)) { 1018 // enable interrupts and notify the debugger 1019 enable_interrupts(); 1020 1021 if (watchpoint) 1022 user_debug_watchpoint_hit(); 1023 else 1024 user_debug_breakpoint_hit(false); 1025 } else { 1026 panic("hit kernel %spoint: dr6: 0x%lx, dr7: 0x%lx", 1027 watchpoint ? "watch" : "break", dr6, dr7); 1028 } 1029 } else if (dr6 & (1 << X86_DR6_BD)) { 1030 // general detect exception 1031 // Occurs only, if GD in DR7 is set (which we don't do) and someone 1032 // tries to write to the debug registers. 1033 if (IFRAME_IS_USER(frame)) { 1034 dprintf("x86_handle_debug_exception(): ignoring spurious general " 1035 "detect exception\n"); 1036 1037 enable_interrupts(); 1038 } else 1039 panic("spurious general detect exception in kernel mode"); 1040 } else if ((dr6 & (1 << X86_DR6_BS)) || sQEmuSingleStepHack) { 1041 // single step 1042 1043 if (IFRAME_IS_USER(frame)) { 1044 // enable interrupts and notify the debugger 1045 enable_interrupts(); 1046 1047 user_debug_single_stepped(); 1048 } else { 1049 // Disable single-stepping -- the next "step" command will re-enable 1050 // it, but we don't want it when continuing otherwise. 1051 frame->flags &= ~(1 << X86_EFLAGS_TF); 1052 1053 // Determine whether the exception occurred at a syscall/trap 1054 // kernel entry or whether this is genuine kernel single-stepping. 1055 bool inKernel = true; 1056 if (thread->team != team_get_kernel_team() 1057 && x86_get_user_iframe() == NULL) { 1058 // TODO: This is not yet fully correct, since a newly created 1059 // thread that hasn't entered userland yet also has this 1060 // property. 1061 inKernel = false; 1062 } 1063 1064 if (inKernel) { 1065 panic("kernel single step"); 1066 } else { 1067 // The thread is a userland thread and it just entered the 1068 // kernel when the single-step exception occurred. This happens 1069 // e.g. when sysenter is called with single-stepping enabled. 1070 // We need to ignore the exception now and send a single-step 1071 // notification later, when the thread wants to return from the 1072 // kernel. 1073 InterruptsSpinLocker threadDebugInfoLocker( 1074 thread->debug_info.lock); 1075 1076 // Check whether the team is still being debugged and set 1077 // the B_THREAD_DEBUG_NOTIFY_SINGLE_STEP and 1078 // B_THREAD_DEBUG_STOP flags, so that the thread will be 1079 // stopped when it is going to leave the kernel and notify the 1080 // debugger about the single-step event. 1081 int32 teamDebugFlags 1082 = atomic_get(&thread->team->debug_info.flags); 1083 if (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) { 1084 atomic_or(&thread->debug_info.flags, 1085 B_THREAD_DEBUG_NOTIFY_SINGLE_STEP 1086 | B_THREAD_DEBUG_STOP); 1087 1088 // also set the respective thread flag 1089 atomic_or(&thread->flags, THREAD_FLAGS_DEBUG_THREAD); 1090 } 1091 } 1092 } 1093 } else if (dr6 & (1 << X86_DR6_BT)) { 1094 // task switch 1095 // Occurs only, if T in EFLAGS is set (which we don't do). 1096 if (IFRAME_IS_USER(frame)) { 1097 dprintf("x86_handle_debug_exception(): ignoring spurious task switch " 1098 "exception\n"); 1099 1100 enable_interrupts(); 1101 } else 1102 panic("spurious task switch exception in kernel mode"); 1103 } else { 1104 if (IFRAME_IS_USER(frame)) { 1105 TRACE(("x86_handle_debug_exception(): ignoring spurious debug " 1106 "exception (no condition recognized)\n")); 1107 1108 enable_interrupts(); 1109 } else { 1110 panic("spurious debug exception in kernel mode (no condition " 1111 "recognized)"); 1112 } 1113 } 1114 } 1115 1116 1117 /** 1118 * Interrupts are disabled and will possibly be enabled by the function. 1119 */ 1120 void 1121 x86_handle_breakpoint_exception(iframe* frame) 1122 { 1123 TRACE(("x86_handle_breakpoint_exception()\n")); 1124 1125 // reset eip to the int3 instruction 1126 frame->ip--; 1127 1128 if (!IFRAME_IS_USER(frame)) { 1129 panic("breakpoint exception in kernel mode"); 1130 return; 1131 } 1132 1133 enable_interrupts(); 1134 1135 user_debug_breakpoint_hit(true); 1136 } 1137 1138 1139 void 1140 x86_init_user_debug() 1141 { 1142 // get debug settings 1143 if (void* handle = load_driver_settings("kernel")) { 1144 sQEmuSingleStepHack = get_driver_boolean_parameter(handle, 1145 "qemu_single_step_hack", false, false);; 1146 1147 unload_driver_settings(handle); 1148 } 1149 1150 #if KERNEL_BREAKPOINTS 1151 // install debugger commands 1152 add_debugger_command_etc("breakpoints", &debugger_breakpoints, 1153 "Lists current break-/watchpoints", 1154 "\n" 1155 "Lists the current kernel break-/watchpoints.\n", 0); 1156 add_debugger_command_alias("watchpoints", "breakpoints", NULL); 1157 add_debugger_command_etc("breakpoint", &debugger_breakpoint, 1158 "Set/clears a breakpoint", 1159 "<address> [ clear ]\n" 1160 "Sets respectively clears the breakpoint at address <address>.\n", 0); 1161 add_debugger_command_etc("watchpoint", &debugger_watchpoint, 1162 "Set/clears a watchpoint", 1163 "<address> <address> ( [ rw ] [ <size> ] | clear )\n" 1164 "Sets respectively clears the watchpoint at address <address>.\n" 1165 "If \"rw\" is given the new watchpoint is a read/write watchpoint\n" 1166 "otherwise a write watchpoint only.\n", 0); 1167 add_debugger_command_etc("step", &debugger_single_step, 1168 "Single-steps to the next instruction", 1169 "\n" 1170 "Single-steps to the next instruction.\n", 0); 1171 #endif 1172 } 1173 1174