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(OUT 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 OUT 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
= (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 #if defined (_M_AMD64)
319 if ((ULONG
)ReadMemory
->TargetBaseAddress
<= 2)
321 switch ((ULONG_PTR
)ReadMemory
->TargetBaseAddress
)
324 ControlStart
= &KiProcessorBlock
[State
->Processor
];
325 RealLength
= sizeof(PVOID
);
329 ControlStart
= &KiProcessorBlock
[State
->Processor
]->
330 ProcessorState
.SpecialRegisters
;
331 RealLength
= sizeof(KSPECIAL_REGISTERS
);
339 if (RealLength
< Length
) Length
= RealLength
;
341 /* Copy the memory */
342 RtlCopyMemory(Data
->Buffer
, ControlStart
, Length
);
343 Data
->Length
= Length
;
346 State
->ReturnStatus
= STATUS_SUCCESS
;
347 ReadMemory
->ActualBytesRead
= Data
->Length
;
350 /* Make sure that this is a valid request */
351 if (((ULONG
)ReadMemory
->TargetBaseAddress
< sizeof(KPROCESSOR_STATE
)) &&
352 (State
->Processor
< KeNumberProcessors
))
354 /* Get the actual length */
355 RealLength
= sizeof(KPROCESSOR_STATE
) -
356 (ULONG_PTR
)ReadMemory
->TargetBaseAddress
;
357 if (RealLength
< Length
) Length
= RealLength
;
359 /* Set the proper address */
360 ControlStart
= (PVOID
)((ULONG_PTR
)ReadMemory
->TargetBaseAddress
+
361 (ULONG_PTR
)&KiProcessorBlock
[State
->Processor
]->
364 /* Copy the memory */
365 RtlCopyMemory(Data
->Buffer
, ControlStart
, Length
);
366 Data
->Length
= Length
;
369 State
->ReturnStatus
= STATUS_SUCCESS
;
370 ReadMemory
->ActualBytesRead
= Data
->Length
;
375 /* Invalid request */
377 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
378 ReadMemory
->ActualBytesRead
= 0;
382 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
390 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
394 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
399 /* Setup the header */
400 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
401 Header
.Buffer
= (PCHAR
)State
;
403 /* Make sure that this is a valid request */
404 Length
= WriteMemory
->TransferCount
;
405 if ((((ULONG
)WriteMemory
->TargetBaseAddress
+ Length
) <=
406 sizeof(KPROCESSOR_STATE
)) &&
407 (State
->Processor
< KeNumberProcessors
))
409 /* Set the proper address */
410 ControlStart
= (PVOID
)((ULONG_PTR
)WriteMemory
->TargetBaseAddress
+
411 (ULONG_PTR
)&KiProcessorBlock
[State
->Processor
]->
414 /* Copy the memory */
415 RtlCopyMemory(ControlStart
, Data
->Buffer
, Data
->Length
);
416 Length
= Data
->Length
;
419 State
->ReturnStatus
= STATUS_SUCCESS
;
420 WriteMemory
->ActualBytesWritten
= Length
;
424 /* Invalid request */
426 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
427 WriteMemory
->ActualBytesWritten
= 0;
431 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
439 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
443 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
446 /* Fill out the header */
447 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
448 Header
.Buffer
= (PCHAR
)State
;
449 ASSERT(Data
->Length
== 0);
451 /* Get the version block */
452 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
455 State
->ReturnStatus
= STATUS_SUCCESS
;
460 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
463 /* Send the packet */
464 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
472 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
479 /* Setup the header */
480 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
481 Header
.Buffer
= (PCHAR
)State
;
482 ASSERT(Data
->Length
== 0);
484 /* Make sure that this is a valid request */
485 if (State
->Processor
< KeNumberProcessors
)
487 /* Check if the request is for this CPU */
488 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
490 /* We're just copying our own context */
491 ControlStart
= Context
;
495 /* SMP not yet handled */
500 /* Copy the memory */
501 RtlCopyMemory(Data
->Buffer
, ControlStart
, sizeof(CONTEXT
));
502 Data
->Length
= sizeof(CONTEXT
);
505 State
->ReturnStatus
= STATUS_SUCCESS
;
509 /* Invalid request */
510 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
514 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
522 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
529 /* Setup the header */
530 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
531 Header
.Buffer
= (PCHAR
)State
;
532 ASSERT(Data
->Length
== sizeof(CONTEXT
));
534 /* Make sure that this is a valid request */
535 if (State
->Processor
< KeNumberProcessors
)
537 /* Check if the request is for this CPU */
538 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
540 /* We're just copying our own context */
541 ControlStart
= Context
;
545 /* SMP not yet handled */
550 /* Copy the memory */
551 RtlCopyMemory(ControlStart
, Data
->Buffer
, sizeof(CONTEXT
));
554 State
->ReturnStatus
= STATUS_SUCCESS
;
558 /* Invalid request */
559 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
563 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
571 KdpSendWaitContinue(IN ULONG PacketType
,
572 IN PSTRING SendHeader
,
573 IN PSTRING SendData OPTIONAL
,
574 IN OUT PCONTEXT Context
)
577 DBGKD_MANIPULATE_STATE64 ManipulateState
;
580 FrLdrDbgPrint("Enter KdpSendWaitContinue\n");
581 /* Setup the Manipulate State structure */
582 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
583 Header
.Buffer
= (PCHAR
)&ManipulateState
;
584 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
585 Data
.Buffer
= KdpMessageBuffer
;
586 //KdpContextSent = FALSE;
589 /* Send the Packet */
590 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
592 /* If the debugger isn't present anymore, just return success */
593 if (KdDebuggerNotPresent
) return ContinueSuccess
;
595 /* Main processing Loop */
601 /* Wait to get a reply to our packet */
602 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
608 /* If we got a resend request, do it */
609 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
610 } while (RecvCode
== KdPacketTimedOut
);
612 /* Now check what API we got */
613 switch (ManipulateState
.ApiNumber
)
615 case DbgKdReadVirtualMemoryApi
:
617 /* Read virtual memory */
618 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
621 case DbgKdWriteVirtualMemoryApi
:
624 Ke386SetCr2(DbgKdWriteVirtualMemoryApi
);
628 case DbgKdGetContextApi
:
630 /* Get the current context */
631 KdpGetContext(&ManipulateState
, &Data
, Context
);
634 case DbgKdSetContextApi
:
636 /* Set a new context */
637 KdpSetContext(&ManipulateState
, &Data
, Context
);
640 case DbgKdWriteBreakPointApi
:
642 /* Write the breakpoint */
643 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
646 case DbgKdRestoreBreakPointApi
:
649 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
652 case DbgKdContinueApi
:
654 /* Simply continue */
655 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
657 case DbgKdReadControlSpaceApi
:
659 /* Read control space */
660 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
663 case DbgKdWriteControlSpaceApi
:
666 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
669 case DbgKdReadIoSpaceApi
:
672 Ke386SetCr2(DbgKdReadIoSpaceApi
);
676 case DbgKdWriteIoSpaceApi
:
679 Ke386SetCr2(DbgKdWriteIoSpaceApi
);
686 Ke386SetCr2(DbgKdRebootApi
);
690 case DbgKdContinueApi2
:
692 /* Check if caller reports success */
693 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
695 /* Update the state */
696 KdpGetStateChange(&ManipulateState
, Context
);
697 return ContinueSuccess
;
701 /* Return an error */
702 return ContinueError
;
706 case DbgKdReadPhysicalMemoryApi
:
710 Ke386SetCr2(DbgKdReadPhysicalMemoryApi
);
714 case DbgKdWritePhysicalMemoryApi
:
717 Ke386SetCr2(DbgKdWritePhysicalMemoryApi
);
721 case DbgKdQuerySpecialCallsApi
:
724 Ke386SetCr2(DbgKdQuerySpecialCallsApi
);
728 case DbgKdSetSpecialCallApi
:
731 Ke386SetCr2(DbgKdSetSpecialCallApi
);
735 case DbgKdClearSpecialCallsApi
:
738 Ke386SetCr2(DbgKdClearSpecialCallsApi
);
742 case DbgKdSetInternalBreakPointApi
:
745 Ke386SetCr2(DbgKdSetInternalBreakPointApi
);
749 case DbgKdGetInternalBreakPointApi
:
752 Ke386SetCr2(DbgKdGetInternalBreakPointApi
);
756 case DbgKdReadIoSpaceExtendedApi
:
759 Ke386SetCr2(DbgKdReadIoSpaceExtendedApi
);
763 case DbgKdWriteIoSpaceExtendedApi
:
766 Ke386SetCr2(DbgKdWriteIoSpaceExtendedApi
);
770 case DbgKdGetVersionApi
:
772 /* Get version data */
773 KdpGetVersion(&ManipulateState
);
776 case DbgKdWriteBreakPointExApi
:
779 Ke386SetCr2(DbgKdWriteBreakPointExApi
);
783 case DbgKdRestoreBreakPointExApi
:
786 Ke386SetCr2(DbgKdRestoreBreakPointExApi
);
790 case DbgKdCauseBugCheckApi
:
793 Ke386SetCr2(DbgKdCauseBugCheckApi
);
797 case DbgKdSwitchProcessor
:
800 Ke386SetCr2(DbgKdSwitchProcessor
);
807 Ke386SetCr2(DbgKdPageInApi
);
811 case DbgKdReadMachineSpecificRegister
:
814 Ke386SetCr2(DbgKdReadMachineSpecificRegister
);
818 case DbgKdWriteMachineSpecificRegister
:
821 Ke386SetCr2(DbgKdWriteMachineSpecificRegister
);
828 Ke386SetCr2(OldVlm1
);
835 Ke386SetCr2(OldVlm2
);
839 case DbgKdSearchMemoryApi
:
842 Ke386SetCr2(DbgKdSearchMemoryApi
);
846 case DbgKdGetBusDataApi
:
849 Ke386SetCr2(DbgKdGetBusDataApi
);
853 case DbgKdSetBusDataApi
:
856 Ke386SetCr2(DbgKdSetBusDataApi
);
860 case DbgKdCheckLowMemoryApi
:
863 Ke386SetCr2(DbgKdCheckLowMemoryApi
);
867 case DbgKdClearAllInternalBreakpointsApi
:
869 /* Just clear the counter */
870 KdpNumInternalBreakpoints
= 0;
873 case DbgKdFillMemoryApi
:
876 Ke386SetCr2(DbgKdFillMemoryApi
);
880 case DbgKdQueryMemoryApi
:
883 KdpQueryMemory(&ManipulateState
, Context
);
886 case DbgKdSwitchPartition
:
889 Ke386SetCr2(DbgKdSwitchPartition
);
893 /* Unsupported Message */
896 /* Setup an empty message, with failure */
900 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
903 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
914 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
915 IN PKD_SYMBOLS_INFO SymbolInfo
,
917 IN OUT PCONTEXT Context
)
921 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
922 KCONTINUE_STATUS Status
;
924 /* Start wait loop */
927 /* Build the architecture common parts of the message */
928 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
932 /* Now finish creating the structure */
933 KdpSetContextState(&WaitStateChange
, Context
);
935 /* Fill out load data */
936 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
937 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONGLONG
)(LONG_PTR
)SymbolInfo
->BaseOfDll
;
938 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
939 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
940 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
942 /* Check if we have a symbol name */
945 /* Setup the information */
946 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathName
->Length
;
947 RtlCopyMemory(KdpPathBuffer
, PathName
->Buffer
, PathName
->Length
);
948 Data
.Buffer
= KdpPathBuffer
;
949 Data
.Length
= WaitStateChange
.u
.LoadSymbols
.PathNameLength
;
955 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
959 /* Setup the header */
960 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
961 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
963 /* Send the packet */
964 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
968 } while(Status
== ContinueProcessorReselected
);
976 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
977 IN OUT PCONTEXT Context
,
978 IN BOOLEAN SecondChanceException
)
981 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
983 FrLdrDbgPrint("Enter KdpReportExceptionStateChange, Rip = 0x%p\n", (PVOID
)Context
->Rip
);
984 /* Start report loop */
987 /* Build the architecture common parts of the message */
988 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
990 /* Convert the exception record to 64-bits and set First Chance flag */
991 ExceptionRecord32To64((PEXCEPTION_RECORD32
)ExceptionRecord
,
992 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
993 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
995 /* Now finish creating the structure */
996 KdpSetContextState(&WaitStateChange
, Context
);
998 /* Setup the actual header to send to KD */
999 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
) - sizeof(CONTEXT
);
1000 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1002 /* Setup the trace data */
1003 DumpTraceData(&Data
);
1004 FrLdrDbgPrint("KdpReportExceptionStateChange 5\n");
1005 /* Send State Change packet and wait for a reply */
1006 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1010 } while (Status
== KdPacketNeedsResend
);
1011 FrLdrDbgPrint("Leave KdpReportExceptionStateChange, Status = 0x%x\n", Status
);
1018 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
1019 IN PVOID DeferredContext
,
1020 IN PVOID SystemArgument1
,
1021 IN PVOID SystemArgument2
)
1023 LONG OldSlip
, NewSlip
, PendingSlip
;
1025 /* Get the current pending slip */
1026 PendingSlip
= KdpTimeSlipPending
;
1029 /* Save the old value and either disable or enable it now. */
1030 OldSlip
= PendingSlip
;
1031 NewSlip
= OldSlip
> 1 ? 1 : 0;
1033 /* Try to change the value */
1034 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1036 OldSlip
) != OldSlip
);
1038 /* If the New Slip value is 1, then do the Time Slipping */
1039 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1044 KdpTimeSlipWork(IN PVOID Context
)
1047 LARGE_INTEGER DueTime
;
1049 /* Update the System time from the CMOS */
1050 ExAcquireTimeRefreshLock(FALSE
);
1051 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1052 ExReleaseTimeRefreshLock();
1054 /* Check if we have a registered Time Slip Event and signal it */
1055 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
1056 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
1057 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
1059 /* Delay the DPC until it runs next time */
1060 DueTime
.QuadPart
= -1800000000;
1061 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1066 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1067 IN OUT PCONTEXT ContextRecord
,
1068 IN BOOLEAN SecondChanceException
)
1072 /* Save the port data */
1075 /* Report a state change */
1076 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1078 SecondChanceException
);
1080 /* Restore the port data and return */
1087 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1089 LARGE_INTEGER Null
= {{0}};
1091 /* Check if interrupts were disabled */
1092 if (!(TrapFrame
->EFlags
& EFLAGS_INTERRUPT_MASK
))
1094 /* Nothing to return */
1098 /* Otherwise, do the call */
1099 return KeQueryPerformanceCounter(NULL
);
1104 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1105 IN PKEXCEPTION_FRAME ExceptionFrame
)
1108 FrLdrDbgPrint("KdEnterDebugger!\n");
1109 /* Check if we have a trap frame */
1112 /* Calculate the time difference for the enter */
1113 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1114 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1115 KdTimerStart
.QuadPart
;
1119 /* No trap frame, so can't calculate */
1120 KdTimerStop
.QuadPart
= 0;
1123 /* Save the current IRQL */
1124 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1126 /* Freeze all CPUs */
1127 Entered
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1129 /* Lock the port, save the state and set debugger entered */
1130 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1132 KdEnteredDebugger
= TRUE
;
1134 /* Check freeze flag */
1135 if (KiFreezeFlag
& 1)
1137 /* Print out errror */
1138 DbgPrint("FreezeLock was jammed! Backup SpinLock was used!\n");
1141 /* Check processor state */
1142 if (KiFreezeFlag
& 2)
1144 /* Print out errror */
1145 DbgPrint("Some processors not frozen in debugger!\n");
1148 /* Make sure we acquired the port */
1149 if (!KdpPortLocked
) DbgPrint("Port lock was not acquired!\n");
1150 FrLdrDbgPrint("KdEnterDebugger returns %d\n", Entered
);
1151 /* Return enter state */
1157 KdExitDebugger(IN BOOLEAN Entered
)
1161 /* Restore the state and unlock the port */
1163 if (KdpPortLocked
) KdpPortUnlock();
1165 /* Unfreeze the CPUs */
1166 KeThawExecution(Entered
);
1168 /* Compare time with the one from KdEnterDebugger */
1169 if (!KdTimerStop
.QuadPart
)
1171 /* We didn't get a trap frame earlier in so never got the time */
1172 KdTimerStart
= KdTimerStop
;
1176 /* Query the timer */
1177 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1180 /* Check if a Time Slip was on queue */
1181 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1184 /* Queue a DPC for the time slip */
1185 InterlockedIncrement(&KdpTimeSlipPending
);
1186 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
);
1192 KdEnableDebuggerWithLock(BOOLEAN NeedLock
)
1194 KIRQL OldIrql
= PASSIVE_LEVEL
;
1196 /* Check if we need to acquire the lock */
1200 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1204 /* Check if we're not disabled */
1205 if (!KdDisableCount
)
1207 /* Check if we had locked the port before */
1211 KeLowerIrql(OldIrql
);
1215 /* Fail: We're already enabled */
1216 return STATUS_INVALID_PARAMETER
;
1219 /* Decrease the disable count */
1220 if (!(--KdDisableCount
))
1222 /* We're now enabled again! Were we enabled before, too? */
1223 if (KdPreviouslyEnabled
)
1225 /* Reinitialize the Debugger */
1226 KdInitSystem(0, NULL
) ;
1227 KdpRestoreAllBreakpoints();
1231 /* Check if we had locked the port before */
1234 /* Yes, now unlock it */
1235 KeLowerIrql(OldIrql
);
1240 return STATUS_SUCCESS
;
1243 /* PUBLIC FUNCTIONS **********************************************************/
1250 KdEnableDebugger(VOID
)
1252 /* Use the internal routine */
1254 return KdEnableDebuggerWithLock(TRUE
);
1262 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
1263 IN PVOID InputBuffer
,
1264 IN ULONG InputBufferLength
,
1265 OUT PVOID OutputBuffer
,
1266 IN ULONG OutputBufferLength
,
1267 IN OUT PULONG ReturnLength
,
1268 IN KPROCESSOR_MODE PreviousMode
)
1271 return STATUS_SUCCESS
;
1279 KdChangeOption(IN KD_OPTION Option
,
1280 IN ULONG InBufferBytes OPTIONAL
,
1282 IN ULONG OutBufferBytes OPTIONAL
,
1283 OUT PVOID OutBuffer
,
1284 OUT PULONG OutBufferNeeded OPTIONAL
)
1287 return STATUS_SUCCESS
;
1295 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
1298 return STATUS_SUCCESS
;
1306 KdDisableDebugger(VOID
)
1309 return STATUS_SUCCESS
;
1317 KdRefreshDebuggerNotPresent(VOID
)
1320 return KdDebuggerNotPresent
;
1325 NtQueryDebugFilterState(ULONG ComponentId
,
1329 return STATUS_SUCCESS
;
1334 NtSetDebugFilterState(ULONG ComponentId
,
1339 return STATUS_SUCCESS
;