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)
9 /* INCLUDES ******************************************************************/
15 /* PRIVATE FUNCTIONS *********************************************************/
19 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
22 PDBGKD_QUERY_MEMORY Memory
= &State
->u
.QueryMemory
;
24 NTSTATUS Status
= STATUS_SUCCESS
;
26 /* Validate the address space */
27 if (Memory
->AddressSpace
== DBGKD_QUERY_MEMORY_VIRTUAL
)
29 /* Check if this is process memory */
30 if ((PVOID
)(LONG_PTR
)Memory
->Address
< MmHighestUserAddress
)
33 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_PROCESS
;
37 /* FIXME: Check if it's session space */
38 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_KERNEL
;
42 Memory
->Flags
= DBGKD_QUERY_MEMORY_READ
|
43 DBGKD_QUERY_MEMORY_WRITE
|
44 DBGKD_QUERY_MEMORY_EXECUTE
;
49 Status
= STATUS_INVALID_PARAMETER
;
52 /* Return structure */
53 State
->ReturnStatus
= Status
;
57 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
58 Header
.Buffer
= (PCHAR
)State
;
61 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
69 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
73 PDBGKD_WRITE_BREAKPOINT64 Breakpoint
= &State
->u
.WriteBreakPoint
;
77 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
78 Header
.Buffer
= (PCHAR
)State
;
79 ASSERT(Data
->Length
== 0);
81 /* Create the breakpoint */
82 Breakpoint
->BreakPointHandle
=
83 KdpAddBreakpoint((PVOID
)(LONG_PTR
)Breakpoint
->BreakPointAddress
);
84 if (!Breakpoint
->BreakPointHandle
)
87 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
92 State
->ReturnStatus
= STATUS_SUCCESS
;
96 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
104 DumpTraceData(IN PSTRING TraceData
)
106 /* Update the buffer */
107 TraceDataBuffer
[0] = TraceDataBufferPosition
;
109 /* Setup the trace data */
110 TraceData
->Length
= TraceDataBufferPosition
* sizeof(ULONG
);
111 TraceData
->Buffer
= (PCHAR
)TraceDataBuffer
;
113 /* Reset the buffer location */
114 TraceDataBufferPosition
= 1;
119 KdpGetStateChange(IN PDBGKD_MANIPULATE_STATE64 State
,
125 /* Check for success */
126 if (NT_SUCCESS(State
->u
.Continue2
.ContinueStatus
))
128 /* Check if we're tracing */
129 if (State
->u
.Continue2
.ControlSet
.TraceFlag
)
132 Context
->EFlags
|= EFLAGS_TF
;
137 Context
->EFlags
&= ~EFLAGS_TF
;
140 /* Loop all processors */
141 for (i
= 0; i
< KeNumberProcessors
; i
++)
143 /* Get the PRCB and update DR7 and DR6 */
144 Prcb
= KiProcessorBlock
[i
];
145 Prcb
->ProcessorState
.SpecialRegisters
.KernelDr7
=
146 State
->u
.Continue2
.ControlSet
.Dr7
;
147 Prcb
->ProcessorState
.SpecialRegisters
.KernelDr6
= 0;
150 /* Check if we have new symbol information */
151 if (State
->u
.Continue2
.ControlSet
.CurrentSymbolStart
!= 1)
154 KdpCurrentSymbolStart
=
155 State
->u
.Continue2
.ControlSet
.CurrentSymbolStart
;
156 KdpCurrentSymbolEnd
= State
->u
.Continue2
.ControlSet
.CurrentSymbolEnd
;
163 KdpSetCommonState(IN ULONG NewState
,
165 IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange
)
167 USHORT InstructionCount
;
168 BOOLEAN HadBreakpoints
;
170 /* Setup common stuff available for all CPU architectures */
171 WaitStateChange
->NewState
= NewState
;
172 WaitStateChange
->ProcessorLevel
= KeProcessorLevel
;
173 WaitStateChange
->Processor
= (USHORT
)KeGetCurrentPrcb()->Number
;
174 WaitStateChange
->NumberProcessors
= (ULONG
)KeNumberProcessors
;
175 WaitStateChange
->Thread
= (ULONG
)(LONG_PTR
)KeGetCurrentThread();
177 WaitStateChange
->ProgramCounter
= (ULONG
)(LONG_PTR
)Context
->Eip
;
178 #elif defined(_M_AMD64)
179 WaitStateChange
->ProgramCounter
= (ULONG
)(LONG_PTR
)Context
->Rip
;
181 #error Unknown platform
184 /* Zero out the Control Report */
185 RtlZeroMemory(&WaitStateChange
->ControlReport
,
186 sizeof(DBGKD_CONTROL_REPORT
));
188 /* Now copy the instruction stream and set the count */
189 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
190 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
192 InstructionCount
= DBGKD_MAXSTREAM
;
193 WaitStateChange
->ControlReport
.InstructionCount
= InstructionCount
;
195 /* Clear all the breakpoints in this region */
197 KdpDeleteBreakpointRange((PVOID
)(LONG_PTR
)WaitStateChange
->ProgramCounter
,
198 (PVOID
)((ULONG_PTR
)WaitStateChange
->ProgramCounter
+
199 WaitStateChange
->ControlReport
.InstructionCount
- 1));
202 /* Copy the instruction stream again, this time without breakpoints */
203 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
204 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
205 WaitStateChange
->ControlReport
.InstructionCount
);
211 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version
)
213 /* Copy the version block */
214 RtlCopyMemory(Version
, &KdVersionBlock
, sizeof(DBGKD_GET_VERSION64
));
219 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State
)
223 /* Fill out the header */
224 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
225 Header
.Buffer
= (PCHAR
)State
;
227 /* Get the version block */
228 KdpSysGetVersion(&State
->u
.GetVersion64
);
230 /* Fill out the state */
231 State
->ApiNumber
= DbgKdGetVersionApi
;
232 State
->ReturnStatus
= STATUS_SUCCESS
;
234 /* Send the packet */
235 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
243 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
248 ULONG Length
= State
->u
.ReadMemory
.TransferCount
;
249 NTSTATUS Status
= STATUS_SUCCESS
;
251 /* Validate length */
252 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
254 /* Overflow, set it to maximum possible */
255 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
259 if (!MmIsAddressValid((PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
))
261 Ke386SetCr2(State
->u
.ReadMemory
.TargetBaseAddress
);
266 if (!State
->u
.ReadMemory
.TargetBaseAddress
)
269 Status
= STATUS_UNSUCCESSFUL
;
273 RtlCopyMemory(Data
->Buffer
,
274 (PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
,
278 /* Fill out the header */
279 Data
->Length
= Length
;
280 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
281 Header
.Buffer
= (PCHAR
)State
;
283 /* Fill out the state */
284 State
->ReturnStatus
= Status
;
285 State
->u
.ReadMemory
.ActualBytesRead
= Length
;
287 /* Send the packet */
288 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
296 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
300 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
302 ULONG Length
, RealLength
;
305 /* Setup the header */
306 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
307 Header
.Buffer
= (PCHAR
)State
;
308 ASSERT(Data
->Length
== 0);
310 /* Check the length requested */
311 Length
= ReadMemory
->TransferCount
;
312 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
314 /* Use maximum allowed */
315 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
318 /* Make sure that this is a valid request */
319 if (((ULONG
)ReadMemory
->TargetBaseAddress
< sizeof(KPROCESSOR_STATE
)) &&
320 (State
->Processor
< KeNumberProcessors
))
322 /* Get the actual length */
323 RealLength
= sizeof(KPROCESSOR_STATE
) -
324 (ULONG_PTR
)ReadMemory
->TargetBaseAddress
;
325 if (RealLength
< Length
) Length
= RealLength
;
327 /* Set the proper address */
328 ControlStart
= (PVOID
)((ULONG_PTR
)ReadMemory
->TargetBaseAddress
+
329 (ULONG_PTR
)&KiProcessorBlock
[State
->Processor
]->
332 /* Copy the memory */
333 RtlCopyMemory(Data
->Buffer
, ControlStart
, Length
);
334 Data
->Length
= Length
;
337 State
->ReturnStatus
= STATUS_SUCCESS
;
338 ReadMemory
->ActualBytesRead
= Data
->Length
;
342 /* Invalid request */
344 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
345 ReadMemory
->ActualBytesRead
= 0;
349 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
357 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
361 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
366 /* Setup the header */
367 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
368 Header
.Buffer
= (PCHAR
)State
;
370 /* Make sure that this is a valid request */
371 Length
= WriteMemory
->TransferCount
;
372 if ((((ULONG
)WriteMemory
->TargetBaseAddress
+ Length
) <=
373 sizeof(KPROCESSOR_STATE
)) &&
374 (State
->Processor
< KeNumberProcessors
))
376 /* Set the proper address */
377 ControlStart
= (PVOID
)((ULONG_PTR
)WriteMemory
->TargetBaseAddress
+
378 (ULONG_PTR
)&KiProcessorBlock
[State
->Processor
]->
381 /* Copy the memory */
382 RtlCopyMemory(ControlStart
, Data
->Buffer
, Data
->Length
);
383 Length
= Data
->Length
;
386 State
->ReturnStatus
= STATUS_SUCCESS
;
387 WriteMemory
->ActualBytesWritten
= Length
;
391 /* Invalid request */
393 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
394 WriteMemory
->ActualBytesWritten
= 0;
398 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
406 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
410 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
413 /* Fill out the header */
414 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
415 Header
.Buffer
= (PCHAR
)State
;
416 ASSERT(Data
->Length
== 0);
418 /* Get the version block */
419 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
422 State
->ReturnStatus
= STATUS_SUCCESS
;
427 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
430 /* Send the packet */
431 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
439 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
446 /* Setup the header */
447 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
448 Header
.Buffer
= (PCHAR
)State
;
449 ASSERT(Data
->Length
== 0);
451 /* Make sure that this is a valid request */
452 if (State
->Processor
< KeNumberProcessors
)
454 /* Check if the request is for this CPU */
455 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
457 /* We're just copying our own context */
458 ControlStart
= Context
;
462 /* SMP not yet handled */
467 /* Copy the memory */
468 RtlCopyMemory(Data
->Buffer
, ControlStart
, sizeof(CONTEXT
));
469 Data
->Length
= sizeof(CONTEXT
);
472 State
->ReturnStatus
= STATUS_SUCCESS
;
476 /* Invalid request */
477 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
481 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
489 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
496 /* Setup the header */
497 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
498 Header
.Buffer
= (PCHAR
)State
;
499 ASSERT(Data
->Length
== sizeof(CONTEXT
));
501 /* Make sure that this is a valid request */
502 if (State
->Processor
< KeNumberProcessors
)
504 /* Check if the request is for this CPU */
505 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
507 /* We're just copying our own context */
508 ControlStart
= Context
;
512 /* SMP not yet handled */
517 /* Copy the memory */
518 RtlCopyMemory(ControlStart
, Data
->Buffer
, sizeof(CONTEXT
));
521 State
->ReturnStatus
= STATUS_SUCCESS
;
525 /* Invalid request */
526 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
530 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
538 KdpSendWaitContinue(IN ULONG PacketType
,
539 IN PSTRING SendHeader
,
540 IN PSTRING SendData OPTIONAL
,
541 IN OUT PCONTEXT Context
)
544 DBGKD_MANIPULATE_STATE64 ManipulateState
;
548 /* Setup the Manipulate State structure */
549 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
550 Header
.Buffer
= (PCHAR
)&ManipulateState
;
551 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
552 Data
.Buffer
= KdpMessageBuffer
;
553 //KdpContextSent = FALSE;
556 /* Send the Packet */
557 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
559 /* If the debugger isn't present anymore, just return success */
560 if (KdDebuggerNotPresent
) return ContinueSuccess
;
562 /* Main processing Loop */
568 /* Wait to get a reply to our packet */
569 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
575 /* If we got a resend request, do it */
576 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
577 } while (RecvCode
== KdPacketTimedOut
);
579 /* Now check what API we got */
580 switch (ManipulateState
.ApiNumber
)
582 case DbgKdReadVirtualMemoryApi
:
584 /* Read virtual memory */
585 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
588 case DbgKdWriteVirtualMemoryApi
:
591 Ke386SetCr2(DbgKdWriteVirtualMemoryApi
);
595 case DbgKdGetContextApi
:
597 /* Get the current context */
598 KdpGetContext(&ManipulateState
, &Data
, Context
);
601 case DbgKdSetContextApi
:
603 /* Set a new context */
604 KdpSetContext(&ManipulateState
, &Data
, Context
);
607 case DbgKdWriteBreakPointApi
:
609 /* Write the breakpoint */
610 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
613 case DbgKdRestoreBreakPointApi
:
616 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
619 case DbgKdContinueApi
:
621 /* Simply continue */
622 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
624 case DbgKdReadControlSpaceApi
:
626 /* Read control space */
627 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
630 case DbgKdWriteControlSpaceApi
:
633 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
636 case DbgKdReadIoSpaceApi
:
639 Ke386SetCr2(DbgKdReadIoSpaceApi
);
643 case DbgKdWriteIoSpaceApi
:
646 Ke386SetCr2(DbgKdWriteIoSpaceApi
);
653 Ke386SetCr2(DbgKdRebootApi
);
657 case DbgKdContinueApi2
:
659 /* Check if caller reports success */
660 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
662 /* Update the state */
663 KdpGetStateChange(&ManipulateState
, Context
);
664 return ContinueSuccess
;
668 /* Return an error */
669 return ContinueError
;
673 case DbgKdReadPhysicalMemoryApi
:
677 Ke386SetCr2(DbgKdReadPhysicalMemoryApi
);
681 case DbgKdWritePhysicalMemoryApi
:
684 Ke386SetCr2(DbgKdWritePhysicalMemoryApi
);
688 case DbgKdQuerySpecialCallsApi
:
691 Ke386SetCr2(DbgKdQuerySpecialCallsApi
);
695 case DbgKdSetSpecialCallApi
:
698 Ke386SetCr2(DbgKdSetSpecialCallApi
);
702 case DbgKdClearSpecialCallsApi
:
705 Ke386SetCr2(DbgKdClearSpecialCallsApi
);
709 case DbgKdSetInternalBreakPointApi
:
712 Ke386SetCr2(DbgKdSetInternalBreakPointApi
);
716 case DbgKdGetInternalBreakPointApi
:
719 Ke386SetCr2(DbgKdGetInternalBreakPointApi
);
723 case DbgKdReadIoSpaceExtendedApi
:
726 Ke386SetCr2(DbgKdReadIoSpaceExtendedApi
);
730 case DbgKdWriteIoSpaceExtendedApi
:
733 Ke386SetCr2(DbgKdWriteIoSpaceExtendedApi
);
737 case DbgKdGetVersionApi
:
739 /* Get version data */
740 KdpGetVersion(&ManipulateState
);
743 case DbgKdWriteBreakPointExApi
:
746 Ke386SetCr2(DbgKdWriteBreakPointExApi
);
750 case DbgKdRestoreBreakPointExApi
:
753 Ke386SetCr2(DbgKdRestoreBreakPointExApi
);
757 case DbgKdCauseBugCheckApi
:
760 Ke386SetCr2(DbgKdCauseBugCheckApi
);
764 case DbgKdSwitchProcessor
:
767 Ke386SetCr2(DbgKdSwitchProcessor
);
774 Ke386SetCr2(DbgKdPageInApi
);
778 case DbgKdReadMachineSpecificRegister
:
781 Ke386SetCr2(DbgKdReadMachineSpecificRegister
);
785 case DbgKdWriteMachineSpecificRegister
:
788 Ke386SetCr2(DbgKdWriteMachineSpecificRegister
);
795 Ke386SetCr2(OldVlm1
);
802 Ke386SetCr2(OldVlm2
);
806 case DbgKdSearchMemoryApi
:
809 Ke386SetCr2(DbgKdSearchMemoryApi
);
813 case DbgKdGetBusDataApi
:
816 Ke386SetCr2(DbgKdGetBusDataApi
);
820 case DbgKdSetBusDataApi
:
823 Ke386SetCr2(DbgKdSetBusDataApi
);
827 case DbgKdCheckLowMemoryApi
:
830 Ke386SetCr2(DbgKdCheckLowMemoryApi
);
834 case DbgKdClearAllInternalBreakpointsApi
:
836 /* Just clear the counter */
837 KdpNumInternalBreakpoints
= 0;
840 case DbgKdFillMemoryApi
:
843 Ke386SetCr2(DbgKdFillMemoryApi
);
847 case DbgKdQueryMemoryApi
:
850 KdpQueryMemory(&ManipulateState
, Context
);
853 case DbgKdSwitchPartition
:
856 Ke386SetCr2(DbgKdSwitchPartition
);
860 /* Unsupported Message */
863 /* Setup an empty message, with failure */
867 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
870 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
881 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
882 IN PKD_SYMBOLS_INFO SymbolInfo
,
884 IN OUT PCONTEXT Context
)
888 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
889 KCONTINUE_STATUS Status
;
891 /* Start wait loop */
894 /* Build the architecture common parts of the message */
895 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
899 /* Now finish creating the structure */
900 KdpSetContextState(&WaitStateChange
, Context
);
902 /* Fill out load data */
903 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
904 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONGLONG
)(LONG_PTR
)SymbolInfo
->BaseOfDll
;
905 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
906 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
907 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
909 /* Check if we have a symbol name */
912 /* Setup the information */
913 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathName
->Length
;
914 RtlCopyMemory(KdpPathBuffer
, PathName
->Buffer
, PathName
->Length
);
915 Data
.Buffer
= KdpPathBuffer
;
916 Data
.Length
= WaitStateChange
.u
.LoadSymbols
.PathNameLength
;
922 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
926 /* Setup the header */
927 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
928 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
930 /* Send the packet */
931 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
935 } while(Status
== ContinueProcessorReselected
);
943 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
944 IN OUT PCONTEXT Context
,
945 IN BOOLEAN SecondChanceException
)
948 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
951 /* Start report loop */
954 /* Build the architecture common parts of the message */
955 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
957 /* Convert the exception record to 64-bits and set First Chance flag */
958 ExceptionRecord32To64((PEXCEPTION_RECORD32
)ExceptionRecord
,
959 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
960 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
962 /* Now finish creating the structure */
963 KdpSetContextState(&WaitStateChange
, Context
);
965 /* Setup the actual header to send to KD */
966 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
967 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
969 /* Setup the trace data */
970 DumpTraceData(&Data
);
972 /* Send State Change packet and wait for a reply */
973 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
977 } while (Status
== KdPacketNeedsResend
);
985 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
986 IN PVOID DeferredContext
,
987 IN PVOID SystemArgument1
,
988 IN PVOID SystemArgument2
)
990 LONG OldSlip
, NewSlip
, PendingSlip
;
992 /* Get the current pending slip */
993 PendingSlip
= KdpTimeSlipPending
;
996 /* Save the old value and either disable or enable it now. */
997 OldSlip
= PendingSlip
;
998 NewSlip
= OldSlip
> 1 ? 1 : 0;
1000 /* Try to change the value */
1001 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1003 OldSlip
) != OldSlip
);
1005 /* If the New Slip value is 1, then do the Time Slipping */
1006 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1011 KdpTimeSlipWork(IN PVOID Context
)
1014 LARGE_INTEGER DueTime
;
1016 /* Update the System time from the CMOS */
1017 ExAcquireTimeRefreshLock(FALSE
);
1018 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1019 ExReleaseTimeRefreshLock();
1021 /* Check if we have a registered Time Slip Event and signal it */
1022 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
1023 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
1024 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
1026 /* Delay the DPC until it runs next time */
1027 DueTime
.QuadPart
= -1800000000;
1028 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1033 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1034 IN OUT PCONTEXT ContextRecord
,
1035 IN BOOLEAN SecondChanceException
)
1039 /* Save the port data */
1042 /* Report a state change */
1043 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1045 SecondChanceException
);
1047 /* Restore the port data and return */
1054 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1056 LARGE_INTEGER Null
= {{0}};
1058 /* Check if interrupts were disabled */
1059 if (!(TrapFrame
->EFlags
& EFLAGS_INTERRUPT_MASK
))
1061 /* Nothing to return */
1065 /* Otherwise, do the call */
1066 return KeQueryPerformanceCounter(NULL
);
1071 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1072 IN PKEXCEPTION_FRAME ExceptionFrame
)
1076 /* Check if we have a trap frame */
1079 /* Calculate the time difference for the enter */
1080 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1081 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1082 KdTimerStart
.QuadPart
;
1086 /* No trap frame, so can't calculate */
1087 KdTimerStop
.QuadPart
= 0;
1090 /* Save the current IRQL */
1091 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1093 /* Freeze all CPUs */
1094 Entered
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1096 /* Lock the port, save the state and set debugger entered */
1097 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1099 KdEnteredDebugger
= TRUE
;
1101 /* Check freeze flag */
1102 if (KiFreezeFlag
& 1)
1104 /* Print out errror */
1105 DbgPrint("FreezeLock was jammed! Backup SpinLock was used!\n");
1108 /* Check processor state */
1109 if (KiFreezeFlag
& 2)
1111 /* Print out errror */
1112 DbgPrint("Some processors not frozen in debugger!\n");
1115 /* Make sure we acquired the port */
1116 if (!KdpPortLocked
) DbgPrint("Port lock was not acquired!\n");
1118 /* Return enter state */
1124 KdExitDebugger(IN BOOLEAN Entered
)
1128 /* Restore the state and unlock the port */
1130 if (KdpPortLocked
) KdpPortUnlock();
1132 /* Unfreeze the CPUs */
1133 KeThawExecution(Entered
);
1135 /* Compare time with the one from KdEnterDebugger */
1136 if (!KdTimerStop
.QuadPart
)
1138 /* We didn't get a trap frame earlier in so never got the time */
1139 KdTimerStart
= KdTimerStop
;
1143 /* Query the timer */
1144 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1147 /* Check if a Time Slip was on queue */
1148 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1151 /* Queue a DPC for the time slip */
1152 InterlockedIncrement(&KdpTimeSlipPending
);
1153 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
);
1159 KdEnableDebuggerWithLock(BOOLEAN NeedLock
)
1161 KIRQL OldIrql
= PASSIVE_LEVEL
;
1163 /* Check if we need to acquire the lock */
1167 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1171 /* Check if we're not disabled */
1172 if (!KdDisableCount
)
1174 /* Check if we had locked the port before */
1178 KeLowerIrql(OldIrql
);
1182 /* Fail: We're already enabled */
1183 return STATUS_INVALID_PARAMETER
;
1186 /* Decrease the disable count */
1187 if (!(--KdDisableCount
))
1189 /* We're now enabled again! Were we enabled before, too? */
1190 if (KdPreviouslyEnabled
)
1192 /* Reinitialize the Debugger */
1193 KdInitSystem(0, NULL
) ;
1194 KdpRestoreAllBreakpoints();
1198 /* Check if we had locked the port before */
1201 /* Yes, now unlock it */
1202 KeLowerIrql(OldIrql
);
1207 return STATUS_SUCCESS
;
1210 /* PUBLIC FUNCTIONS **********************************************************/
1217 KdEnableDebugger(VOID
)
1219 /* Use the internal routine */
1221 return KdEnableDebuggerWithLock(TRUE
);
1229 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
1230 IN PVOID InputBuffer
,
1231 IN ULONG InputBufferLength
,
1232 OUT PVOID OutputBuffer
,
1233 IN ULONG OutputBufferLength
,
1234 IN OUT PULONG ReturnLength
,
1235 IN KPROCESSOR_MODE PreviousMode
)
1238 return STATUS_SUCCESS
;
1246 KdChangeOption(IN KD_OPTION Option
,
1247 IN ULONG InBufferBytes OPTIONAL
,
1249 IN ULONG OutBufferBytes OPTIONAL
,
1250 OUT PVOID OutBuffer
,
1251 OUT PULONG OutBufferNeeded OPTIONAL
)
1254 return STATUS_SUCCESS
;
1262 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
1265 return STATUS_SUCCESS
;
1273 KdDisableDebugger(VOID
)
1276 return STATUS_SUCCESS
;
1284 KdRefreshDebuggerNotPresent(VOID
)
1287 return KdDebuggerNotPresent
;
1292 NtQueryDebugFilterState(ULONG ComponentId
,
1296 return STATUS_SUCCESS
;
1301 NtSetDebugFilterState(ULONG ComponentId
,
1306 return STATUS_SUCCESS
;