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
= (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 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State
)
215 /* Fill out the header */
216 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
217 Header
.Buffer
= (PCHAR
)State
;
219 /* Get the version block */
220 KdpSysGetVersion(&State
->u
.GetVersion64
);
222 /* Fill out the state */
223 State
->ApiNumber
= DbgKdGetVersionApi
;
224 State
->ReturnStatus
= STATUS_SUCCESS
;
226 /* Send the packet */
227 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
235 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
240 ULONG Length
= State
->u
.ReadMemory
.TransferCount
;
241 NTSTATUS Status
= STATUS_SUCCESS
;
242 ULONG64 TargetBaseAddress
= State
->u
.ReadMemory
.TargetBaseAddress
;
244 /* Validate length */
245 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
247 /* Overflow, set it to maximum possible */
248 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
252 if (!MmIsAddressValid((PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
))
254 Ke386SetCr2(State
->u
.ReadMemory
.TargetBaseAddress
);
259 // HACK for x64, until KD stops sending bogus addresses to WinDbg
260 if (TargetBaseAddress
< (ULONG_PTR
)MM_LOWEST_SYSTEM_ADDRESS
)
262 FrLdrDbgPrint("Trying to read memory at 0x%p\n", TargetBaseAddress
);
263 // DPRINT1("Trying to read memory at 0x%p\n", TargetBaseAddress);
264 TargetBaseAddress
= 0;
267 if (!TargetBaseAddress
)
270 Status
= STATUS_UNSUCCESSFUL
;
274 RtlCopyMemory(Data
->Buffer
,
275 (PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
,
279 /* Fill out the header */
280 Data
->Length
= Length
;
281 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
282 Header
.Buffer
= (PCHAR
)State
;
284 /* Fill out the state */
285 State
->ReturnStatus
= Status
;
286 State
->u
.ReadMemory
.ActualBytesRead
= Length
;
288 /* Send the packet */
289 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
297 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
301 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
303 ULONG Length
, RealLength
;
306 /* Setup the header */
307 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
308 Header
.Buffer
= (PCHAR
)State
;
309 ASSERT(Data
->Length
== 0);
311 /* Check the length requested */
312 Length
= ReadMemory
->TransferCount
;
313 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
315 /* Use maximum allowed */
316 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
319 #if defined (_M_AMD64)
320 if ((ULONG
)ReadMemory
->TargetBaseAddress
<= 2)
322 PKPRCB Prcb
= KiProcessorBlock
[State
->Processor
];
323 PKIPCR Pcr
= CONTAINING_RECORD(Prcb
, KIPCR
, Prcb
);
325 switch ((ULONG_PTR
)ReadMemory
->TargetBaseAddress
)
328 /* Copy a pointer to the Pcr */
330 RealLength
= sizeof(PVOID
);
334 /* Copy a pointer to the Prcb */
335 ControlStart
= &Prcb
;
336 RealLength
= sizeof(PVOID
);
340 /* Copy SpecialRegisters */
341 ControlStart
= &Prcb
->ProcessorState
.SpecialRegisters
;
342 RealLength
= sizeof(KSPECIAL_REGISTERS
);
351 if (RealLength
< Length
) Length
= RealLength
;
353 /* Copy the memory */
354 RtlCopyMemory(Data
->Buffer
, ControlStart
, Length
);
355 Data
->Length
= Length
;
358 State
->ReturnStatus
= STATUS_SUCCESS
;
359 ReadMemory
->ActualBytesRead
= Data
->Length
;
362 /* Make sure that this is a valid request */
363 if (((ULONG
)ReadMemory
->TargetBaseAddress
< sizeof(KPROCESSOR_STATE
)) &&
364 (State
->Processor
< KeNumberProcessors
))
366 /* Get the actual length */
367 RealLength
= sizeof(KPROCESSOR_STATE
) -
368 (ULONG_PTR
)ReadMemory
->TargetBaseAddress
;
369 if (RealLength
< Length
) Length
= RealLength
;
371 /* Set the proper address */
372 ControlStart
= (PVOID
)((ULONG_PTR
)ReadMemory
->TargetBaseAddress
+
373 (ULONG_PTR
)&KiProcessorBlock
[State
->Processor
]->
376 /* Copy the memory */
377 RtlCopyMemory(Data
->Buffer
, ControlStart
, Length
);
378 Data
->Length
= Length
;
381 State
->ReturnStatus
= STATUS_SUCCESS
;
382 ReadMemory
->ActualBytesRead
= Data
->Length
;
387 /* Invalid request */
389 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
390 ReadMemory
->ActualBytesRead
= 0;
394 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
402 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
406 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
411 /* Setup the header */
412 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
413 Header
.Buffer
= (PCHAR
)State
;
415 /* Make sure that this is a valid request */
416 Length
= WriteMemory
->TransferCount
;
417 if ((((ULONG
)WriteMemory
->TargetBaseAddress
+ Length
) <=
418 sizeof(KPROCESSOR_STATE
)) &&
419 (State
->Processor
< KeNumberProcessors
))
421 /* Set the proper address */
422 ControlStart
= (PVOID
)((ULONG_PTR
)WriteMemory
->TargetBaseAddress
+
423 (ULONG_PTR
)&KiProcessorBlock
[State
->Processor
]->
426 /* Copy the memory */
427 RtlCopyMemory(ControlStart
, Data
->Buffer
, Data
->Length
);
428 Length
= Data
->Length
;
431 State
->ReturnStatus
= STATUS_SUCCESS
;
432 WriteMemory
->ActualBytesWritten
= Length
;
436 /* Invalid request */
438 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
439 WriteMemory
->ActualBytesWritten
= 0;
443 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
451 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
455 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
458 /* Fill out the header */
459 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
460 Header
.Buffer
= (PCHAR
)State
;
461 ASSERT(Data
->Length
== 0);
463 /* Get the version block */
464 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
467 State
->ReturnStatus
= STATUS_SUCCESS
;
472 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
475 /* Send the packet */
476 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
484 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
491 /* Setup the header */
492 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
493 Header
.Buffer
= (PCHAR
)State
;
494 ASSERT(Data
->Length
== 0);
496 /* Make sure that this is a valid request */
497 if (State
->Processor
< KeNumberProcessors
)
499 /* Check if the request is for this CPU */
500 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
502 /* We're just copying our own context */
503 ControlStart
= Context
;
507 /* SMP not yet handled */
512 /* Copy the memory */
513 RtlCopyMemory(Data
->Buffer
, ControlStart
, sizeof(CONTEXT
));
514 Data
->Length
= sizeof(CONTEXT
);
517 State
->ReturnStatus
= STATUS_SUCCESS
;
521 /* Invalid request */
522 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
526 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
534 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
541 /* Setup the header */
542 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
543 Header
.Buffer
= (PCHAR
)State
;
544 ASSERT(Data
->Length
== sizeof(CONTEXT
));
546 /* Make sure that this is a valid request */
547 if (State
->Processor
< KeNumberProcessors
)
549 /* Check if the request is for this CPU */
550 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
552 /* We're just copying our own context */
553 ControlStart
= Context
;
557 /* SMP not yet handled */
562 /* Copy the memory */
563 RtlCopyMemory(ControlStart
, Data
->Buffer
, sizeof(CONTEXT
));
566 State
->ReturnStatus
= STATUS_SUCCESS
;
570 /* Invalid request */
571 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
575 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
583 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
588 PDBGKD_READ_WRITE_MSR ReadMsr
;
591 /* Setup the header */
592 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
593 Header
.Buffer
= (PCHAR
)State
;
596 ReadMsr
= &State
->u
.ReadWriteMsr
;
599 Value
.QuadPart
= __readmsr(ReadMsr
->Msr
);
602 ReadMsr
->DataValueLow
= Value
.LowPart
;
603 ReadMsr
->DataValueHigh
= Value
.HighPart
;
606 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
614 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
619 PDBGKD_READ_WRITE_MSR WriteMsr
;
622 /* Setup the header */
623 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
624 Header
.Buffer
= (PCHAR
)State
;
627 WriteMsr
= &State
->u
.ReadWriteMsr
;
630 Value
.LowPart
= WriteMsr
->DataValueLow
;
631 Value
.HighPart
= WriteMsr
->DataValueHigh
;
634 __writemsr(WriteMsr
->Msr
, Value
.QuadPart
);
637 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
645 KdpSendWaitContinue(IN ULONG PacketType
,
646 IN PSTRING SendHeader
,
647 IN PSTRING SendData OPTIONAL
,
648 IN OUT PCONTEXT Context
)
651 DBGKD_MANIPULATE_STATE64 ManipulateState
;
655 /* Setup the Manipulate State structure */
656 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
657 Header
.Buffer
= (PCHAR
)&ManipulateState
;
658 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
659 Data
.Buffer
= KdpMessageBuffer
;
660 //KdpContextSent = FALSE;
663 /* Send the Packet */
664 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
666 /* If the debugger isn't present anymore, just return success */
667 if (KdDebuggerNotPresent
) return ContinueSuccess
;
669 /* Main processing Loop */
675 /* Wait to get a reply to our packet */
676 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
682 /* If we got a resend request, do it */
683 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
684 } while (RecvCode
== KdPacketTimedOut
);
686 /* Now check what API we got */
687 switch (ManipulateState
.ApiNumber
)
689 case DbgKdReadVirtualMemoryApi
:
691 /* Read virtual memory */
692 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
695 case DbgKdWriteVirtualMemoryApi
:
698 Ke386SetCr2(DbgKdWriteVirtualMemoryApi
);
702 case DbgKdGetContextApi
:
704 /* Get the current context */
705 KdpGetContext(&ManipulateState
, &Data
, Context
);
708 case DbgKdSetContextApi
:
710 /* Set a new context */
711 KdpSetContext(&ManipulateState
, &Data
, Context
);
714 case DbgKdWriteBreakPointApi
:
716 /* Write the breakpoint */
717 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
720 case DbgKdRestoreBreakPointApi
:
723 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
726 case DbgKdContinueApi
:
728 /* Simply continue */
729 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
731 case DbgKdReadControlSpaceApi
:
733 /* Read control space */
734 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
737 case DbgKdWriteControlSpaceApi
:
740 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
743 case DbgKdReadIoSpaceApi
:
746 Ke386SetCr2(DbgKdReadIoSpaceApi
);
750 case DbgKdWriteIoSpaceApi
:
753 Ke386SetCr2(DbgKdWriteIoSpaceApi
);
760 Ke386SetCr2(DbgKdRebootApi
);
764 case DbgKdContinueApi2
:
766 /* Check if caller reports success */
767 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
769 /* Update the state */
770 KdpGetStateChange(&ManipulateState
, Context
);
771 return ContinueSuccess
;
775 /* Return an error */
776 return ContinueError
;
780 case DbgKdReadPhysicalMemoryApi
:
784 Ke386SetCr2(DbgKdReadPhysicalMemoryApi
);
788 case DbgKdWritePhysicalMemoryApi
:
791 Ke386SetCr2(DbgKdWritePhysicalMemoryApi
);
795 case DbgKdQuerySpecialCallsApi
:
798 Ke386SetCr2(DbgKdQuerySpecialCallsApi
);
802 case DbgKdSetSpecialCallApi
:
805 Ke386SetCr2(DbgKdSetSpecialCallApi
);
809 case DbgKdClearSpecialCallsApi
:
812 Ke386SetCr2(DbgKdClearSpecialCallsApi
);
816 case DbgKdSetInternalBreakPointApi
:
819 Ke386SetCr2(DbgKdSetInternalBreakPointApi
);
823 case DbgKdGetInternalBreakPointApi
:
826 Ke386SetCr2(DbgKdGetInternalBreakPointApi
);
830 case DbgKdReadIoSpaceExtendedApi
:
833 Ke386SetCr2(DbgKdReadIoSpaceExtendedApi
);
837 case DbgKdWriteIoSpaceExtendedApi
:
840 Ke386SetCr2(DbgKdWriteIoSpaceExtendedApi
);
844 case DbgKdGetVersionApi
:
846 /* Get version data */
847 KdpGetVersion(&ManipulateState
);
850 case DbgKdWriteBreakPointExApi
:
853 Ke386SetCr2(DbgKdWriteBreakPointExApi
);
857 case DbgKdRestoreBreakPointExApi
:
860 Ke386SetCr2(DbgKdRestoreBreakPointExApi
);
864 case DbgKdCauseBugCheckApi
:
867 Ke386SetCr2(DbgKdCauseBugCheckApi
);
871 case DbgKdSwitchProcessor
:
874 Ke386SetCr2(DbgKdSwitchProcessor
);
881 Ke386SetCr2(DbgKdPageInApi
);
885 case DbgKdReadMachineSpecificRegister
:
887 /* Read the specified MSR */
888 KdpReadMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
891 case DbgKdWriteMachineSpecificRegister
:
893 /* Write the specified MSR */
894 KdpWriteMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
900 Ke386SetCr2(OldVlm1
);
907 Ke386SetCr2(OldVlm2
);
911 case DbgKdSearchMemoryApi
:
914 Ke386SetCr2(DbgKdSearchMemoryApi
);
918 case DbgKdGetBusDataApi
:
921 Ke386SetCr2(DbgKdGetBusDataApi
);
925 case DbgKdSetBusDataApi
:
928 Ke386SetCr2(DbgKdSetBusDataApi
);
932 case DbgKdCheckLowMemoryApi
:
935 Ke386SetCr2(DbgKdCheckLowMemoryApi
);
939 case DbgKdClearAllInternalBreakpointsApi
:
941 /* Just clear the counter */
942 KdpNumInternalBreakpoints
= 0;
945 case DbgKdFillMemoryApi
:
948 Ke386SetCr2(DbgKdFillMemoryApi
);
952 case DbgKdQueryMemoryApi
:
955 KdpQueryMemory(&ManipulateState
, Context
);
958 case DbgKdSwitchPartition
:
961 Ke386SetCr2(DbgKdSwitchPartition
);
965 /* Unsupported Message */
968 /* Setup an empty message, with failure */
972 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
975 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
986 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
987 IN PKD_SYMBOLS_INFO SymbolInfo
,
989 IN OUT PCONTEXT Context
)
993 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
994 KCONTINUE_STATUS Status
;
996 /* Start wait loop */
999 /* Build the architecture common parts of the message */
1000 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
1004 /* Now finish creating the structure */
1005 KdpSetContextState(&WaitStateChange
, Context
);
1007 /* Fill out load data */
1008 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
1009 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONGLONG
)(LONG_PTR
)SymbolInfo
->BaseOfDll
;
1010 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
1011 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
1012 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
1014 /* Check if we have a symbol name */
1017 /* Setup the information */
1018 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathName
->Length
;
1019 RtlCopyMemory(KdpPathBuffer
, PathName
->Buffer
, PathName
->Length
);
1020 Data
.Buffer
= KdpPathBuffer
;
1021 Data
.Length
= WaitStateChange
.u
.LoadSymbols
.PathNameLength
;
1027 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
1031 /* Setup the header */
1032 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
1033 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1035 /* Send the packet */
1036 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1040 } while(Status
== ContinueProcessorReselected
);
1048 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
1049 IN OUT PCONTEXT Context
,
1050 IN BOOLEAN SecondChanceException
)
1052 STRING Header
, Data
;
1053 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
1056 /* Start report loop */
1059 /* Build the architecture common parts of the message */
1060 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
1062 /* Convert the exception record to 64-bits and set First Chance flag */
1063 ExceptionRecordTo64(ExceptionRecord
,
1064 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
1065 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
1067 /* Now finish creating the structure */
1068 KdpSetContextState(&WaitStateChange
, Context
);
1070 /* Setup the actual header to send to KD */
1071 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
) - sizeof(CONTEXT
);
1072 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1074 /* Setup the trace data */
1075 DumpTraceData(&Data
);
1077 /* Send State Change packet and wait for a reply */
1078 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1082 } while (Status
== KdPacketNeedsResend
);
1090 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
1091 IN PVOID DeferredContext
,
1092 IN PVOID SystemArgument1
,
1093 IN PVOID SystemArgument2
)
1095 LONG OldSlip
, NewSlip
, PendingSlip
;
1097 /* Get the current pending slip */
1098 PendingSlip
= KdpTimeSlipPending
;
1101 /* Save the old value and either disable or enable it now. */
1102 OldSlip
= PendingSlip
;
1103 NewSlip
= OldSlip
> 1 ? 1 : 0;
1105 /* Try to change the value */
1106 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1108 OldSlip
) != OldSlip
);
1110 /* If the New Slip value is 1, then do the Time Slipping */
1111 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1116 KdpTimeSlipWork(IN PVOID Context
)
1119 LARGE_INTEGER DueTime
;
1121 /* Update the System time from the CMOS */
1122 ExAcquireTimeRefreshLock(FALSE
);
1123 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1124 ExReleaseTimeRefreshLock();
1126 /* Check if we have a registered Time Slip Event and signal it */
1127 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
1128 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
1129 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
1131 /* Delay the DPC until it runs next time */
1132 DueTime
.QuadPart
= -1800000000;
1133 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1138 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1139 IN OUT PCONTEXT ContextRecord
,
1140 IN BOOLEAN SecondChanceException
)
1144 /* Save the port data */
1147 /* Report a state change */
1148 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1150 SecondChanceException
);
1152 /* Restore the port data and return */
1159 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1161 LARGE_INTEGER Null
= {{0}};
1163 /* Check if interrupts were disabled */
1164 if (!(TrapFrame
->EFlags
& EFLAGS_INTERRUPT_MASK
))
1166 /* Nothing to return */
1170 /* Otherwise, do the call */
1171 return KeQueryPerformanceCounter(NULL
);
1176 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1177 IN PKEXCEPTION_FRAME ExceptionFrame
)
1181 /* Check if we have a trap frame */
1184 /* Calculate the time difference for the enter */
1185 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1186 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1187 KdTimerStart
.QuadPart
;
1191 /* No trap frame, so can't calculate */
1192 KdTimerStop
.QuadPart
= 0;
1195 /* Save the current IRQL */
1196 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1198 /* Freeze all CPUs */
1199 Entered
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1201 /* Lock the port, save the state and set debugger entered */
1202 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1204 KdEnteredDebugger
= TRUE
;
1206 /* Check freeze flag */
1207 if (KiFreezeFlag
& 1)
1209 /* Print out errror */
1210 DbgPrint("FreezeLock was jammed! Backup SpinLock was used!\n");
1213 /* Check processor state */
1214 if (KiFreezeFlag
& 2)
1216 /* Print out errror */
1217 DbgPrint("Some processors not frozen in debugger!\n");
1220 /* Make sure we acquired the port */
1221 if (!KdpPortLocked
) DbgPrint("Port lock was not acquired!\n");
1223 /* Return enter state */
1229 KdExitDebugger(IN BOOLEAN Entered
)
1233 /* Restore the state and unlock the port */
1235 if (KdpPortLocked
) KdpPortUnlock();
1237 /* Unfreeze the CPUs */
1238 KeThawExecution(Entered
);
1240 /* Compare time with the one from KdEnterDebugger */
1241 if (!KdTimerStop
.QuadPart
)
1243 /* We didn't get a trap frame earlier in so never got the time */
1244 KdTimerStart
= KdTimerStop
;
1248 /* Query the timer */
1249 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1252 /* Check if a Time Slip was on queue */
1253 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1256 /* Queue a DPC for the time slip */
1257 InterlockedIncrement(&KdpTimeSlipPending
);
1258 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
);
1264 KdEnableDebuggerWithLock(BOOLEAN NeedLock
)
1266 KIRQL OldIrql
= PASSIVE_LEVEL
;
1268 /* Check if we need to acquire the lock */
1272 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1276 /* Check if we're not disabled */
1277 if (!KdDisableCount
)
1279 /* Check if we had locked the port before */
1283 KeLowerIrql(OldIrql
);
1287 /* Fail: We're already enabled */
1288 return STATUS_INVALID_PARAMETER
;
1291 /* Decrease the disable count */
1292 if (!(--KdDisableCount
))
1294 /* We're now enabled again! Were we enabled before, too? */
1295 if (KdPreviouslyEnabled
)
1297 /* Reinitialize the Debugger */
1298 KdInitSystem(0, NULL
) ;
1299 KdpRestoreAllBreakpoints();
1303 /* Check if we had locked the port before */
1306 /* Yes, now unlock it */
1307 KeLowerIrql(OldIrql
);
1312 return STATUS_SUCCESS
;
1315 /* PUBLIC FUNCTIONS **********************************************************/
1322 KdEnableDebugger(VOID
)
1324 /* Use the internal routine */
1326 return KdEnableDebuggerWithLock(TRUE
);
1334 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
1335 IN PVOID InputBuffer
,
1336 IN ULONG InputBufferLength
,
1337 OUT PVOID OutputBuffer
,
1338 IN ULONG OutputBufferLength
,
1339 IN OUT PULONG ReturnLength
,
1340 IN KPROCESSOR_MODE PreviousMode
)
1343 return STATUS_SUCCESS
;
1351 KdChangeOption(IN KD_OPTION Option
,
1352 IN ULONG InBufferBytes OPTIONAL
,
1354 IN ULONG OutBufferBytes OPTIONAL
,
1355 OUT PVOID OutBuffer
,
1356 OUT PULONG OutBufferNeeded OPTIONAL
)
1359 return STATUS_SUCCESS
;
1367 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
1370 return STATUS_SUCCESS
;
1378 KdDisableDebugger(VOID
)
1381 return STATUS_SUCCESS
;
1389 KdRefreshDebuggerNotPresent(VOID
)
1392 return KdDebuggerNotPresent
;
1397 NtQueryDebugFilterState(ULONG ComponentId
,
1401 return STATUS_SUCCESS
;
1406 NtSetDebugFilterState(ULONG ComponentId
,
1411 return STATUS_SUCCESS
;