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
)(ULONG_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 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
74 KdpDprintf("KdpSearchMemory called\n");
80 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
85 KdpDprintf("KdpFillMemory called\n");
91 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
95 PDBGKD_WRITE_BREAKPOINT64 Breakpoint
= &State
->u
.WriteBreakPoint
;
99 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
100 Header
.Buffer
= (PCHAR
)State
;
101 ASSERT(Data
->Length
== 0);
103 /* Create the breakpoint */
104 Breakpoint
->BreakPointHandle
=
105 KdpAddBreakpoint((PVOID
)(ULONG_PTR
)Breakpoint
->BreakPointAddress
);
106 if (!Breakpoint
->BreakPointHandle
)
109 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
114 State
->ReturnStatus
= STATUS_SUCCESS
;
117 /* Send the packet */
118 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
126 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
130 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
133 /* Fill out the header */
134 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
135 Header
.Buffer
= (PCHAR
)State
;
136 ASSERT(Data
->Length
== 0);
138 /* Get the version block */
139 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
142 State
->ReturnStatus
= STATUS_SUCCESS
;
147 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
150 /* Send the packet */
151 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
159 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
164 KdpDprintf("KdpWriteBreakPointEx called\n");
166 return STATUS_UNSUCCESSFUL
;
171 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
176 KdpDprintf("KdpRestoreBreakPointEx called\n");
182 DumpTraceData(IN PSTRING TraceData
)
184 /* Update the buffer */
185 TraceDataBuffer
[0] = TraceDataBufferPosition
;
187 /* Setup the trace data */
188 TraceData
->Length
= TraceDataBufferPosition
* sizeof(ULONG
);
189 TraceData
->Buffer
= (PCHAR
)TraceDataBuffer
;
191 /* Reset the buffer location */
192 TraceDataBufferPosition
= 1;
197 KdpSetCommonState(IN ULONG NewState
,
199 IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange
)
201 USHORT InstructionCount
;
202 BOOLEAN HadBreakpoints
;
204 /* Setup common stuff available for all CPU architectures */
205 WaitStateChange
->NewState
= NewState
;
206 WaitStateChange
->ProcessorLevel
= KeProcessorLevel
;
207 WaitStateChange
->Processor
= (USHORT
)KeGetCurrentPrcb()->Number
;
208 WaitStateChange
->NumberProcessors
= (ULONG
)KeNumberProcessors
;
209 WaitStateChange
->Thread
= (ULONG64
)(LONG_PTR
)KeGetCurrentThread();
210 WaitStateChange
->ProgramCounter
= (ULONG64
)(LONG_PTR
)KeGetContextPc(Context
);
212 /* Zero out the Control Report */
213 RtlZeroMemory(&WaitStateChange
->ControlReport
,
214 sizeof(DBGKD_CONTROL_REPORT
));
216 /* Now copy the instruction stream and set the count */
217 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
218 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
220 InstructionCount
= DBGKD_MAXSTREAM
;
221 WaitStateChange
->ControlReport
.InstructionCount
= InstructionCount
;
223 /* Clear all the breakpoints in this region */
225 KdpDeleteBreakpointRange((PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
226 (PVOID
)((ULONG_PTR
)WaitStateChange
->ProgramCounter
+
227 WaitStateChange
->ControlReport
.InstructionCount
- 1));
230 /* Copy the instruction stream again, this time without breakpoints */
231 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
232 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
233 WaitStateChange
->ControlReport
.InstructionCount
);
239 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State
)
243 /* Fill out the header */
244 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
245 Header
.Buffer
= (PCHAR
)State
;
247 /* Get the version block */
248 KdpSysGetVersion(&State
->u
.GetVersion64
);
250 /* Fill out the state */
251 State
->ApiNumber
= DbgKdGetVersionApi
;
252 State
->ReturnStatus
= STATUS_SUCCESS
;
254 /* Send the packet */
255 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
263 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
268 ULONG Length
= State
->u
.ReadMemory
.TransferCount
;
269 NTSTATUS Status
= STATUS_SUCCESS
;
271 /* Validate length */
272 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
274 /* Overflow, set it to maximum possible */
275 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
279 if (!MmIsAddressValid((PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
))
281 KdpDprintf("Tried to read invalid address %p\n",
282 (PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
);
287 if (!State
->u
.ReadMemory
.TargetBaseAddress
)
290 Status
= STATUS_UNSUCCESSFUL
;
294 RtlCopyMemory(Data
->Buffer
,
295 (PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
,
299 /* Fill out the header */
300 Data
->Length
= Length
;
301 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
302 Header
.Buffer
= (PCHAR
)State
;
304 /* Fill out the state */
305 State
->ReturnStatus
= Status
;
306 State
->u
.ReadMemory
.ActualBytesRead
= Length
;
308 /* Send the packet */
309 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
317 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
322 KdpDprintf("KdpWriteVirtualMemory called for Address: %p Length %x\n",
323 (PVOID
)(ULONG_PTR
)State
->u
.ReadMemory
.TargetBaseAddress
,
324 State
->u
.ReadMemory
.TransferCount
);
330 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
337 KdpDprintf("KdpWritePhysicalMemory called for Address %I64x Length: %x\n",
338 State
->u
.ReadMemory
.TargetBaseAddress
,
339 State
->u
.ReadMemory
.TransferCount
);
341 /* Setup an empty message, with failure */
342 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
343 Header
.Buffer
= (PCHAR
)State
;
345 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
348 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
356 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
363 KdpDprintf("KdpWritePhysicalMemory called for Address %I64x Length: %x\n",
364 State
->u
.ReadMemory
.TargetBaseAddress
,
365 State
->u
.ReadMemory
.TransferCount
);
367 /* Setup an empty message, with failure */
368 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
369 Header
.Buffer
= (PCHAR
)State
;
371 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
374 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
382 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
386 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
390 /* Setup the header */
391 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
392 Header
.Buffer
= (PCHAR
)State
;
393 ASSERT(Data
->Length
== 0);
395 /* Check the length requested */
396 Length
= ReadMemory
->TransferCount
;
397 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
399 /* Use maximum allowed */
400 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
403 /* Call the internal routine */
404 State
->ReturnStatus
= KdpSysReadControlSpace(State
->Processor
,
405 ReadMemory
->TargetBaseAddress
,
410 /* Return the actual length read */
411 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
414 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
422 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
426 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
430 /* Setup the header */
431 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
432 Header
.Buffer
= (PCHAR
)State
;
434 /* Call the internal routine */
435 State
->ReturnStatus
= KdpSysWriteControlSpace(State
->Processor
,
436 WriteMemory
->TargetBaseAddress
,
441 /* Return the length written */
442 WriteMemory
->ActualBytesWritten
= Length
;
445 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
453 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
460 /* Setup the header */
461 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
462 Header
.Buffer
= (PCHAR
)State
;
463 ASSERT(Data
->Length
== 0);
465 /* Make sure that this is a valid request */
466 if (State
->Processor
< KeNumberProcessors
)
468 /* Check if the request is for this CPU */
469 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
471 /* We're just copying our own context */
472 ControlStart
= Context
;
476 /* SMP not yet handled */
477 KdpDprintf("SMP UNHANDLED\n");
482 /* Copy the memory */
483 RtlCopyMemory(Data
->Buffer
, ControlStart
, sizeof(CONTEXT
));
484 Data
->Length
= sizeof(CONTEXT
);
487 State
->ReturnStatus
= STATUS_SUCCESS
;
491 /* Invalid request */
492 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
496 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
504 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
511 /* Setup the header */
512 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
513 Header
.Buffer
= (PCHAR
)State
;
514 ASSERT(Data
->Length
== sizeof(CONTEXT
));
516 /* Make sure that this is a valid request */
517 if (State
->Processor
< KeNumberProcessors
)
519 /* Check if the request is for this CPU */
520 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
522 /* We're just copying our own context */
523 ControlStart
= Context
;
527 /* SMP not yet handled */
528 KdpDprintf("SMP UNHANDLED\n");
533 /* Copy the memory */
534 RtlCopyMemory(ControlStart
, Data
->Buffer
, sizeof(CONTEXT
));
537 State
->ReturnStatus
= STATUS_SUCCESS
;
541 /* Invalid request */
542 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
546 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
554 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State
)
556 /* Crash with the special code */
557 KeBugCheck(MANUALLY_INITIATED_CRASH
);
562 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
567 PDBGKD_READ_WRITE_MSR ReadMsr
= &State
->u
.ReadWriteMsr
;
568 LARGE_INTEGER MsrValue
;
570 /* Setup the header */
571 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
572 Header
.Buffer
= (PCHAR
)State
;
573 ASSERT(Data
->Length
== 0);
575 /* Call the internal routine */
576 State
->ReturnStatus
= KdpSysReadMsr(ReadMsr
->Msr
,
579 /* Return the data */
580 ReadMsr
->DataValueLow
= MsrValue
.LowPart
;
581 ReadMsr
->DataValueHigh
= MsrValue
.HighPart
;
584 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
592 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
597 PDBGKD_READ_WRITE_MSR WriteMsr
= &State
->u
.ReadWriteMsr
;
598 LARGE_INTEGER MsrValue
;
600 /* Setup the header */
601 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
602 Header
.Buffer
= (PCHAR
)State
;
603 ASSERT(Data
->Length
== 0);
605 /* Call the internal routine */
606 MsrValue
.LowPart
= WriteMsr
->DataValueLow
;
607 MsrValue
.HighPart
= WriteMsr
->DataValueHigh
;
608 State
->ReturnStatus
= KdpSysWriteMsr(WriteMsr
->Msr
,
612 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
620 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
625 PDBGKD_GET_SET_BUS_DATA GetBusData
= &State
->u
.GetSetBusData
;
628 /* Setup the header */
629 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
630 Header
.Buffer
= (PCHAR
)State
;
631 ASSERT(Data
->Length
== 0);
633 /* Check the length requested */
634 Length
= GetBusData
->Length
;
635 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
637 /* Use maximum allowed */
638 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
641 /* Call the internal routine */
642 State
->ReturnStatus
= KdpSysReadBusData(GetBusData
->BusDataType
,
643 GetBusData
->BusNumber
,
644 GetBusData
->SlotNumber
,
650 /* Return the actual length read */
651 Data
->Length
= GetBusData
->Length
= Length
;
654 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
662 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
667 PDBGKD_GET_SET_BUS_DATA SetBusData
= &State
->u
.GetSetBusData
;
670 /* Setup the header */
671 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
672 Header
.Buffer
= (PCHAR
)State
;
674 /* Call the internal routine */
675 State
->ReturnStatus
= KdpSysWriteBusData(SetBusData
->BusDataType
,
676 SetBusData
->BusNumber
,
677 SetBusData
->SlotNumber
,
683 /* Return the actual length written */
684 SetBusData
->Length
= Length
;
687 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
695 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
700 PDBGKD_READ_WRITE_IO64 ReadIo
= &State
->u
.ReadWriteIo
;
702 /* Setup the header */
703 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
704 Header
.Buffer
= (PCHAR
)State
;
705 ASSERT(Data
->Length
== 0);
708 * Clear the value so 1 or 2 byte reads
709 * don't leave the higher bits unmodified
711 ReadIo
->DataValue
= 0;
713 /* Call the internal routine */
714 State
->ReturnStatus
= KdpSysReadIoSpace(Isa
,
723 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
731 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
736 PDBGKD_READ_WRITE_IO64 WriteIo
= &State
->u
.ReadWriteIo
;
738 /* Setup the header */
739 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
740 Header
.Buffer
= (PCHAR
)State
;
741 ASSERT(Data
->Length
== 0);
743 /* Call the internal routine */
744 State
->ReturnStatus
= KdpSysWriteIoSpace(Isa
,
753 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
761 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
766 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended
= &State
->u
.
769 /* Setup the header */
770 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
771 Header
.Buffer
= (PCHAR
)State
;
772 ASSERT(Data
->Length
== 0);
775 * Clear the value so 1 or 2 byte reads
776 * don't leave the higher bits unmodified
778 ReadIoExtended
->DataValue
= 0;
780 /* Call the internal routine */
781 State
->ReturnStatus
= KdpSysReadIoSpace(ReadIoExtended
->InterfaceType
,
782 ReadIoExtended
->BusNumber
,
783 ReadIoExtended
->AddressSpace
,
784 ReadIoExtended
->IoAddress
,
785 &ReadIoExtended
->DataValue
,
786 ReadIoExtended
->DataSize
,
787 &ReadIoExtended
->DataSize
);
790 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
798 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
803 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended
= &State
->u
.
806 /* Setup the header */
807 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
808 Header
.Buffer
= (PCHAR
)State
;
809 ASSERT(Data
->Length
== 0);
811 /* Call the internal routine */
812 State
->ReturnStatus
= KdpSysReadIoSpace(WriteIoExtended
->InterfaceType
,
813 WriteIoExtended
->BusNumber
,
814 WriteIoExtended
->AddressSpace
,
815 WriteIoExtended
->IoAddress
,
816 &WriteIoExtended
->DataValue
,
817 WriteIoExtended
->DataSize
,
818 &WriteIoExtended
->DataSize
);
821 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
829 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State
)
833 /* Setup the header */
834 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
835 Header
.Buffer
= (PCHAR
)State
;
837 /* Call the internal routine */
838 State
->ReturnStatus
= KdpSysCheckLowMemory(0x4);
841 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
849 KdpSendWaitContinue(IN ULONG PacketType
,
850 IN PSTRING SendHeader
,
851 IN PSTRING SendData OPTIONAL
,
852 IN OUT PCONTEXT Context
)
855 DBGKD_MANIPULATE_STATE64 ManipulateState
;
859 /* Setup the Manipulate State structure */
860 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
861 Header
.Buffer
= (PCHAR
)&ManipulateState
;
862 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
863 Data
.Buffer
= KdpMessageBuffer
;
864 //KdpContextSent = FALSE;
867 /* Send the Packet */
868 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
870 /* If the debugger isn't present anymore, just return success */
871 if (KdDebuggerNotPresent
) return ContinueSuccess
;
873 /* Main processing Loop */
879 /* Wait to get a reply to our packet */
880 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
886 /* If we got a resend request, do it */
887 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
888 } while (RecvCode
== KdPacketTimedOut
);
890 /* Now check what API we got */
891 switch (ManipulateState
.ApiNumber
)
893 case DbgKdReadVirtualMemoryApi
:
895 /* Read virtual memory */
896 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
899 case DbgKdWriteVirtualMemoryApi
:
901 /* Write virtual memory */
902 KdpWriteVirtualMemory(&ManipulateState
, &Data
, Context
);
905 case DbgKdGetContextApi
:
907 /* Get the current context */
908 KdpGetContext(&ManipulateState
, &Data
, Context
);
911 case DbgKdSetContextApi
:
913 /* Set a new context */
914 KdpSetContext(&ManipulateState
, &Data
, Context
);
917 case DbgKdWriteBreakPointApi
:
919 /* Write the breakpoint */
920 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
923 case DbgKdRestoreBreakPointApi
:
925 /* Restore the breakpoint */
926 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
929 case DbgKdContinueApi
:
931 /* Simply continue */
932 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
934 case DbgKdReadControlSpaceApi
:
936 /* Read control space */
937 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
940 case DbgKdWriteControlSpaceApi
:
942 /* Write control space */
943 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
946 case DbgKdReadIoSpaceApi
:
949 KdpReadIoSpace(&ManipulateState
, &Data
, Context
);
952 case DbgKdWriteIoSpaceApi
:
954 /* Write I/O Space */
955 KdpWriteIoSpace(&ManipulateState
, &Data
, Context
);
960 /* Reboot the system */
961 HalReturnToFirmware(HalRebootRoutine
);
964 case DbgKdContinueApi2
:
966 /* Check if caller reports success */
967 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
969 /* Update the state */
970 KdpGetStateChange(&ManipulateState
, Context
);
971 return ContinueSuccess
;
975 /* Return an error */
976 return ContinueError
;
979 case DbgKdReadPhysicalMemoryApi
:
981 /* Read physical memory */
982 KdpReadPhysicalmemory(&ManipulateState
, &Data
, Context
);
985 case DbgKdWritePhysicalMemoryApi
:
987 /* Write physical memory */
988 KdpWritePhysicalmemory(&ManipulateState
, &Data
, Context
);
991 case DbgKdQuerySpecialCallsApi
:
994 KdpDprintf("DbgKdQuerySpecialCallsApi called\n");
998 case DbgKdSetSpecialCallApi
:
1001 KdpDprintf("DbgKdSetSpecialCallApi called\n");
1005 case DbgKdClearSpecialCallsApi
:
1008 KdpDprintf("DbgKdClearSpecialCallsApi called\n");
1012 case DbgKdSetInternalBreakPointApi
:
1015 KdpDprintf("DbgKdSetInternalBreakPointApi called\n");
1019 case DbgKdGetInternalBreakPointApi
:
1022 KdpDprintf("DbgKdGetInternalBreakPointApi called\n");
1026 case DbgKdReadIoSpaceExtendedApi
:
1028 /* Read I/O Space */
1029 KdpReadIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1032 case DbgKdWriteIoSpaceExtendedApi
:
1034 /* Write I/O Space */
1035 KdpWriteIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1038 case DbgKdGetVersionApi
:
1040 /* Get version data */
1041 KdpGetVersion(&ManipulateState
);
1044 case DbgKdWriteBreakPointExApi
:
1046 /* Write the breakpoint and check if it failed */
1047 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState
,
1051 /* Return an error */
1052 return ContinueError
;
1056 case DbgKdRestoreBreakPointExApi
:
1058 /* Restore the breakpoint */
1059 KdpRestoreBreakPointEx(&ManipulateState
, &Data
, Context
);
1062 case DbgKdCauseBugCheckApi
:
1064 /* Crash the system */
1065 KdpCauseBugCheck(&ManipulateState
);
1068 case DbgKdSwitchProcessor
:
1071 KdpDprintf("DbgKdSwitchProcessor called\n");
1075 case DbgKdPageInApi
:
1078 KdpDprintf("DbgKdPageInApi called\n");
1082 case DbgKdReadMachineSpecificRegister
:
1084 /* Read from the specified MSR */
1085 KdpReadMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1088 case DbgKdWriteMachineSpecificRegister
:
1090 /* Write to the specified MSR */
1091 KdpWriteMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1094 case DbgKdSearchMemoryApi
:
1097 KdpSearchMemory(&ManipulateState
, &Data
, Context
);
1100 case DbgKdGetBusDataApi
:
1102 /* Read from the bus */
1103 KdpGetBusData(&ManipulateState
, &Data
, Context
);
1106 case DbgKdSetBusDataApi
:
1108 /* Write to the bus */
1109 KdpSetBusData(&ManipulateState
, &Data
, Context
);
1112 case DbgKdCheckLowMemoryApi
:
1114 /* Check for memory corruption in the lower 4 GB */
1115 KdpCheckLowMemory(&ManipulateState
);
1118 case DbgKdClearAllInternalBreakpointsApi
:
1120 /* Just clear the counter */
1121 KdpNumInternalBreakpoints
= 0;
1124 case DbgKdFillMemoryApi
:
1127 KdpFillMemory(&ManipulateState
, &Data
, Context
);
1130 case DbgKdQueryMemoryApi
:
1133 KdpQueryMemory(&ManipulateState
, Context
);
1136 case DbgKdSwitchPartition
:
1139 KdpDprintf("DbgKdSwitchPartition called\n");
1143 /* Unsupported Message */
1146 /* Setup an empty message, with failure */
1147 KdpDprintf("Received Unhandled API %lx\n", ManipulateState
.ApiNumber
);
1149 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
1152 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1163 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
1164 IN PKD_SYMBOLS_INFO SymbolInfo
,
1166 IN OUT PCONTEXT Context
)
1169 STRING Data
, Header
;
1170 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
1171 KCONTINUE_STATUS Status
;
1173 /* Start wait loop */
1176 /* Build the architecture common parts of the message */
1177 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
1181 /* Now finish creating the structure */
1182 KdpSetContextState(&WaitStateChange
, Context
);
1184 /* Fill out load data */
1185 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
1186 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONG64
)(LONG_PTR
)SymbolInfo
->BaseOfDll
;
1187 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
1188 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
1189 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
1191 /* Check if we have a symbol name */
1194 /* Setup the information */
1195 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathName
->Length
;
1196 RtlCopyMemory(KdpPathBuffer
, PathName
->Buffer
, PathName
->Length
);
1197 Data
.Buffer
= KdpPathBuffer
;
1198 Data
.Length
= WaitStateChange
.u
.LoadSymbols
.PathNameLength
;
1204 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
1208 /* Setup the header */
1209 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
1210 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1212 /* Send the packet */
1213 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1217 } while (Status
== ContinueProcessorReselected
);
1225 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
1226 IN OUT PCONTEXT Context
,
1227 IN BOOLEAN SecondChanceException
)
1229 STRING Header
, Data
;
1230 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
1231 KCONTINUE_STATUS Status
;
1233 /* Start report loop */
1236 /* Build the architecture common parts of the message */
1237 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
1239 /* Copy the Exception Record and set First Chance flag */
1240 CopyExceptionRecord(ExceptionRecord
,
1241 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
1242 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
1244 /* Now finish creating the structure */
1245 KdpSetContextState(&WaitStateChange
, Context
);
1247 /* Setup the actual header to send to KD */
1248 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
1249 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1251 /* Setup the trace data */
1252 DumpTraceData(&Data
);
1254 /* Send State Change packet and wait for a reply */
1255 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1259 } while (Status
== ContinueProcessorReselected
);
1267 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
1268 IN PVOID DeferredContext
,
1269 IN PVOID SystemArgument1
,
1270 IN PVOID SystemArgument2
)
1272 LONG OldSlip
, NewSlip
, PendingSlip
;
1274 /* Get the current pending slip */
1275 PendingSlip
= KdpTimeSlipPending
;
1278 /* Save the old value and either disable or enable it now. */
1279 OldSlip
= PendingSlip
;
1280 NewSlip
= OldSlip
> 1 ? 1 : 0;
1282 /* Try to change the value */
1283 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1285 OldSlip
) != OldSlip
);
1287 /* If the New Slip value is 1, then do the Time Slipping */
1288 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1293 KdpTimeSlipWork(IN PVOID Context
)
1296 LARGE_INTEGER DueTime
;
1298 /* Update the System time from the CMOS */
1299 ExAcquireTimeRefreshLock(FALSE
);
1300 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1301 ExReleaseTimeRefreshLock();
1303 /* Check if we have a registered Time Slip Event and signal it */
1304 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
1305 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
1306 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
1308 /* Delay the DPC until it runs next time */
1309 DueTime
.QuadPart
= -1800000000;
1310 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1315 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1316 IN OUT PCONTEXT ContextRecord
,
1317 IN BOOLEAN SecondChanceException
)
1321 /* Save the port data */
1324 /* Report a state change */
1325 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1327 SecondChanceException
);
1329 /* Restore the port data and return */
1336 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1338 LARGE_INTEGER Null
= {{0}};
1340 /* Check if interrupts were disabled */
1341 if (!KeGetTrapFrameInterruptState(TrapFrame
))
1343 /* Nothing to return */
1347 /* Otherwise, do the call */
1348 return KeQueryPerformanceCounter(NULL
);
1353 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1354 IN PKEXCEPTION_FRAME ExceptionFrame
)
1358 /* Check if we have a trap frame */
1361 /* Calculate the time difference for the enter */
1362 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1363 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1364 KdTimerStart
.QuadPart
;
1368 /* No trap frame, so can't calculate */
1369 KdTimerStop
.QuadPart
= 0;
1372 /* Save the current IRQL */
1373 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1375 /* Freeze all CPUs */
1376 Entered
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1378 /* Lock the port, save the state and set debugger entered */
1379 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1381 KdEnteredDebugger
= TRUE
;
1383 /* Check freeze flag */
1384 if (KiFreezeFlag
& 1)
1386 /* Print out errror */
1387 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1390 /* Check processor state */
1391 if (KiFreezeFlag
& 2)
1393 /* Print out errror */
1394 KdpDprintf("Some processors not frozen in debugger!\n");
1397 /* Make sure we acquired the port */
1398 if (!KdpPortLocked
) KdpDprintf("Port lock was not acquired!\n");
1400 /* Return enter state */
1406 KdExitDebugger(IN BOOLEAN Entered
)
1410 /* Restore the state and unlock the port */
1412 if (KdpPortLocked
) KdpPortUnlock();
1414 /* Unfreeze the CPUs */
1415 KeThawExecution(Entered
);
1417 /* Compare time with the one from KdEnterDebugger */
1418 if (!KdTimerStop
.QuadPart
)
1420 /* We didn't get a trap frame earlier in so never got the time */
1421 KdTimerStart
= KdTimerStop
;
1425 /* Query the timer */
1426 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1429 /* Check if a Time Slip was on queue */
1430 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1433 /* Queue a DPC for the time slip */
1434 InterlockedIncrement(&KdpTimeSlipPending
);
1435 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
);
1441 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock
)
1445 #if defined(__GNUC__)
1446 /* Make gcc happy */
1447 OldIrql
= PASSIVE_LEVEL
;
1450 /* Check if we need to acquire the lock */
1454 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1458 /* Check if we're not disabled */
1459 if (!KdDisableCount
)
1461 /* Check if we had locked the port before */
1465 KeLowerIrql(OldIrql
);
1469 /* Fail: We're already enabled */
1470 return STATUS_INVALID_PARAMETER
;
1473 /* Decrease the disable count */
1474 if (!(--KdDisableCount
))
1476 /* We're now enabled again! Were we enabled before, too? */
1477 if (KdPreviouslyEnabled
)
1479 /* Reinitialize the Debugger */
1480 KdInitSystem(0, NULL
) ;
1481 KdpRestoreAllBreakpoints();
1485 /* Check if we had locked the port before */
1488 /* Yes, now unlock it */
1489 KeLowerIrql(OldIrql
);
1494 return STATUS_SUCCESS
;
1497 /* PUBLIC FUNCTIONS **********************************************************/
1504 KdEnableDebugger(VOID
)
1506 /* Use the internal routine */
1507 KdpDprintf("KdEnableDebugger called\n");
1509 return KdEnableDebuggerWithLock(TRUE
);
1517 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
1518 IN PVOID InputBuffer
,
1519 IN ULONG InputBufferLength
,
1520 OUT PVOID OutputBuffer
,
1521 IN ULONG OutputBufferLength
,
1522 IN OUT PULONG ReturnLength
,
1523 IN KPROCESSOR_MODE PreviousMode
)
1526 return STATUS_SUCCESS
;
1534 KdChangeOption(IN KD_OPTION Option
,
1535 IN ULONG InBufferBytes OPTIONAL
,
1537 IN ULONG OutBufferBytes OPTIONAL
,
1538 OUT PVOID OutBuffer
,
1539 OUT PULONG OutBufferNeeded OPTIONAL
)
1542 return STATUS_SUCCESS
;
1550 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
1553 return STATUS_SUCCESS
;
1561 KdDisableDebugger(VOID
)
1564 return STATUS_SUCCESS
;
1572 KdRefreshDebuggerNotPresent(VOID
)
1575 return KdDebuggerNotPresent
;
1580 NtQueryDebugFilterState(ULONG ComponentId
,
1584 return STATUS_SUCCESS
;
1589 NtSetDebugFilterState(ULONG ComponentId
,
1594 return STATUS_SUCCESS
;