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