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 KdpGetStateChange(IN PDBGKD_MANIPULATE_STATE64 State
,
25 /* Check for success */
26 if (NT_SUCCESS(State
->u
.Continue2
.ContinueStatus
))
28 /* Check if we're tracing */
29 if (State
->u
.Continue2
.ControlSet
.TraceFlag
)
32 Context
->EFlags
|= EFLAGS_TF
;
37 Context
->EFlags
&= ~EFLAGS_TF
;
40 /* Loop all processors */
41 for (i
= 0; i
< KeNumberProcessors
; i
++)
43 /* Get the PRCB and update DR7 and DR6 */
44 Prcb
= KiProcessorBlock
[i
];
45 Prcb
->ProcessorState
.SpecialRegisters
.KernelDr7
=
46 State
->u
.Continue2
.ControlSet
.Dr7
;
47 Prcb
->ProcessorState
.SpecialRegisters
.KernelDr6
= 0;
50 /* Check if we have new symbol information */
51 if (State
->u
.Continue2
.ControlSet
.CurrentSymbolStart
!= 1)
54 KdpCurrentSymbolStart
=
55 State
->u
.Continue2
.ControlSet
.CurrentSymbolStart
;
56 KdpCurrentSymbolEnd
= State
->u
.Continue2
.ControlSet
.CurrentSymbolEnd
;
63 KdpSetCommonState(IN ULONG NewState
,
65 IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange
)
67 USHORT InstructionCount
;
68 BOOLEAN HadBreakpoints
;
70 /* Setup common stuff available for all CPU architectures */
71 WaitStateChange
->NewState
= NewState
;
72 WaitStateChange
->ProcessorLevel
= KeProcessorLevel
;
73 WaitStateChange
->Processor
= (USHORT
)KeGetCurrentPrcb()->Number
;
74 WaitStateChange
->NumberProcessors
= (ULONG
)KeNumberProcessors
;
75 WaitStateChange
->Thread
= (ULONG
)KeGetCurrentThread();
76 WaitStateChange
->ProgramCounter
= (ULONG64
)Context
->Eip
;
78 /* Zero out the Control Report */
79 RtlZeroMemory(&WaitStateChange
->ControlReport
,
80 sizeof(DBGKD_CONTROL_REPORT
));
82 /* Now copy the instruction stream and set the count */
83 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
84 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
86 InstructionCount
= DBGKD_MAXSTREAM
;
87 WaitStateChange
->ControlReport
.InstructionCount
= InstructionCount
;
89 /* Clear all the breakpoints in this region */
90 HadBreakpoints
= FALSE
;
92 KdpDeleteBreakpointRange((PVOID
)WaitStateChange
->ProgramCounter
,
93 (PVOID
)(WaitStateChange
->ProgramCounter
+
94 WaitStateChange
->ControlReport
.
95 InstructionCount
- 1));
99 /* Copy the instruction stream again, this time without breakpoints */
100 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
101 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
102 WaitStateChange
->ControlReport
.InstructionCount
);
108 KdpSetContextState(IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange
,
111 PKPRCB Prcb
= KeGetCurrentPrcb();
113 /* Copy i386 specific debug registers */
114 WaitStateChange
->ControlReport
.Dr6
= Prcb
->ProcessorState
.SpecialRegisters
.
116 WaitStateChange
->ControlReport
.Dr7
= Prcb
->ProcessorState
.SpecialRegisters
.
119 /* Copy i386 specific segments */
120 WaitStateChange
->ControlReport
.SegCs
= (USHORT
)Context
->SegCs
;
121 WaitStateChange
->ControlReport
.SegDs
= (USHORT
)Context
->SegDs
;
122 WaitStateChange
->ControlReport
.SegEs
= (USHORT
)Context
->SegEs
;
123 WaitStateChange
->ControlReport
.SegFs
= (USHORT
)Context
->SegFs
;
126 WaitStateChange
->ControlReport
.EFlags
= Context
->EFlags
;
128 /* Set Report Flags */
129 WaitStateChange
->ControlReport
.ReportFlags
= REPORT_INCLUDES_SEGS
;
130 if (WaitStateChange
->ControlReport
.SegCs
== KGDT_R0_CODE
)
132 WaitStateChange
->ControlReport
.ReportFlags
= REPORT_INCLUDES_CS
;
138 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version
)
140 /* Copy the version block */
141 RtlCopyMemory(Version
, &KdVersionBlock
, sizeof(DBGKD_GET_VERSION64
));
146 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State
)
150 /* Fill out the header */
151 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
152 Header
.Buffer
= (PCHAR
)State
;
154 /* Get the version block */
155 KdpSysGetVersion(&State
->u
.GetVersion64
);
157 /* Fill out the state */
158 State
->ApiNumber
= DbgKdGetVersionApi
;
159 State
->ReturnStatus
= STATUS_SUCCESS
;
161 /* Send the packet */
162 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
170 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
175 ULONG Length
= State
->u
.ReadMemory
.TransferCount
;
176 NTSTATUS Status
= STATUS_SUCCESS
;
178 /* Validate length */
179 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
181 /* Overflow, set it to maximum possible */
182 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
186 if (!MmIsAddressValid((PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
))
188 Ke386SetCr2(State
->u
.ReadMemory
.TargetBaseAddress
);
193 if ((ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
< KSEG0_BASE
)
196 Status
= STATUS_UNSUCCESSFUL
;
198 else if ((ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
>= (ULONG_PTR
)SharedUserData
)
201 Status
= STATUS_UNSUCCESSFUL
;
205 RtlCopyMemory(Data
->Buffer
,
206 (PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
,
210 /* Fill out the header */
211 Data
->Length
= Length
;
212 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
213 Header
.Buffer
= (PCHAR
)State
;
215 /* Fill out the state */
216 State
->ReturnStatus
= Status
;
217 State
->u
.ReadMemory
.ActualBytesRead
= Length
;
219 /* Send the packet */
220 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
228 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
232 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
234 ULONG Length
, RealLength
;
237 /* Setup the header */
238 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
239 Header
.Buffer
= (PCHAR
)State
;
240 ASSERT(Data
->Length
== 0);
242 /* Check the length requested */
243 Length
= ReadMemory
->TransferCount
;
244 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
246 /* Use maximum allowed */
247 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
250 /* Make sure that this is a valid request */
251 if (((ULONG
)ReadMemory
->TargetBaseAddress
< sizeof(KPROCESSOR_STATE
)) &&
252 (State
->Processor
< KeNumberProcessors
))
254 /* Get the actual length */
255 RealLength
= sizeof(KPROCESSOR_STATE
) -
256 (ULONG_PTR
)ReadMemory
->TargetBaseAddress
;
257 if (RealLength
< Length
) Length
= RealLength
;
259 /* Set the proper address */
260 ControlStart
= (PVOID
)((ULONG_PTR
)ReadMemory
->TargetBaseAddress
+
261 (ULONG_PTR
)&KiProcessorBlock
[State
->Processor
]->
264 /* Copy the memory */
265 RtlCopyMemory(Data
->Buffer
, ControlStart
, Length
);
266 Data
->Length
= Length
;
269 State
->ReturnStatus
= STATUS_SUCCESS
;
270 ReadMemory
->ActualBytesRead
= Data
->Length
;
274 /* Invalid request */
276 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
277 ReadMemory
->ActualBytesRead
= 0;
281 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
289 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
293 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
298 /* Setup the header */
299 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
300 Header
.Buffer
= (PCHAR
)State
;
302 /* Make sure that this is a valid request */
303 Length
= WriteMemory
->TransferCount
;
304 if ((((ULONG
)WriteMemory
->TargetBaseAddress
+ Length
) <=
305 sizeof(KPROCESSOR_STATE
)) &&
306 (State
->Processor
< KeNumberProcessors
))
308 /* Set the proper address */
309 ControlStart
= (PVOID
)((ULONG_PTR
)WriteMemory
->TargetBaseAddress
+
310 (ULONG_PTR
)&KiProcessorBlock
[State
->Processor
]->
313 /* Copy the memory */
314 RtlCopyMemory(ControlStart
, Data
->Buffer
, Data
->Length
);
315 Length
= Data
->Length
;
318 State
->ReturnStatus
= STATUS_SUCCESS
;
319 WriteMemory
->ActualBytesWritten
= Length
;
323 /* Invalid request */
325 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
326 WriteMemory
->ActualBytesWritten
= 0;
330 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
338 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
342 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
345 /* Fill out the header */
346 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
347 Header
.Buffer
= (PCHAR
)State
;
348 ASSERT(Data
->Length
== 0);
350 /* Get the version block */
351 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
354 State
->ReturnStatus
= STATUS_SUCCESS
;
359 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
362 /* Send the packet */
363 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
371 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
378 /* Setup the header */
379 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
380 Header
.Buffer
= (PCHAR
)State
;
381 ASSERT(Data
->Length
== 0);
383 /* Make sure that this is a valid request */
384 if (State
->Processor
< KeNumberProcessors
)
386 /* Check if the request is for this CPU */
387 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
389 /* We're just copying our own context */
390 ControlStart
= Context
;
394 /* SMP not yet handled */
399 /* Copy the memory */
400 RtlCopyMemory(Data
->Buffer
, ControlStart
, sizeof(CONTEXT
));
401 Data
->Length
= sizeof(CONTEXT
);
404 State
->ReturnStatus
= STATUS_SUCCESS
;
408 /* Invalid request */
409 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
413 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
421 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
428 /* Setup the header */
429 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
430 Header
.Buffer
= (PCHAR
)State
;
431 ASSERT(Data
->Length
== sizeof(CONTEXT
));
433 /* Make sure that this is a valid request */
434 if (State
->Processor
< KeNumberProcessors
)
436 /* Check if the request is for this CPU */
437 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
439 /* We're just copying our own context */
440 ControlStart
= Context
;
444 /* SMP not yet handled */
449 /* Copy the memory */
450 RtlCopyMemory(ControlStart
, Data
->Buffer
, sizeof(CONTEXT
));
453 State
->ReturnStatus
= STATUS_SUCCESS
;
457 /* Invalid request */
458 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
462 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
470 KdpSendWaitContinue(IN ULONG PacketType
,
471 IN PSTRING SendHeader
,
472 IN PSTRING SendData OPTIONAL
,
473 IN OUT PCONTEXT Context
)
476 DBGKD_MANIPULATE_STATE64 ManipulateState
;
480 /* Setup the Manipulate State structure */
481 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
482 Header
.Buffer
= (PCHAR
)&ManipulateState
;
483 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
484 Data
.Buffer
= KdpMessageBuffer
;
485 //KdpContextSent = FALSE;
488 /* Send the Packet */
489 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
491 /* If the debugger isn't present anymore, just return success */
492 if (KdDebuggerNotPresent
) return ContinueSuccess
;
494 /* Main processing Loop */
500 /* Wait to get a reply to our packet */
501 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
507 /* If we got a resend request, do it */
508 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
509 } while (RecvCode
== KdPacketTimedOut
);
511 /* Now check what API we got */
512 switch (ManipulateState
.ApiNumber
)
514 case DbgKdReadVirtualMemoryApi
:
516 /* Read virtual memory */
517 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
520 case DbgKdWriteVirtualMemoryApi
:
523 Ke386SetCr2(DbgKdWriteVirtualMemoryApi
);
527 case DbgKdGetContextApi
:
529 /* Get the current context */
530 KdpGetContext(&ManipulateState
, &Data
, Context
);
533 case DbgKdSetContextApi
:
535 /* Set a new context */
536 KdpSetContext(&ManipulateState
, &Data
, Context
);
539 case DbgKdWriteBreakPointApi
:
542 Ke386SetCr2(DbgKdWriteBreakPointApi
);
546 case DbgKdRestoreBreakPointApi
:
549 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
552 case DbgKdContinueApi
:
554 /* Simply continue */
555 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
557 case DbgKdReadControlSpaceApi
:
559 /* Read control space */
560 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
563 case DbgKdWriteControlSpaceApi
:
566 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
569 case DbgKdReadIoSpaceApi
:
572 Ke386SetCr2(DbgKdReadIoSpaceApi
);
576 case DbgKdWriteIoSpaceApi
:
579 Ke386SetCr2(DbgKdWriteIoSpaceApi
);
586 Ke386SetCr2(DbgKdRebootApi
);
590 case DbgKdContinueApi2
:
592 /* Check if caller reports success */
593 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
595 /* Update the state */
596 KdpGetStateChange(&ManipulateState
, Context
);
597 return ContinueSuccess
;
601 /* Return an error */
602 return ContinueError
;
606 case DbgKdReadPhysicalMemoryApi
:
610 Ke386SetCr2(DbgKdReadPhysicalMemoryApi
);
614 case DbgKdWritePhysicalMemoryApi
:
617 Ke386SetCr2(DbgKdWritePhysicalMemoryApi
);
621 case DbgKdQuerySpecialCallsApi
:
624 Ke386SetCr2(DbgKdQuerySpecialCallsApi
);
628 case DbgKdSetSpecialCallApi
:
631 Ke386SetCr2(DbgKdSetSpecialCallApi
);
635 case DbgKdClearSpecialCallsApi
:
638 Ke386SetCr2(DbgKdClearSpecialCallsApi
);
642 case DbgKdSetInternalBreakPointApi
:
645 Ke386SetCr2(DbgKdSetInternalBreakPointApi
);
649 case DbgKdGetInternalBreakPointApi
:
652 Ke386SetCr2(DbgKdGetInternalBreakPointApi
);
656 case DbgKdReadIoSpaceExtendedApi
:
659 Ke386SetCr2(DbgKdReadIoSpaceExtendedApi
);
663 case DbgKdWriteIoSpaceExtendedApi
:
666 Ke386SetCr2(DbgKdWriteIoSpaceExtendedApi
);
670 case DbgKdGetVersionApi
:
672 /* Get version data */
673 KdpGetVersion(&ManipulateState
);
676 case DbgKdWriteBreakPointExApi
:
679 Ke386SetCr2(DbgKdWriteBreakPointExApi
);
683 case DbgKdRestoreBreakPointExApi
:
686 Ke386SetCr2(DbgKdRestoreBreakPointExApi
);
690 case DbgKdCauseBugCheckApi
:
693 Ke386SetCr2(DbgKdCauseBugCheckApi
);
697 case DbgKdSwitchProcessor
:
700 Ke386SetCr2(DbgKdSwitchProcessor
);
707 Ke386SetCr2(DbgKdPageInApi
);
711 case DbgKdReadMachineSpecificRegister
:
714 Ke386SetCr2(DbgKdReadMachineSpecificRegister
);
718 case DbgKdWriteMachineSpecificRegister
:
721 Ke386SetCr2(DbgKdWriteMachineSpecificRegister
);
728 Ke386SetCr2(OldVlm1
);
735 Ke386SetCr2(OldVlm2
);
739 case DbgKdSearchMemoryApi
:
742 Ke386SetCr2(DbgKdSearchMemoryApi
);
746 case DbgKdGetBusDataApi
:
749 Ke386SetCr2(DbgKdGetBusDataApi
);
753 case DbgKdSetBusDataApi
:
756 Ke386SetCr2(DbgKdSetBusDataApi
);
760 case DbgKdCheckLowMemoryApi
:
763 Ke386SetCr2(DbgKdCheckLowMemoryApi
);
767 case DbgKdClearAllInternalBreakpointsApi
:
769 /* Just clear the counter */
770 KdpNumInternalBreakpoints
= 0;
773 case DbgKdFillMemoryApi
:
776 Ke386SetCr2(DbgKdFillMemoryApi
);
780 case DbgKdQueryMemoryApi
:
783 Ke386SetCr2(DbgKdQueryMemoryApi
);
787 case DbgKdSwitchPartition
:
790 Ke386SetCr2(DbgKdSwitchPartition
);
794 /* Unsupported Message */
797 /* Setup an empty message, with failure */
801 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
804 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
815 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
816 IN PKD_SYMBOLS_INFO SymbolInfo
,
818 IN OUT PCONTEXT Context
)
822 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
823 KCONTINUE_STATUS Status
;
825 /* Start wait loop */
828 /* Build the architecture common parts of the message */
829 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
833 /* Now finish creating the structure */
834 KdpSetContextState(&WaitStateChange
, Context
);
836 /* Fill out load data */
837 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
838 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONG
)SymbolInfo
->BaseOfDll
;
839 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
840 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
841 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
843 /* Check if we have a symbol name */
846 /* Setup the information */
847 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathName
->Length
;
848 Data
.Buffer
= KdpPathBuffer
;
849 Data
.Length
= WaitStateChange
.u
.LoadSymbols
.PathNameLength
;
855 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
859 /* Setup the header */
860 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
861 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
863 /* Send the packet */
864 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
868 } while(Status
== ContinueProcessorReselected
);
876 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
877 IN PVOID DeferredContext
,
878 IN PVOID SystemArgument1
,
879 IN PVOID SystemArgument2
)
881 LONG OldSlip
, NewSlip
, PendingSlip
;
883 /* Get the current pending slip */
884 PendingSlip
= KdpTimeSlipPending
;
887 /* Save the old value and either disable or enable it now. */
888 OldSlip
= PendingSlip
;
889 NewSlip
= OldSlip
> 1 ? 1 : 0;
891 /* Try to change the value */
892 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
894 OldSlip
) != OldSlip
);
896 /* If the New Slip value is 1, then do the Time Slipping */
897 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
902 KdpTimeSlipWork(IN PVOID Context
)
905 LARGE_INTEGER DueTime
;
907 /* Update the System time from the CMOS */
908 ExAcquireTimeRefreshLock(FALSE
);
909 ExUpdateSystemTimeFromCmos(FALSE
, 0);
910 ExReleaseTimeRefreshLock();
912 /* Check if we have a registered Time Slip Event and signal it */
913 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
914 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
915 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
917 /* Delay the DPC until it runs next time */
918 DueTime
.QuadPart
= -1800000000;
919 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
924 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
925 IN OUT PCONTEXT ContextRecord
,
926 IN BOOLEAN SecondChanceException
)
930 /* Save the port data */
933 /* Report a state change */
935 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
937 SecondChanceException
);
942 /* Restore the port data and return */
949 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
951 LARGE_INTEGER Null
= {{0}};
953 /* Check if interrupts were disabled */
954 if (!(TrapFrame
->EFlags
& EFLAGS_INTERRUPT_MASK
))
956 /* Nothing to return */
960 /* Otherwise, do the call */
961 return KeQueryPerformanceCounter(NULL
);
966 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
967 IN PKEXCEPTION_FRAME ExceptionFrame
)
971 /* Check if we have a trap frame */
974 /* Calculate the time difference for the enter */
975 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
976 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
977 KdTimerStart
.QuadPart
;
981 /* No trap frame, so can't calculate */
982 KdTimerStop
.QuadPart
= 0;
985 /* Save the current IRQL */
986 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
988 /* Freeze all CPUs */
989 Entered
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
991 /* Lock the port, save the state and set debugger entered */
992 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
994 KdEnteredDebugger
= TRUE
;
996 /* Check freeze flag */
997 if (KiFreezeFlag
& 1)
999 /* Print out errror */
1000 DbgPrint("FreezeLock was jammed! Backup SpinLock was used!\n");
1003 /* Check processor state */
1004 if (KiFreezeFlag
& 2)
1006 /* Print out errror */
1007 DbgPrint("Some processors not frozen in debugger!\n");
1010 /* Make sure we acquired the port */
1011 if (!KdpPortLocked
) DbgPrint("Port lock was not acquired!\n");
1013 /* Return enter state */
1019 KdExitDebugger(IN BOOLEAN Entered
)
1023 /* Restore the state and unlock the port */
1025 if (KdpPortLocked
) KdpPortUnlock();
1027 /* Unfreeze the CPUs */
1028 KeThawExecution(Entered
);
1030 /* Compare time with the one from KdEnterDebugger */
1031 if (!KdTimerStop
.QuadPart
)
1033 /* We didn't get a trap frame earlier in so never got the time */
1034 KdTimerStart
= KdTimerStop
;
1038 /* Query the timer */
1039 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1042 /* Check if a Time Slip was on queue */
1043 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1046 /* Queue a DPC for the time slip */
1047 InterlockedIncrement(&KdpTimeSlipPending
);
1048 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
);
1054 KdEnableDebuggerWithLock(BOOLEAN NeedLock
)
1058 /* Check if we need to acquire the lock */
1062 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1066 /* Check if we're not disabled */
1067 if (!KdDisableCount
)
1069 /* Check if we had locked the port before */
1073 KeLowerIrql(OldIrql
);
1077 /* Fail: We're already enabled */
1078 return STATUS_INVALID_PARAMETER
;
1081 /* Decrease the disable count */
1082 if (!(--KdDisableCount
))
1084 /* We're now enabled again! Were we enabled before, too? */
1085 if (KdPreviouslyEnabled
)
1087 /* Reinitialize the Debugger */
1088 KdInitSystem(0, NULL
) ;
1089 KdpRestoreAllBreakpoints();
1093 /* Check if we had locked the port before */
1096 /* Yes, now unlock it */
1097 KeLowerIrql(OldIrql
);
1102 return STATUS_SUCCESS
;
1105 /* PUBLIC FUNCTIONS **********************************************************/
1112 KdEnableDebugger(VOID
)
1114 /* Use the internal routine */
1116 return KdEnableDebuggerWithLock(TRUE
);