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