1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/kd64/kdapi.c 5 * PURPOSE: KD64 Public Routines and Internal Support 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 * Stefan Ginsberg (stefan.ginsberg@reactos.org) 8 */ 9 10 /* INCLUDES ******************************************************************/ 11 12 #include <ntoskrnl.h> 13 14 #ifdef KDBG 15 #include <kdbg/kdb.h> 16 #endif 17 18 #define NDEBUG 19 #include <debug.h> 20 21 VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads); 22 23 /* PRIVATE FUNCTIONS *********************************************************/ 24 25 VOID 26 NTAPI 27 KdpMoveMemory( 28 _In_ PVOID Destination, 29 _In_ PVOID Source, 30 _In_ SIZE_T Length) 31 { 32 PCHAR DestinationBytes, SourceBytes; 33 34 /* Copy the buffers 1 byte at a time */ 35 DestinationBytes = Destination; 36 SourceBytes = Source; 37 while (Length--) *DestinationBytes++ = *SourceBytes++; 38 } 39 40 VOID 41 NTAPI 42 KdpZeroMemory( 43 _In_ PVOID Destination, 44 _In_ SIZE_T Length) 45 { 46 PCHAR DestinationBytes; 47 48 /* Zero the buffer 1 byte at a time */ 49 DestinationBytes = Destination; 50 while (Length--) *DestinationBytes++ = 0; 51 } 52 53 NTSTATUS 54 NTAPI 55 KdpCopyMemoryChunks( 56 _In_ ULONG64 Address, 57 _In_ PVOID Buffer, 58 _In_ ULONG TotalSize, 59 _In_ ULONG ChunkSize, 60 _In_ ULONG Flags, 61 _Out_opt_ PULONG ActualSize) 62 { 63 NTSTATUS Status; 64 ULONG RemainingLength, CopyChunk; 65 66 /* Check if we didn't get a chunk size or if it is too big */ 67 if (ChunkSize == 0) 68 { 69 /* Default to 4 byte chunks */ 70 ChunkSize = 4; 71 } 72 else if (ChunkSize > MMDBG_COPY_MAX_SIZE) 73 { 74 /* Normalize to maximum size */ 75 ChunkSize = MMDBG_COPY_MAX_SIZE; 76 } 77 78 /* Copy the whole range in aligned chunks */ 79 RemainingLength = TotalSize; 80 CopyChunk = 1; 81 while (RemainingLength > 0) 82 { 83 /* 84 * Determine the best chunk size for this round. 85 * The ideal size is aligned, isn't larger than the 86 * the remaining length and respects the chunk limit. 87 */ 88 while (((CopyChunk * 2) <= RemainingLength) && 89 (CopyChunk < ChunkSize) && 90 ((Address & ((CopyChunk * 2) - 1)) == 0)) 91 { 92 /* Increase it */ 93 CopyChunk *= 2; 94 } 95 96 /* 97 * The chunk size can be larger than the remaining size if this 98 * isn't the first round, so check if we need to shrink it back. 99 */ 100 while (CopyChunk > RemainingLength) 101 { 102 /* Shrink it */ 103 CopyChunk /= 2; 104 } 105 106 /* Do the copy */ 107 Status = MmDbgCopyMemory(Address, Buffer, CopyChunk, Flags); 108 if (!NT_SUCCESS(Status)) 109 { 110 /* Copy failed, break out */ 111 break; 112 } 113 114 /* Update pointers and length for the next run */ 115 Address = Address + CopyChunk; 116 Buffer = (PVOID)((ULONG_PTR)Buffer + CopyChunk); 117 RemainingLength = RemainingLength - CopyChunk; 118 } 119 120 /* We may have modified executable code, flush the instruction cache */ 121 KeSweepICache((PVOID)(ULONG_PTR)Address, TotalSize); 122 123 /* 124 * Return the size we managed to copy and return 125 * success if we could copy the whole range. 126 */ 127 if (ActualSize) *ActualSize = TotalSize - RemainingLength; 128 return RemainingLength == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 129 } 130 131 VOID 132 NTAPI 133 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State, 134 IN PCONTEXT Context) 135 { 136 PDBGKD_QUERY_MEMORY Memory = &State->u.QueryMemory; 137 STRING Header; 138 NTSTATUS Status = STATUS_SUCCESS; 139 140 /* Validate the address space */ 141 if (Memory->AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL) 142 { 143 /* Check if this is process memory */ 144 if ((PVOID)(ULONG_PTR)Memory->Address < MmHighestUserAddress) 145 { 146 /* It is */ 147 Memory->AddressSpace = DBGKD_QUERY_MEMORY_PROCESS; 148 } 149 else 150 { 151 /* Check if it's session space */ 152 if (MmIsSessionAddress((PVOID)(ULONG_PTR)Memory->Address)) 153 { 154 /* It is */ 155 Memory->AddressSpace = DBGKD_QUERY_MEMORY_SESSION; 156 } 157 else 158 { 159 /* Not session space but some other kernel memory */ 160 Memory->AddressSpace = DBGKD_QUERY_MEMORY_KERNEL; 161 } 162 } 163 164 /* Set flags */ 165 Memory->Flags = DBGKD_QUERY_MEMORY_READ | 166 DBGKD_QUERY_MEMORY_WRITE | 167 DBGKD_QUERY_MEMORY_EXECUTE; 168 } 169 else 170 { 171 /* Invalid */ 172 Status = STATUS_INVALID_PARAMETER; 173 } 174 175 /* Return structure */ 176 State->ReturnStatus = Status; 177 Memory->Reserved = 0; 178 179 /* Build header */ 180 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 181 Header.Buffer = (PCHAR)State; 182 183 /* Send the packet */ 184 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 185 &Header, 186 NULL, 187 &KdpContext); 188 } 189 190 VOID 191 NTAPI 192 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State, 193 IN PSTRING Data, 194 IN PCONTEXT Context) 195 { 196 //PDBGKD_SEARCH_MEMORY SearchMemory = &State->u.SearchMemory; 197 STRING Header; 198 199 /* TODO */ 200 KdpDprintf("Memory Search support is unimplemented!\n"); 201 202 /* Send a failure packet */ 203 State->ReturnStatus = STATUS_UNSUCCESSFUL; 204 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 205 Header.Buffer = (PCHAR)State; 206 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 207 &Header, 208 NULL, 209 &KdpContext); 210 } 211 212 VOID 213 NTAPI 214 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State, 215 IN PSTRING Data, 216 IN PCONTEXT Context) 217 { 218 //PDBGKD_FILL_MEMORY FillMemory = &State->u.FillMemory; 219 STRING Header; 220 221 /* TODO */ 222 KdpDprintf("Memory Fill support is unimplemented!\n"); 223 224 /* Send a failure packet */ 225 State->ReturnStatus = STATUS_UNSUCCESSFUL; 226 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 227 Header.Buffer = (PCHAR)State; 228 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 229 &Header, 230 NULL, 231 &KdpContext); 232 } 233 234 VOID 235 NTAPI 236 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State, 237 IN PSTRING Data, 238 IN PCONTEXT Context) 239 { 240 PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint; 241 STRING Header; 242 243 /* Build header */ 244 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 245 Header.Buffer = (PCHAR)State; 246 ASSERT(Data->Length == 0); 247 248 /* Create the breakpoint */ 249 Breakpoint->BreakPointHandle = 250 KdpAddBreakpoint((PVOID)(ULONG_PTR)Breakpoint->BreakPointAddress); 251 if (!Breakpoint->BreakPointHandle) 252 { 253 /* We failed */ 254 State->ReturnStatus = STATUS_UNSUCCESSFUL; 255 } 256 else 257 { 258 /* Success! */ 259 State->ReturnStatus = STATUS_SUCCESS; 260 } 261 262 /* Send the packet */ 263 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 264 &Header, 265 NULL, 266 &KdpContext); 267 } 268 269 VOID 270 NTAPI 271 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State, 272 IN PSTRING Data, 273 IN PCONTEXT Context) 274 { 275 PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint; 276 STRING Header; 277 278 /* Fill out the header */ 279 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 280 Header.Buffer = (PCHAR)State; 281 ASSERT(Data->Length == 0); 282 283 /* Get the version block */ 284 if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle)) 285 { 286 /* We're all good */ 287 State->ReturnStatus = STATUS_SUCCESS; 288 } 289 else 290 { 291 /* We failed */ 292 State->ReturnStatus = STATUS_UNSUCCESSFUL; 293 } 294 295 /* Send the packet */ 296 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 297 &Header, 298 NULL, 299 &KdpContext); 300 } 301 302 NTSTATUS 303 NTAPI 304 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State, 305 IN PSTRING Data, 306 IN PCONTEXT Context) 307 { 308 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx; 309 STRING Header; 310 311 /* TODO */ 312 KdpDprintf("Extended Breakpoint Write support is unimplemented!\n"); 313 314 /* Send a failure packet */ 315 State->ReturnStatus = STATUS_UNSUCCESSFUL; 316 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 317 Header.Buffer = (PCHAR)State; 318 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 319 &Header, 320 Data, 321 &KdpContext); 322 return STATUS_UNSUCCESSFUL; 323 } 324 325 VOID 326 NTAPI 327 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State, 328 IN PSTRING Data, 329 IN PCONTEXT Context) 330 { 331 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx; 332 STRING Header; 333 334 /* TODO */ 335 KdpDprintf("Extended Breakpoint Restore support is unimplemented!\n"); 336 337 /* Send a failure packet */ 338 State->ReturnStatus = STATUS_UNSUCCESSFUL; 339 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 340 Header.Buffer = (PCHAR)State; 341 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 342 &Header, 343 Data, 344 &KdpContext); 345 } 346 347 VOID 348 NTAPI 349 KdpWriteCustomBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State, 350 IN PSTRING Data, 351 IN PCONTEXT Context) 352 { 353 //PDBGKD_WRITE_CUSTOM_BREAKPOINT = &State->u.WriteCustomBreakpoint; 354 STRING Header; 355 356 /* Not supported */ 357 KdpDprintf("Custom Breakpoint Write is unimplemented\n"); 358 359 /* Send a failure packet */ 360 State->ReturnStatus = STATUS_UNSUCCESSFUL; 361 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 362 Header.Buffer = (PCHAR)State; 363 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 364 &Header, 365 NULL, 366 &KdpContext); 367 } 368 369 VOID 370 NTAPI 371 DumpTraceData(IN PSTRING TraceData) 372 { 373 /* Update the buffer */ 374 TraceDataBuffer[0] = TraceDataBufferPosition; 375 376 /* Setup the trace data */ 377 TraceData->Length = (USHORT)(TraceDataBufferPosition * sizeof(ULONG)); 378 TraceData->Buffer = (PCHAR)TraceDataBuffer; 379 380 /* Reset the buffer location */ 381 TraceDataBufferPosition = 1; 382 } 383 384 VOID 385 NTAPI 386 KdpSetCommonState(IN ULONG NewState, 387 IN PCONTEXT Context, 388 IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange) 389 { 390 ULONG InstructionCount; 391 BOOLEAN HadBreakpoints; 392 393 /* Setup common stuff available for all CPU architectures */ 394 WaitStateChange->NewState = NewState; 395 WaitStateChange->ProcessorLevel = KeProcessorLevel; 396 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number; 397 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors; 398 WaitStateChange->Thread = (ULONG64)(LONG_PTR)KeGetCurrentThread(); 399 WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context); 400 401 /* Zero out the entire Control Report */ 402 KdpZeroMemory(&WaitStateChange->AnyControlReport, 403 sizeof(DBGKD_ANY_CONTROL_REPORT)); 404 405 /* Now copy the instruction stream and set the count */ 406 KdpCopyMemoryChunks((ULONG_PTR)WaitStateChange->ProgramCounter, 407 &WaitStateChange->ControlReport.InstructionStream[0], 408 DBGKD_MAXSTREAM, 409 0, 410 MMDBG_COPY_UNSAFE, 411 &InstructionCount); 412 WaitStateChange->ControlReport.InstructionCount = (USHORT)InstructionCount; 413 414 /* Clear all the breakpoints in this region */ 415 HadBreakpoints = 416 KdpDeleteBreakpointRange((PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter, 417 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter + 418 WaitStateChange->ControlReport.InstructionCount - 1)); 419 if (HadBreakpoints) 420 { 421 /* Copy the instruction stream again, this time without breakpoints */ 422 KdpCopyMemoryChunks((ULONG_PTR)WaitStateChange->ProgramCounter, 423 &WaitStateChange->ControlReport.InstructionStream[0], 424 InstructionCount, 425 0, 426 MMDBG_COPY_UNSAFE, 427 NULL); 428 } 429 } 430 431 VOID 432 NTAPI 433 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version) 434 { 435 /* Copy the version block */ 436 KdpMoveMemory(Version, 437 &KdVersionBlock, 438 sizeof(DBGKD_GET_VERSION64)); 439 } 440 441 VOID 442 NTAPI 443 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State) 444 { 445 STRING Header; 446 447 /* Fill out the header */ 448 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 449 Header.Buffer = (PCHAR)State; 450 451 /* Get the version block */ 452 KdpSysGetVersion(&State->u.GetVersion64); 453 454 /* Fill out the state */ 455 State->ApiNumber = DbgKdGetVersionApi; 456 State->ReturnStatus = STATUS_SUCCESS; 457 458 /* Send the packet */ 459 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 460 &Header, 461 NULL, 462 &KdpContext); 463 } 464 465 VOID 466 NTAPI 467 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State, 468 IN PSTRING Data, 469 IN PCONTEXT Context) 470 { 471 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory; 472 STRING Header; 473 ULONG Length = ReadMemory->TransferCount; 474 475 /* Setup the header */ 476 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 477 Header.Buffer = (PCHAR)State; 478 ASSERT(Data->Length == 0); 479 480 /* Validate length */ 481 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) 482 { 483 /* Overflow, set it to maximum possible */ 484 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64); 485 } 486 487 /* Do the read */ 488 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress, 489 Data->Buffer, 490 Length, 491 0, 492 MMDBG_COPY_UNSAFE, 493 &Length); 494 495 /* Return the actual length read */ 496 ReadMemory->ActualBytesRead = Length; 497 Data->Length = (USHORT)Length; 498 499 /* Send the packet */ 500 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 501 &Header, 502 Data, 503 &KdpContext); 504 } 505 506 VOID 507 NTAPI 508 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State, 509 IN PSTRING Data, 510 IN PCONTEXT Context) 511 { 512 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory; 513 STRING Header; 514 515 /* Setup the header */ 516 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 517 Header.Buffer = (PCHAR)State; 518 519 /* Do the write */ 520 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress, 521 Data->Buffer, 522 Data->Length, 523 0, 524 MMDBG_COPY_UNSAFE | 525 MMDBG_COPY_WRITE, 526 &WriteMemory->ActualBytesWritten); 527 528 /* Send the packet */ 529 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 530 &Header, 531 NULL, 532 &KdpContext); 533 } 534 535 VOID 536 NTAPI 537 KdpReadPhysicalMemory(IN PDBGKD_MANIPULATE_STATE64 State, 538 IN PSTRING Data, 539 IN PCONTEXT Context) 540 { 541 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory; 542 STRING Header; 543 ULONG Length = ReadMemory->TransferCount; 544 ULONG Flags, CacheFlags; 545 546 /* Setup the header */ 547 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 548 Header.Buffer = (PCHAR)State; 549 ASSERT(Data->Length == 0); 550 551 /* Validate length */ 552 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) 553 { 554 /* Overflow, set it to maximum possible */ 555 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64); 556 } 557 558 /* Start with the default flags */ 559 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_PHYSICAL; 560 561 /* Get the caching flags and check if a type is specified */ 562 CacheFlags = ReadMemory->ActualBytesRead; 563 if (CacheFlags == DBGKD_CACHING_CACHED) 564 { 565 /* Cached */ 566 Flags |= MMDBG_COPY_CACHED; 567 } 568 else if (CacheFlags == DBGKD_CACHING_UNCACHED) 569 { 570 /* Uncached */ 571 Flags |= MMDBG_COPY_UNCACHED; 572 } 573 else if (CacheFlags == DBGKD_CACHING_WRITE_COMBINED) 574 { 575 /* Write Combined */ 576 Flags |= MMDBG_COPY_WRITE_COMBINED; 577 } 578 579 /* Do the read */ 580 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress, 581 Data->Buffer, 582 Length, 583 0, 584 Flags, 585 &Length); 586 587 /* Return the actual length read */ 588 ReadMemory->ActualBytesRead = Length; 589 Data->Length = (USHORT)Length; 590 591 /* Send the packet */ 592 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 593 &Header, 594 Data, 595 &KdpContext); 596 } 597 598 VOID 599 NTAPI 600 KdpWritePhysicalMemory(IN PDBGKD_MANIPULATE_STATE64 State, 601 IN PSTRING Data, 602 IN PCONTEXT Context) 603 { 604 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory; 605 STRING Header; 606 ULONG Flags, CacheFlags; 607 608 /* Setup the header */ 609 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 610 Header.Buffer = (PCHAR)State; 611 612 /* Start with the default flags */ 613 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE | MMDBG_COPY_PHYSICAL; 614 615 /* Get the caching flags and check if a type is specified */ 616 CacheFlags = WriteMemory->ActualBytesWritten; 617 if (CacheFlags == DBGKD_CACHING_CACHED) 618 { 619 /* Cached */ 620 Flags |= MMDBG_COPY_CACHED; 621 } 622 else if (CacheFlags == DBGKD_CACHING_UNCACHED) 623 { 624 /* Uncached */ 625 Flags |= MMDBG_COPY_UNCACHED; 626 } 627 else if (CacheFlags == DBGKD_CACHING_WRITE_COMBINED) 628 { 629 /* Write Combined */ 630 Flags |= MMDBG_COPY_WRITE_COMBINED; 631 } 632 633 /* Do the write */ 634 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress, 635 Data->Buffer, 636 Data->Length, 637 0, 638 Flags, 639 &WriteMemory->ActualBytesWritten); 640 641 /* Send the packet */ 642 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 643 &Header, 644 NULL, 645 &KdpContext); 646 } 647 648 VOID 649 NTAPI 650 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State, 651 IN PSTRING Data, 652 IN PCONTEXT Context) 653 { 654 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory; 655 STRING Header; 656 ULONG Length; 657 658 /* Setup the header */ 659 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 660 Header.Buffer = (PCHAR)State; 661 ASSERT(Data->Length == 0); 662 663 /* Check the length requested */ 664 Length = ReadMemory->TransferCount; 665 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) 666 { 667 /* Use maximum allowed */ 668 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64); 669 } 670 671 /* Call the internal routine */ 672 State->ReturnStatus = KdpSysReadControlSpace(State->Processor, 673 ReadMemory->TargetBaseAddress, 674 Data->Buffer, 675 Length, 676 &Length); 677 678 /* Return the actual length read */ 679 ReadMemory->ActualBytesRead = Length; 680 Data->Length = (USHORT)Length; 681 682 /* Send the reply */ 683 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 684 &Header, 685 Data, 686 &KdpContext); 687 } 688 689 VOID 690 NTAPI 691 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State, 692 IN PSTRING Data, 693 IN PCONTEXT Context) 694 { 695 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory; 696 STRING Header; 697 698 /* Setup the header */ 699 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 700 Header.Buffer = (PCHAR)State; 701 702 /* Call the internal routine */ 703 State->ReturnStatus = KdpSysWriteControlSpace(State->Processor, 704 WriteMemory->TargetBaseAddress, 705 Data->Buffer, 706 Data->Length, 707 &WriteMemory->ActualBytesWritten); 708 709 /* Send the reply */ 710 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 711 &Header, 712 Data, 713 &KdpContext); 714 } 715 716 VOID 717 NTAPI 718 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State, 719 IN PSTRING Data, 720 IN PCONTEXT Context) 721 { 722 STRING Header; 723 PCONTEXT TargetContext; 724 725 /* Setup the header */ 726 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 727 Header.Buffer = (PCHAR)State; 728 ASSERT(Data->Length == 0); 729 730 /* Make sure that this is a valid request */ 731 if (State->Processor < KeNumberProcessors) 732 { 733 /* Check if the request is for this CPU */ 734 if (State->Processor == KeGetCurrentPrcb()->Number) 735 { 736 /* We're just copying our own context */ 737 TargetContext = Context; 738 } 739 else 740 { 741 /* Get the context from the PRCB array */ 742 TargetContext = &KiProcessorBlock[State->Processor]-> 743 ProcessorState.ContextFrame; 744 } 745 746 /* Copy it over to the debugger */ 747 KdpMoveMemory(Data->Buffer, 748 TargetContext, 749 sizeof(CONTEXT)); 750 Data->Length = sizeof(CONTEXT); 751 752 /* Let the debugger set the context now */ 753 KdpContextSent = TRUE; 754 755 /* Finish up */ 756 State->ReturnStatus = STATUS_SUCCESS; 757 } 758 else 759 { 760 /* Invalid request */ 761 State->ReturnStatus = STATUS_UNSUCCESSFUL; 762 } 763 764 /* Send the reply */ 765 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 766 &Header, 767 Data, 768 &KdpContext); 769 } 770 771 VOID 772 NTAPI 773 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State, 774 IN PSTRING Data, 775 IN PCONTEXT Context) 776 { 777 STRING Header; 778 PCONTEXT TargetContext; 779 780 /* Setup the header */ 781 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 782 Header.Buffer = (PCHAR)State; 783 ASSERT(Data->Length == sizeof(CONTEXT)); 784 785 /* Make sure that this is a valid request */ 786 if ((State->Processor < KeNumberProcessors) && 787 (KdpContextSent)) 788 { 789 /* Check if the request is for this CPU */ 790 if (State->Processor == KeGetCurrentPrcb()->Number) 791 { 792 /* We're just copying our own context */ 793 TargetContext = Context; 794 } 795 else 796 { 797 /* Get the context from the PRCB array */ 798 TargetContext = &KiProcessorBlock[State->Processor]-> 799 ProcessorState.ContextFrame; 800 } 801 802 /* Copy the new context to it */ 803 KdpMoveMemory(TargetContext, 804 Data->Buffer, 805 sizeof(CONTEXT)); 806 807 /* Finish up */ 808 State->ReturnStatus = STATUS_SUCCESS; 809 } 810 else 811 { 812 /* Invalid request */ 813 State->ReturnStatus = STATUS_UNSUCCESSFUL; 814 } 815 816 /* Send the reply */ 817 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 818 &Header, 819 NULL, 820 &KdpContext); 821 } 822 823 VOID 824 NTAPI 825 KdpGetContextEx(IN PDBGKD_MANIPULATE_STATE64 State, 826 IN PSTRING Data, 827 IN PCONTEXT Context) 828 { 829 STRING Header; 830 PDBGKD_CONTEXT_EX ContextEx; 831 PCONTEXT TargetContext; 832 ASSERT(Data->Length == 0); 833 834 /* Get our struct */ 835 ContextEx = &State->u.ContextEx; 836 837 /* Set up the header */ 838 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 839 Header.Buffer = (PCHAR)State; 840 841 /* Make sure that this is a valid request */ 842 if ((State->Processor < KeNumberProcessors) && 843 (ContextEx->Offset + ContextEx->ByteCount) <= sizeof(CONTEXT)) 844 { 845 /* Check if the request is for this CPU */ 846 if (State->Processor == KeGetCurrentPrcb()->Number) 847 { 848 /* We're just copying our own context */ 849 TargetContext = Context; 850 } 851 else 852 { 853 /* Get the context from the PRCB array */ 854 TargetContext = &KiProcessorBlock[State->Processor]-> 855 ProcessorState.ContextFrame; 856 } 857 858 /* Copy what is requested */ 859 KdpMoveMemory(Data->Buffer, 860 (PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset), 861 ContextEx->ByteCount); 862 863 /* KD copies all */ 864 Data->Length = ContextEx->BytesCopied = ContextEx->ByteCount; 865 866 /* Let the debugger set the context now */ 867 KdpContextSent = TRUE; 868 869 /* Finish up */ 870 State->ReturnStatus = STATUS_SUCCESS; 871 } 872 else 873 { 874 /* Invalid request */ 875 ContextEx->BytesCopied = 0; 876 State->ReturnStatus = STATUS_UNSUCCESSFUL; 877 } 878 879 /* Send the reply */ 880 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 881 &Header, 882 Data, 883 &KdpContext); 884 } 885 886 VOID 887 NTAPI 888 KdpSetContextEx(IN PDBGKD_MANIPULATE_STATE64 State, 889 IN PSTRING Data, 890 IN PCONTEXT Context) 891 { 892 STRING Header; 893 PDBGKD_CONTEXT_EX ContextEx; 894 PCONTEXT TargetContext; 895 896 /* Get our struct */ 897 ContextEx = &State->u.ContextEx; 898 ASSERT(Data->Length == ContextEx->ByteCount); 899 900 /* Set up the header */ 901 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 902 Header.Buffer = (PCHAR)State; 903 904 /* Make sure that this is a valid request */ 905 if ((State->Processor < KeNumberProcessors) && 906 ((ContextEx->Offset + ContextEx->ByteCount) <= sizeof(CONTEXT)) && 907 (KdpContextSent)) 908 { 909 /* Check if the request is for this CPU */ 910 if (State->Processor == KeGetCurrentPrcb()->Number) 911 { 912 /* We're just copying our own context */ 913 TargetContext = Context; 914 } 915 else 916 { 917 /* Get the context from the PRCB array */ 918 TargetContext = &KiProcessorBlock[State->Processor]-> 919 ProcessorState.ContextFrame; 920 } 921 922 /* Copy what is requested */ 923 KdpMoveMemory((PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset), 924 Data->Buffer, 925 ContextEx->ByteCount); 926 927 /* KD copies all */ 928 ContextEx->BytesCopied = ContextEx->ByteCount; 929 930 /* Finish up */ 931 State->ReturnStatus = STATUS_SUCCESS; 932 } 933 else 934 { 935 /* Invalid request */ 936 ContextEx->BytesCopied = 0; 937 State->ReturnStatus = STATUS_UNSUCCESSFUL; 938 } 939 940 /* Send the reply */ 941 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 942 &Header, 943 NULL, 944 &KdpContext); 945 } 946 947 VOID 948 NTAPI 949 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State) 950 { 951 /* Crash with the special code */ 952 KeBugCheck(MANUALLY_INITIATED_CRASH); 953 } 954 955 VOID 956 NTAPI 957 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State, 958 IN PSTRING Data, 959 IN PCONTEXT Context) 960 { 961 STRING Header; 962 PDBGKD_READ_WRITE_MSR ReadMsr = &State->u.ReadWriteMsr; 963 LARGE_INTEGER MsrValue; 964 965 /* Setup the header */ 966 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 967 Header.Buffer = (PCHAR)State; 968 ASSERT(Data->Length == 0); 969 970 /* Call the internal routine */ 971 State->ReturnStatus = KdpSysReadMsr(ReadMsr->Msr, 972 &MsrValue); 973 974 /* Return the data */ 975 ReadMsr->DataValueLow = MsrValue.LowPart; 976 ReadMsr->DataValueHigh = MsrValue.HighPart; 977 978 /* Send the reply */ 979 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 980 &Header, 981 NULL, 982 &KdpContext); 983 } 984 985 VOID 986 NTAPI 987 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State, 988 IN PSTRING Data, 989 IN PCONTEXT Context) 990 { 991 STRING Header; 992 PDBGKD_READ_WRITE_MSR WriteMsr = &State->u.ReadWriteMsr; 993 LARGE_INTEGER MsrValue; 994 995 /* Setup the header */ 996 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 997 Header.Buffer = (PCHAR)State; 998 ASSERT(Data->Length == 0); 999 1000 /* Call the internal routine */ 1001 MsrValue.LowPart = WriteMsr->DataValueLow; 1002 MsrValue.HighPart = WriteMsr->DataValueHigh; 1003 State->ReturnStatus = KdpSysWriteMsr(WriteMsr->Msr, 1004 &MsrValue); 1005 1006 /* Send the reply */ 1007 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1008 &Header, 1009 NULL, 1010 &KdpContext); 1011 } 1012 1013 VOID 1014 NTAPI 1015 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State, 1016 IN PSTRING Data, 1017 IN PCONTEXT Context) 1018 { 1019 STRING Header; 1020 PDBGKD_GET_SET_BUS_DATA GetBusData = &State->u.GetSetBusData; 1021 ULONG Length; 1022 1023 /* Setup the header */ 1024 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 1025 Header.Buffer = (PCHAR)State; 1026 ASSERT(Data->Length == 0); 1027 1028 /* Check the length requested */ 1029 Length = GetBusData->Length; 1030 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) 1031 { 1032 /* Use maximum allowed */ 1033 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64); 1034 } 1035 1036 /* Call the internal routine */ 1037 State->ReturnStatus = KdpSysReadBusData(GetBusData->BusDataType, 1038 GetBusData->BusNumber, 1039 GetBusData->SlotNumber, 1040 GetBusData->Offset, 1041 Data->Buffer, 1042 Length, 1043 &Length); 1044 1045 /* Return the actual length read */ 1046 GetBusData->Length = Length; 1047 Data->Length = (USHORT)Length; 1048 1049 /* Send the reply */ 1050 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1051 &Header, 1052 Data, 1053 &KdpContext); 1054 } 1055 1056 VOID 1057 NTAPI 1058 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State, 1059 IN PSTRING Data, 1060 IN PCONTEXT Context) 1061 { 1062 STRING Header; 1063 PDBGKD_GET_SET_BUS_DATA SetBusData = &State->u.GetSetBusData; 1064 ULONG Length; 1065 1066 /* Setup the header */ 1067 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 1068 Header.Buffer = (PCHAR)State; 1069 1070 /* Call the internal routine */ 1071 State->ReturnStatus = KdpSysWriteBusData(SetBusData->BusDataType, 1072 SetBusData->BusNumber, 1073 SetBusData->SlotNumber, 1074 SetBusData->Offset, 1075 Data->Buffer, 1076 SetBusData->Length, 1077 &Length); 1078 1079 /* Return the actual length written */ 1080 SetBusData->Length = Length; 1081 1082 /* Send the reply */ 1083 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1084 &Header, 1085 NULL, 1086 &KdpContext); 1087 } 1088 1089 VOID 1090 NTAPI 1091 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State, 1092 IN PSTRING Data, 1093 IN PCONTEXT Context) 1094 { 1095 STRING Header; 1096 PDBGKD_READ_WRITE_IO64 ReadIo = &State->u.ReadWriteIo; 1097 1098 /* Setup the header */ 1099 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 1100 Header.Buffer = (PCHAR)State; 1101 ASSERT(Data->Length == 0); 1102 1103 /* 1104 * Clear the value so 1 or 2 byte reads 1105 * don't leave the higher bits unmodified 1106 */ 1107 ReadIo->DataValue = 0; 1108 1109 /* Call the internal routine */ 1110 State->ReturnStatus = KdpSysReadIoSpace(Isa, 1111 0, 1112 1, 1113 ReadIo->IoAddress, 1114 &ReadIo->DataValue, 1115 ReadIo->DataSize, 1116 &ReadIo->DataSize); 1117 1118 /* Send the reply */ 1119 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1120 &Header, 1121 NULL, 1122 &KdpContext); 1123 } 1124 1125 VOID 1126 NTAPI 1127 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State, 1128 IN PSTRING Data, 1129 IN PCONTEXT Context) 1130 { 1131 STRING Header; 1132 PDBGKD_READ_WRITE_IO64 WriteIo = &State->u.ReadWriteIo; 1133 1134 /* Setup the header */ 1135 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 1136 Header.Buffer = (PCHAR)State; 1137 ASSERT(Data->Length == 0); 1138 1139 /* Call the internal routine */ 1140 State->ReturnStatus = KdpSysWriteIoSpace(Isa, 1141 0, 1142 1, 1143 WriteIo->IoAddress, 1144 &WriteIo->DataValue, 1145 WriteIo->DataSize, 1146 &WriteIo->DataSize); 1147 1148 /* Send the reply */ 1149 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1150 &Header, 1151 NULL, 1152 &KdpContext); 1153 } 1154 1155 VOID 1156 NTAPI 1157 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State, 1158 IN PSTRING Data, 1159 IN PCONTEXT Context) 1160 { 1161 STRING Header; 1162 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended = &State->u. 1163 ReadWriteIoExtended; 1164 1165 /* Setup the header */ 1166 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 1167 Header.Buffer = (PCHAR)State; 1168 ASSERT(Data->Length == 0); 1169 1170 /* 1171 * Clear the value so 1 or 2 byte reads 1172 * don't leave the higher bits unmodified 1173 */ 1174 ReadIoExtended->DataValue = 0; 1175 1176 /* Call the internal routine */ 1177 State->ReturnStatus = KdpSysReadIoSpace(ReadIoExtended->InterfaceType, 1178 ReadIoExtended->BusNumber, 1179 ReadIoExtended->AddressSpace, 1180 ReadIoExtended->IoAddress, 1181 &ReadIoExtended->DataValue, 1182 ReadIoExtended->DataSize, 1183 &ReadIoExtended->DataSize); 1184 1185 /* Send the reply */ 1186 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1187 &Header, 1188 NULL, 1189 &KdpContext); 1190 } 1191 1192 VOID 1193 NTAPI 1194 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State, 1195 IN PSTRING Data, 1196 IN PCONTEXT Context) 1197 { 1198 STRING Header; 1199 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended = &State->u. 1200 ReadWriteIoExtended; 1201 1202 /* Setup the header */ 1203 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 1204 Header.Buffer = (PCHAR)State; 1205 ASSERT(Data->Length == 0); 1206 1207 /* Call the internal routine */ 1208 State->ReturnStatus = KdpSysWriteIoSpace(WriteIoExtended->InterfaceType, 1209 WriteIoExtended->BusNumber, 1210 WriteIoExtended->AddressSpace, 1211 WriteIoExtended->IoAddress, 1212 &WriteIoExtended->DataValue, 1213 WriteIoExtended->DataSize, 1214 &WriteIoExtended->DataSize); 1215 1216 /* Send the reply */ 1217 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1218 &Header, 1219 NULL, 1220 &KdpContext); 1221 } 1222 1223 VOID 1224 NTAPI 1225 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State) 1226 { 1227 STRING Header; 1228 1229 /* Setup the header */ 1230 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 1231 Header.Buffer = (PCHAR)State; 1232 1233 /* Call the internal routine */ 1234 State->ReturnStatus = KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE); 1235 1236 /* Send the reply */ 1237 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1238 &Header, 1239 NULL, 1240 &KdpContext); 1241 } 1242 1243 VOID 1244 NTAPI 1245 KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State) 1246 { 1247 STRING Header; 1248 1249 /* Set failure */ 1250 State->ReturnStatus = STATUS_UNSUCCESSFUL; 1251 1252 /* Setup the packet */ 1253 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 1254 Header.Buffer = (PCHAR)State; 1255 1256 /* Send it */ 1257 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1258 &Header, 1259 NULL, 1260 &KdpContext); 1261 } 1262 1263 static 1264 KCONTINUE_STATUS 1265 KdpSwitchProcessor( 1266 _In_ USHORT ProcessorIndex) 1267 { 1268 /* Make sure that the processor index is valid */ 1269 if (ProcessorIndex >= KeNumberProcessors) 1270 { 1271 KdpDprintf("%u is not a valid processor number\n", ProcessorIndex); 1272 return ContinueProcessorReselected; 1273 } 1274 1275 /* If the new processor is the current one, there is nothing to do */ 1276 if (ProcessorIndex == KeGetCurrentProcessorNumber()) 1277 { 1278 return ContinueProcessorReselected; 1279 } 1280 1281 /* Call the architecture specific Ke routine */ 1282 return KxSwitchKdProcessor(ProcessorIndex); 1283 } 1284 1285 KCONTINUE_STATUS 1286 NTAPI 1287 KdpSendWaitContinue(IN ULONG PacketType, 1288 IN PSTRING SendHeader, 1289 IN PSTRING SendData OPTIONAL, 1290 IN OUT PCONTEXT Context) 1291 { 1292 STRING Data, Header; 1293 DBGKD_MANIPULATE_STATE64 ManipulateState; 1294 ULONG Length; 1295 KDSTATUS RecvCode; 1296 1297 /* Setup the Manipulate State structure */ 1298 Header.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64); 1299 Header.Buffer = (PCHAR)&ManipulateState; 1300 Data.MaximumLength = sizeof(KdpMessageBuffer); 1301 Data.Buffer = KdpMessageBuffer; 1302 1303 /* 1304 * Reset the context state to ensure the debugger has received 1305 * the current context before it sets it. 1306 */ 1307 KdpContextSent = FALSE; 1308 1309 SendPacket: 1310 /* Send the Packet */ 1311 KdSendPacket(PacketType, SendHeader, SendData, &KdpContext); 1312 1313 /* If the debugger isn't present anymore, just return success */ 1314 if (KdDebuggerNotPresent) return ContinueSuccess; 1315 1316 /* Main processing Loop */ 1317 for (;;) 1318 { 1319 /* Receive Loop */ 1320 do 1321 { 1322 /* Wait to get a reply to our packet */ 1323 RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1324 &Header, 1325 &Data, 1326 &Length, 1327 &KdpContext); 1328 1329 /* If we got a resend request, do it */ 1330 if (RecvCode == KdPacketNeedsResend) goto SendPacket; 1331 } while (RecvCode == KdPacketTimedOut); 1332 1333 /* Now check what API we got */ 1334 switch (ManipulateState.ApiNumber) 1335 { 1336 case DbgKdReadVirtualMemoryApi: 1337 1338 /* Read virtual memory */ 1339 KdpReadVirtualMemory(&ManipulateState, &Data, Context); 1340 break; 1341 1342 case DbgKdWriteVirtualMemoryApi: 1343 1344 /* Write virtual memory */ 1345 KdpWriteVirtualMemory(&ManipulateState, &Data, Context); 1346 break; 1347 1348 case DbgKdGetContextApi: 1349 1350 /* Get the current context */ 1351 KdpGetContext(&ManipulateState, &Data, Context); 1352 break; 1353 1354 case DbgKdSetContextApi: 1355 1356 /* Set a new context */ 1357 KdpSetContext(&ManipulateState, &Data, Context); 1358 break; 1359 1360 case DbgKdWriteBreakPointApi: 1361 1362 /* Write the breakpoint */ 1363 KdpWriteBreakpoint(&ManipulateState, &Data, Context); 1364 break; 1365 1366 case DbgKdRestoreBreakPointApi: 1367 1368 /* Restore the breakpoint */ 1369 KdpRestoreBreakpoint(&ManipulateState, &Data, Context); 1370 break; 1371 1372 case DbgKdContinueApi: 1373 1374 /* Simply continue */ 1375 return NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus); 1376 1377 case DbgKdReadControlSpaceApi: 1378 1379 /* Read control space */ 1380 KdpReadControlSpace(&ManipulateState, &Data, Context); 1381 break; 1382 1383 case DbgKdWriteControlSpaceApi: 1384 1385 /* Write control space */ 1386 KdpWriteControlSpace(&ManipulateState, &Data, Context); 1387 break; 1388 1389 case DbgKdReadIoSpaceApi: 1390 1391 /* Read I/O Space */ 1392 KdpReadIoSpace(&ManipulateState, &Data, Context); 1393 break; 1394 1395 case DbgKdWriteIoSpaceApi: 1396 1397 /* Write I/O Space */ 1398 KdpWriteIoSpace(&ManipulateState, &Data, Context); 1399 break; 1400 1401 case DbgKdRebootApi: 1402 1403 /* Reboot the system */ 1404 HalReturnToFirmware(HalRebootRoutine); 1405 break; 1406 1407 case DbgKdContinueApi2: 1408 1409 /* Check if caller reports success */ 1410 if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus)) 1411 { 1412 /* Update the state */ 1413 KdpGetStateChange(&ManipulateState, Context); 1414 return ContinueSuccess; 1415 } 1416 else 1417 { 1418 /* Return an error */ 1419 return ContinueError; 1420 } 1421 1422 case DbgKdReadPhysicalMemoryApi: 1423 1424 /* Read physical memory */ 1425 KdpReadPhysicalMemory(&ManipulateState, &Data, Context); 1426 break; 1427 1428 case DbgKdWritePhysicalMemoryApi: 1429 1430 /* Write physical memory */ 1431 KdpWritePhysicalMemory(&ManipulateState, &Data, Context); 1432 break; 1433 1434 case DbgKdQuerySpecialCallsApi: 1435 case DbgKdSetSpecialCallApi: 1436 case DbgKdClearSpecialCallsApi: 1437 1438 /* TODO */ 1439 KdpDprintf("Special Call support is unimplemented!\n"); 1440 KdpNotSupported(&ManipulateState); 1441 break; 1442 1443 case DbgKdSetInternalBreakPointApi: 1444 case DbgKdGetInternalBreakPointApi: 1445 1446 /* TODO */ 1447 KdpDprintf("Internal Breakpoint support is unimplemented!\n"); 1448 KdpNotSupported(&ManipulateState); 1449 break; 1450 1451 case DbgKdReadIoSpaceExtendedApi: 1452 1453 /* Read I/O Space */ 1454 KdpReadIoSpaceExtended(&ManipulateState, &Data, Context); 1455 break; 1456 1457 case DbgKdWriteIoSpaceExtendedApi: 1458 1459 /* Write I/O Space */ 1460 KdpWriteIoSpaceExtended(&ManipulateState, &Data, Context); 1461 break; 1462 1463 case DbgKdGetVersionApi: 1464 1465 /* Get version data */ 1466 KdpGetVersion(&ManipulateState); 1467 break; 1468 1469 case DbgKdWriteBreakPointExApi: 1470 1471 /* Write the breakpoint and check if it failed */ 1472 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState, 1473 &Data, 1474 Context))) 1475 { 1476 /* Return an error */ 1477 return ContinueError; 1478 } 1479 break; 1480 1481 case DbgKdRestoreBreakPointExApi: 1482 1483 /* Restore the breakpoint */ 1484 KdpRestoreBreakPointEx(&ManipulateState, &Data, Context); 1485 break; 1486 1487 case DbgKdCauseBugCheckApi: 1488 1489 /* Crash the system */ 1490 KdpCauseBugCheck(&ManipulateState); 1491 break; 1492 1493 case DbgKdSwitchProcessor: 1494 1495 /* Switch the processor and return */ 1496 return KdpSwitchProcessor(ManipulateState.Processor); 1497 1498 case DbgKdPageInApi: 1499 1500 /* This API, introduced in NT4, has been obsoleted in NT5. It is 1501 * replaced by ExpDebuggerPageIn support in ExpDebuggerWorker(). */ 1502 KdpDprintf("DbgKdPageInApi is obsolete!\n"); 1503 KdpNotSupported(&ManipulateState); 1504 break; 1505 1506 case DbgKdReadMachineSpecificRegister: 1507 1508 /* Read from the specified MSR */ 1509 KdpReadMachineSpecificRegister(&ManipulateState, &Data, Context); 1510 break; 1511 1512 case DbgKdWriteMachineSpecificRegister: 1513 1514 /* Write to the specified MSR */ 1515 KdpWriteMachineSpecificRegister(&ManipulateState, &Data, Context); 1516 break; 1517 1518 case DbgKdSearchMemoryApi: 1519 1520 /* Search memory */ 1521 KdpSearchMemory(&ManipulateState, &Data, Context); 1522 break; 1523 1524 case DbgKdGetBusDataApi: 1525 1526 /* Read from the bus */ 1527 KdpGetBusData(&ManipulateState, &Data, Context); 1528 break; 1529 1530 case DbgKdSetBusDataApi: 1531 1532 /* Write to the bus */ 1533 KdpSetBusData(&ManipulateState, &Data, Context); 1534 break; 1535 1536 case DbgKdCheckLowMemoryApi: 1537 1538 /* Check for memory corruption in the lower 4 GB */ 1539 KdpCheckLowMemory(&ManipulateState); 1540 break; 1541 1542 case DbgKdClearAllInternalBreakpointsApi: 1543 1544 /* Just clear the counter */ 1545 KdpNumInternalBreakpoints = 0; 1546 break; 1547 1548 case DbgKdFillMemoryApi: 1549 1550 /* Fill memory */ 1551 KdpFillMemory(&ManipulateState, &Data, Context); 1552 break; 1553 1554 case DbgKdQueryMemoryApi: 1555 1556 /* Query memory */ 1557 KdpQueryMemory(&ManipulateState, Context); 1558 break; 1559 1560 case DbgKdSwitchPartition: 1561 1562 /* TODO */ 1563 KdpDprintf("Partition Switch support is unimplemented!\n"); 1564 KdpNotSupported(&ManipulateState); 1565 break; 1566 1567 case DbgKdWriteCustomBreakpointApi: 1568 1569 /* Write the customized breakpoint */ 1570 KdpWriteCustomBreakpoint(&ManipulateState, &Data, Context); 1571 break; 1572 1573 case DbgKdGetContextExApi: 1574 1575 /* Extended Context Get */ 1576 KdpGetContextEx(&ManipulateState, &Data, Context); 1577 break; 1578 1579 case DbgKdSetContextExApi: 1580 1581 /* Extended Context Set */ 1582 KdpSetContextEx(&ManipulateState, &Data, Context); 1583 break; 1584 1585 /* Unsupported Messages */ 1586 default: 1587 1588 /* Send warning */ 1589 KdpDprintf("Received Unrecognized API 0x%lx\n", ManipulateState.ApiNumber); 1590 1591 /* Setup an empty message, with failure */ 1592 Data.Length = 0; 1593 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL; 1594 1595 /* Send it */ 1596 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1597 &Header, 1598 &Data, 1599 &KdpContext); 1600 break; 1601 } 1602 } 1603 } 1604 1605 VOID 1606 NTAPI 1607 KdpReportLoadSymbolsStateChange(IN PSTRING PathName, 1608 IN PKD_SYMBOLS_INFO SymbolInfo, 1609 IN BOOLEAN Unload, 1610 IN OUT PCONTEXT Context) 1611 { 1612 PSTRING ExtraData; 1613 STRING Data, Header; 1614 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange; 1615 ULONG PathNameLength; 1616 KCONTINUE_STATUS Status; 1617 1618 /* Start wait loop */ 1619 do 1620 { 1621 /* Build the architecture common parts of the message */ 1622 KdpSetCommonState(DbgKdLoadSymbolsStateChange, 1623 Context, 1624 &WaitStateChange); 1625 1626 /* Now finish creating the structure */ 1627 KdpSetContextState(&WaitStateChange, Context); 1628 1629 /* Fill out load data */ 1630 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload; 1631 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)(LONG_PTR)SymbolInfo->BaseOfDll; 1632 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId; 1633 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum; 1634 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage; 1635 1636 /* Check if we have a path name */ 1637 if (PathName) 1638 { 1639 /* Copy it to the path buffer */ 1640 KdpCopyMemoryChunks((ULONG_PTR)PathName->Buffer, 1641 KdpPathBuffer, 1642 PathName->Length, 1643 0, 1644 MMDBG_COPY_UNSAFE, 1645 &PathNameLength); 1646 1647 /* Null terminate */ 1648 KdpPathBuffer[PathNameLength++] = ANSI_NULL; 1649 1650 /* Set the path length */ 1651 WaitStateChange.u.LoadSymbols.PathNameLength = PathNameLength; 1652 1653 /* Set up the data */ 1654 Data.Buffer = KdpPathBuffer; 1655 Data.Length = (USHORT)PathNameLength; 1656 ExtraData = &Data; 1657 } 1658 else 1659 { 1660 /* No name */ 1661 WaitStateChange.u.LoadSymbols.PathNameLength = 0; 1662 ExtraData = NULL; 1663 } 1664 1665 /* Setup the header */ 1666 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE); 1667 Header.Buffer = (PCHAR)&WaitStateChange; 1668 1669 /* Send the packet */ 1670 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64, 1671 &Header, 1672 ExtraData, 1673 Context); 1674 } while (Status == ContinueProcessorReselected); 1675 } 1676 1677 VOID 1678 NTAPI 1679 KdpReportCommandStringStateChange(IN PSTRING NameString, 1680 IN PSTRING CommandString, 1681 IN OUT PCONTEXT Context) 1682 { 1683 STRING Header, Data; 1684 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange; 1685 ULONG Length, ActualLength, TotalLength; 1686 KCONTINUE_STATUS Status; 1687 1688 /* Start wait loop */ 1689 do 1690 { 1691 /* Build the architecture common parts of the message */ 1692 KdpSetCommonState(DbgKdCommandStringStateChange, 1693 Context, 1694 &WaitStateChange); 1695 1696 /* Set the context */ 1697 KdpSetContextState(&WaitStateChange, Context); 1698 1699 /* Clear the command string structure */ 1700 KdpZeroMemory(&WaitStateChange.u.CommandString, 1701 sizeof(DBGKD_COMMAND_STRING)); 1702 1703 /* Normalize name string to max */ 1704 Length = min(128 - 1, NameString->Length); 1705 1706 /* Copy it to the message buffer */ 1707 KdpCopyMemoryChunks((ULONG_PTR)NameString->Buffer, 1708 KdpMessageBuffer, 1709 Length, 1710 0, 1711 MMDBG_COPY_UNSAFE, 1712 &ActualLength); 1713 1714 /* Null terminate and calculate the total length */ 1715 TotalLength = ActualLength; 1716 KdpMessageBuffer[TotalLength++] = ANSI_NULL; 1717 1718 /* Check if the command string is too long */ 1719 Length = CommandString->Length; 1720 if (Length > (PACKET_MAX_SIZE - 1721 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength)) 1722 { 1723 /* Use maximum possible size */ 1724 Length = (PACKET_MAX_SIZE - 1725 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength); 1726 } 1727 1728 /* Copy it to the message buffer */ 1729 KdpCopyMemoryChunks((ULONG_PTR)CommandString->Buffer, 1730 KdpMessageBuffer + TotalLength, 1731 Length, 1732 0, 1733 MMDBG_COPY_UNSAFE, 1734 &ActualLength); 1735 1736 /* Null terminate and calculate the total length */ 1737 TotalLength += ActualLength; 1738 KdpMessageBuffer[TotalLength++] = ANSI_NULL; 1739 1740 /* Now set up the header and the data */ 1741 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE); 1742 Header.Buffer = (PCHAR)&WaitStateChange; 1743 Data.Length = (USHORT)TotalLength; 1744 Data.Buffer = KdpMessageBuffer; 1745 1746 /* Send State Change packet and wait for a reply */ 1747 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64, 1748 &Header, 1749 &Data, 1750 Context); 1751 } while (Status == ContinueProcessorReselected); 1752 } 1753 1754 BOOLEAN 1755 NTAPI 1756 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord, 1757 IN OUT PCONTEXT Context, 1758 IN BOOLEAN SecondChanceException) 1759 { 1760 STRING Header, Data; 1761 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange; 1762 KCONTINUE_STATUS Status; 1763 1764 /* Start report loop */ 1765 do 1766 { 1767 /* Build the architecture common parts of the message */ 1768 KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange); 1769 1770 #if !defined(_WIN64) 1771 1772 /* Convert it and copy it over */ 1773 ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord, 1774 &WaitStateChange.u.Exception.ExceptionRecord); 1775 1776 #else 1777 1778 /* Just copy it directly, no need to convert */ 1779 KdpMoveMemory(&WaitStateChange.u.Exception.ExceptionRecord, 1780 ExceptionRecord, 1781 sizeof(EXCEPTION_RECORD)); 1782 1783 #endif 1784 1785 /* Set the First Chance flag */ 1786 WaitStateChange.u.Exception.FirstChance = !SecondChanceException; 1787 1788 /* Now finish creating the structure */ 1789 KdpSetContextState(&WaitStateChange, Context); 1790 1791 /* Setup the actual header to send to KD */ 1792 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE); 1793 Header.Buffer = (PCHAR)&WaitStateChange; 1794 1795 /* Setup the trace data */ 1796 DumpTraceData(&Data); 1797 1798 /* Send State Change packet and wait for a reply */ 1799 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64, 1800 &Header, 1801 &Data, 1802 Context); 1803 } while (Status == ContinueProcessorReselected); 1804 1805 /* Return */ 1806 return Status; 1807 } 1808 1809 KCONTINUE_STATUS 1810 NTAPI 1811 KdReportProcessorChange( 1812 VOID) 1813 { 1814 PKPRCB CurrentPrcb = KeGetCurrentPrcb(); 1815 PCONTEXT ContextRecord = &CurrentPrcb->ProcessorState.ContextFrame; 1816 EXCEPTION_RECORD ExceptionRecord = {0}; 1817 KCONTINUE_STATUS Status; 1818 1819 /* Save the port data */ 1820 KdSave(FALSE); 1821 1822 ExceptionRecord.ExceptionAddress = (PVOID)KeGetContextPc(ContextRecord); 1823 ExceptionRecord.ExceptionCode = STATUS_WAKE_SYSTEM_DEBUGGER; 1824 1825 /* Report the new state */ 1826 Status = KdpReportExceptionStateChange(&ExceptionRecord, 1827 ContextRecord, 1828 FALSE); 1829 1830 /* Restore the port data */ 1831 KdRestore(FALSE); 1832 1833 return Status; 1834 } 1835 1836 VOID 1837 NTAPI 1838 KdpTimeSlipDpcRoutine(IN PKDPC Dpc, 1839 IN PVOID DeferredContext, 1840 IN PVOID SystemArgument1, 1841 IN PVOID SystemArgument2) 1842 { 1843 LONG OldSlip, NewSlip, PendingSlip; 1844 1845 /* Get the current pending slip */ 1846 PendingSlip = KdpTimeSlipPending; 1847 do 1848 { 1849 /* Save the old value and either disable or enable it now. */ 1850 OldSlip = PendingSlip; 1851 NewSlip = OldSlip > 1 ? 1 : 0; 1852 1853 /* Try to change the value */ 1854 } while (InterlockedCompareExchange(&KdpTimeSlipPending, 1855 NewSlip, 1856 OldSlip) != OldSlip); 1857 1858 /* If the New Slip value is 1, then do the Time Slipping */ 1859 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue); 1860 } 1861 1862 VOID 1863 NTAPI 1864 KdpTimeSlipWork(IN PVOID Context) 1865 { 1866 KIRQL OldIrql; 1867 LARGE_INTEGER DueTime; 1868 1869 /* Update the System time from the CMOS */ 1870 ExAcquireTimeRefreshLock(FALSE); 1871 ExUpdateSystemTimeFromCmos(FALSE, 0); 1872 ExReleaseTimeRefreshLock(); 1873 1874 /* Check if we have a registered Time Slip Event and signal it */ 1875 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql); 1876 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE); 1877 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql); 1878 1879 /* Delay the DPC until it runs next time */ 1880 DueTime.QuadPart = -1800000000; 1881 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc); 1882 } 1883 1884 LARGE_INTEGER 1885 NTAPI 1886 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame) 1887 { 1888 LARGE_INTEGER Null = {{0}}; 1889 1890 /* Check if interrupts were disabled */ 1891 if (!KeGetTrapFrameInterruptState(TrapFrame)) 1892 { 1893 /* Nothing to return */ 1894 return Null; 1895 } 1896 1897 /* Otherwise, do the call */ 1898 return KeQueryPerformanceCounter(NULL); 1899 } 1900 1901 BOOLEAN 1902 NTAPI 1903 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame, 1904 IN PKEXCEPTION_FRAME ExceptionFrame) 1905 { 1906 BOOLEAN Enable; 1907 1908 /* Check if we have a trap frame */ 1909 if (TrapFrame) 1910 { 1911 /* Calculate the time difference for the enter */ 1912 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame); 1913 KdTimerDifference.QuadPart = KdTimerStop.QuadPart - 1914 KdTimerStart.QuadPart; 1915 } 1916 else 1917 { 1918 /* No trap frame, so can't calculate */ 1919 KdTimerStop.QuadPart = 0; 1920 } 1921 1922 /* Save the current IRQL */ 1923 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql(); 1924 1925 /* Freeze all CPUs, raising also the IRQL to HIGH_LEVEL */ 1926 Enable = KeFreezeExecution(TrapFrame, ExceptionFrame); 1927 1928 /* Lock the port, save the state and set debugger entered */ 1929 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock); 1930 KdSave(FALSE); 1931 KdEnteredDebugger = TRUE; 1932 1933 /* Check freeze flag */ 1934 if (KiFreezeFlag & 1) 1935 { 1936 /* Print out errror */ 1937 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n"); 1938 } 1939 1940 /* Check processor state */ 1941 if (KiFreezeFlag & 2) 1942 { 1943 /* Print out errror */ 1944 KdpDprintf("Some processors not frozen in debugger!\n"); 1945 } 1946 1947 /* Make sure we acquired the port */ 1948 if (!KdpPortLocked) KdpDprintf("Port lock was not acquired!\n"); 1949 1950 /* Return if interrupts needs to be re-enabled */ 1951 return Enable; 1952 } 1953 1954 VOID 1955 NTAPI 1956 KdExitDebugger(IN BOOLEAN Enable) 1957 { 1958 ULONG TimeSlip; 1959 1960 /* Restore the state and unlock the port */ 1961 KdRestore(FALSE); 1962 if (KdpPortLocked) KdpPortUnlock(); 1963 1964 /* Unfreeze the CPUs, restoring also the IRQL */ 1965 KeThawExecution(Enable); 1966 1967 /* Compare time with the one from KdEnterDebugger */ 1968 if (!KdTimerStop.QuadPart) 1969 { 1970 /* We didn't get a trap frame earlier in so never got the time */ 1971 KdTimerStart = KdTimerStop; 1972 } 1973 else 1974 { 1975 /* Query the timer */ 1976 KdTimerStart = KeQueryPerformanceCounter(NULL); 1977 } 1978 1979 /* Check if a Time Slip was on queue */ 1980 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending); 1981 if (TimeSlip == 1) 1982 { 1983 /* Queue a DPC for the time slip */ 1984 InterlockedIncrement(&KdpTimeSlipPending); 1985 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL); // FIXME: this can trigger context switches! 1986 } 1987 } 1988 1989 NTSTATUS 1990 NTAPI 1991 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock) 1992 { 1993 KIRQL OldIrql; 1994 1995 #if defined(__GNUC__) 1996 /* Make gcc happy */ 1997 OldIrql = PASSIVE_LEVEL; 1998 #endif 1999 2000 /* Check if enabling the debugger is blocked */ 2001 if (KdBlockEnable) 2002 { 2003 /* It is, fail the enable */ 2004 return STATUS_ACCESS_DENIED; 2005 } 2006 2007 /* Check if we need to acquire the lock */ 2008 if (NeedLock) 2009 { 2010 /* Lock the port */ 2011 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 2012 KdpPortLock(); 2013 } 2014 2015 /* Check if we're not disabled */ 2016 if (!KdDisableCount) 2017 { 2018 /* Check if we had locked the port before */ 2019 if (NeedLock) 2020 { 2021 /* Do the unlock */ 2022 KdpPortUnlock(); 2023 KeLowerIrql(OldIrql); 2024 2025 /* Fail: We're already enabled */ 2026 return STATUS_INVALID_PARAMETER; 2027 } 2028 else 2029 { 2030 /* 2031 * This can only happen if we are called from a bugcheck 2032 * and were never initialized, so initialize the debugger now. 2033 */ 2034 KdInitSystem(0, NULL); 2035 2036 /* Return success since we initialized */ 2037 return STATUS_SUCCESS; 2038 } 2039 } 2040 2041 /* Decrease the disable count */ 2042 if (!(--KdDisableCount)) 2043 { 2044 /* We're now enabled again! Were we enabled before, too? */ 2045 if (KdPreviouslyEnabled) 2046 { 2047 /* Reinitialize the Debugger */ 2048 KdInitSystem(0, NULL); 2049 KdpRestoreAllBreakpoints(); 2050 } 2051 } 2052 2053 /* Check if we had locked the port before */ 2054 if (NeedLock) 2055 { 2056 /* Yes, now unlock it */ 2057 KdpPortUnlock(); 2058 KeLowerIrql(OldIrql); 2059 } 2060 2061 /* We're done */ 2062 return STATUS_SUCCESS; 2063 } 2064 2065 NTSTATUS 2066 NTAPI 2067 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock) 2068 { 2069 KIRQL OldIrql; 2070 NTSTATUS Status; 2071 2072 #if defined(__GNUC__) 2073 /* Make gcc happy */ 2074 OldIrql = PASSIVE_LEVEL; 2075 #endif 2076 2077 /* 2078 * If enabling the debugger is blocked 2079 * then there is nothing to disable (duh) 2080 */ 2081 if (KdBlockEnable) 2082 { 2083 /* Fail */ 2084 return STATUS_ACCESS_DENIED; 2085 } 2086 2087 /* Check if we need to acquire the lock */ 2088 if (NeedLock) 2089 { 2090 /* Lock the port */ 2091 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 2092 KdpPortLock(); 2093 } 2094 2095 /* Check if we're not disabled */ 2096 if (!KdDisableCount) 2097 { 2098 /* Check if the debugger was never actually initialized */ 2099 if (!(KdDebuggerEnabled) && !(KdPitchDebugger)) 2100 { 2101 /* It wasn't, so don't re-enable it later */ 2102 KdPreviouslyEnabled = FALSE; 2103 } 2104 else 2105 { 2106 /* It was, so we will re-enable it later */ 2107 KdPreviouslyEnabled = TRUE; 2108 } 2109 2110 /* Check if we were called from the exported API and are enabled */ 2111 if ((NeedLock) && (KdPreviouslyEnabled)) 2112 { 2113 /* Check if it is safe to disable the debugger */ 2114 Status = KdpAllowDisable(); 2115 if (!NT_SUCCESS(Status)) 2116 { 2117 /* Release the lock and fail */ 2118 KdpPortUnlock(); 2119 KeLowerIrql(OldIrql); 2120 return Status; 2121 } 2122 } 2123 2124 /* Only disable the debugger if it is enabled */ 2125 if (KdDebuggerEnabled) 2126 { 2127 /* 2128 * Disable the debugger; suspend breakpoints 2129 * and reset the debug stub 2130 */ 2131 KdpSuspendAllBreakPoints(); 2132 KiDebugRoutine = KdpStub; 2133 2134 /* We are disabled now */ 2135 KdDebuggerEnabled = FALSE; 2136 SharedUserData->KdDebuggerEnabled = FALSE; 2137 } 2138 } 2139 2140 /* Increment the disable count */ 2141 KdDisableCount++; 2142 2143 /* Check if we had locked the port before */ 2144 if (NeedLock) 2145 { 2146 /* Yes, now unlock it */ 2147 KdpPortUnlock(); 2148 KeLowerIrql(OldIrql); 2149 } 2150 2151 /* We're done */ 2152 return STATUS_SUCCESS; 2153 } 2154 2155 /* PUBLIC FUNCTIONS **********************************************************/ 2156 2157 /* 2158 * @implemented 2159 */ 2160 NTSTATUS 2161 NTAPI 2162 KdEnableDebugger(VOID) 2163 { 2164 /* Use the internal routine */ 2165 return KdEnableDebuggerWithLock(TRUE); 2166 } 2167 2168 /* 2169 * @implemented 2170 */ 2171 NTSTATUS 2172 NTAPI 2173 KdDisableDebugger(VOID) 2174 { 2175 /* Use the internal routine */ 2176 return KdDisableDebuggerWithLock(TRUE); 2177 } 2178 2179 /* 2180 * @unimplemented 2181 */ 2182 NTSTATUS 2183 NTAPI 2184 KdSystemDebugControl( 2185 _In_ SYSDBG_COMMAND Command, 2186 _In_ PVOID InputBuffer, 2187 _In_ ULONG InputBufferLength, 2188 _Out_ PVOID OutputBuffer, 2189 _In_ ULONG OutputBufferLength, 2190 _Inout_ PULONG ReturnLength, 2191 _In_ KPROCESSOR_MODE PreviousMode) 2192 { 2193 /* Handle some internal commands */ 2194 switch ((ULONG)Command) 2195 { 2196 #if DBG 2197 case ' soR': /* ROS-INTERNAL */ 2198 { 2199 switch ((ULONG_PTR)InputBuffer) 2200 { 2201 case 0x21: // DumpAllThreads: 2202 PspDumpThreads(TRUE); 2203 break; 2204 2205 case 0x22: // DumpUserThreads: 2206 PspDumpThreads(FALSE); 2207 break; 2208 2209 case 0x24: // KdSpare3: 2210 MmDumpArmPfnDatabase(FALSE); 2211 break; 2212 2213 default: 2214 break; 2215 } 2216 return STATUS_SUCCESS; 2217 } 2218 2219 #if defined(_M_IX86) && !defined(_WINKD_) // See ke/i386/traphdlr.c 2220 /* Register a debug callback */ 2221 case 'CsoR': 2222 { 2223 switch (InputBufferLength) 2224 { 2225 case ID_Win32PreServiceHook: 2226 KeWin32PreServiceHook = InputBuffer; 2227 break; 2228 2229 case ID_Win32PostServiceHook: 2230 KeWin32PostServiceHook = InputBuffer; 2231 break; 2232 2233 } 2234 break; 2235 } 2236 #endif 2237 2238 /* Special case for stack frame dumps */ 2239 case 'DsoR': 2240 { 2241 KeRosDumpStackFrames((PULONG_PTR)InputBuffer, InputBufferLength); 2242 break; 2243 } 2244 #ifdef KDBG 2245 /* Register KDBG CLI callback */ 2246 case 'RbdK': 2247 { 2248 return KdbRegisterCliCallback(InputBuffer, InputBufferLength); 2249 } 2250 #endif // KDBG 2251 #endif 2252 default: 2253 break; 2254 } 2255 2256 /* Local kernel debugging is not yet supported */ 2257 DbgPrint("KdSystemDebugControl is unimplemented!\n"); 2258 return STATUS_NOT_IMPLEMENTED; 2259 } 2260 2261 /* 2262 * @implemented 2263 */ 2264 NTSTATUS 2265 NTAPI 2266 KdChangeOption(IN KD_OPTION Option, 2267 IN ULONG InBufferBytes OPTIONAL, 2268 IN PVOID InBuffer, 2269 IN ULONG OutBufferBytes OPTIONAL, 2270 OUT PVOID OutBuffer, 2271 OUT PULONG OutBufferNeeded OPTIONAL) 2272 { 2273 /* Fail if there is no debugger */ 2274 if (KdPitchDebugger) 2275 { 2276 /* No debugger, no options */ 2277 return STATUS_DEBUGGER_INACTIVE; 2278 } 2279 2280 /* Do we recognize this option? */ 2281 if (Option != KD_OPTION_SET_BLOCK_ENABLE) 2282 { 2283 /* We don't, clear the output length and fail */ 2284 if (OutBufferNeeded) *OutBufferNeeded = 0; 2285 return STATUS_INVALID_INFO_CLASS; 2286 } 2287 2288 /* Verify parameters */ 2289 if ((InBufferBytes != sizeof(BOOLEAN)) || 2290 (OutBufferBytes != 0) || 2291 (OutBuffer != NULL)) 2292 { 2293 /* Invalid parameters for this option, fail */ 2294 return STATUS_INVALID_PARAMETER; 2295 } 2296 2297 /* 2298 * Check if the high bit is set, meaning we don't 2299 * allow the debugger to be enabled 2300 */ 2301 if (KdBlockEnable & 0x80) 2302 { 2303 /* Fail regardless of what state the caller tried to set */ 2304 return STATUS_ACCESS_VIOLATION; 2305 } 2306 2307 /* Set the new block enable state */ 2308 KdBlockEnable = *(PBOOLEAN)InBuffer; 2309 2310 /* No output buffer required for this option */ 2311 if (OutBufferNeeded) *OutBufferNeeded = 0; 2312 2313 /* We are done */ 2314 return STATUS_SUCCESS; 2315 } 2316 2317 /* 2318 * @implemented 2319 */ 2320 NTSTATUS 2321 NTAPI 2322 KdPowerTransition(IN DEVICE_POWER_STATE NewState) 2323 { 2324 /* Check what power state this is */ 2325 if (NewState == PowerDeviceD0) 2326 { 2327 /* Wake up the debug port */ 2328 KdD0Transition(); 2329 return STATUS_SUCCESS; 2330 } 2331 else if ((NewState == PowerDeviceD1) || 2332 (NewState == PowerDeviceD2) || 2333 (NewState == PowerDeviceD3)) 2334 { 2335 /* Power down the debug port */ 2336 KdD3Transition(); 2337 return STATUS_SUCCESS; 2338 } 2339 else 2340 { 2341 /* Invalid state! */ 2342 return STATUS_INVALID_PARAMETER_1; 2343 } 2344 } 2345 2346 /* 2347 * @implemented 2348 */ 2349 BOOLEAN 2350 NTAPI 2351 KdRefreshDebuggerNotPresent(VOID) 2352 { 2353 BOOLEAN Enable, DebuggerNotPresent; 2354 2355 /* Check if the debugger is completely disabled */ 2356 if (KdPitchDebugger) 2357 { 2358 /* Don't try to refresh then, fail early */ 2359 return TRUE; 2360 } 2361 2362 /* Enter the debugger */ 2363 Enable = KdEnterDebugger(NULL, NULL); 2364 2365 /* 2366 * Attempt to send a string to the debugger 2367 * to refresh the connection state. 2368 */ 2369 KdpDprintf("KDTARGET: Refreshing KD connection\n"); 2370 2371 /* Save the state while we are holding the lock */ 2372 DebuggerNotPresent = KdDebuggerNotPresent; 2373 2374 /* Exit the debugger and return the state */ 2375 KdExitDebugger(Enable); 2376 return DebuggerNotPresent; 2377 } 2378 2379 /* 2380 * @implemented 2381 */ 2382 NTSTATUS 2383 NTAPI 2384 NtQueryDebugFilterState( 2385 _In_ ULONG ComponentId, 2386 _In_ ULONG Level) 2387 { 2388 PULONG Mask; 2389 2390 /* Check if the ID fits in the component table */ 2391 if (ComponentId < KdComponentTableSize) 2392 { 2393 /* It does, so get the mask from there */ 2394 Mask = KdComponentTable[ComponentId]; 2395 } 2396 else if (ComponentId == MAXULONG) 2397 { 2398 /* 2399 * This is the internal ID used for DbgPrint messages without ID 2400 * and Level. Use the system-wide mask for those. 2401 */ 2402 Mask = &Kd_WIN2000_Mask; 2403 } 2404 else 2405 { 2406 #if (NTDDI_VERSION >= NTDDI_VISTA) 2407 /* Use the default component ID */ 2408 Mask = &Kd_DEFAULT_Mask; 2409 // Level = DPFLTR_INFO_LEVEL; // Override the Level. 2410 #else 2411 /* Invalid ID, fail */ 2412 return STATUS_INVALID_PARAMETER_1; 2413 #endif 2414 } 2415 2416 /* Convert Level to bit field if required */ 2417 if (Level < 32) Level = 1 << Level; 2418 Level &= ~DPFLTR_MASK; 2419 2420 /* Determine if this Level is filtered out */ 2421 if ((Kd_WIN2000_Mask & Level) || (*Mask & Level)) 2422 { 2423 /* This mask will get through to the debugger */ 2424 return (NTSTATUS)TRUE; 2425 } 2426 else 2427 { 2428 /* This mask is filtered out */ 2429 return (NTSTATUS)FALSE; 2430 } 2431 } 2432 2433 /* 2434 * @implemented 2435 */ 2436 NTSTATUS 2437 NTAPI 2438 NtSetDebugFilterState( 2439 _In_ ULONG ComponentId, 2440 _In_ ULONG Level, 2441 _In_ BOOLEAN State) 2442 { 2443 PULONG Mask; 2444 2445 /* Modifying debug filters requires the debug privilege */ 2446 if (!SeSinglePrivilegeCheck(SeDebugPrivilege, ExGetPreviousMode())) 2447 { 2448 /* Fail */ 2449 return STATUS_ACCESS_DENIED; 2450 } 2451 2452 /* Check if the ID fits in the component table */ 2453 if (ComponentId < KdComponentTableSize) 2454 { 2455 /* It does, so get the mask from there */ 2456 Mask = KdComponentTable[ComponentId]; 2457 } 2458 else if (ComponentId == MAXULONG) 2459 { 2460 /* 2461 * This is the internal ID used for DbgPrint messages without ID 2462 * and Level. Use the system-wide mask for those. 2463 */ 2464 Mask = &Kd_WIN2000_Mask; 2465 } 2466 else 2467 { 2468 #if (NTDDI_VERSION >= NTDDI_VISTA) 2469 /* Use the default component ID */ 2470 Mask = &Kd_DEFAULT_Mask; 2471 #else 2472 /* Invalid ID, fail */ 2473 return STATUS_INVALID_PARAMETER_1; 2474 #endif 2475 } 2476 2477 /* Convert Level to bit field if required */ 2478 if (Level < 32) Level = 1 << Level; 2479 Level &= ~DPFLTR_MASK; 2480 2481 /* Set or remove the Level */ 2482 if (State) 2483 *Mask |= Level; 2484 else 2485 *Mask &= ~Level; 2486 2487 return STATUS_SUCCESS; 2488 } 2489