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 KdpMoveMemory(IN PVOID Destination
,
24 PCHAR DestinationBytes
, SourceBytes
;
26 /* Copy the buffers 1 byte at a time */
27 DestinationBytes
= Destination
;
29 while (Length
--) *DestinationBytes
++ = *SourceBytes
++;
34 KdpZeroMemory(IN PVOID Destination
,
37 PCHAR DestinationBytes
;
39 /* Zero the buffer 1 byte at a time */
40 DestinationBytes
= Destination
;
41 while (Length
--) *DestinationBytes
++ = 0;
46 KdpCopyMemoryChunks(IN ULONG64 Address
,
51 OUT PULONG ActualSize OPTIONAL
)
54 ULONG RemainingLength
, CopyChunk
;
56 /* Check if we didn't get a chunk size or if it is too big */
59 /* Default to 4 byte chunks */
62 else if (ChunkSize
> MMDBG_COPY_MAX_SIZE
)
64 /* Normalize to maximum size */
65 ChunkSize
= MMDBG_COPY_MAX_SIZE
;
68 /* Copy the whole range in aligned chunks */
69 RemainingLength
= TotalSize
;
71 while (RemainingLength
> 0)
74 * Determine the best chunk size for this round.
75 * The ideal size is aligned, isn't larger than the
76 * the remaining length and respects the chunk limit.
78 while (((CopyChunk
* 2) <= RemainingLength
) &&
79 (CopyChunk
< ChunkSize
) &&
80 ((Address
& ((CopyChunk
* 2) - 1)) == 0))
87 * The chunk size can be larger than the remaining size if this isn't
88 * the first round, so check if we need to shrink it back
90 while (CopyChunk
> RemainingLength
)
97 Status
= MmDbgCopyMemory(Address
,
101 if (!NT_SUCCESS(Status
))
103 /* Copy failed, break out */
107 /* Update pointers and length for the next run */
108 Address
= Address
+ CopyChunk
;
109 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CopyChunk
);
110 RemainingLength
= RemainingLength
- CopyChunk
;
114 * We may have modified executable code, flush the instruction cache
116 KeSweepICache((PVOID
)(ULONG_PTR
)Address
, TotalSize
);
119 * Return the size we managed to copy
120 * and return success if we could copy the whole range
122 if (ActualSize
) *ActualSize
= TotalSize
- RemainingLength
;
123 return RemainingLength
== 0 ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
128 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
131 PDBGKD_QUERY_MEMORY Memory
= &State
->u
.QueryMemory
;
133 NTSTATUS Status
= STATUS_SUCCESS
;
135 /* Validate the address space */
136 if (Memory
->AddressSpace
== DBGKD_QUERY_MEMORY_VIRTUAL
)
138 /* Check if this is process memory */
139 if ((PVOID
)(ULONG_PTR
)Memory
->Address
< MmHighestUserAddress
)
142 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_PROCESS
;
146 /* Check if it's session space */
147 if (MmIsSessionAddress((PVOID
)(ULONG_PTR
)Memory
->Address
))
150 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_SESSION
;
154 /* Not session space but some other kernel memory */
155 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_KERNEL
;
160 Memory
->Flags
= DBGKD_QUERY_MEMORY_READ
|
161 DBGKD_QUERY_MEMORY_WRITE
|
162 DBGKD_QUERY_MEMORY_EXECUTE
;
167 Status
= STATUS_INVALID_PARAMETER
;
170 /* Return structure */
171 State
->ReturnStatus
= Status
;
172 Memory
->Reserved
= 0;
175 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
176 Header
.Buffer
= (PCHAR
)State
;
178 /* Send the packet */
179 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
187 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
191 //PDBGKD_SEARCH_MEMORY SearchMemory = &State->u.SearchMemory;
195 KdpDprintf("Memory Search support is unimplemented!\n");
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
,
209 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
213 //PDBGKD_FILL_MEMORY FillMemory = &State->u.FillMemory;
217 KdpDprintf("Memory Fill support is unimplemented!\n");
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
,
231 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
235 PDBGKD_WRITE_BREAKPOINT64 Breakpoint
= &State
->u
.WriteBreakPoint
;
239 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
240 Header
.Buffer
= (PCHAR
)State
;
241 ASSERT(Data
->Length
== 0);
243 /* Create the breakpoint */
244 Breakpoint
->BreakPointHandle
=
245 KdpAddBreakpoint((PVOID
)(ULONG_PTR
)Breakpoint
->BreakPointAddress
);
246 if (!Breakpoint
->BreakPointHandle
)
249 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
254 State
->ReturnStatus
= STATUS_SUCCESS
;
257 /* Send the packet */
258 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
266 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
270 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
273 /* Fill out the header */
274 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
275 Header
.Buffer
= (PCHAR
)State
;
276 ASSERT(Data
->Length
== 0);
278 /* Get the version block */
279 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
282 State
->ReturnStatus
= STATUS_SUCCESS
;
287 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
290 /* Send the packet */
291 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
299 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
303 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
307 KdpDprintf("Extended Breakpoint Write support is unimplemented!\n");
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
,
317 return STATUS_UNSUCCESSFUL
;
322 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
326 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
330 KdpDprintf("Extended Breakpoint Restore support is unimplemented!\n");
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
,
344 KdpWriteCustomBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
348 //PDBGKD_WRITE_CUSTOM_BREAKPOINT = &State->u.WriteCustomBreakpoint;
352 KdpDprintf("Custom Breakpoint Write is unimplemented\n");
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
,
366 DumpTraceData(IN PSTRING TraceData
)
368 /* Update the buffer */
369 TraceDataBuffer
[0] = TraceDataBufferPosition
;
371 /* Setup the trace data */
372 TraceData
->Length
= (USHORT
)(TraceDataBufferPosition
* sizeof(ULONG
));
373 TraceData
->Buffer
= (PCHAR
)TraceDataBuffer
;
375 /* Reset the buffer location */
376 TraceDataBufferPosition
= 1;
381 KdpSetCommonState(IN ULONG NewState
,
383 IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
)
385 ULONG InstructionCount
;
386 BOOLEAN HadBreakpoints
;
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
);
396 /* Zero out the entire Control Report */
397 KdpZeroMemory(&WaitStateChange
->AnyControlReport
,
398 sizeof(DBGKD_ANY_CONTROL_REPORT
));
400 /* Now copy the instruction stream and set the count */
401 KdpCopyMemoryChunks((ULONG_PTR
)WaitStateChange
->ProgramCounter
,
402 &WaitStateChange
->ControlReport
.InstructionStream
[0],
407 WaitStateChange
->ControlReport
.InstructionCount
= (USHORT
)InstructionCount
;
409 /* Clear all the breakpoints in this region */
411 KdpDeleteBreakpointRange((PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
412 (PVOID
)((ULONG_PTR
)WaitStateChange
->ProgramCounter
+
413 WaitStateChange
->ControlReport
.InstructionCount
- 1));
416 /* Copy the instruction stream again, this time without breakpoints */
417 KdpCopyMemoryChunks((ULONG_PTR
)WaitStateChange
->ProgramCounter
,
418 &WaitStateChange
->ControlReport
.InstructionStream
[0],
428 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version
)
430 /* Copy the version block */
431 KdpMoveMemory(Version
,
433 sizeof(DBGKD_GET_VERSION64
));
438 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State
)
442 /* Fill out the header */
443 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
444 Header
.Buffer
= (PCHAR
)State
;
446 /* Get the version block */
447 KdpSysGetVersion(&State
->u
.GetVersion64
);
449 /* Fill out the state */
450 State
->ApiNumber
= DbgKdGetVersionApi
;
451 State
->ReturnStatus
= STATUS_SUCCESS
;
453 /* Send the packet */
454 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
462 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
466 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
468 ULONG Length
= ReadMemory
->TransferCount
;
470 /* Setup the header */
471 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
472 Header
.Buffer
= (PCHAR
)State
;
473 ASSERT(Data
->Length
== 0);
475 /* Validate length */
476 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
478 /* Overflow, set it to maximum possible */
479 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
483 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
490 /* Return the actual length read */
491 ReadMemory
->ActualBytesRead
= Length
;
492 Data
->Length
= (USHORT
)Length
;
494 /* Send the packet */
495 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
503 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
507 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
510 /* Setup the header */
511 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
512 Header
.Buffer
= (PCHAR
)State
;
515 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
521 &WriteMemory
->ActualBytesWritten
);
523 /* Send the packet */
524 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
532 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
536 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
538 ULONG Length
= ReadMemory
->TransferCount
;
539 ULONG Flags
, CacheFlags
;
541 /* Setup the header */
542 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
543 Header
.Buffer
= (PCHAR
)State
;
544 ASSERT(Data
->Length
== 0);
546 /* Validate length */
547 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
549 /* Overflow, set it to maximum possible */
550 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
553 /* Start with the default flags */
554 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_PHYSICAL
;
556 /* Get the caching flags and check if a type is specified */
557 CacheFlags
= ReadMemory
->ActualBytesRead
;
558 if (CacheFlags
== DBGKD_CACHING_CACHED
)
561 Flags
|= MMDBG_COPY_CACHED
;
563 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
566 Flags
|= MMDBG_COPY_UNCACHED
;
568 else if (CacheFlags
== DBGKD_CACHING_WRITE_COMBINED
)
571 Flags
|= MMDBG_COPY_WRITE_COMBINED
;
575 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
582 /* Return the actual length read */
583 ReadMemory
->ActualBytesRead
= Length
;
584 Data
->Length
= (USHORT
)Length
;
586 /* Send the packet */
587 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
595 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
599 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
601 ULONG Flags
, CacheFlags
;
603 /* Setup the header */
604 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
605 Header
.Buffer
= (PCHAR
)State
;
607 /* Start with the default flags */
608 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_WRITE
| MMDBG_COPY_PHYSICAL
;
610 /* Get the caching flags and check if a type is specified */
611 CacheFlags
= WriteMemory
->ActualBytesWritten
;
612 if (CacheFlags
== DBGKD_CACHING_CACHED
)
615 Flags
|= MMDBG_COPY_CACHED
;
617 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
620 Flags
|= MMDBG_COPY_UNCACHED
;
622 else if (CacheFlags
== DBGKD_CACHING_WRITE_COMBINED
)
625 Flags
|= MMDBG_COPY_WRITE_COMBINED
;
629 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
634 &WriteMemory
->ActualBytesWritten
);
636 /* Send the packet */
637 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
645 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
649 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
653 /* Setup the header */
654 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
655 Header
.Buffer
= (PCHAR
)State
;
656 ASSERT(Data
->Length
== 0);
658 /* Check the length requested */
659 Length
= ReadMemory
->TransferCount
;
660 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
662 /* Use maximum allowed */
663 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
666 /* Call the internal routine */
667 State
->ReturnStatus
= KdpSysReadControlSpace(State
->Processor
,
668 ReadMemory
->TargetBaseAddress
,
673 /* Return the actual length read */
674 ReadMemory
->ActualBytesRead
= Length
;
675 Data
->Length
= (USHORT
)Length
;
678 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
686 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
690 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
693 /* Setup the header */
694 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
695 Header
.Buffer
= (PCHAR
)State
;
697 /* Call the internal routine */
698 State
->ReturnStatus
= KdpSysWriteControlSpace(State
->Processor
,
699 WriteMemory
->TargetBaseAddress
,
702 &WriteMemory
->ActualBytesWritten
);
705 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
713 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
718 PCONTEXT TargetContext
;
720 /* Setup the header */
721 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
722 Header
.Buffer
= (PCHAR
)State
;
723 ASSERT(Data
->Length
== 0);
725 /* Make sure that this is a valid request */
726 if (State
->Processor
< KeNumberProcessors
)
728 /* Check if the request is for this CPU */
729 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
731 /* We're just copying our own context */
732 TargetContext
= Context
;
736 /* Get the context from the PRCB array */
737 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
738 ProcessorState
.ContextFrame
;
741 /* Copy it over to the debugger */
742 KdpMoveMemory(Data
->Buffer
,
745 Data
->Length
= sizeof(CONTEXT
);
747 /* Let the debugger set the context now */
748 KdpContextSent
= TRUE
;
751 State
->ReturnStatus
= STATUS_SUCCESS
;
755 /* Invalid request */
756 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
760 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
768 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
773 PCONTEXT TargetContext
;
775 /* Setup the header */
776 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
777 Header
.Buffer
= (PCHAR
)State
;
778 ASSERT(Data
->Length
== sizeof(CONTEXT
));
780 /* Make sure that this is a valid request */
781 if ((State
->Processor
< KeNumberProcessors
) &&
784 /* Check if the request is for this CPU */
785 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
787 /* We're just copying our own context */
788 TargetContext
= Context
;
792 /* Get the context from the PRCB array */
793 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
794 ProcessorState
.ContextFrame
;
797 /* Copy the new context to it */
798 KdpMoveMemory(TargetContext
,
803 State
->ReturnStatus
= STATUS_SUCCESS
;
807 /* Invalid request */
808 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
812 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
820 KdpGetContextEx(IN PDBGKD_MANIPULATE_STATE64 State
,
825 PDBGKD_CONTEXT_EX ContextEx
;
826 PCONTEXT TargetContext
;
827 ASSERT(Data
->Length
== 0);
830 ContextEx
= &State
->u
.ContextEx
;
832 /* Set up the header */
833 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
834 Header
.Buffer
= (PCHAR
)State
;
836 /* Make sure that this is a valid request */
837 if ((State
->Processor
< KeNumberProcessors
) &&
838 (ContextEx
->Offset
+ ContextEx
->ByteCount
) <= sizeof(CONTEXT
))
840 /* Check if the request is for this CPU */
841 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
843 /* We're just copying our own context */
844 TargetContext
= Context
;
848 /* Get the context from the PRCB array */
849 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
850 ProcessorState
.ContextFrame
;
853 /* Copy what is requested */
854 KdpMoveMemory(Data
->Buffer
,
855 (PVOID
)((ULONG_PTR
)TargetContext
+ ContextEx
->Offset
),
856 ContextEx
->ByteCount
);
859 Data
->Length
= ContextEx
->BytesCopied
= ContextEx
->ByteCount
;
861 /* Let the debugger set the context now */
862 KdpContextSent
= TRUE
;
865 State
->ReturnStatus
= STATUS_SUCCESS
;
869 /* Invalid request */
870 ContextEx
->BytesCopied
= 0;
871 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
875 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
883 KdpSetContextEx(IN PDBGKD_MANIPULATE_STATE64 State
,
888 PDBGKD_CONTEXT_EX ContextEx
;
889 PCONTEXT TargetContext
;
892 ContextEx
= &State
->u
.ContextEx
;
893 ASSERT(Data
->Length
== ContextEx
->ByteCount
);
895 /* Set up the header */
896 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
897 Header
.Buffer
= (PCHAR
)State
;
899 /* Make sure that this is a valid request */
900 if ((State
->Processor
< KeNumberProcessors
) &&
901 ((ContextEx
->Offset
+ ContextEx
->ByteCount
) <= sizeof(CONTEXT
)) &&
904 /* Check if the request is for this CPU */
905 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
907 /* We're just copying our own context */
908 TargetContext
= Context
;
912 /* Get the context from the PRCB array */
913 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
914 ProcessorState
.ContextFrame
;
917 /* Copy what is requested */
918 KdpMoveMemory((PVOID
)((ULONG_PTR
)TargetContext
+ ContextEx
->Offset
),
920 ContextEx
->ByteCount
);
923 ContextEx
->BytesCopied
= ContextEx
->ByteCount
;
926 State
->ReturnStatus
= STATUS_SUCCESS
;
930 /* Invalid request */
931 ContextEx
->BytesCopied
= 0;
932 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
936 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
944 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State
)
946 /* Crash with the special code */
947 KeBugCheck(MANUALLY_INITIATED_CRASH
);
952 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
957 PDBGKD_READ_WRITE_MSR ReadMsr
= &State
->u
.ReadWriteMsr
;
958 LARGE_INTEGER MsrValue
;
960 /* Setup the header */
961 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
962 Header
.Buffer
= (PCHAR
)State
;
963 ASSERT(Data
->Length
== 0);
965 /* Call the internal routine */
966 State
->ReturnStatus
= KdpSysReadMsr(ReadMsr
->Msr
,
969 /* Return the data */
970 ReadMsr
->DataValueLow
= MsrValue
.LowPart
;
971 ReadMsr
->DataValueHigh
= MsrValue
.HighPart
;
974 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
982 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
987 PDBGKD_READ_WRITE_MSR WriteMsr
= &State
->u
.ReadWriteMsr
;
988 LARGE_INTEGER MsrValue
;
990 /* Setup the header */
991 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
992 Header
.Buffer
= (PCHAR
)State
;
993 ASSERT(Data
->Length
== 0);
995 /* Call the internal routine */
996 MsrValue
.LowPart
= WriteMsr
->DataValueLow
;
997 MsrValue
.HighPart
= WriteMsr
->DataValueHigh
;
998 State
->ReturnStatus
= KdpSysWriteMsr(WriteMsr
->Msr
,
1001 /* Send the reply */
1002 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1010 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
1012 IN PCONTEXT Context
)
1015 PDBGKD_GET_SET_BUS_DATA GetBusData
= &State
->u
.GetSetBusData
;
1018 /* Setup the header */
1019 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1020 Header
.Buffer
= (PCHAR
)State
;
1021 ASSERT(Data
->Length
== 0);
1023 /* Check the length requested */
1024 Length
= GetBusData
->Length
;
1025 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
1027 /* Use maximum allowed */
1028 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
1031 /* Call the internal routine */
1032 State
->ReturnStatus
= KdpSysReadBusData(GetBusData
->BusDataType
,
1033 GetBusData
->BusNumber
,
1034 GetBusData
->SlotNumber
,
1040 /* Return the actual length read */
1041 GetBusData
->Length
= Length
;
1042 Data
->Length
= (USHORT
)Length
;
1044 /* Send the reply */
1045 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1053 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
1055 IN PCONTEXT Context
)
1058 PDBGKD_GET_SET_BUS_DATA SetBusData
= &State
->u
.GetSetBusData
;
1061 /* Setup the header */
1062 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1063 Header
.Buffer
= (PCHAR
)State
;
1065 /* Call the internal routine */
1066 State
->ReturnStatus
= KdpSysWriteBusData(SetBusData
->BusDataType
,
1067 SetBusData
->BusNumber
,
1068 SetBusData
->SlotNumber
,
1074 /* Return the actual length written */
1075 SetBusData
->Length
= Length
;
1077 /* Send the reply */
1078 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1086 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
1088 IN PCONTEXT Context
)
1091 PDBGKD_READ_WRITE_IO64 ReadIo
= &State
->u
.ReadWriteIo
;
1093 /* Setup the header */
1094 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1095 Header
.Buffer
= (PCHAR
)State
;
1096 ASSERT(Data
->Length
== 0);
1099 * Clear the value so 1 or 2 byte reads
1100 * don't leave the higher bits unmodified
1102 ReadIo
->DataValue
= 0;
1104 /* Call the internal routine */
1105 State
->ReturnStatus
= KdpSysReadIoSpace(Isa
,
1113 /* Send the reply */
1114 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1122 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
1124 IN PCONTEXT Context
)
1127 PDBGKD_READ_WRITE_IO64 WriteIo
= &State
->u
.ReadWriteIo
;
1129 /* Setup the header */
1130 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1131 Header
.Buffer
= (PCHAR
)State
;
1132 ASSERT(Data
->Length
== 0);
1134 /* Call the internal routine */
1135 State
->ReturnStatus
= KdpSysWriteIoSpace(Isa
,
1139 &WriteIo
->DataValue
,
1141 &WriteIo
->DataSize
);
1143 /* Send the reply */
1144 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1152 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
1154 IN PCONTEXT Context
)
1157 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended
= &State
->u
.
1158 ReadWriteIoExtended
;
1160 /* Setup the header */
1161 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1162 Header
.Buffer
= (PCHAR
)State
;
1163 ASSERT(Data
->Length
== 0);
1166 * Clear the value so 1 or 2 byte reads
1167 * don't leave the higher bits unmodified
1169 ReadIoExtended
->DataValue
= 0;
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
);
1180 /* Send the reply */
1181 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1189 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
1191 IN PCONTEXT Context
)
1194 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended
= &State
->u
.
1195 ReadWriteIoExtended
;
1197 /* Setup the header */
1198 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1199 Header
.Buffer
= (PCHAR
)State
;
1200 ASSERT(Data
->Length
== 0);
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
);
1211 /* Send the reply */
1212 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1220 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State
)
1224 /* Setup the header */
1225 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1226 Header
.Buffer
= (PCHAR
)State
;
1228 /* Call the internal routine */
1229 State
->ReturnStatus
= KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE
);
1231 /* Send the reply */
1232 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1240 KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State
)
1245 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
1247 /* Setup the packet */
1248 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1249 Header
.Buffer
= (PCHAR
)State
;
1252 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1260 KdpSendWaitContinue(IN ULONG PacketType
,
1261 IN PSTRING SendHeader
,
1262 IN PSTRING SendData OPTIONAL
,
1263 IN OUT PCONTEXT Context
)
1265 STRING Data
, Header
;
1266 DBGKD_MANIPULATE_STATE64 ManipulateState
;
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
;
1277 * Reset the context state to ensure the debugger has received
1278 * the current context before it sets it
1280 KdpContextSent
= FALSE
;
1283 /* Send the Packet */
1284 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
1286 /* If the debugger isn't present anymore, just return success */
1287 if (KdDebuggerNotPresent
) return ContinueSuccess
;
1289 /* Main processing Loop */
1295 /* Wait to get a reply to our packet */
1296 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1302 /* If we got a resend request, do it */
1303 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
1304 } while (RecvCode
== KdPacketTimedOut
);
1306 /* Now check what API we got */
1307 switch (ManipulateState
.ApiNumber
)
1309 case DbgKdReadVirtualMemoryApi
:
1311 /* Read virtual memory */
1312 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
1315 case DbgKdWriteVirtualMemoryApi
:
1317 /* Write virtual memory */
1318 KdpWriteVirtualMemory(&ManipulateState
, &Data
, Context
);
1321 case DbgKdGetContextApi
:
1323 /* Get the current context */
1324 KdpGetContext(&ManipulateState
, &Data
, Context
);
1327 case DbgKdSetContextApi
:
1329 /* Set a new context */
1330 KdpSetContext(&ManipulateState
, &Data
, Context
);
1333 case DbgKdWriteBreakPointApi
:
1335 /* Write the breakpoint */
1336 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
1339 case DbgKdRestoreBreakPointApi
:
1341 /* Restore the breakpoint */
1342 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
1345 case DbgKdContinueApi
:
1347 /* Simply continue */
1348 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
1350 case DbgKdReadControlSpaceApi
:
1352 /* Read control space */
1353 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
1356 case DbgKdWriteControlSpaceApi
:
1358 /* Write control space */
1359 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
1362 case DbgKdReadIoSpaceApi
:
1364 /* Read I/O Space */
1365 KdpReadIoSpace(&ManipulateState
, &Data
, Context
);
1368 case DbgKdWriteIoSpaceApi
:
1370 /* Write I/O Space */
1371 KdpWriteIoSpace(&ManipulateState
, &Data
, Context
);
1374 case DbgKdRebootApi
:
1376 /* Reboot the system */
1377 HalReturnToFirmware(HalRebootRoutine
);
1380 case DbgKdContinueApi2
:
1382 /* Check if caller reports success */
1383 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
1385 /* Update the state */
1386 KdpGetStateChange(&ManipulateState
, Context
);
1387 return ContinueSuccess
;
1391 /* Return an error */
1392 return ContinueError
;
1395 case DbgKdReadPhysicalMemoryApi
:
1397 /* Read physical memory */
1398 KdpReadPhysicalmemory(&ManipulateState
, &Data
, Context
);
1401 case DbgKdWritePhysicalMemoryApi
:
1403 /* Write physical memory */
1404 KdpWritePhysicalmemory(&ManipulateState
, &Data
, Context
);
1407 case DbgKdQuerySpecialCallsApi
:
1408 case DbgKdSetSpecialCallApi
:
1409 case DbgKdClearSpecialCallsApi
:
1412 KdpDprintf("Special Call support is unimplemented!\n");
1413 KdpNotSupported(&ManipulateState
);
1416 case DbgKdSetInternalBreakPointApi
:
1417 case DbgKdGetInternalBreakPointApi
:
1420 KdpDprintf("Internal Breakpoint support is unimplemented!\n");
1421 KdpNotSupported(&ManipulateState
);
1424 case DbgKdReadIoSpaceExtendedApi
:
1426 /* Read I/O Space */
1427 KdpReadIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1430 case DbgKdWriteIoSpaceExtendedApi
:
1432 /* Write I/O Space */
1433 KdpWriteIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1436 case DbgKdGetVersionApi
:
1438 /* Get version data */
1439 KdpGetVersion(&ManipulateState
);
1442 case DbgKdWriteBreakPointExApi
:
1444 /* Write the breakpoint and check if it failed */
1445 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState
,
1449 /* Return an error */
1450 return ContinueError
;
1454 case DbgKdRestoreBreakPointExApi
:
1456 /* Restore the breakpoint */
1457 KdpRestoreBreakPointEx(&ManipulateState
, &Data
, Context
);
1460 case DbgKdCauseBugCheckApi
:
1462 /* Crash the system */
1463 KdpCauseBugCheck(&ManipulateState
);
1466 case DbgKdSwitchProcessor
:
1469 KdpDprintf("Processor Switch support is unimplemented!\n");
1470 KdpNotSupported(&ManipulateState
);
1473 case DbgKdPageInApi
:
1476 KdpDprintf("Page-In support is unimplemented!\n");
1477 KdpNotSupported(&ManipulateState
);
1480 case DbgKdReadMachineSpecificRegister
:
1482 /* Read from the specified MSR */
1483 KdpReadMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1486 case DbgKdWriteMachineSpecificRegister
:
1488 /* Write to the specified MSR */
1489 KdpWriteMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1492 case DbgKdSearchMemoryApi
:
1495 KdpSearchMemory(&ManipulateState
, &Data
, Context
);
1498 case DbgKdGetBusDataApi
:
1500 /* Read from the bus */
1501 KdpGetBusData(&ManipulateState
, &Data
, Context
);
1504 case DbgKdSetBusDataApi
:
1506 /* Write to the bus */
1507 KdpSetBusData(&ManipulateState
, &Data
, Context
);
1510 case DbgKdCheckLowMemoryApi
:
1512 /* Check for memory corruption in the lower 4 GB */
1513 KdpCheckLowMemory(&ManipulateState
);
1516 case DbgKdClearAllInternalBreakpointsApi
:
1518 /* Just clear the counter */
1519 KdpNumInternalBreakpoints
= 0;
1522 case DbgKdFillMemoryApi
:
1525 KdpFillMemory(&ManipulateState
, &Data
, Context
);
1528 case DbgKdQueryMemoryApi
:
1531 KdpQueryMemory(&ManipulateState
, Context
);
1534 case DbgKdSwitchPartition
:
1537 KdpDprintf("Partition Switch support is unimplemented!\n");
1538 KdpNotSupported(&ManipulateState
);
1541 case DbgKdWriteCustomBreakpointApi
:
1543 /* Write the customized breakpoint */
1544 KdpWriteCustomBreakpoint(&ManipulateState
, &Data
, Context
);
1547 case DbgKdGetContextExApi
:
1549 /* Extended Context Get */
1550 KdpGetContextEx(&ManipulateState
, &Data
, Context
);
1553 case DbgKdSetContextExApi
:
1555 /* Extended Context Set */
1556 KdpSetContextEx(&ManipulateState
, &Data
, Context
);
1559 /* Unsupported Messages */
1563 KdpDprintf("Received Unrecognized API 0x%lx\n", ManipulateState
.ApiNumber
);
1565 /* Setup an empty message, with failure */
1567 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
1570 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1581 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
1582 IN PKD_SYMBOLS_INFO SymbolInfo
,
1584 IN OUT PCONTEXT Context
)
1587 STRING Data
, Header
;
1588 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1589 ULONG PathNameLength
;
1590 KCONTINUE_STATUS Status
;
1592 /* Start wait loop */
1595 /* Build the architecture common parts of the message */
1596 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
1600 /* Now finish creating the structure */
1601 KdpSetContextState(&WaitStateChange
, Context
);
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
;
1610 /* Check if we have a path name */
1613 /* Copy it to the path buffer */
1614 KdpCopyMemoryChunks((ULONG_PTR
)PathName
->Buffer
,
1621 /* Null terminate */
1622 KdpPathBuffer
[PathNameLength
++] = ANSI_NULL
;
1624 /* Set the path length */
1625 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathNameLength
;
1627 /* Set up the data */
1628 Data
.Buffer
= KdpPathBuffer
;
1629 Data
.Length
= (USHORT
)PathNameLength
;
1635 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
1639 /* Setup the header */
1640 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1641 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1643 /* Send the packet */
1644 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1648 } while (Status
== ContinueProcessorReselected
);
1653 KdpReportCommandStringStateChange(IN PSTRING NameString
,
1654 IN PSTRING CommandString
,
1655 IN OUT PCONTEXT Context
)
1657 STRING Header
, Data
;
1658 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1659 ULONG Length
, ActualLength
, TotalLength
;
1660 KCONTINUE_STATUS Status
;
1662 /* Start wait loop */
1665 /* Build the architecture common parts of the message */
1666 KdpSetCommonState(DbgKdCommandStringStateChange
,
1670 /* Set the context */
1671 KdpSetContextState(&WaitStateChange
, Context
);
1673 /* Clear the command string structure */
1674 KdpZeroMemory(&WaitStateChange
.u
.CommandString
,
1675 sizeof(DBGKD_COMMAND_STRING
));
1677 /* Normalize name string to max */
1678 Length
= min(128 - 1, NameString
->Length
);
1680 /* Copy it to the message buffer */
1681 KdpCopyMemoryChunks((ULONG_PTR
)NameString
->Buffer
,
1688 /* Null terminate and calculate the total length */
1689 TotalLength
= ActualLength
;
1690 KdpMessageBuffer
[TotalLength
++] = ANSI_NULL
;
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
))
1697 /* Use maximum possible size */
1698 Length
= (PACKET_MAX_SIZE
-
1699 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
) - TotalLength
);
1702 /* Copy it to the message buffer */
1703 KdpCopyMemoryChunks((ULONG_PTR
)CommandString
->Buffer
,
1704 KdpMessageBuffer
+ TotalLength
,
1710 /* Null terminate and calculate the total length */
1711 TotalLength
+= ActualLength
;
1712 KdpMessageBuffer
[TotalLength
++] = ANSI_NULL
;
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
;
1720 /* Send State Change packet and wait for a reply */
1721 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1725 } while (Status
== ContinueProcessorReselected
);
1730 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
1731 IN OUT PCONTEXT Context
,
1732 IN BOOLEAN SecondChanceException
)
1734 STRING Header
, Data
;
1735 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1736 KCONTINUE_STATUS Status
;
1738 /* Start report loop */
1741 /* Build the architecture common parts of the message */
1742 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
1744 #if !defined(_WIN64)
1746 /* Convert it and copy it over */
1747 ExceptionRecord32To64((PEXCEPTION_RECORD32
)ExceptionRecord
,
1748 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
1752 /* Just copy it directly, no need to convert */
1753 KdpMoveMemory(&WaitStateChange
.u
.Exception
.ExceptionRecord
,
1755 sizeof(EXCEPTION_RECORD
));
1759 /* Set the First Chance flag */
1760 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
1762 /* Now finish creating the structure */
1763 KdpSetContextState(&WaitStateChange
, Context
);
1765 /* Setup the actual header to send to KD */
1766 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1767 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1769 /* Setup the trace data */
1770 DumpTraceData(&Data
);
1772 /* Send State Change packet and wait for a reply */
1773 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1777 } while (Status
== ContinueProcessorReselected
);
1785 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
1786 IN PVOID DeferredContext
,
1787 IN PVOID SystemArgument1
,
1788 IN PVOID SystemArgument2
)
1790 LONG OldSlip
, NewSlip
, PendingSlip
;
1792 /* Get the current pending slip */
1793 PendingSlip
= KdpTimeSlipPending
;
1796 /* Save the old value and either disable or enable it now. */
1797 OldSlip
= PendingSlip
;
1798 NewSlip
= OldSlip
> 1 ? 1 : 0;
1800 /* Try to change the value */
1801 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1803 OldSlip
) != OldSlip
);
1805 /* If the New Slip value is 1, then do the Time Slipping */
1806 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1811 KdpTimeSlipWork(IN PVOID Context
)
1814 LARGE_INTEGER DueTime
;
1816 /* Update the System time from the CMOS */
1817 ExAcquireTimeRefreshLock(FALSE
);
1818 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1819 ExReleaseTimeRefreshLock();
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
);
1826 /* Delay the DPC until it runs next time */
1827 DueTime
.QuadPart
= -1800000000;
1828 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1833 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1834 IN OUT PCONTEXT ContextRecord
,
1835 IN BOOLEAN SecondChanceException
)
1839 /* Save the port data */
1842 /* Report a state change */
1843 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1845 SecondChanceException
);
1847 /* Restore the port data and return */
1854 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1856 LARGE_INTEGER Null
= {{0}};
1858 /* Check if interrupts were disabled */
1859 if (!KeGetTrapFrameInterruptState(TrapFrame
))
1861 /* Nothing to return */
1865 /* Otherwise, do the call */
1866 return KeQueryPerformanceCounter(NULL
);
1871 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1872 IN PKEXCEPTION_FRAME ExceptionFrame
)
1876 /* Check if we have a trap frame */
1879 /* Calculate the time difference for the enter */
1880 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1881 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1882 KdTimerStart
.QuadPart
;
1886 /* No trap frame, so can't calculate */
1887 KdTimerStop
.QuadPart
= 0;
1890 /* Save the current IRQL */
1891 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1893 /* Freeze all CPUs */
1894 Enable
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1896 /* Lock the port, save the state and set debugger entered */
1897 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1899 KdEnteredDebugger
= TRUE
;
1901 /* Check freeze flag */
1902 if (KiFreezeFlag
& 1)
1904 /* Print out errror */
1905 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1908 /* Check processor state */
1909 if (KiFreezeFlag
& 2)
1911 /* Print out errror */
1912 KdpDprintf("Some processors not frozen in debugger!\n");
1915 /* Make sure we acquired the port */
1916 if (!KdpPortLocked
) KdpDprintf("Port lock was not acquired!\n");
1918 /* Return if interrupts needs to be re-enabled */
1924 KdExitDebugger(IN BOOLEAN Enable
)
1928 /* Restore the state and unlock the port */
1930 if (KdpPortLocked
) KdpPortUnlock();
1932 /* Unfreeze the CPUs */
1933 KeThawExecution(Enable
);
1935 /* Compare time with the one from KdEnterDebugger */
1936 if (!KdTimerStop
.QuadPart
)
1938 /* We didn't get a trap frame earlier in so never got the time */
1939 KdTimerStart
= KdTimerStop
;
1943 /* Query the timer */
1944 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1947 /* Check if a Time Slip was on queue */
1948 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1951 /* Queue a DPC for the time slip */
1952 InterlockedIncrement(&KdpTimeSlipPending
);
1953 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
); // FIXME: this can trigger context switches!
1959 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock
)
1963 #if defined(__GNUC__)
1964 /* Make gcc happy */
1965 OldIrql
= PASSIVE_LEVEL
;
1968 /* Check if enabling the debugger is blocked */
1971 /* It is, fail the enable */
1972 return STATUS_ACCESS_DENIED
;
1975 /* Check if we need to acquire the lock */
1979 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1983 /* Check if we're not disabled */
1984 if (!KdDisableCount
)
1986 /* Check if we had locked the port before */
1990 KeLowerIrql(OldIrql
);
1993 /* Fail: We're already enabled */
1994 return STATUS_INVALID_PARAMETER
;
1999 * This can only happen if we are called from a bugcheck
2000 * and were never initialized, so initialize the debugger now.
2002 KdInitSystem(0, NULL
);
2004 /* Return success since we initialized */
2005 return STATUS_SUCCESS
;
2009 /* Decrease the disable count */
2010 if (!(--KdDisableCount
))
2012 /* We're now enabled again! Were we enabled before, too? */
2013 if (KdPreviouslyEnabled
)
2015 /* Reinitialize the Debugger */
2016 KdInitSystem(0, NULL
);
2017 KdpRestoreAllBreakpoints();
2021 /* Check if we had locked the port before */
2024 /* Yes, now unlock it */
2025 KeLowerIrql(OldIrql
);
2030 return STATUS_SUCCESS
;
2035 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock
)
2040 #if defined(__GNUC__)
2041 /* Make gcc happy */
2042 OldIrql
= PASSIVE_LEVEL
;
2046 * If enabling the debugger is blocked
2047 * then there is nothing to disable (duh)
2052 return STATUS_ACCESS_DENIED
;
2055 /* Check if we need to acquire the lock */
2059 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
2063 /* Check if we're not disabled */
2064 if (!KdDisableCount
)
2066 /* Check if the debugger was never actually initialized */
2067 if (!(KdDebuggerEnabled
) && !(KdPitchDebugger
))
2069 /* It wasn't, so don't re-enable it later */
2070 KdPreviouslyEnabled
= FALSE
;
2074 /* It was, so we will re-enable it later */
2075 KdPreviouslyEnabled
= TRUE
;
2078 /* Check if we were called from the exported API and are enabled */
2079 if ((NeedLock
) && (KdPreviouslyEnabled
))
2081 /* Check if it is safe to disable the debugger */
2082 Status
= KdpAllowDisable();
2083 if (!NT_SUCCESS(Status
))
2085 /* Release the lock and fail */
2086 KeLowerIrql(OldIrql
);
2092 /* Only disable the debugger if it is enabled */
2093 if (KdDebuggerEnabled
)
2096 * Disable the debugger; suspend breakpoints
2097 * and reset the debug stub
2099 KdpSuspendAllBreakPoints();
2100 KiDebugRoutine
= KdpStub
;
2102 /* We are disabled now */
2103 KdDebuggerEnabled
= FALSE
;
2104 SharedUserData
->KdDebuggerEnabled
= FALSE
;
2108 /* Increment the disable count */
2111 /* Check if we had locked the port before */
2114 /* Yes, now unlock it */
2115 KeLowerIrql(OldIrql
);
2120 return STATUS_SUCCESS
;
2123 /* PUBLIC FUNCTIONS **********************************************************/
2130 KdEnableDebugger(VOID
)
2132 /* Use the internal routine */
2133 return KdEnableDebuggerWithLock(TRUE
);
2141 KdDisableDebugger(VOID
)
2143 /* Use the internal routine */
2144 return KdDisableDebuggerWithLock(TRUE
);
2152 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
2153 IN PVOID InputBuffer
,
2154 IN ULONG InputBufferLength
,
2155 OUT PVOID OutputBuffer
,
2156 IN ULONG OutputBufferLength
,
2157 IN OUT PULONG ReturnLength
,
2158 IN KPROCESSOR_MODE PreviousMode
)
2160 /* handle sime internal commands */
2161 if (Command
== ' soR')
2163 switch ((ULONG_PTR
)InputBuffer
)
2166 MmDumpArmPfnDatabase(FALSE
);
2169 return STATUS_SUCCESS
;
2172 /* Local kernel debugging is not yet supported */
2173 DbgPrint("KdSystemDebugControl is unimplemented!\n");
2174 return STATUS_NOT_IMPLEMENTED
;
2182 KdChangeOption(IN KD_OPTION Option
,
2183 IN ULONG InBufferBytes OPTIONAL
,
2185 IN ULONG OutBufferBytes OPTIONAL
,
2186 OUT PVOID OutBuffer
,
2187 OUT PULONG OutBufferNeeded OPTIONAL
)
2189 /* Fail if there is no debugger */
2190 if (KdPitchDebugger
)
2192 /* No debugger, no options */
2193 return STATUS_DEBUGGER_INACTIVE
;
2196 /* Do we recognize this option? */
2197 if (Option
!= KD_OPTION_SET_BLOCK_ENABLE
)
2199 /* We don't, clear the output length and fail */
2200 if (OutBufferNeeded
) *OutBufferNeeded
= 0;
2201 return STATUS_INVALID_INFO_CLASS
;
2204 /* Verify parameters */
2205 if ((InBufferBytes
!= sizeof(BOOLEAN
)) ||
2206 (OutBufferBytes
!= 0) ||
2207 (OutBuffer
!= NULL
))
2209 /* Invalid parameters for this option, fail */
2210 return STATUS_INVALID_PARAMETER
;
2214 * Check if the high bit is set, meaning we don't
2215 * allow the debugger to be enabled
2217 if (KdBlockEnable
& 0x80)
2219 /* Fail regardless of what state the caller tried to set */
2220 return STATUS_ACCESS_VIOLATION
;
2223 /* Set the new block enable state */
2224 KdBlockEnable
= *(PBOOLEAN
)InBuffer
;
2226 /* No output buffer required for this option */
2227 if (OutBufferNeeded
) *OutBufferNeeded
= 0;
2230 return STATUS_SUCCESS
;
2238 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
2240 /* Check what power state this is */
2241 if (NewState
== PowerDeviceD0
)
2243 /* Wake up the debug port */
2245 return STATUS_SUCCESS
;
2247 else if ((NewState
== PowerDeviceD1
) ||
2248 (NewState
== PowerDeviceD2
) ||
2249 (NewState
== PowerDeviceD3
))
2251 /* Power down the debug port */
2253 return STATUS_SUCCESS
;
2257 /* Invalid state! */
2258 return STATUS_INVALID_PARAMETER_1
;
2267 KdRefreshDebuggerNotPresent(VOID
)
2269 BOOLEAN Enable
, DebuggerNotPresent
;
2271 /* Check if the debugger is completely disabled */
2272 if (KdPitchDebugger
)
2274 /* Don't try to refresh then -- fail early */
2278 /* Enter the debugger */
2279 Enable
= KdEnterDebugger(NULL
, NULL
);
2282 * Attempt to send a string to the debugger to refresh the
2285 KdpDprintf("KDTARGET: Refreshing KD connection\n");
2287 /* Save the state while we are holding the lock */
2288 DebuggerNotPresent
= KdDebuggerNotPresent
;
2290 /* Exit the debugger and return the state */
2291 KdExitDebugger(Enable
);
2292 return DebuggerNotPresent
;
2300 NtQueryDebugFilterState(IN ULONG ComponentId
,
2305 /* Check if the ID fits in the component table */
2306 if (ComponentId
< KdComponentTableSize
)
2308 /* It does, so get the mask from there */
2309 Mask
= KdComponentTable
[ComponentId
];
2311 else if (ComponentId
== MAXULONG
)
2314 * This is the internal ID used for DbgPrint messages without ID and
2315 * Level. Use the system-wide mask for those.
2317 Mask
= &Kd_WIN2000_Mask
;
2321 /* Invalid ID, fail */
2322 return STATUS_INVALID_PARAMETER_1
;
2325 /* Convert Level to bit field if necessary */
2326 if (Level
< 32) Level
= 1 << Level
;
2328 /* Determine if this Level is filtered out */
2329 if ((Kd_WIN2000_Mask
& Level
) ||
2332 /* This mask will get through to the debugger */
2333 return (NTSTATUS
)TRUE
;
2337 /* This mask is filtered out */
2338 return (NTSTATUS
)FALSE
;
2347 NtSetDebugFilterState(IN ULONG ComponentId
,
2353 /* Modifying debug filters requires the debug privilege */
2354 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
,
2355 ExGetPreviousMode()))
2358 return STATUS_ACCESS_DENIED
;
2361 /* Check if the ID fits in the component table */
2362 if (ComponentId
< KdComponentTableSize
)
2364 /* It does, so get the mask from there */
2365 Mask
= KdComponentTable
[ComponentId
];
2367 else if (ComponentId
== MAXULONG
)
2370 * This is the internal ID used for DbgPrint messages without ID and
2371 * Level. Use the system-wide mask for those.
2373 Mask
= &Kd_WIN2000_Mask
;
2377 /* Invalid ID, fail */
2378 return STATUS_INVALID_PARAMETER_1
;
2381 /* Convert Level to bit field if required */
2382 if (Level
< 32) Level
= 1 << Level
;
2384 /* Check what kind of operation this is */
2392 /* Remove the Level */
2397 return STATUS_SUCCESS
;