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 /* TODO */ 1501 KdpDprintf("Page-In support is unimplemented!\n"); 1502 KdpNotSupported(&ManipulateState); 1503 break; 1504 1505 case DbgKdReadMachineSpecificRegister: 1506 1507 /* Read from the specified MSR */ 1508 KdpReadMachineSpecificRegister(&ManipulateState, &Data, Context); 1509 break; 1510 1511 case DbgKdWriteMachineSpecificRegister: 1512 1513 /* Write to the specified MSR */ 1514 KdpWriteMachineSpecificRegister(&ManipulateState, &Data, Context); 1515 break; 1516 1517 case DbgKdSearchMemoryApi: 1518 1519 /* Search memory */ 1520 KdpSearchMemory(&ManipulateState, &Data, Context); 1521 break; 1522 1523 case DbgKdGetBusDataApi: 1524 1525 /* Read from the bus */ 1526 KdpGetBusData(&ManipulateState, &Data, Context); 1527 break; 1528 1529 case DbgKdSetBusDataApi: 1530 1531 /* Write to the bus */ 1532 KdpSetBusData(&ManipulateState, &Data, Context); 1533 break; 1534 1535 case DbgKdCheckLowMemoryApi: 1536 1537 /* Check for memory corruption in the lower 4 GB */ 1538 KdpCheckLowMemory(&ManipulateState); 1539 break; 1540 1541 case DbgKdClearAllInternalBreakpointsApi: 1542 1543 /* Just clear the counter */ 1544 KdpNumInternalBreakpoints = 0; 1545 break; 1546 1547 case DbgKdFillMemoryApi: 1548 1549 /* Fill memory */ 1550 KdpFillMemory(&ManipulateState, &Data, Context); 1551 break; 1552 1553 case DbgKdQueryMemoryApi: 1554 1555 /* Query memory */ 1556 KdpQueryMemory(&ManipulateState, Context); 1557 break; 1558 1559 case DbgKdSwitchPartition: 1560 1561 /* TODO */ 1562 KdpDprintf("Partition Switch support is unimplemented!\n"); 1563 KdpNotSupported(&ManipulateState); 1564 break; 1565 1566 case DbgKdWriteCustomBreakpointApi: 1567 1568 /* Write the customized breakpoint */ 1569 KdpWriteCustomBreakpoint(&ManipulateState, &Data, Context); 1570 break; 1571 1572 case DbgKdGetContextExApi: 1573 1574 /* Extended Context Get */ 1575 KdpGetContextEx(&ManipulateState, &Data, Context); 1576 break; 1577 1578 case DbgKdSetContextExApi: 1579 1580 /* Extended Context Set */ 1581 KdpSetContextEx(&ManipulateState, &Data, Context); 1582 break; 1583 1584 /* Unsupported Messages */ 1585 default: 1586 1587 /* Send warning */ 1588 KdpDprintf("Received Unrecognized API 0x%lx\n", ManipulateState.ApiNumber); 1589 1590 /* Setup an empty message, with failure */ 1591 Data.Length = 0; 1592 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL; 1593 1594 /* Send it */ 1595 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 1596 &Header, 1597 &Data, 1598 &KdpContext); 1599 break; 1600 } 1601 } 1602 } 1603 1604 VOID 1605 NTAPI 1606 KdpReportLoadSymbolsStateChange(IN PSTRING PathName, 1607 IN PKD_SYMBOLS_INFO SymbolInfo, 1608 IN BOOLEAN Unload, 1609 IN OUT PCONTEXT Context) 1610 { 1611 PSTRING ExtraData; 1612 STRING Data, Header; 1613 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange; 1614 ULONG PathNameLength; 1615 KCONTINUE_STATUS Status; 1616 1617 /* Start wait loop */ 1618 do 1619 { 1620 /* Build the architecture common parts of the message */ 1621 KdpSetCommonState(DbgKdLoadSymbolsStateChange, 1622 Context, 1623 &WaitStateChange); 1624 1625 /* Now finish creating the structure */ 1626 KdpSetContextState(&WaitStateChange, Context); 1627 1628 /* Fill out load data */ 1629 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload; 1630 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)(LONG_PTR)SymbolInfo->BaseOfDll; 1631 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId; 1632 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum; 1633 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage; 1634 1635 /* Check if we have a path name */ 1636 if (PathName) 1637 { 1638 /* Copy it to the path buffer */ 1639 KdpCopyMemoryChunks((ULONG_PTR)PathName->Buffer, 1640 KdpPathBuffer, 1641 PathName->Length, 1642 0, 1643 MMDBG_COPY_UNSAFE, 1644 &PathNameLength); 1645 1646 /* Null terminate */ 1647 KdpPathBuffer[PathNameLength++] = ANSI_NULL; 1648 1649 /* Set the path length */ 1650 WaitStateChange.u.LoadSymbols.PathNameLength = PathNameLength; 1651 1652 /* Set up the data */ 1653 Data.Buffer = KdpPathBuffer; 1654 Data.Length = (USHORT)PathNameLength; 1655 ExtraData = &Data; 1656 } 1657 else 1658 { 1659 /* No name */ 1660 WaitStateChange.u.LoadSymbols.PathNameLength = 0; 1661 ExtraData = NULL; 1662 } 1663 1664 /* Setup the header */ 1665 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE); 1666 Header.Buffer = (PCHAR)&WaitStateChange; 1667 1668 /* Send the packet */ 1669 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64, 1670 &Header, 1671 ExtraData, 1672 Context); 1673 } while (Status == ContinueProcessorReselected); 1674 } 1675 1676 VOID 1677 NTAPI 1678 KdpReportCommandStringStateChange(IN PSTRING NameString, 1679 IN PSTRING CommandString, 1680 IN OUT PCONTEXT Context) 1681 { 1682 STRING Header, Data; 1683 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange; 1684 ULONG Length, ActualLength, TotalLength; 1685 KCONTINUE_STATUS Status; 1686 1687 /* Start wait loop */ 1688 do 1689 { 1690 /* Build the architecture common parts of the message */ 1691 KdpSetCommonState(DbgKdCommandStringStateChange, 1692 Context, 1693 &WaitStateChange); 1694 1695 /* Set the context */ 1696 KdpSetContextState(&WaitStateChange, Context); 1697 1698 /* Clear the command string structure */ 1699 KdpZeroMemory(&WaitStateChange.u.CommandString, 1700 sizeof(DBGKD_COMMAND_STRING)); 1701 1702 /* Normalize name string to max */ 1703 Length = min(128 - 1, NameString->Length); 1704 1705 /* Copy it to the message buffer */ 1706 KdpCopyMemoryChunks((ULONG_PTR)NameString->Buffer, 1707 KdpMessageBuffer, 1708 Length, 1709 0, 1710 MMDBG_COPY_UNSAFE, 1711 &ActualLength); 1712 1713 /* Null terminate and calculate the total length */ 1714 TotalLength = ActualLength; 1715 KdpMessageBuffer[TotalLength++] = ANSI_NULL; 1716 1717 /* Check if the command string is too long */ 1718 Length = CommandString->Length; 1719 if (Length > (PACKET_MAX_SIZE - 1720 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength)) 1721 { 1722 /* Use maximum possible size */ 1723 Length = (PACKET_MAX_SIZE - 1724 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength); 1725 } 1726 1727 /* Copy it to the message buffer */ 1728 KdpCopyMemoryChunks((ULONG_PTR)CommandString->Buffer, 1729 KdpMessageBuffer + TotalLength, 1730 Length, 1731 0, 1732 MMDBG_COPY_UNSAFE, 1733 &ActualLength); 1734 1735 /* Null terminate and calculate the total length */ 1736 TotalLength += ActualLength; 1737 KdpMessageBuffer[TotalLength++] = ANSI_NULL; 1738 1739 /* Now set up the header and the data */ 1740 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE); 1741 Header.Buffer = (PCHAR)&WaitStateChange; 1742 Data.Length = (USHORT)TotalLength; 1743 Data.Buffer = KdpMessageBuffer; 1744 1745 /* Send State Change packet and wait for a reply */ 1746 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64, 1747 &Header, 1748 &Data, 1749 Context); 1750 } while (Status == ContinueProcessorReselected); 1751 } 1752 1753 BOOLEAN 1754 NTAPI 1755 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord, 1756 IN OUT PCONTEXT Context, 1757 IN BOOLEAN SecondChanceException) 1758 { 1759 STRING Header, Data; 1760 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange; 1761 KCONTINUE_STATUS Status; 1762 1763 /* Start report loop */ 1764 do 1765 { 1766 /* Build the architecture common parts of the message */ 1767 KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange); 1768 1769 #if !defined(_WIN64) 1770 1771 /* Convert it and copy it over */ 1772 ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord, 1773 &WaitStateChange.u.Exception.ExceptionRecord); 1774 1775 #else 1776 1777 /* Just copy it directly, no need to convert */ 1778 KdpMoveMemory(&WaitStateChange.u.Exception.ExceptionRecord, 1779 ExceptionRecord, 1780 sizeof(EXCEPTION_RECORD)); 1781 1782 #endif 1783 1784 /* Set the First Chance flag */ 1785 WaitStateChange.u.Exception.FirstChance = !SecondChanceException; 1786 1787 /* Now finish creating the structure */ 1788 KdpSetContextState(&WaitStateChange, Context); 1789 1790 /* Setup the actual header to send to KD */ 1791 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE); 1792 Header.Buffer = (PCHAR)&WaitStateChange; 1793 1794 /* Setup the trace data */ 1795 DumpTraceData(&Data); 1796 1797 /* Send State Change packet and wait for a reply */ 1798 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64, 1799 &Header, 1800 &Data, 1801 Context); 1802 } while (Status == ContinueProcessorReselected); 1803 1804 /* Return */ 1805 return Status; 1806 } 1807 1808 KCONTINUE_STATUS 1809 NTAPI 1810 KdReportProcessorChange( 1811 VOID) 1812 { 1813 PKPRCB CurrentPrcb = KeGetCurrentPrcb(); 1814 PCONTEXT ContextRecord = &CurrentPrcb->ProcessorState.ContextFrame; 1815 EXCEPTION_RECORD ExceptionRecord = {0}; 1816 KCONTINUE_STATUS Status; 1817 1818 /* Save the port data */ 1819 KdSave(FALSE); 1820 1821 ExceptionRecord.ExceptionAddress = (PVOID)KeGetContextPc(ContextRecord); 1822 ExceptionRecord.ExceptionCode = STATUS_WAKE_SYSTEM_DEBUGGER; 1823 1824 /* Report the new state */ 1825 Status = KdpReportExceptionStateChange(&ExceptionRecord, 1826 ContextRecord, 1827 FALSE); 1828 1829 /* Restore the port data */ 1830 KdRestore(FALSE); 1831 1832 return Status; 1833 } 1834 1835 VOID 1836 NTAPI 1837 KdpTimeSlipDpcRoutine(IN PKDPC Dpc, 1838 IN PVOID DeferredContext, 1839 IN PVOID SystemArgument1, 1840 IN PVOID SystemArgument2) 1841 { 1842 LONG OldSlip, NewSlip, PendingSlip; 1843 1844 /* Get the current pending slip */ 1845 PendingSlip = KdpTimeSlipPending; 1846 do 1847 { 1848 /* Save the old value and either disable or enable it now. */ 1849 OldSlip = PendingSlip; 1850 NewSlip = OldSlip > 1 ? 1 : 0; 1851 1852 /* Try to change the value */ 1853 } while (InterlockedCompareExchange(&KdpTimeSlipPending, 1854 NewSlip, 1855 OldSlip) != OldSlip); 1856 1857 /* If the New Slip value is 1, then do the Time Slipping */ 1858 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue); 1859 } 1860 1861 VOID 1862 NTAPI 1863 KdpTimeSlipWork(IN PVOID Context) 1864 { 1865 KIRQL OldIrql; 1866 LARGE_INTEGER DueTime; 1867 1868 /* Update the System time from the CMOS */ 1869 ExAcquireTimeRefreshLock(FALSE); 1870 ExUpdateSystemTimeFromCmos(FALSE, 0); 1871 ExReleaseTimeRefreshLock(); 1872 1873 /* Check if we have a registered Time Slip Event and signal it */ 1874 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql); 1875 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE); 1876 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql); 1877 1878 /* Delay the DPC until it runs next time */ 1879 DueTime.QuadPart = -1800000000; 1880 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc); 1881 } 1882 1883 LARGE_INTEGER 1884 NTAPI 1885 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame) 1886 { 1887 LARGE_INTEGER Null = {{0}}; 1888 1889 /* Check if interrupts were disabled */ 1890 if (!KeGetTrapFrameInterruptState(TrapFrame)) 1891 { 1892 /* Nothing to return */ 1893 return Null; 1894 } 1895 1896 /* Otherwise, do the call */ 1897 return KeQueryPerformanceCounter(NULL); 1898 } 1899 1900 BOOLEAN 1901 NTAPI 1902 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame, 1903 IN PKEXCEPTION_FRAME ExceptionFrame) 1904 { 1905 BOOLEAN Enable; 1906 1907 /* Check if we have a trap frame */ 1908 if (TrapFrame) 1909 { 1910 /* Calculate the time difference for the enter */ 1911 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame); 1912 KdTimerDifference.QuadPart = KdTimerStop.QuadPart - 1913 KdTimerStart.QuadPart; 1914 } 1915 else 1916 { 1917 /* No trap frame, so can't calculate */ 1918 KdTimerStop.QuadPart = 0; 1919 } 1920 1921 /* Save the current IRQL */ 1922 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql(); 1923 1924 /* Freeze all CPUs, raising also the IRQL to HIGH_LEVEL */ 1925 Enable = KeFreezeExecution(TrapFrame, ExceptionFrame); 1926 1927 /* Lock the port, save the state and set debugger entered */ 1928 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock); 1929 KdSave(FALSE); 1930 KdEnteredDebugger = TRUE; 1931 1932 /* Check freeze flag */ 1933 if (KiFreezeFlag & 1) 1934 { 1935 /* Print out errror */ 1936 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n"); 1937 } 1938 1939 /* Check processor state */ 1940 if (KiFreezeFlag & 2) 1941 { 1942 /* Print out errror */ 1943 KdpDprintf("Some processors not frozen in debugger!\n"); 1944 } 1945 1946 /* Make sure we acquired the port */ 1947 if (!KdpPortLocked) KdpDprintf("Port lock was not acquired!\n"); 1948 1949 /* Return if interrupts needs to be re-enabled */ 1950 return Enable; 1951 } 1952 1953 VOID 1954 NTAPI 1955 KdExitDebugger(IN BOOLEAN Enable) 1956 { 1957 ULONG TimeSlip; 1958 1959 /* Restore the state and unlock the port */ 1960 KdRestore(FALSE); 1961 if (KdpPortLocked) KdpPortUnlock(); 1962 1963 /* Unfreeze the CPUs, restoring also the IRQL */ 1964 KeThawExecution(Enable); 1965 1966 /* Compare time with the one from KdEnterDebugger */ 1967 if (!KdTimerStop.QuadPart) 1968 { 1969 /* We didn't get a trap frame earlier in so never got the time */ 1970 KdTimerStart = KdTimerStop; 1971 } 1972 else 1973 { 1974 /* Query the timer */ 1975 KdTimerStart = KeQueryPerformanceCounter(NULL); 1976 } 1977 1978 /* Check if a Time Slip was on queue */ 1979 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending); 1980 if (TimeSlip == 1) 1981 { 1982 /* Queue a DPC for the time slip */ 1983 InterlockedIncrement(&KdpTimeSlipPending); 1984 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL); // FIXME: this can trigger context switches! 1985 } 1986 } 1987 1988 NTSTATUS 1989 NTAPI 1990 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock) 1991 { 1992 KIRQL OldIrql; 1993 1994 #if defined(__GNUC__) 1995 /* Make gcc happy */ 1996 OldIrql = PASSIVE_LEVEL; 1997 #endif 1998 1999 /* Check if enabling the debugger is blocked */ 2000 if (KdBlockEnable) 2001 { 2002 /* It is, fail the enable */ 2003 return STATUS_ACCESS_DENIED; 2004 } 2005 2006 /* Check if we need to acquire the lock */ 2007 if (NeedLock) 2008 { 2009 /* Lock the port */ 2010 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 2011 KdpPortLock(); 2012 } 2013 2014 /* Check if we're not disabled */ 2015 if (!KdDisableCount) 2016 { 2017 /* Check if we had locked the port before */ 2018 if (NeedLock) 2019 { 2020 /* Do the unlock */ 2021 KdpPortUnlock(); 2022 KeLowerIrql(OldIrql); 2023 2024 /* Fail: We're already enabled */ 2025 return STATUS_INVALID_PARAMETER; 2026 } 2027 else 2028 { 2029 /* 2030 * This can only happen if we are called from a bugcheck 2031 * and were never initialized, so initialize the debugger now. 2032 */ 2033 KdInitSystem(0, NULL); 2034 2035 /* Return success since we initialized */ 2036 return STATUS_SUCCESS; 2037 } 2038 } 2039 2040 /* Decrease the disable count */ 2041 if (!(--KdDisableCount)) 2042 { 2043 /* We're now enabled again! Were we enabled before, too? */ 2044 if (KdPreviouslyEnabled) 2045 { 2046 /* Reinitialize the Debugger */ 2047 KdInitSystem(0, NULL); 2048 KdpRestoreAllBreakpoints(); 2049 } 2050 } 2051 2052 /* Check if we had locked the port before */ 2053 if (NeedLock) 2054 { 2055 /* Yes, now unlock it */ 2056 KdpPortUnlock(); 2057 KeLowerIrql(OldIrql); 2058 } 2059 2060 /* We're done */ 2061 return STATUS_SUCCESS; 2062 } 2063 2064 NTSTATUS 2065 NTAPI 2066 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock) 2067 { 2068 KIRQL OldIrql; 2069 NTSTATUS Status; 2070 2071 #if defined(__GNUC__) 2072 /* Make gcc happy */ 2073 OldIrql = PASSIVE_LEVEL; 2074 #endif 2075 2076 /* 2077 * If enabling the debugger is blocked 2078 * then there is nothing to disable (duh) 2079 */ 2080 if (KdBlockEnable) 2081 { 2082 /* Fail */ 2083 return STATUS_ACCESS_DENIED; 2084 } 2085 2086 /* Check if we need to acquire the lock */ 2087 if (NeedLock) 2088 { 2089 /* Lock the port */ 2090 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 2091 KdpPortLock(); 2092 } 2093 2094 /* Check if we're not disabled */ 2095 if (!KdDisableCount) 2096 { 2097 /* Check if the debugger was never actually initialized */ 2098 if (!(KdDebuggerEnabled) && !(KdPitchDebugger)) 2099 { 2100 /* It wasn't, so don't re-enable it later */ 2101 KdPreviouslyEnabled = FALSE; 2102 } 2103 else 2104 { 2105 /* It was, so we will re-enable it later */ 2106 KdPreviouslyEnabled = TRUE; 2107 } 2108 2109 /* Check if we were called from the exported API and are enabled */ 2110 if ((NeedLock) && (KdPreviouslyEnabled)) 2111 { 2112 /* Check if it is safe to disable the debugger */ 2113 Status = KdpAllowDisable(); 2114 if (!NT_SUCCESS(Status)) 2115 { 2116 /* Release the lock and fail */ 2117 KdpPortUnlock(); 2118 KeLowerIrql(OldIrql); 2119 return Status; 2120 } 2121 } 2122 2123 /* Only disable the debugger if it is enabled */ 2124 if (KdDebuggerEnabled) 2125 { 2126 /* 2127 * Disable the debugger; suspend breakpoints 2128 * and reset the debug stub 2129 */ 2130 KdpSuspendAllBreakPoints(); 2131 KiDebugRoutine = KdpStub; 2132 2133 /* We are disabled now */ 2134 KdDebuggerEnabled = FALSE; 2135 SharedUserData->KdDebuggerEnabled = FALSE; 2136 } 2137 } 2138 2139 /* Increment the disable count */ 2140 KdDisableCount++; 2141 2142 /* Check if we had locked the port before */ 2143 if (NeedLock) 2144 { 2145 /* Yes, now unlock it */ 2146 KdpPortUnlock(); 2147 KeLowerIrql(OldIrql); 2148 } 2149 2150 /* We're done */ 2151 return STATUS_SUCCESS; 2152 } 2153 2154 /* PUBLIC FUNCTIONS **********************************************************/ 2155 2156 /* 2157 * @implemented 2158 */ 2159 NTSTATUS 2160 NTAPI 2161 KdEnableDebugger(VOID) 2162 { 2163 /* Use the internal routine */ 2164 return KdEnableDebuggerWithLock(TRUE); 2165 } 2166 2167 /* 2168 * @implemented 2169 */ 2170 NTSTATUS 2171 NTAPI 2172 KdDisableDebugger(VOID) 2173 { 2174 /* Use the internal routine */ 2175 return KdDisableDebuggerWithLock(TRUE); 2176 } 2177 2178 /* 2179 * @unimplemented 2180 */ 2181 NTSTATUS 2182 NTAPI 2183 KdSystemDebugControl( 2184 _In_ SYSDBG_COMMAND Command, 2185 _In_ PVOID InputBuffer, 2186 _In_ ULONG InputBufferLength, 2187 _Out_ PVOID OutputBuffer, 2188 _In_ ULONG OutputBufferLength, 2189 _Inout_ PULONG ReturnLength, 2190 _In_ KPROCESSOR_MODE PreviousMode) 2191 { 2192 /* Handle some internal commands */ 2193 switch ((ULONG)Command) 2194 { 2195 #if DBG 2196 case ' soR': /* ROS-INTERNAL */ 2197 { 2198 switch ((ULONG_PTR)InputBuffer) 2199 { 2200 case 0x21: // DumpAllThreads: 2201 PspDumpThreads(TRUE); 2202 break; 2203 2204 case 0x22: // DumpUserThreads: 2205 PspDumpThreads(FALSE); 2206 break; 2207 2208 case 0x24: // KdSpare3: 2209 MmDumpArmPfnDatabase(FALSE); 2210 break; 2211 2212 default: 2213 break; 2214 } 2215 return STATUS_SUCCESS; 2216 } 2217 2218 #if defined(_M_IX86) && !defined(_WINKD_) // See ke/i386/traphdlr.c 2219 /* Register a debug callback */ 2220 case 'CsoR': 2221 { 2222 switch (InputBufferLength) 2223 { 2224 case ID_Win32PreServiceHook: 2225 KeWin32PreServiceHook = InputBuffer; 2226 break; 2227 2228 case ID_Win32PostServiceHook: 2229 KeWin32PostServiceHook = InputBuffer; 2230 break; 2231 2232 } 2233 break; 2234 } 2235 #endif 2236 2237 /* Special case for stack frame dumps */ 2238 case 'DsoR': 2239 { 2240 KeRosDumpStackFrames((PULONG_PTR)InputBuffer, InputBufferLength); 2241 break; 2242 } 2243 #ifdef KDBG 2244 /* Register KDBG CLI callback */ 2245 case 'RbdK': 2246 { 2247 return KdbRegisterCliCallback(InputBuffer, InputBufferLength); 2248 } 2249 #endif // KDBG 2250 #endif 2251 default: 2252 break; 2253 } 2254 2255 /* Local kernel debugging is not yet supported */ 2256 DbgPrint("KdSystemDebugControl is unimplemented!\n"); 2257 return STATUS_NOT_IMPLEMENTED; 2258 } 2259 2260 /* 2261 * @implemented 2262 */ 2263 NTSTATUS 2264 NTAPI 2265 KdChangeOption(IN KD_OPTION Option, 2266 IN ULONG InBufferBytes OPTIONAL, 2267 IN PVOID InBuffer, 2268 IN ULONG OutBufferBytes OPTIONAL, 2269 OUT PVOID OutBuffer, 2270 OUT PULONG OutBufferNeeded OPTIONAL) 2271 { 2272 /* Fail if there is no debugger */ 2273 if (KdPitchDebugger) 2274 { 2275 /* No debugger, no options */ 2276 return STATUS_DEBUGGER_INACTIVE; 2277 } 2278 2279 /* Do we recognize this option? */ 2280 if (Option != KD_OPTION_SET_BLOCK_ENABLE) 2281 { 2282 /* We don't, clear the output length and fail */ 2283 if (OutBufferNeeded) *OutBufferNeeded = 0; 2284 return STATUS_INVALID_INFO_CLASS; 2285 } 2286 2287 /* Verify parameters */ 2288 if ((InBufferBytes != sizeof(BOOLEAN)) || 2289 (OutBufferBytes != 0) || 2290 (OutBuffer != NULL)) 2291 { 2292 /* Invalid parameters for this option, fail */ 2293 return STATUS_INVALID_PARAMETER; 2294 } 2295 2296 /* 2297 * Check if the high bit is set, meaning we don't 2298 * allow the debugger to be enabled 2299 */ 2300 if (KdBlockEnable & 0x80) 2301 { 2302 /* Fail regardless of what state the caller tried to set */ 2303 return STATUS_ACCESS_VIOLATION; 2304 } 2305 2306 /* Set the new block enable state */ 2307 KdBlockEnable = *(PBOOLEAN)InBuffer; 2308 2309 /* No output buffer required for this option */ 2310 if (OutBufferNeeded) *OutBufferNeeded = 0; 2311 2312 /* We are done */ 2313 return STATUS_SUCCESS; 2314 } 2315 2316 /* 2317 * @implemented 2318 */ 2319 NTSTATUS 2320 NTAPI 2321 KdPowerTransition(IN DEVICE_POWER_STATE NewState) 2322 { 2323 /* Check what power state this is */ 2324 if (NewState == PowerDeviceD0) 2325 { 2326 /* Wake up the debug port */ 2327 KdD0Transition(); 2328 return STATUS_SUCCESS; 2329 } 2330 else if ((NewState == PowerDeviceD1) || 2331 (NewState == PowerDeviceD2) || 2332 (NewState == PowerDeviceD3)) 2333 { 2334 /* Power down the debug port */ 2335 KdD3Transition(); 2336 return STATUS_SUCCESS; 2337 } 2338 else 2339 { 2340 /* Invalid state! */ 2341 return STATUS_INVALID_PARAMETER_1; 2342 } 2343 } 2344 2345 /* 2346 * @implemented 2347 */ 2348 BOOLEAN 2349 NTAPI 2350 KdRefreshDebuggerNotPresent(VOID) 2351 { 2352 BOOLEAN Enable, DebuggerNotPresent; 2353 2354 /* Check if the debugger is completely disabled */ 2355 if (KdPitchDebugger) 2356 { 2357 /* Don't try to refresh then, fail early */ 2358 return TRUE; 2359 } 2360 2361 /* Enter the debugger */ 2362 Enable = KdEnterDebugger(NULL, NULL); 2363 2364 /* 2365 * Attempt to send a string to the debugger 2366 * to refresh the connection state. 2367 */ 2368 KdpDprintf("KDTARGET: Refreshing KD connection\n"); 2369 2370 /* Save the state while we are holding the lock */ 2371 DebuggerNotPresent = KdDebuggerNotPresent; 2372 2373 /* Exit the debugger and return the state */ 2374 KdExitDebugger(Enable); 2375 return DebuggerNotPresent; 2376 } 2377 2378 /* 2379 * @implemented 2380 */ 2381 NTSTATUS 2382 NTAPI 2383 NtQueryDebugFilterState( 2384 _In_ ULONG ComponentId, 2385 _In_ ULONG Level) 2386 { 2387 PULONG Mask; 2388 2389 /* Check if the ID fits in the component table */ 2390 if (ComponentId < KdComponentTableSize) 2391 { 2392 /* It does, so get the mask from there */ 2393 Mask = KdComponentTable[ComponentId]; 2394 } 2395 else if (ComponentId == MAXULONG) 2396 { 2397 /* 2398 * This is the internal ID used for DbgPrint messages without ID 2399 * and Level. Use the system-wide mask for those. 2400 */ 2401 Mask = &Kd_WIN2000_Mask; 2402 } 2403 else 2404 { 2405 #if (NTDDI_VERSION >= NTDDI_VISTA) 2406 /* Use the default component ID */ 2407 Mask = &Kd_DEFAULT_Mask; 2408 // Level = DPFLTR_INFO_LEVEL; // Override the Level. 2409 #else 2410 /* Invalid ID, fail */ 2411 return STATUS_INVALID_PARAMETER_1; 2412 #endif 2413 } 2414 2415 /* Convert Level to bit field if required */ 2416 if (Level < 32) Level = 1 << Level; 2417 Level &= ~DPFLTR_MASK; 2418 2419 /* Determine if this Level is filtered out */ 2420 if ((Kd_WIN2000_Mask & Level) || (*Mask & Level)) 2421 { 2422 /* This mask will get through to the debugger */ 2423 return (NTSTATUS)TRUE; 2424 } 2425 else 2426 { 2427 /* This mask is filtered out */ 2428 return (NTSTATUS)FALSE; 2429 } 2430 } 2431 2432 /* 2433 * @implemented 2434 */ 2435 NTSTATUS 2436 NTAPI 2437 NtSetDebugFilterState( 2438 _In_ ULONG ComponentId, 2439 _In_ ULONG Level, 2440 _In_ BOOLEAN State) 2441 { 2442 PULONG Mask; 2443 2444 /* Modifying debug filters requires the debug privilege */ 2445 if (!SeSinglePrivilegeCheck(SeDebugPrivilege, ExGetPreviousMode())) 2446 { 2447 /* Fail */ 2448 return STATUS_ACCESS_DENIED; 2449 } 2450 2451 /* Check if the ID fits in the component table */ 2452 if (ComponentId < KdComponentTableSize) 2453 { 2454 /* It does, so get the mask from there */ 2455 Mask = KdComponentTable[ComponentId]; 2456 } 2457 else if (ComponentId == MAXULONG) 2458 { 2459 /* 2460 * This is the internal ID used for DbgPrint messages without ID 2461 * and Level. Use the system-wide mask for those. 2462 */ 2463 Mask = &Kd_WIN2000_Mask; 2464 } 2465 else 2466 { 2467 #if (NTDDI_VERSION >= NTDDI_VISTA) 2468 /* Use the default component ID */ 2469 Mask = &Kd_DEFAULT_Mask; 2470 #else 2471 /* Invalid ID, fail */ 2472 return STATUS_INVALID_PARAMETER_1; 2473 #endif 2474 } 2475 2476 /* Convert Level to bit field if required */ 2477 if (Level < 32) Level = 1 << Level; 2478 Level &= ~DPFLTR_MASK; 2479 2480 /* Set or remove the Level */ 2481 if (State) 2482 *Mask |= Level; 2483 else 2484 *Mask &= ~Level; 2485 2486 return STATUS_SUCCESS; 2487 } 2488