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)
10 /* INCLUDES ******************************************************************/
16 /* PRIVATE FUNCTIONS *********************************************************/
20 KdpCopyMemoryChunks(IN ULONG64 Address
,
25 OUT PULONG ActualSize OPTIONAL
)
28 ULONG RemainingLength
, CopyChunk
;
30 /* Check if we didn't get a chunk size or if it is too big */
33 /* Default to 4 byte chunks */
36 else if (ChunkSize
> MMDBG_COPY_MAX_SIZE
)
38 /* Normalize to maximum size */
39 ChunkSize
= MMDBG_COPY_MAX_SIZE
;
42 /* Copy the whole range in aligned chunks */
43 RemainingLength
= TotalSize
;
45 while (RemainingLength
> 0)
48 * Determine the best chunk size for this round.
49 * The ideal size is aligned, isn't larger than the
50 * the remaining length and respects the chunk limit.
52 while (((CopyChunk
* 2) <= RemainingLength
) &&
53 (CopyChunk
< ChunkSize
) &&
54 ((Address
& ((CopyChunk
* 2) - 1)) == 0))
61 * The chunk size can be larger than the remaining size if this isn't
62 * the first round, so check if we need to shrink it back
64 while (CopyChunk
> RemainingLength
)
71 Status
= MmDbgCopyMemory(Address
,
75 if (!NT_SUCCESS(Status
))
77 /* Copy failed, break out */
81 /* Update pointers and length for the next run */
82 Address
= Address
+ CopyChunk
;
83 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CopyChunk
);
84 RemainingLength
= RemainingLength
- CopyChunk
;
88 * Return the size we managed to copy
89 * and return success if we could copy the whole range
91 if (ActualSize
) *ActualSize
= TotalSize
- RemainingLength
;
92 return RemainingLength
== 0 ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
97 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
100 PDBGKD_QUERY_MEMORY Memory
= &State
->u
.QueryMemory
;
102 NTSTATUS Status
= STATUS_SUCCESS
;
104 /* Validate the address space */
105 if (Memory
->AddressSpace
== DBGKD_QUERY_MEMORY_VIRTUAL
)
107 /* Check if this is process memory */
108 if ((PVOID
)(ULONG_PTR
)Memory
->Address
< MmHighestUserAddress
)
111 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_PROCESS
;
115 /* Check if it's session space */
116 if (MmIsSessionAddress((PVOID
)(ULONG_PTR
)Memory
->Address
))
119 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_SESSION
;
123 /* Not session space but some other kernel memory */
124 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_KERNEL
;
129 Memory
->Flags
= DBGKD_QUERY_MEMORY_READ
|
130 DBGKD_QUERY_MEMORY_WRITE
|
131 DBGKD_QUERY_MEMORY_EXECUTE
;
136 Status
= STATUS_INVALID_PARAMETER
;
139 /* Return structure */
140 State
->ReturnStatus
= Status
;
141 Memory
->Reserved
= 0;
144 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
145 Header
.Buffer
= (PCHAR
)State
;
147 /* Send the packet */
148 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
156 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
160 //PDBGKD_SEARCH_MEMORY SearchMemory = &State->u.SearchMemory;
164 KdpDprintf("Memory Search support is unimplemented!\n");
166 /* Send a failure packet */
167 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
168 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
169 Header
.Buffer
= (PCHAR
)State
;
170 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
178 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
182 //PDBGKD_FILL_MEMORY FillMemory = &State->u.FillMemory;
186 KdpDprintf("Memory Fill support is unimplemented!\n");
188 /* Send a failure packet */
189 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
190 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
191 Header
.Buffer
= (PCHAR
)State
;
192 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
200 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
204 PDBGKD_WRITE_BREAKPOINT64 Breakpoint
= &State
->u
.WriteBreakPoint
;
208 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
209 Header
.Buffer
= (PCHAR
)State
;
210 ASSERT(Data
->Length
== 0);
212 /* Create the breakpoint */
213 Breakpoint
->BreakPointHandle
=
214 KdpAddBreakpoint((PVOID
)(ULONG_PTR
)Breakpoint
->BreakPointAddress
);
215 if (!Breakpoint
->BreakPointHandle
)
218 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
223 State
->ReturnStatus
= STATUS_SUCCESS
;
226 /* Send the packet */
227 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
235 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
239 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
242 /* Fill out the header */
243 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
244 Header
.Buffer
= (PCHAR
)State
;
245 ASSERT(Data
->Length
== 0);
247 /* Get the version block */
248 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
251 State
->ReturnStatus
= STATUS_SUCCESS
;
256 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
259 /* Send the packet */
260 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
268 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
272 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
276 KdpDprintf("Extended Breakpoint Write support is unimplemented!\n");
278 /* Send a failure packet */
279 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
280 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
281 Header
.Buffer
= (PCHAR
)State
;
282 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
286 return STATUS_UNSUCCESSFUL
;
291 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
295 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
299 KdpDprintf("Extended Breakpoint Restore support is unimplemented!\n");
301 /* Send a failure packet */
302 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
303 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
304 Header
.Buffer
= (PCHAR
)State
;
305 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
313 DumpTraceData(IN PSTRING TraceData
)
315 /* Update the buffer */
316 TraceDataBuffer
[0] = TraceDataBufferPosition
;
318 /* Setup the trace data */
319 TraceData
->Length
= (USHORT
)(TraceDataBufferPosition
* sizeof(ULONG
));
320 TraceData
->Buffer
= (PCHAR
)TraceDataBuffer
;
322 /* Reset the buffer location */
323 TraceDataBufferPosition
= 1;
328 KdpSetCommonState(IN ULONG NewState
,
330 IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
)
332 ULONG InstructionCount
;
333 BOOLEAN HadBreakpoints
;
335 /* Setup common stuff available for all CPU architectures */
336 WaitStateChange
->NewState
= NewState
;
337 WaitStateChange
->ProcessorLevel
= KeProcessorLevel
;
338 WaitStateChange
->Processor
= (USHORT
)KeGetCurrentPrcb()->Number
;
339 WaitStateChange
->NumberProcessors
= (ULONG
)KeNumberProcessors
;
340 WaitStateChange
->Thread
= (ULONG64
)(LONG_PTR
)KeGetCurrentThread();
341 WaitStateChange
->ProgramCounter
= (ULONG64
)(LONG_PTR
)KeGetContextPc(Context
);
343 /* Zero out the entire Control Report */
344 RtlZeroMemory(&WaitStateChange
->AnyControlReport
,
345 sizeof(DBGKD_ANY_CONTROL_REPORT
));
347 /* Now copy the instruction stream and set the count */
348 KdpCopyMemoryChunks((ULONG_PTR
)WaitStateChange
->ProgramCounter
,
349 &WaitStateChange
->ControlReport
.InstructionStream
[0],
354 WaitStateChange
->ControlReport
.InstructionCount
= (USHORT
)InstructionCount
;
356 /* Clear all the breakpoints in this region */
358 KdpDeleteBreakpointRange((PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
359 (PVOID
)((ULONG_PTR
)WaitStateChange
->ProgramCounter
+
360 WaitStateChange
->ControlReport
.InstructionCount
- 1));
363 /* Copy the instruction stream again, this time without breakpoints */
364 KdpCopyMemoryChunks((ULONG_PTR
)WaitStateChange
->ProgramCounter
,
365 &WaitStateChange
->ControlReport
.InstructionStream
[0],
375 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version
)
377 /* Copy the version block */
378 RtlCopyMemory(Version
, &KdVersionBlock
, sizeof(DBGKD_GET_VERSION64
));
383 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State
)
387 /* Fill out the header */
388 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
389 Header
.Buffer
= (PCHAR
)State
;
391 /* Get the version block */
392 KdpSysGetVersion(&State
->u
.GetVersion64
);
394 /* Fill out the state */
395 State
->ApiNumber
= DbgKdGetVersionApi
;
396 State
->ReturnStatus
= STATUS_SUCCESS
;
398 /* Send the packet */
399 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
407 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
411 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
413 ULONG Length
= ReadMemory
->TransferCount
;
415 /* Setup the header */
416 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
417 Header
.Buffer
= (PCHAR
)State
;
418 ASSERT(Data
->Length
== 0);
420 /* Validate length */
421 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
423 /* Overflow, set it to maximum possible */
424 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
428 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
435 /* Return the actual length read */
436 ReadMemory
->ActualBytesRead
= Length
;
437 Data
->Length
= (USHORT
)Length
;
439 /* Send the packet */
440 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
448 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
452 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
455 /* Setup the header */
456 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
457 Header
.Buffer
= (PCHAR
)State
;
460 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
466 &WriteMemory
->ActualBytesWritten
);
468 /* Send the packet */
469 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
477 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
481 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
483 ULONG Length
= ReadMemory
->TransferCount
;
484 ULONG Flags
, CacheFlags
;
486 /* Setup the header */
487 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
488 Header
.Buffer
= (PCHAR
)State
;
489 ASSERT(Data
->Length
== 0);
491 /* Validate length */
492 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
494 /* Overflow, set it to maximum possible */
495 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
498 /* Start with the default flags */
499 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_PHYSICAL
;
501 /* Get the caching flags and check if a type is specified */
502 CacheFlags
= ReadMemory
->ActualBytesRead
;
503 if (CacheFlags
== DBGKD_CACHING_CACHED
)
506 Flags
|= MMDBG_COPY_CACHED
;
508 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
511 Flags
|= MMDBG_COPY_UNCACHED
;
513 else if (CacheFlags
== DBGKD_CACHING_WRITE_COMBINED
)
516 Flags
|= MMDBG_COPY_WRITE_COMBINED
;
520 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
527 /* Return the actual length read */
528 ReadMemory
->ActualBytesRead
= Length
;
529 Data
->Length
= (USHORT
)Length
;
531 /* Send the packet */
532 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
540 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
544 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
546 ULONG Flags
, CacheFlags
;
548 /* Setup the header */
549 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
550 Header
.Buffer
= (PCHAR
)State
;
552 /* Start with the default flags */
553 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_WRITE
| MMDBG_COPY_PHYSICAL
;
555 /* Get the caching flags and check if a type is specified */
556 CacheFlags
= WriteMemory
->ActualBytesWritten
;
557 if (CacheFlags
== DBGKD_CACHING_CACHED
)
560 Flags
|= MMDBG_COPY_CACHED
;
562 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
565 Flags
|= MMDBG_COPY_UNCACHED
;
567 else if (CacheFlags
== DBGKD_CACHING_WRITE_COMBINED
)
570 Flags
|= MMDBG_COPY_WRITE_COMBINED
;
574 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
579 &WriteMemory
->ActualBytesWritten
);
581 /* Send the packet */
582 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
590 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
594 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
598 /* Setup the header */
599 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
600 Header
.Buffer
= (PCHAR
)State
;
601 ASSERT(Data
->Length
== 0);
603 /* Check the length requested */
604 Length
= ReadMemory
->TransferCount
;
605 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
607 /* Use maximum allowed */
608 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
611 /* Call the internal routine */
612 State
->ReturnStatus
= KdpSysReadControlSpace(State
->Processor
,
613 ReadMemory
->TargetBaseAddress
,
618 /* Return the actual length read */
619 ReadMemory
->ActualBytesRead
= Length
;
620 Data
->Length
= (USHORT
)Length
;
623 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
631 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
635 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
638 /* Setup the header */
639 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
640 Header
.Buffer
= (PCHAR
)State
;
642 /* Call the internal routine */
643 State
->ReturnStatus
= KdpSysWriteControlSpace(State
->Processor
,
644 WriteMemory
->TargetBaseAddress
,
647 &WriteMemory
->ActualBytesWritten
);
650 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
658 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
663 PCONTEXT TargetContext
;
665 /* Setup the header */
666 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
667 Header
.Buffer
= (PCHAR
)State
;
668 ASSERT(Data
->Length
== 0);
670 /* Make sure that this is a valid request */
671 if (State
->Processor
< KeNumberProcessors
)
673 /* Check if the request is for this CPU */
674 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
676 /* We're just copying our own context */
677 TargetContext
= Context
;
681 /* Get the context from the PRCB array */
682 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
683 ProcessorState
.ContextFrame
;
686 /* Copy it over to the debugger */
687 RtlCopyMemory(Data
->Buffer
, TargetContext
, sizeof(CONTEXT
));
688 Data
->Length
= sizeof(CONTEXT
);
690 /* Let the debugger set the context now */
691 KdpContextSent
= TRUE
;
694 State
->ReturnStatus
= STATUS_SUCCESS
;
698 /* Invalid request */
699 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
703 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
711 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
716 PCONTEXT TargetContext
;
718 /* Setup the header */
719 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
720 Header
.Buffer
= (PCHAR
)State
;
721 ASSERT(Data
->Length
== sizeof(CONTEXT
));
723 /* Make sure that this is a valid request */
724 if ((State
->Processor
< KeNumberProcessors
) && (KdpContextSent
== TRUE
))
726 /* Check if the request is for this CPU */
727 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
729 /* We're just copying our own context */
730 TargetContext
= Context
;
734 /* Get the context from the PRCB array */
735 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
736 ProcessorState
.ContextFrame
;
739 /* Copy the new context to it */
740 RtlCopyMemory(TargetContext
, Data
->Buffer
, sizeof(CONTEXT
));
743 State
->ReturnStatus
= STATUS_SUCCESS
;
747 /* Invalid request */
748 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
752 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
760 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State
)
762 /* Crash with the special code */
763 KeBugCheck(MANUALLY_INITIATED_CRASH
);
768 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
773 PDBGKD_READ_WRITE_MSR ReadMsr
= &State
->u
.ReadWriteMsr
;
774 LARGE_INTEGER MsrValue
;
776 /* Setup the header */
777 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
778 Header
.Buffer
= (PCHAR
)State
;
779 ASSERT(Data
->Length
== 0);
781 /* Call the internal routine */
782 State
->ReturnStatus
= KdpSysReadMsr(ReadMsr
->Msr
,
785 /* Return the data */
786 ReadMsr
->DataValueLow
= MsrValue
.LowPart
;
787 ReadMsr
->DataValueHigh
= MsrValue
.HighPart
;
790 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
798 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
803 PDBGKD_READ_WRITE_MSR WriteMsr
= &State
->u
.ReadWriteMsr
;
804 LARGE_INTEGER MsrValue
;
806 /* Setup the header */
807 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
808 Header
.Buffer
= (PCHAR
)State
;
809 ASSERT(Data
->Length
== 0);
811 /* Call the internal routine */
812 MsrValue
.LowPart
= WriteMsr
->DataValueLow
;
813 MsrValue
.HighPart
= WriteMsr
->DataValueHigh
;
814 State
->ReturnStatus
= KdpSysWriteMsr(WriteMsr
->Msr
,
818 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
826 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
831 PDBGKD_GET_SET_BUS_DATA GetBusData
= &State
->u
.GetSetBusData
;
834 /* Setup the header */
835 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
836 Header
.Buffer
= (PCHAR
)State
;
837 ASSERT(Data
->Length
== 0);
839 /* Check the length requested */
840 Length
= GetBusData
->Length
;
841 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
843 /* Use maximum allowed */
844 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
847 /* Call the internal routine */
848 State
->ReturnStatus
= KdpSysReadBusData(GetBusData
->BusDataType
,
849 GetBusData
->BusNumber
,
850 GetBusData
->SlotNumber
,
856 /* Return the actual length read */
857 GetBusData
->Length
= Length
;
858 Data
->Length
= (USHORT
)Length
;
861 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
869 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
874 PDBGKD_GET_SET_BUS_DATA SetBusData
= &State
->u
.GetSetBusData
;
877 /* Setup the header */
878 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
879 Header
.Buffer
= (PCHAR
)State
;
881 /* Call the internal routine */
882 State
->ReturnStatus
= KdpSysWriteBusData(SetBusData
->BusDataType
,
883 SetBusData
->BusNumber
,
884 SetBusData
->SlotNumber
,
890 /* Return the actual length written */
891 SetBusData
->Length
= Length
;
894 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
902 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
907 PDBGKD_READ_WRITE_IO64 ReadIo
= &State
->u
.ReadWriteIo
;
909 /* Setup the header */
910 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
911 Header
.Buffer
= (PCHAR
)State
;
912 ASSERT(Data
->Length
== 0);
915 * Clear the value so 1 or 2 byte reads
916 * don't leave the higher bits unmodified
918 ReadIo
->DataValue
= 0;
920 /* Call the internal routine */
921 State
->ReturnStatus
= KdpSysReadIoSpace(Isa
,
930 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
938 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
943 PDBGKD_READ_WRITE_IO64 WriteIo
= &State
->u
.ReadWriteIo
;
945 /* Setup the header */
946 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
947 Header
.Buffer
= (PCHAR
)State
;
948 ASSERT(Data
->Length
== 0);
950 /* Call the internal routine */
951 State
->ReturnStatus
= KdpSysWriteIoSpace(Isa
,
960 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
968 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
973 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended
= &State
->u
.
976 /* Setup the header */
977 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
978 Header
.Buffer
= (PCHAR
)State
;
979 ASSERT(Data
->Length
== 0);
982 * Clear the value so 1 or 2 byte reads
983 * don't leave the higher bits unmodified
985 ReadIoExtended
->DataValue
= 0;
987 /* Call the internal routine */
988 State
->ReturnStatus
= KdpSysReadIoSpace(ReadIoExtended
->InterfaceType
,
989 ReadIoExtended
->BusNumber
,
990 ReadIoExtended
->AddressSpace
,
991 ReadIoExtended
->IoAddress
,
992 &ReadIoExtended
->DataValue
,
993 ReadIoExtended
->DataSize
,
994 &ReadIoExtended
->DataSize
);
997 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1005 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
1007 IN PCONTEXT Context
)
1010 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended
= &State
->u
.
1011 ReadWriteIoExtended
;
1013 /* Setup the header */
1014 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1015 Header
.Buffer
= (PCHAR
)State
;
1016 ASSERT(Data
->Length
== 0);
1018 /* Call the internal routine */
1019 State
->ReturnStatus
= KdpSysReadIoSpace(WriteIoExtended
->InterfaceType
,
1020 WriteIoExtended
->BusNumber
,
1021 WriteIoExtended
->AddressSpace
,
1022 WriteIoExtended
->IoAddress
,
1023 &WriteIoExtended
->DataValue
,
1024 WriteIoExtended
->DataSize
,
1025 &WriteIoExtended
->DataSize
);
1027 /* Send the reply */
1028 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1036 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State
)
1040 /* Setup the header */
1041 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1042 Header
.Buffer
= (PCHAR
)State
;
1044 /* Call the internal routine */
1045 State
->ReturnStatus
= KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE
);
1047 /* Send the reply */
1048 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1056 KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State
)
1061 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
1063 /* Setup the packet */
1064 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1065 Header
.Buffer
= (PCHAR
)State
;
1068 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1076 KdpSendWaitContinue(IN ULONG PacketType
,
1077 IN PSTRING SendHeader
,
1078 IN PSTRING SendData OPTIONAL
,
1079 IN OUT PCONTEXT Context
)
1081 STRING Data
, Header
;
1082 DBGKD_MANIPULATE_STATE64 ManipulateState
;
1086 /* Setup the Manipulate State structure */
1087 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
1088 Header
.Buffer
= (PCHAR
)&ManipulateState
;
1089 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
1090 Data
.Buffer
= KdpMessageBuffer
;
1093 * Reset the context state to ensure the debugger has received
1094 * the current context before it sets it
1096 KdpContextSent
= FALSE
;
1099 /* Send the Packet */
1100 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
1102 /* If the debugger isn't present anymore, just return success */
1103 if (KdDebuggerNotPresent
) return ContinueSuccess
;
1105 /* Main processing Loop */
1111 /* Wait to get a reply to our packet */
1112 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1118 /* If we got a resend request, do it */
1119 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
1120 } while (RecvCode
== KdPacketTimedOut
);
1122 /* Now check what API we got */
1123 switch (ManipulateState
.ApiNumber
)
1125 case DbgKdReadVirtualMemoryApi
:
1127 /* Read virtual memory */
1128 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
1131 case DbgKdWriteVirtualMemoryApi
:
1133 /* Write virtual memory */
1134 KdpWriteVirtualMemory(&ManipulateState
, &Data
, Context
);
1137 case DbgKdGetContextApi
:
1139 /* Get the current context */
1140 KdpGetContext(&ManipulateState
, &Data
, Context
);
1143 case DbgKdSetContextApi
:
1145 /* Set a new context */
1146 KdpSetContext(&ManipulateState
, &Data
, Context
);
1149 case DbgKdWriteBreakPointApi
:
1151 /* Write the breakpoint */
1152 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
1155 case DbgKdRestoreBreakPointApi
:
1157 /* Restore the breakpoint */
1158 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
1161 case DbgKdContinueApi
:
1163 /* Simply continue */
1164 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
1166 case DbgKdReadControlSpaceApi
:
1168 /* Read control space */
1169 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
1172 case DbgKdWriteControlSpaceApi
:
1174 /* Write control space */
1175 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
1178 case DbgKdReadIoSpaceApi
:
1180 /* Read I/O Space */
1181 KdpReadIoSpace(&ManipulateState
, &Data
, Context
);
1184 case DbgKdWriteIoSpaceApi
:
1186 /* Write I/O Space */
1187 KdpWriteIoSpace(&ManipulateState
, &Data
, Context
);
1190 case DbgKdRebootApi
:
1192 /* Reboot the system */
1193 HalReturnToFirmware(HalRebootRoutine
);
1196 case DbgKdContinueApi2
:
1198 /* Check if caller reports success */
1199 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
1201 /* Update the state */
1202 KdpGetStateChange(&ManipulateState
, Context
);
1203 return ContinueSuccess
;
1207 /* Return an error */
1208 return ContinueError
;
1211 case DbgKdReadPhysicalMemoryApi
:
1213 /* Read physical memory */
1214 KdpReadPhysicalmemory(&ManipulateState
, &Data
, Context
);
1217 case DbgKdWritePhysicalMemoryApi
:
1219 /* Write physical memory */
1220 KdpWritePhysicalmemory(&ManipulateState
, &Data
, Context
);
1223 case DbgKdQuerySpecialCallsApi
:
1224 case DbgKdSetSpecialCallApi
:
1225 case DbgKdClearSpecialCallsApi
:
1228 KdpDprintf("Special Call support is unimplemented!\n");
1229 KdpNotSupported(&ManipulateState
);
1232 case DbgKdSetInternalBreakPointApi
:
1233 case DbgKdGetInternalBreakPointApi
:
1236 KdpDprintf("Internal Breakpoint support is unimplemented!\n");
1237 KdpNotSupported(&ManipulateState
);
1240 case DbgKdReadIoSpaceExtendedApi
:
1242 /* Read I/O Space */
1243 KdpReadIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1246 case DbgKdWriteIoSpaceExtendedApi
:
1248 /* Write I/O Space */
1249 KdpWriteIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1252 case DbgKdGetVersionApi
:
1254 /* Get version data */
1255 KdpGetVersion(&ManipulateState
);
1258 case DbgKdWriteBreakPointExApi
:
1260 /* Write the breakpoint and check if it failed */
1261 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState
,
1265 /* Return an error */
1266 return ContinueError
;
1270 case DbgKdRestoreBreakPointExApi
:
1272 /* Restore the breakpoint */
1273 KdpRestoreBreakPointEx(&ManipulateState
, &Data
, Context
);
1276 case DbgKdCauseBugCheckApi
:
1278 /* Crash the system */
1279 KdpCauseBugCheck(&ManipulateState
);
1282 case DbgKdSwitchProcessor
:
1285 KdpDprintf("Processor Switch support is unimplemented!\n");
1286 KdpNotSupported(&ManipulateState
);
1289 case DbgKdPageInApi
:
1292 KdpDprintf("Page-In support is unimplemented!\n");
1293 KdpNotSupported(&ManipulateState
);
1296 case DbgKdReadMachineSpecificRegister
:
1298 /* Read from the specified MSR */
1299 KdpReadMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1302 case DbgKdWriteMachineSpecificRegister
:
1304 /* Write to the specified MSR */
1305 KdpWriteMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1308 case DbgKdSearchMemoryApi
:
1311 KdpSearchMemory(&ManipulateState
, &Data
, Context
);
1314 case DbgKdGetBusDataApi
:
1316 /* Read from the bus */
1317 KdpGetBusData(&ManipulateState
, &Data
, Context
);
1320 case DbgKdSetBusDataApi
:
1322 /* Write to the bus */
1323 KdpSetBusData(&ManipulateState
, &Data
, Context
);
1326 case DbgKdCheckLowMemoryApi
:
1328 /* Check for memory corruption in the lower 4 GB */
1329 KdpCheckLowMemory(&ManipulateState
);
1332 case DbgKdClearAllInternalBreakpointsApi
:
1334 /* Just clear the counter */
1335 KdpNumInternalBreakpoints
= 0;
1338 case DbgKdFillMemoryApi
:
1341 KdpFillMemory(&ManipulateState
, &Data
, Context
);
1344 case DbgKdQueryMemoryApi
:
1347 KdpQueryMemory(&ManipulateState
, Context
);
1350 case DbgKdSwitchPartition
:
1353 KdpDprintf("Partition Switch support is unimplemented!\n");
1354 KdpNotSupported(&ManipulateState
);
1357 case 0x315f: // This one is unknown, but used by WinDbg, keep silent!
1359 /* Setup an empty message, with failure */
1361 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
1364 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1370 /* Unsupported Message */
1373 /* Setup an empty message, with failure */
1374 KdpDprintf("Received Unhandled API %lx\n", ManipulateState
.ApiNumber
);
1376 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
1379 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1390 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
1391 IN PKD_SYMBOLS_INFO SymbolInfo
,
1393 IN OUT PCONTEXT Context
)
1396 STRING Data
, Header
;
1397 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1398 ULONG PathNameLength
;
1399 KCONTINUE_STATUS Status
;
1401 /* Start wait loop */
1404 /* Build the architecture common parts of the message */
1405 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
1409 /* Now finish creating the structure */
1410 KdpSetContextState(&WaitStateChange
, Context
);
1412 /* Fill out load data */
1413 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
1414 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONG64
)(LONG_PTR
)SymbolInfo
->BaseOfDll
;
1415 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
1416 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
1417 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
1419 /* Check if we have a path name */
1422 /* Copy it to the path buffer */
1423 KdpCopyMemoryChunks((ULONG_PTR
)PathName
->Buffer
,
1430 /* Null terminate */
1431 KdpPathBuffer
[PathNameLength
++] = ANSI_NULL
;
1433 /* Set the path length */
1434 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathNameLength
;
1436 /* Set up the data */
1437 Data
.Buffer
= KdpPathBuffer
;
1438 Data
.Length
= (USHORT
)PathNameLength
;
1444 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
1448 /* Setup the header */
1449 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1450 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1452 /* Send the packet */
1453 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1457 } while (Status
== ContinueProcessorReselected
);
1462 KdpReportCommandStringStateChange(IN PSTRING NameString
,
1463 IN PSTRING CommandString
,
1464 IN OUT PCONTEXT Context
)
1466 STRING Header
, Data
;
1467 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1468 ULONG Length
, ActualLength
, TotalLength
;
1469 KCONTINUE_STATUS Status
;
1471 /* Start wait loop */
1474 /* Build the architecture common parts of the message */
1475 KdpSetCommonState(DbgKdCommandStringStateChange
,
1479 /* Set the context */
1480 KdpSetContextState(&WaitStateChange
, Context
);
1482 /* Clear the command string structure */
1483 RtlZeroMemory(&WaitStateChange
.u
.CommandString
,
1484 sizeof(DBGKD_COMMAND_STRING
));
1486 /* Normalize name string to max */
1487 Length
= min(128 - 1, NameString
->Length
);
1489 /* Copy it to the message buffer */
1490 KdpCopyMemoryChunks((ULONG_PTR
)NameString
->Buffer
,
1497 /* Null terminate and calculate the total length */
1498 TotalLength
= ActualLength
;
1499 KdpMessageBuffer
[TotalLength
++] = ANSI_NULL
;
1501 /* Check if the command string is too long */
1502 Length
= CommandString
->Length
;
1503 if (Length
> (PACKET_MAX_SIZE
-
1504 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
) - TotalLength
))
1506 /* Use maximum possible size */
1507 Length
= (PACKET_MAX_SIZE
-
1508 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
) - TotalLength
);
1511 /* Copy it to the message buffer */
1512 KdpCopyMemoryChunks((ULONG_PTR
)CommandString
->Buffer
,
1513 KdpMessageBuffer
+ TotalLength
,
1519 /* Null terminate and calculate the total length */
1520 TotalLength
+= ActualLength
;
1521 KdpMessageBuffer
[TotalLength
++] = ANSI_NULL
;
1523 /* Now set up the header and the data */
1524 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1525 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1526 Data
.Length
= (USHORT
)TotalLength
;
1527 Data
.Buffer
= KdpMessageBuffer
;
1529 /* Send State Change packet and wait for a reply */
1530 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1534 } while (Status
== ContinueProcessorReselected
);
1539 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
1540 IN OUT PCONTEXT Context
,
1541 IN BOOLEAN SecondChanceException
)
1543 STRING Header
, Data
;
1544 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1545 KCONTINUE_STATUS Status
;
1547 /* Start report loop */
1550 /* Build the architecture common parts of the message */
1551 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
1553 /* Copy the Exception Record and set First Chance flag */
1554 #if !defined(_WIN64)
1555 ExceptionRecord32To64((PEXCEPTION_RECORD32
)ExceptionRecord
,
1556 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
1558 RtlCopyMemory(&WaitStateChange
.u
.Exception
.ExceptionRecord
,
1560 sizeof(EXCEPTION_RECORD
));
1562 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
1564 /* Now finish creating the structure */
1565 KdpSetContextState(&WaitStateChange
, Context
);
1567 /* Setup the actual header to send to KD */
1568 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1569 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1571 /* Setup the trace data */
1572 DumpTraceData(&Data
);
1574 /* Send State Change packet and wait for a reply */
1575 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1579 } while (Status
== ContinueProcessorReselected
);
1587 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
1588 IN PVOID DeferredContext
,
1589 IN PVOID SystemArgument1
,
1590 IN PVOID SystemArgument2
)
1592 LONG OldSlip
, NewSlip
, PendingSlip
;
1594 /* Get the current pending slip */
1595 PendingSlip
= KdpTimeSlipPending
;
1598 /* Save the old value and either disable or enable it now. */
1599 OldSlip
= PendingSlip
;
1600 NewSlip
= OldSlip
> 1 ? 1 : 0;
1602 /* Try to change the value */
1603 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1605 OldSlip
) != OldSlip
);
1607 /* If the New Slip value is 1, then do the Time Slipping */
1608 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1613 KdpTimeSlipWork(IN PVOID Context
)
1616 LARGE_INTEGER DueTime
;
1618 /* Update the System time from the CMOS */
1619 ExAcquireTimeRefreshLock(FALSE
);
1620 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1621 ExReleaseTimeRefreshLock();
1623 /* Check if we have a registered Time Slip Event and signal it */
1624 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
1625 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
1626 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
1628 /* Delay the DPC until it runs next time */
1629 DueTime
.QuadPart
= -1800000000;
1630 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1635 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1636 IN OUT PCONTEXT ContextRecord
,
1637 IN BOOLEAN SecondChanceException
)
1641 /* Save the port data */
1644 /* Report a state change */
1645 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1647 SecondChanceException
);
1649 /* Restore the port data and return */
1656 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1658 LARGE_INTEGER Null
= {{0}};
1660 /* Check if interrupts were disabled */
1661 if (!KeGetTrapFrameInterruptState(TrapFrame
))
1663 /* Nothing to return */
1667 /* Otherwise, do the call */
1668 return KeQueryPerformanceCounter(NULL
);
1673 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1674 IN PKEXCEPTION_FRAME ExceptionFrame
)
1678 /* Check if we have a trap frame */
1681 /* Calculate the time difference for the enter */
1682 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1683 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1684 KdTimerStart
.QuadPart
;
1688 /* No trap frame, so can't calculate */
1689 KdTimerStop
.QuadPart
= 0;
1692 /* Save the current IRQL */
1693 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1695 /* Freeze all CPUs */
1696 Enable
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1698 /* Lock the port, save the state and set debugger entered */
1699 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1701 KdEnteredDebugger
= TRUE
;
1703 /* Check freeze flag */
1704 if (KiFreezeFlag
& 1)
1706 /* Print out errror */
1707 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1710 /* Check processor state */
1711 if (KiFreezeFlag
& 2)
1713 /* Print out errror */
1714 KdpDprintf("Some processors not frozen in debugger!\n");
1717 /* Make sure we acquired the port */
1718 if (!KdpPortLocked
) KdpDprintf("Port lock was not acquired!\n");
1720 /* Return if interrupts needs to be re-enabled */
1726 KdExitDebugger(IN BOOLEAN Enable
)
1730 /* Restore the state and unlock the port */
1732 if (KdpPortLocked
) KdpPortUnlock();
1734 /* Unfreeze the CPUs */
1735 KeThawExecution(Enable
);
1737 /* Compare time with the one from KdEnterDebugger */
1738 if (!KdTimerStop
.QuadPart
)
1740 /* We didn't get a trap frame earlier in so never got the time */
1741 KdTimerStart
= KdTimerStop
;
1745 /* Query the timer */
1746 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1749 /* Check if a Time Slip was on queue */
1750 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1753 /* Queue a DPC for the time slip */
1754 InterlockedIncrement(&KdpTimeSlipPending
);
1755 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
); // FIXME: this can trigger context switches!
1761 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock
)
1765 #if defined(__GNUC__)
1766 /* Make gcc happy */
1767 OldIrql
= PASSIVE_LEVEL
;
1770 /* Check if enabling the debugger is blocked */
1773 /* It is, fail the enable */
1774 return STATUS_ACCESS_DENIED
;
1777 /* Check if we need to acquire the lock */
1781 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1785 /* Check if we're not disabled */
1786 if (!KdDisableCount
)
1788 /* Check if we had locked the port before */
1792 KeLowerIrql(OldIrql
);
1795 /* Fail: We're already enabled */
1796 return STATUS_INVALID_PARAMETER
;
1801 * This can only happen if we are called from a bugcheck
1802 * and were never initialized, so initialize the debugger now.
1804 KdInitSystem(0, NULL
);
1806 /* Return success since we initialized */
1807 return STATUS_SUCCESS
;
1811 /* Decrease the disable count */
1812 if (!(--KdDisableCount
))
1814 /* We're now enabled again! Were we enabled before, too? */
1815 if (KdPreviouslyEnabled
)
1817 /* Reinitialize the Debugger */
1818 KdInitSystem(0, NULL
) ;
1819 KdpRestoreAllBreakpoints();
1823 /* Check if we had locked the port before */
1826 /* Yes, now unlock it */
1827 KeLowerIrql(OldIrql
);
1832 return STATUS_SUCCESS
;
1837 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock
)
1842 #if defined(__GNUC__)
1843 /* Make gcc happy */
1844 OldIrql
= PASSIVE_LEVEL
;
1848 * If enabling the debugger is blocked
1849 * then there is nothing to disable (duh)
1854 return STATUS_ACCESS_DENIED
;
1857 /* Check if we need to acquire the lock */
1861 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1865 /* Check if we're not disabled */
1866 if (!KdDisableCount
)
1868 /* Check if the debugger was never actually initialized */
1869 if (!(KdDebuggerEnabled
) && !(KdPitchDebugger
))
1871 /* It wasn't, so don't re-enable it later */
1872 KdPreviouslyEnabled
= FALSE
;
1876 /* It was, so we will re-enable it later */
1877 KdPreviouslyEnabled
= TRUE
;
1880 /* Check if we were called from the exported API and are enabled */
1881 if ((NeedLock
) && (KdPreviouslyEnabled
))
1883 /* Check if it is safe to disable the debugger */
1884 Status
= KdpAllowDisable();
1885 if (!NT_SUCCESS(Status
))
1887 /* Release the lock and fail */
1888 KeLowerIrql(OldIrql
);
1894 /* Only disable the debugger if it is enabled */
1895 if (KdDebuggerEnabled
)
1898 * Disable the debugger; suspend breakpoints
1899 * and reset the debug stub
1901 KdpSuspendAllBreakPoints();
1902 KiDebugRoutine
= KdpStub
;
1904 /* We are disabled now */
1905 KdDebuggerEnabled
= FALSE
;
1906 SharedUserData
->KdDebuggerEnabled
= FALSE
;
1910 /* Increment the disable count */
1913 /* Check if we had locked the port before */
1916 /* Yes, now unlock it */
1917 KeLowerIrql(OldIrql
);
1922 return STATUS_SUCCESS
;
1925 /* PUBLIC FUNCTIONS **********************************************************/
1932 KdEnableDebugger(VOID
)
1934 /* Use the internal routine */
1935 return KdEnableDebuggerWithLock(TRUE
);
1943 KdDisableDebugger(VOID
)
1945 /* Use the internal routine */
1946 return KdDisableDebuggerWithLock(TRUE
);
1954 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
1955 IN PVOID InputBuffer
,
1956 IN ULONG InputBufferLength
,
1957 OUT PVOID OutputBuffer
,
1958 IN ULONG OutputBufferLength
,
1959 IN OUT PULONG ReturnLength
,
1960 IN KPROCESSOR_MODE PreviousMode
)
1962 /* handle sime internal commands */
1963 if (Command
== ' soR')
1965 switch ((ULONG_PTR
)InputBuffer
)
1968 MmDumpArmPfnDatabase(FALSE
);
1971 return STATUS_SUCCESS
;
1974 /* Local kernel debugging is not yet supported */
1975 DbgPrint("KdSystemDebugControl is unimplemented!\n");
1976 return STATUS_NOT_IMPLEMENTED
;
1984 KdChangeOption(IN KD_OPTION Option
,
1985 IN ULONG InBufferBytes OPTIONAL
,
1987 IN ULONG OutBufferBytes OPTIONAL
,
1988 OUT PVOID OutBuffer
,
1989 OUT PULONG OutBufferNeeded OPTIONAL
)
1991 /* Fail if there is no debugger */
1992 if (KdPitchDebugger
)
1994 /* No debugger, no options */
1995 return STATUS_DEBUGGER_INACTIVE
;
1998 /* Do we recognize this option? */
1999 if (Option
!= KD_OPTION_SET_BLOCK_ENABLE
)
2001 /* We don't, clear the output length and fail */
2002 if (OutBufferNeeded
) *OutBufferNeeded
= 0;
2003 return STATUS_INVALID_INFO_CLASS
;
2006 /* Verify parameters */
2007 if ((InBufferBytes
!= sizeof(BOOLEAN
)) ||
2008 (OutBufferBytes
!= 0) ||
2009 (OutBuffer
!= NULL
))
2011 /* Invalid parameters for this option, fail */
2012 return STATUS_INVALID_PARAMETER
;
2016 * Check if the high bit is set, meaning we don't
2017 * allow the debugger to be enabled
2019 if (KdBlockEnable
& 0x80)
2021 /* Fail regardless of what state the caller tried to set */
2022 return STATUS_ACCESS_VIOLATION
;
2025 /* Set the new block enable state */
2026 KdBlockEnable
= *(PBOOLEAN
)InBuffer
;
2028 /* No output buffer required for this option */
2029 if (OutBufferNeeded
) *OutBufferNeeded
= 0;
2032 return STATUS_SUCCESS
;
2040 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
2042 /* Check what power state this is */
2043 if (NewState
== PowerDeviceD0
)
2045 /* Wake up the debug port */
2047 return STATUS_SUCCESS
;
2049 else if ((NewState
== PowerDeviceD1
) ||
2050 (NewState
== PowerDeviceD2
) ||
2051 (NewState
== PowerDeviceD3
))
2053 /* Power down the debug port */
2055 return STATUS_SUCCESS
;
2059 /* Invalid state! */
2060 return STATUS_INVALID_PARAMETER_1
;
2069 KdRefreshDebuggerNotPresent(VOID
)
2071 BOOLEAN Enable
, DebuggerNotPresent
;
2073 /* Check if the debugger is completely disabled */
2074 if (KdPitchDebugger
)
2076 /* Don't try to refresh then -- fail early */
2080 /* Enter the debugger */
2081 Enable
= KdEnterDebugger(NULL
, NULL
);
2084 * Attempt to send a string to the debugger to refresh the
2087 KdpDprintf("KDTARGET: Refreshing KD connection\n");
2089 /* Save the state while we are holding the lock */
2090 DebuggerNotPresent
= KdDebuggerNotPresent
;
2092 /* Exit the debugger and return the state */
2093 KdExitDebugger(Enable
);
2094 return DebuggerNotPresent
;
2102 NtQueryDebugFilterState(IN ULONG ComponentId
,
2107 /* Check if the ID fits in the component table */
2108 if (ComponentId
< KdComponentTableSize
)
2110 /* It does, so get the mask from there */
2111 Mask
= KdComponentTable
[ComponentId
];
2113 else if (ComponentId
== MAXULONG
)
2116 * This is the internal ID used for DbgPrint messages without ID and
2117 * Level. Use the system-wide mask for those.
2119 Mask
= &Kd_WIN2000_Mask
;
2123 /* Invalid ID, fail */
2124 return STATUS_INVALID_PARAMETER_1
;
2127 /* Convert Level to bit field if necessary */
2128 if (Level
< 32) Level
= 1 << Level
;
2130 /* Determine if this Level is filtered out */
2131 if ((Kd_WIN2000_Mask
& Level
) ||
2134 /* This mask will get through to the debugger */
2135 return (NTSTATUS
)TRUE
;
2139 /* This mask is filtered out */
2140 return (NTSTATUS
)FALSE
;
2149 NtSetDebugFilterState(IN ULONG ComponentId
,
2155 /* Modifying debug filters requires the debug privilege */
2156 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
,
2157 ExGetPreviousMode()))
2160 return STATUS_ACCESS_DENIED
;
2163 /* Check if the ID fits in the component table */
2164 if (ComponentId
< KdComponentTableSize
)
2166 /* It does, so get the mask from there */
2167 Mask
= KdComponentTable
[ComponentId
];
2169 else if (ComponentId
== MAXULONG
)
2172 * This is the internal ID used for DbgPrint messages without ID and
2173 * Level. Use the system-wide mask for those.
2175 Mask
= &Kd_WIN2000_Mask
;
2179 /* Invalid ID, fail */
2180 return STATUS_INVALID_PARAMETER_1
;
2183 /* Convert Level to bit field if required */
2184 if (Level
< 32) Level
= 1 << Level
;
2186 /* Check what kind of operation this is */
2194 /* Remove the Level */
2199 return STATUS_SUCCESS
;