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
= (ULONG64
)(LONG_PTR
)KeGetCurrentThread();
176 WaitStateChange
->ProgramCounter
= (ULONG64
)(LONG_PTR
)KeGetContextPc(Context
);
178 /* Zero out the Control Report */
179 RtlZeroMemory(&WaitStateChange
->ControlReport
,
180 sizeof(DBGKD_CONTROL_REPORT
));
182 /* Now copy the instruction stream and set the count */
183 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
184 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
186 InstructionCount
= DBGKD_MAXSTREAM
;
187 WaitStateChange
->ControlReport
.InstructionCount
= InstructionCount
;
189 /* Clear all the breakpoints in this region */
191 KdpDeleteBreakpointRange((PVOID
)(LONG_PTR
)WaitStateChange
->ProgramCounter
,
192 (PVOID
)((ULONG_PTR
)WaitStateChange
->ProgramCounter
+
193 WaitStateChange
->ControlReport
.InstructionCount
- 1));
196 /* Copy the instruction stream again, this time without breakpoints */
197 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
198 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
199 WaitStateChange
->ControlReport
.InstructionCount
);
205 KdpSetContextState(IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange
,
208 PKPRCB Prcb
= KeGetCurrentPrcb();
210 /* Copy i386 specific debug registers */
211 WaitStateChange
->ControlReport
.Dr6
= Prcb
->ProcessorState
.SpecialRegisters
.
213 WaitStateChange
->ControlReport
.Dr7
= Prcb
->ProcessorState
.SpecialRegisters
.
216 /* Copy i386 specific segments */
217 WaitStateChange
->ControlReport
.SegCs
= (USHORT
)Context
->SegCs
;
218 WaitStateChange
->ControlReport
.SegDs
= (USHORT
)Context
->SegDs
;
219 WaitStateChange
->ControlReport
.SegEs
= (USHORT
)Context
->SegEs
;
220 WaitStateChange
->ControlReport
.SegFs
= (USHORT
)Context
->SegFs
;
223 WaitStateChange
->ControlReport
.EFlags
= Context
->EFlags
;
225 /* Set Report Flags */
226 WaitStateChange
->ControlReport
.ReportFlags
= REPORT_INCLUDES_SEGS
;
227 if (WaitStateChange
->ControlReport
.SegCs
== KGDT_R0_CODE
)
229 WaitStateChange
->ControlReport
.ReportFlags
= REPORT_INCLUDES_CS
;
235 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version
)
237 /* Copy the version block */
238 RtlCopyMemory(Version
, &KdVersionBlock
, sizeof(DBGKD_GET_VERSION64
));
243 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State
)
247 /* Fill out the header */
248 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
249 Header
.Buffer
= (PCHAR
)State
;
251 /* Get the version block */
252 KdpSysGetVersion(&State
->u
.GetVersion64
);
254 /* Fill out the state */
255 State
->ApiNumber
= DbgKdGetVersionApi
;
256 State
->ReturnStatus
= STATUS_SUCCESS
;
258 /* Send the packet */
259 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
267 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
272 ULONG Length
= State
->u
.ReadMemory
.TransferCount
;
273 NTSTATUS Status
= STATUS_SUCCESS
;
275 /* Validate length */
276 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
278 /* Overflow, set it to maximum possible */
279 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
283 if (!MmIsAddressValid((PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
))
285 Ke386SetCr2(State
->u
.ReadMemory
.TargetBaseAddress
);
290 if (!State
->u
.ReadMemory
.TargetBaseAddress
)
293 Status
= STATUS_UNSUCCESSFUL
;
297 RtlCopyMemory(Data
->Buffer
,
298 (PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
,
302 /* Fill out the header */
303 Data
->Length
= Length
;
304 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
305 Header
.Buffer
= (PCHAR
)State
;
307 /* Fill out the state */
308 State
->ReturnStatus
= Status
;
309 State
->u
.ReadMemory
.ActualBytesRead
= Length
;
311 /* Send the packet */
312 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
320 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
324 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
326 ULONG Length
, RealLength
;
329 /* Setup the header */
330 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
331 Header
.Buffer
= (PCHAR
)State
;
332 ASSERT(Data
->Length
== 0);
334 /* Check the length requested */
335 Length
= ReadMemory
->TransferCount
;
336 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
338 /* Use maximum allowed */
339 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
342 /* Make sure that this is a valid request */
343 if (((ULONG
)ReadMemory
->TargetBaseAddress
< sizeof(KPROCESSOR_STATE
)) &&
344 (State
->Processor
< KeNumberProcessors
))
346 /* Get the actual length */
347 RealLength
= sizeof(KPROCESSOR_STATE
) -
348 (ULONG_PTR
)ReadMemory
->TargetBaseAddress
;
349 if (RealLength
< Length
) Length
= RealLength
;
351 /* Set the proper address */
352 ControlStart
= (PVOID
)((ULONG_PTR
)ReadMemory
->TargetBaseAddress
+
353 (ULONG_PTR
)&KiProcessorBlock
[State
->Processor
]->
356 /* Copy the memory */
357 RtlCopyMemory(Data
->Buffer
, ControlStart
, Length
);
358 Data
->Length
= Length
;
361 State
->ReturnStatus
= STATUS_SUCCESS
;
362 ReadMemory
->ActualBytesRead
= Data
->Length
;
366 /* Invalid request */
368 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
369 ReadMemory
->ActualBytesRead
= 0;
373 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
381 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
385 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
390 /* Setup the header */
391 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
392 Header
.Buffer
= (PCHAR
)State
;
394 /* Make sure that this is a valid request */
395 Length
= WriteMemory
->TransferCount
;
396 if ((((ULONG
)WriteMemory
->TargetBaseAddress
+ Length
) <=
397 sizeof(KPROCESSOR_STATE
)) &&
398 (State
->Processor
< KeNumberProcessors
))
400 /* Set the proper address */
401 ControlStart
= (PVOID
)((ULONG_PTR
)WriteMemory
->TargetBaseAddress
+
402 (ULONG_PTR
)&KiProcessorBlock
[State
->Processor
]->
405 /* Copy the memory */
406 RtlCopyMemory(ControlStart
, Data
->Buffer
, Data
->Length
);
407 Length
= Data
->Length
;
410 State
->ReturnStatus
= STATUS_SUCCESS
;
411 WriteMemory
->ActualBytesWritten
= Length
;
415 /* Invalid request */
417 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
418 WriteMemory
->ActualBytesWritten
= 0;
422 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
430 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
434 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
437 /* Fill out the header */
438 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
439 Header
.Buffer
= (PCHAR
)State
;
440 ASSERT(Data
->Length
== 0);
442 /* Get the version block */
443 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
446 State
->ReturnStatus
= STATUS_SUCCESS
;
451 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
454 /* Send the packet */
455 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
463 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
470 /* Setup the header */
471 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
472 Header
.Buffer
= (PCHAR
)State
;
473 ASSERT(Data
->Length
== 0);
475 /* Make sure that this is a valid request */
476 if (State
->Processor
< KeNumberProcessors
)
478 /* Check if the request is for this CPU */
479 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
481 /* We're just copying our own context */
482 ControlStart
= Context
;
486 /* SMP not yet handled */
491 /* Copy the memory */
492 RtlCopyMemory(Data
->Buffer
, ControlStart
, sizeof(CONTEXT
));
493 Data
->Length
= sizeof(CONTEXT
);
496 State
->ReturnStatus
= STATUS_SUCCESS
;
500 /* Invalid request */
501 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
505 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
513 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
520 /* Setup the header */
521 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
522 Header
.Buffer
= (PCHAR
)State
;
523 ASSERT(Data
->Length
== sizeof(CONTEXT
));
525 /* Make sure that this is a valid request */
526 if (State
->Processor
< KeNumberProcessors
)
528 /* Check if the request is for this CPU */
529 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
531 /* We're just copying our own context */
532 ControlStart
= Context
;
536 /* SMP not yet handled */
541 /* Copy the memory */
542 RtlCopyMemory(ControlStart
, Data
->Buffer
, sizeof(CONTEXT
));
545 State
->ReturnStatus
= STATUS_SUCCESS
;
549 /* Invalid request */
550 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
554 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
562 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State
)
564 /* Crash with the special code */
565 KeBugCheck(MANUALLY_INITIATED_CRASH
);
570 KdpSendWaitContinue(IN ULONG PacketType
,
571 IN PSTRING SendHeader
,
572 IN PSTRING SendData OPTIONAL
,
573 IN OUT PCONTEXT Context
)
576 DBGKD_MANIPULATE_STATE64 ManipulateState
;
580 /* Setup the Manipulate State structure */
581 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
582 Header
.Buffer
= (PCHAR
)&ManipulateState
;
583 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
584 Data
.Buffer
= KdpMessageBuffer
;
585 //KdpContextSent = FALSE;
588 /* Send the Packet */
589 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
591 /* If the debugger isn't present anymore, just return success */
592 if (KdDebuggerNotPresent
) return ContinueSuccess
;
594 /* Main processing Loop */
600 /* Wait to get a reply to our packet */
601 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
607 /* If we got a resend request, do it */
608 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
609 } while (RecvCode
== KdPacketTimedOut
);
611 /* Now check what API we got */
612 switch (ManipulateState
.ApiNumber
)
614 case DbgKdReadVirtualMemoryApi
:
616 /* Read virtual memory */
617 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
620 case DbgKdWriteVirtualMemoryApi
:
623 Ke386SetCr2(DbgKdWriteVirtualMemoryApi
);
627 case DbgKdGetContextApi
:
629 /* Get the current context */
630 KdpGetContext(&ManipulateState
, &Data
, Context
);
633 case DbgKdSetContextApi
:
635 /* Set a new context */
636 KdpSetContext(&ManipulateState
, &Data
, Context
);
639 case DbgKdWriteBreakPointApi
:
641 /* Write the breakpoint */
642 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
645 case DbgKdRestoreBreakPointApi
:
647 /* Restore the breakpoint */
648 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
651 case DbgKdContinueApi
:
653 /* Simply continue */
654 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
656 case DbgKdReadControlSpaceApi
:
658 /* Read control space */
659 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
662 case DbgKdWriteControlSpaceApi
:
664 /* Write control space */
665 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
668 case DbgKdReadIoSpaceApi
:
671 Ke386SetCr2(DbgKdReadIoSpaceApi
);
675 case DbgKdWriteIoSpaceApi
:
678 Ke386SetCr2(DbgKdWriteIoSpaceApi
);
684 /* Reboot the system */
685 HalReturnToFirmware(HalRebootRoutine
);
688 case DbgKdContinueApi2
:
690 /* Check if caller reports success */
691 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
693 /* Update the state */
694 KdpGetStateChange(&ManipulateState
, Context
);
695 return ContinueSuccess
;
699 /* Return an error */
700 return ContinueError
;
704 case DbgKdReadPhysicalMemoryApi
:
708 Ke386SetCr2(DbgKdReadPhysicalMemoryApi
);
712 case DbgKdWritePhysicalMemoryApi
:
715 Ke386SetCr2(DbgKdWritePhysicalMemoryApi
);
719 case DbgKdQuerySpecialCallsApi
:
722 Ke386SetCr2(DbgKdQuerySpecialCallsApi
);
726 case DbgKdSetSpecialCallApi
:
729 Ke386SetCr2(DbgKdSetSpecialCallApi
);
733 case DbgKdClearSpecialCallsApi
:
736 Ke386SetCr2(DbgKdClearSpecialCallsApi
);
740 case DbgKdSetInternalBreakPointApi
:
743 Ke386SetCr2(DbgKdSetInternalBreakPointApi
);
747 case DbgKdGetInternalBreakPointApi
:
750 Ke386SetCr2(DbgKdGetInternalBreakPointApi
);
754 case DbgKdReadIoSpaceExtendedApi
:
757 Ke386SetCr2(DbgKdReadIoSpaceExtendedApi
);
761 case DbgKdWriteIoSpaceExtendedApi
:
764 Ke386SetCr2(DbgKdWriteIoSpaceExtendedApi
);
768 case DbgKdGetVersionApi
:
770 /* Get version data */
771 KdpGetVersion(&ManipulateState
);
774 case DbgKdWriteBreakPointExApi
:
777 Ke386SetCr2(DbgKdWriteBreakPointExApi
);
781 case DbgKdRestoreBreakPointExApi
:
784 Ke386SetCr2(DbgKdRestoreBreakPointExApi
);
788 case DbgKdCauseBugCheckApi
:
790 /* Crash the system */
791 KdpCauseBugCheck(&ManipulateState
);
794 case DbgKdSwitchProcessor
:
797 Ke386SetCr2(DbgKdSwitchProcessor
);
804 Ke386SetCr2(DbgKdPageInApi
);
808 case DbgKdReadMachineSpecificRegister
:
811 Ke386SetCr2(DbgKdReadMachineSpecificRegister
);
815 case DbgKdWriteMachineSpecificRegister
:
818 Ke386SetCr2(DbgKdWriteMachineSpecificRegister
);
825 Ke386SetCr2(OldVlm1
);
832 Ke386SetCr2(OldVlm2
);
836 case DbgKdSearchMemoryApi
:
839 Ke386SetCr2(DbgKdSearchMemoryApi
);
843 case DbgKdGetBusDataApi
:
846 Ke386SetCr2(DbgKdGetBusDataApi
);
850 case DbgKdSetBusDataApi
:
853 Ke386SetCr2(DbgKdSetBusDataApi
);
857 case DbgKdCheckLowMemoryApi
:
860 Ke386SetCr2(DbgKdCheckLowMemoryApi
);
864 case DbgKdClearAllInternalBreakpointsApi
:
866 /* Just clear the counter */
867 KdpNumInternalBreakpoints
= 0;
870 case DbgKdFillMemoryApi
:
873 Ke386SetCr2(DbgKdFillMemoryApi
);
877 case DbgKdQueryMemoryApi
:
880 KdpQueryMemory(&ManipulateState
, Context
);
883 case DbgKdSwitchPartition
:
886 Ke386SetCr2(DbgKdSwitchPartition
);
890 /* Unsupported Message */
893 /* Setup an empty message, with failure */
897 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
900 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
911 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
912 IN PKD_SYMBOLS_INFO SymbolInfo
,
914 IN OUT PCONTEXT Context
)
918 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
919 KCONTINUE_STATUS Status
;
921 /* Start wait loop */
924 /* Build the architecture common parts of the message */
925 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
929 /* Now finish creating the structure */
930 KdpSetContextState(&WaitStateChange
, Context
);
932 /* Fill out load data */
933 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
934 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONGLONG
)(LONG_PTR
)SymbolInfo
->BaseOfDll
;
935 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
936 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
937 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
939 /* Check if we have a symbol name */
942 /* Setup the information */
943 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathName
->Length
;
944 RtlCopyMemory(KdpPathBuffer
, PathName
->Buffer
, PathName
->Length
);
945 Data
.Buffer
= KdpPathBuffer
;
946 Data
.Length
= WaitStateChange
.u
.LoadSymbols
.PathNameLength
;
952 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
956 /* Setup the header */
957 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
958 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
960 /* Send the packet */
961 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
965 } while (Status
== ContinueProcessorReselected
);
973 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
974 IN OUT PCONTEXT Context
,
975 IN BOOLEAN SecondChanceException
)
978 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
981 /* Start report loop */
984 /* Build the architecture common parts of the message */
985 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
987 /* Convert the exception record to 64-bits and set First Chance flag */
988 ExceptionRecord32To64((PEXCEPTION_RECORD32
)ExceptionRecord
,
989 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
990 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
992 /* Now finish creating the structure */
993 KdpSetContextState(&WaitStateChange
, Context
);
995 /* Setup the actual header to send to KD */
996 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
997 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
999 /* Setup the trace data */
1000 DumpTraceData(&Data
);
1002 /* Send State Change packet and wait for a reply */
1003 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1007 } while (Status
== ContinueProcessorReselected
);
1015 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
1016 IN PVOID DeferredContext
,
1017 IN PVOID SystemArgument1
,
1018 IN PVOID SystemArgument2
)
1020 LONG OldSlip
, NewSlip
, PendingSlip
;
1022 /* Get the current pending slip */
1023 PendingSlip
= KdpTimeSlipPending
;
1026 /* Save the old value and either disable or enable it now. */
1027 OldSlip
= PendingSlip
;
1028 NewSlip
= OldSlip
> 1 ? 1 : 0;
1030 /* Try to change the value */
1031 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1033 OldSlip
) != OldSlip
);
1035 /* If the New Slip value is 1, then do the Time Slipping */
1036 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1041 KdpTimeSlipWork(IN PVOID Context
)
1044 LARGE_INTEGER DueTime
;
1046 /* Update the System time from the CMOS */
1047 ExAcquireTimeRefreshLock(FALSE
);
1048 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1049 ExReleaseTimeRefreshLock();
1051 /* Check if we have a registered Time Slip Event and signal it */
1052 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
1053 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
1054 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
1056 /* Delay the DPC until it runs next time */
1057 DueTime
.QuadPart
= -1800000000;
1058 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1063 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1064 IN OUT PCONTEXT ContextRecord
,
1065 IN BOOLEAN SecondChanceException
)
1069 /* Save the port data */
1072 /* Report a state change */
1073 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1075 SecondChanceException
);
1077 /* Restore the port data and return */
1084 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1086 LARGE_INTEGER Null
= {{0}};
1088 /* Check if interrupts were disabled */
1089 if (!(TrapFrame
->EFlags
& EFLAGS_INTERRUPT_MASK
))
1091 /* Nothing to return */
1095 /* Otherwise, do the call */
1096 return KeQueryPerformanceCounter(NULL
);
1101 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1102 IN PKEXCEPTION_FRAME ExceptionFrame
)
1106 /* Check if we have a trap frame */
1109 /* Calculate the time difference for the enter */
1110 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1111 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1112 KdTimerStart
.QuadPart
;
1116 /* No trap frame, so can't calculate */
1117 KdTimerStop
.QuadPart
= 0;
1120 /* Save the current IRQL */
1121 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1123 /* Freeze all CPUs */
1124 Entered
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1126 /* Lock the port, save the state and set debugger entered */
1127 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1129 KdEnteredDebugger
= TRUE
;
1131 /* Check freeze flag */
1132 if (KiFreezeFlag
& 1)
1134 /* Print out errror */
1135 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1138 /* Check processor state */
1139 if (KiFreezeFlag
& 2)
1141 /* Print out errror */
1142 KdpDprintf("Some processors not frozen in debugger!\n");
1145 /* Make sure we acquired the port */
1146 if (!KdpPortLocked
) KdpDprintf("Port lock was not acquired!\n");
1148 /* Return enter state */
1154 KdExitDebugger(IN BOOLEAN Entered
)
1158 /* Restore the state and unlock the port */
1160 if (KdpPortLocked
) KdpPortUnlock();
1162 /* Unfreeze the CPUs */
1163 KeThawExecution(Entered
);
1165 /* Compare time with the one from KdEnterDebugger */
1166 if (!KdTimerStop
.QuadPart
)
1168 /* We didn't get a trap frame earlier in so never got the time */
1169 KdTimerStart
= KdTimerStop
;
1173 /* Query the timer */
1174 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1177 /* Check if a Time Slip was on queue */
1178 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1181 /* Queue a DPC for the time slip */
1182 InterlockedIncrement(&KdpTimeSlipPending
);
1183 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
);
1189 KdEnableDebuggerWithLock(BOOLEAN NeedLock
)
1191 KIRQL OldIrql
= PASSIVE_LEVEL
;
1193 /* Check if we need to acquire the lock */
1197 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1201 /* Check if we're not disabled */
1202 if (!KdDisableCount
)
1204 /* Check if we had locked the port before */
1208 KeLowerIrql(OldIrql
);
1212 /* Fail: We're already enabled */
1213 return STATUS_INVALID_PARAMETER
;
1216 /* Decrease the disable count */
1217 if (!(--KdDisableCount
))
1219 /* We're now enabled again! Were we enabled before, too? */
1220 if (KdPreviouslyEnabled
)
1222 /* Reinitialize the Debugger */
1223 KdInitSystem(0, NULL
) ;
1224 KdpRestoreAllBreakpoints();
1228 /* Check if we had locked the port before */
1231 /* Yes, now unlock it */
1232 KeLowerIrql(OldIrql
);
1237 return STATUS_SUCCESS
;
1240 /* PUBLIC FUNCTIONS **********************************************************/
1247 KdEnableDebugger(VOID
)
1249 /* Use the internal routine */
1251 return KdEnableDebuggerWithLock(TRUE
);
1259 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
1260 IN PVOID InputBuffer
,
1261 IN ULONG InputBufferLength
,
1262 OUT PVOID OutputBuffer
,
1263 IN ULONG OutputBufferLength
,
1264 IN OUT PULONG ReturnLength
,
1265 IN KPROCESSOR_MODE PreviousMode
)
1268 return STATUS_SUCCESS
;
1276 KdChangeOption(IN KD_OPTION Option
,
1277 IN ULONG InBufferBytes OPTIONAL
,
1279 IN ULONG OutBufferBytes OPTIONAL
,
1280 OUT PVOID OutBuffer
,
1281 OUT PULONG OutBufferNeeded OPTIONAL
)
1284 return STATUS_SUCCESS
;
1292 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
1295 return STATUS_SUCCESS
;
1303 KdDisableDebugger(VOID
)
1306 return STATUS_SUCCESS
;
1314 KdRefreshDebuggerNotPresent(VOID
)
1317 return KdDebuggerNotPresent
;
1322 NtQueryDebugFilterState(ULONG ComponentId
,
1326 return STATUS_SUCCESS
;
1331 NtSetDebugFilterState(ULONG ComponentId
,
1336 return STATUS_SUCCESS
;