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 KdpCopyMemoryChunks(IN ULONG64 Address
,
24 OUT PULONG ActualSize OPTIONAL
)
29 /* Check if this is physical or virtual copy */
30 if (Flags
& MMDBG_COPY_PHYSICAL
)
32 /* Fail physical memory read/write for now */
33 if (Flags
& MMDBG_COPY_WRITE
)
35 KdpDprintf("KdpCopyMemoryChunks: Failing write for Physical Address 0x%I64x Length: %x\n",
41 KdpDprintf("KdpCopyMemoryChunks: Failing read for Physical Address 0x%I64x Length: %x\n",
48 Status
= STATUS_UNSUCCESSFUL
;
52 /* Protect against NULL */
55 if (ActualSize
) *ActualSize
= 0;
56 return STATUS_UNSUCCESSFUL
;
59 /* Check if this is read or write */
60 if (Flags
& MMDBG_COPY_WRITE
)
63 RtlCopyMemory((PVOID
)(ULONG_PTR
)Address
,
71 (PVOID
)(ULONG_PTR
)Address
,
75 /* Set size and status */
77 Status
= STATUS_SUCCESS
;
80 /* Return the actual length if requested */
81 if (ActualSize
) *ActualSize
= Length
;
89 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
92 PDBGKD_QUERY_MEMORY Memory
= &State
->u
.QueryMemory
;
94 NTSTATUS Status
= STATUS_SUCCESS
;
96 /* Validate the address space */
97 if (Memory
->AddressSpace
== DBGKD_QUERY_MEMORY_VIRTUAL
)
99 /* Check if this is process memory */
100 if ((PVOID
)(ULONG_PTR
)Memory
->Address
< MmHighestUserAddress
)
103 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_PROCESS
;
107 /* FIXME: Check if it's session space */
108 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_KERNEL
;
112 Memory
->Flags
= DBGKD_QUERY_MEMORY_READ
|
113 DBGKD_QUERY_MEMORY_WRITE
|
114 DBGKD_QUERY_MEMORY_EXECUTE
;
119 Status
= STATUS_INVALID_PARAMETER
;
122 /* Return structure */
123 State
->ReturnStatus
= Status
;
124 Memory
->Reserved
= 0;
127 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
128 Header
.Buffer
= (PCHAR
)State
;
130 /* Send the packet */
131 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
139 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
144 KdpDprintf("KdpSearchMemory called\n");
150 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
155 KdpDprintf("KdpFillMemory called\n");
161 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
165 PDBGKD_WRITE_BREAKPOINT64 Breakpoint
= &State
->u
.WriteBreakPoint
;
169 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
170 Header
.Buffer
= (PCHAR
)State
;
171 ASSERT(Data
->Length
== 0);
173 /* Create the breakpoint */
174 Breakpoint
->BreakPointHandle
=
175 KdpAddBreakpoint((PVOID
)(ULONG_PTR
)Breakpoint
->BreakPointAddress
);
176 if (!Breakpoint
->BreakPointHandle
)
179 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
184 State
->ReturnStatus
= STATUS_SUCCESS
;
187 /* Send the packet */
188 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
196 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
200 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
203 /* Fill out the header */
204 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
205 Header
.Buffer
= (PCHAR
)State
;
206 ASSERT(Data
->Length
== 0);
208 /* Get the version block */
209 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
212 State
->ReturnStatus
= STATUS_SUCCESS
;
217 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
220 /* Send the packet */
221 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
229 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
234 KdpDprintf("KdpWriteBreakPointEx called\n");
236 return STATUS_UNSUCCESSFUL
;
241 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
246 KdpDprintf("KdpRestoreBreakPointEx called\n");
252 DumpTraceData(IN PSTRING TraceData
)
254 /* Update the buffer */
255 TraceDataBuffer
[0] = TraceDataBufferPosition
;
257 /* Setup the trace data */
258 TraceData
->Length
= TraceDataBufferPosition
* sizeof(ULONG
);
259 TraceData
->Buffer
= (PCHAR
)TraceDataBuffer
;
261 /* Reset the buffer location */
262 TraceDataBufferPosition
= 1;
267 KdpSetCommonState(IN ULONG NewState
,
269 IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange
)
271 USHORT InstructionCount
;
272 BOOLEAN HadBreakpoints
;
274 /* Setup common stuff available for all CPU architectures */
275 WaitStateChange
->NewState
= NewState
;
276 WaitStateChange
->ProcessorLevel
= KeProcessorLevel
;
277 WaitStateChange
->Processor
= (USHORT
)KeGetCurrentPrcb()->Number
;
278 WaitStateChange
->NumberProcessors
= (ULONG
)KeNumberProcessors
;
279 WaitStateChange
->Thread
= (ULONG64
)(LONG_PTR
)KeGetCurrentThread();
280 WaitStateChange
->ProgramCounter
= (ULONG64
)(LONG_PTR
)KeGetContextPc(Context
);
282 /* Zero out the Control Report */
283 RtlZeroMemory(&WaitStateChange
->ControlReport
,
284 sizeof(DBGKD_CONTROL_REPORT
));
286 /* Now copy the instruction stream and set the count */
287 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
288 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
290 InstructionCount
= DBGKD_MAXSTREAM
;
291 WaitStateChange
->ControlReport
.InstructionCount
= InstructionCount
;
293 /* Clear all the breakpoints in this region */
295 KdpDeleteBreakpointRange((PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
296 (PVOID
)((ULONG_PTR
)WaitStateChange
->ProgramCounter
+
297 WaitStateChange
->ControlReport
.InstructionCount
- 1));
300 /* Copy the instruction stream again, this time without breakpoints */
301 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
302 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
303 WaitStateChange
->ControlReport
.InstructionCount
);
309 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State
)
313 /* Fill out the header */
314 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
315 Header
.Buffer
= (PCHAR
)State
;
317 /* Get the version block */
318 KdpSysGetVersion(&State
->u
.GetVersion64
);
320 /* Fill out the state */
321 State
->ApiNumber
= DbgKdGetVersionApi
;
322 State
->ReturnStatus
= STATUS_SUCCESS
;
324 /* Send the packet */
325 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
333 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
337 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
339 ULONG Length
= ReadMemory
->TransferCount
;
341 /* Setup the header */
342 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
343 Header
.Buffer
= (PCHAR
)State
;
344 ASSERT(Data
->Length
== 0);
346 /* Validate length */
347 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
349 /* Overflow, set it to maximum possible */
350 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
354 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
361 /* Return the actual length read */
362 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
364 /* Send the packet */
365 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
373 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
377 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
380 /* Setup the header */
381 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
382 Header
.Buffer
= (PCHAR
)State
;
385 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
391 &WriteMemory
->ActualBytesWritten
);
393 /* Send the packet */
394 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
402 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
406 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
408 ULONG Length
= ReadMemory
->TransferCount
;
409 ULONG Flags
, CacheFlags
;
411 /* Setup the header */
412 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
413 Header
.Buffer
= (PCHAR
)State
;
414 ASSERT(Data
->Length
== 0);
416 /* Validate length */
417 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
419 /* Overflow, set it to maximum possible */
420 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
423 /* Start with the default flags */
424 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_PHYSICAL
;
426 /* Get the caching flags and check if a type is specified */
427 CacheFlags
= ReadMemory
->ActualBytesRead
;
428 if (CacheFlags
== DBGKD_CACHING_CACHED
)
431 Flags
|= MMDBG_COPY_CACHED
;
433 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
436 Flags
|= MMDBG_COPY_UNCACHED
;
438 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
441 Flags
|= DBGKD_CACHING_WRITE_COMBINED
;
445 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
452 /* Return the actual length read */
453 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
455 /* Send the packet */
456 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
464 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
468 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
470 ULONG Flags
, CacheFlags
;
472 /* Setup the header */
473 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
474 Header
.Buffer
= (PCHAR
)State
;
476 /* Start with the default flags */
477 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_WRITE
| MMDBG_COPY_PHYSICAL
;
479 /* Get the caching flags and check if a type is specified */
480 CacheFlags
= WriteMemory
->ActualBytesWritten
;
481 if (CacheFlags
== DBGKD_CACHING_CACHED
)
484 Flags
|= MMDBG_COPY_CACHED
;
486 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
489 Flags
|= MMDBG_COPY_UNCACHED
;
491 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
494 Flags
|= DBGKD_CACHING_WRITE_COMBINED
;
498 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
503 &WriteMemory
->ActualBytesWritten
);
505 /* Send the packet */
506 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
514 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
518 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
522 /* Setup the header */
523 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
524 Header
.Buffer
= (PCHAR
)State
;
525 ASSERT(Data
->Length
== 0);
527 /* Check the length requested */
528 Length
= ReadMemory
->TransferCount
;
529 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
531 /* Use maximum allowed */
532 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
535 /* Call the internal routine */
536 State
->ReturnStatus
= KdpSysReadControlSpace(State
->Processor
,
537 ReadMemory
->TargetBaseAddress
,
542 /* Return the actual length read */
543 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
546 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
554 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
558 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
561 /* Setup the header */
562 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
563 Header
.Buffer
= (PCHAR
)State
;
565 /* Call the internal routine */
566 State
->ReturnStatus
= KdpSysWriteControlSpace(State
->Processor
,
567 WriteMemory
->TargetBaseAddress
,
570 &WriteMemory
->ActualBytesWritten
);
573 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
581 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
588 /* Setup the header */
589 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
590 Header
.Buffer
= (PCHAR
)State
;
591 ASSERT(Data
->Length
== 0);
593 /* Make sure that this is a valid request */
594 if (State
->Processor
< KeNumberProcessors
)
596 /* Check if the request is for this CPU */
597 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
599 /* We're just copying our own context */
600 ControlStart
= Context
;
604 /* SMP not yet handled */
605 KdpDprintf("SMP UNHANDLED\n");
610 /* Copy the memory */
611 RtlCopyMemory(Data
->Buffer
, ControlStart
, sizeof(CONTEXT
));
612 Data
->Length
= sizeof(CONTEXT
);
615 State
->ReturnStatus
= STATUS_SUCCESS
;
619 /* Invalid request */
620 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
624 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
632 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
639 /* Setup the header */
640 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
641 Header
.Buffer
= (PCHAR
)State
;
642 ASSERT(Data
->Length
== sizeof(CONTEXT
));
644 /* Make sure that this is a valid request */
645 if (State
->Processor
< KeNumberProcessors
)
647 /* Check if the request is for this CPU */
648 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
650 /* We're just copying our own context */
651 ControlStart
= Context
;
655 /* SMP not yet handled */
656 KdpDprintf("SMP UNHANDLED\n");
661 /* Copy the memory */
662 RtlCopyMemory(ControlStart
, Data
->Buffer
, sizeof(CONTEXT
));
665 State
->ReturnStatus
= STATUS_SUCCESS
;
669 /* Invalid request */
670 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
674 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
682 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State
)
684 /* Crash with the special code */
685 KeBugCheck(MANUALLY_INITIATED_CRASH
);
690 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
695 PDBGKD_READ_WRITE_MSR ReadMsr
= &State
->u
.ReadWriteMsr
;
696 LARGE_INTEGER MsrValue
;
698 /* Setup the header */
699 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
700 Header
.Buffer
= (PCHAR
)State
;
701 ASSERT(Data
->Length
== 0);
703 /* Call the internal routine */
704 State
->ReturnStatus
= KdpSysReadMsr(ReadMsr
->Msr
,
707 /* Return the data */
708 ReadMsr
->DataValueLow
= MsrValue
.LowPart
;
709 ReadMsr
->DataValueHigh
= MsrValue
.HighPart
;
712 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
720 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
725 PDBGKD_READ_WRITE_MSR WriteMsr
= &State
->u
.ReadWriteMsr
;
726 LARGE_INTEGER MsrValue
;
728 /* Setup the header */
729 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
730 Header
.Buffer
= (PCHAR
)State
;
731 ASSERT(Data
->Length
== 0);
733 /* Call the internal routine */
734 MsrValue
.LowPart
= WriteMsr
->DataValueLow
;
735 MsrValue
.HighPart
= WriteMsr
->DataValueHigh
;
736 State
->ReturnStatus
= KdpSysWriteMsr(WriteMsr
->Msr
,
740 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
748 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
753 PDBGKD_GET_SET_BUS_DATA GetBusData
= &State
->u
.GetSetBusData
;
756 /* Setup the header */
757 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
758 Header
.Buffer
= (PCHAR
)State
;
759 ASSERT(Data
->Length
== 0);
761 /* Check the length requested */
762 Length
= GetBusData
->Length
;
763 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
765 /* Use maximum allowed */
766 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
769 /* Call the internal routine */
770 State
->ReturnStatus
= KdpSysReadBusData(GetBusData
->BusDataType
,
771 GetBusData
->BusNumber
,
772 GetBusData
->SlotNumber
,
778 /* Return the actual length read */
779 Data
->Length
= GetBusData
->Length
= Length
;
782 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
790 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
795 PDBGKD_GET_SET_BUS_DATA SetBusData
= &State
->u
.GetSetBusData
;
798 /* Setup the header */
799 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
800 Header
.Buffer
= (PCHAR
)State
;
802 /* Call the internal routine */
803 State
->ReturnStatus
= KdpSysWriteBusData(SetBusData
->BusDataType
,
804 SetBusData
->BusNumber
,
805 SetBusData
->SlotNumber
,
811 /* Return the actual length written */
812 SetBusData
->Length
= Length
;
815 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
823 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
828 PDBGKD_READ_WRITE_IO64 ReadIo
= &State
->u
.ReadWriteIo
;
830 /* Setup the header */
831 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
832 Header
.Buffer
= (PCHAR
)State
;
833 ASSERT(Data
->Length
== 0);
836 * Clear the value so 1 or 2 byte reads
837 * don't leave the higher bits unmodified
839 ReadIo
->DataValue
= 0;
841 /* Call the internal routine */
842 State
->ReturnStatus
= KdpSysReadIoSpace(Isa
,
851 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
859 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
864 PDBGKD_READ_WRITE_IO64 WriteIo
= &State
->u
.ReadWriteIo
;
866 /* Setup the header */
867 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
868 Header
.Buffer
= (PCHAR
)State
;
869 ASSERT(Data
->Length
== 0);
871 /* Call the internal routine */
872 State
->ReturnStatus
= KdpSysWriteIoSpace(Isa
,
881 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
889 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
894 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended
= &State
->u
.
897 /* Setup the header */
898 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
899 Header
.Buffer
= (PCHAR
)State
;
900 ASSERT(Data
->Length
== 0);
903 * Clear the value so 1 or 2 byte reads
904 * don't leave the higher bits unmodified
906 ReadIoExtended
->DataValue
= 0;
908 /* Call the internal routine */
909 State
->ReturnStatus
= KdpSysReadIoSpace(ReadIoExtended
->InterfaceType
,
910 ReadIoExtended
->BusNumber
,
911 ReadIoExtended
->AddressSpace
,
912 ReadIoExtended
->IoAddress
,
913 &ReadIoExtended
->DataValue
,
914 ReadIoExtended
->DataSize
,
915 &ReadIoExtended
->DataSize
);
918 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
926 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
931 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended
= &State
->u
.
934 /* Setup the header */
935 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
936 Header
.Buffer
= (PCHAR
)State
;
937 ASSERT(Data
->Length
== 0);
939 /* Call the internal routine */
940 State
->ReturnStatus
= KdpSysReadIoSpace(WriteIoExtended
->InterfaceType
,
941 WriteIoExtended
->BusNumber
,
942 WriteIoExtended
->AddressSpace
,
943 WriteIoExtended
->IoAddress
,
944 &WriteIoExtended
->DataValue
,
945 WriteIoExtended
->DataSize
,
946 &WriteIoExtended
->DataSize
);
949 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
957 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State
)
961 /* Setup the header */
962 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
963 Header
.Buffer
= (PCHAR
)State
;
965 /* Call the internal routine */
966 State
->ReturnStatus
= KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE
);
969 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
977 KdpSendWaitContinue(IN ULONG PacketType
,
978 IN PSTRING SendHeader
,
979 IN PSTRING SendData OPTIONAL
,
980 IN OUT PCONTEXT Context
)
983 DBGKD_MANIPULATE_STATE64 ManipulateState
;
987 /* Setup the Manipulate State structure */
988 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
989 Header
.Buffer
= (PCHAR
)&ManipulateState
;
990 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
991 Data
.Buffer
= KdpMessageBuffer
;
992 //KdpContextSent = FALSE;
995 /* Send the Packet */
996 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
998 /* If the debugger isn't present anymore, just return success */
999 if (KdDebuggerNotPresent
) return ContinueSuccess
;
1001 /* Main processing Loop */
1007 /* Wait to get a reply to our packet */
1008 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1014 /* If we got a resend request, do it */
1015 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
1016 } while (RecvCode
== KdPacketTimedOut
);
1018 /* Now check what API we got */
1019 switch (ManipulateState
.ApiNumber
)
1021 case DbgKdReadVirtualMemoryApi
:
1023 /* Read virtual memory */
1024 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
1027 case DbgKdWriteVirtualMemoryApi
:
1029 /* Write virtual memory */
1030 KdpWriteVirtualMemory(&ManipulateState
, &Data
, Context
);
1033 case DbgKdGetContextApi
:
1035 /* Get the current context */
1036 KdpGetContext(&ManipulateState
, &Data
, Context
);
1039 case DbgKdSetContextApi
:
1041 /* Set a new context */
1042 KdpSetContext(&ManipulateState
, &Data
, Context
);
1045 case DbgKdWriteBreakPointApi
:
1047 /* Write the breakpoint */
1048 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
1051 case DbgKdRestoreBreakPointApi
:
1053 /* Restore the breakpoint */
1054 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
1057 case DbgKdContinueApi
:
1059 /* Simply continue */
1060 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
1062 case DbgKdReadControlSpaceApi
:
1064 /* Read control space */
1065 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
1068 case DbgKdWriteControlSpaceApi
:
1070 /* Write control space */
1071 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
1074 case DbgKdReadIoSpaceApi
:
1076 /* Read I/O Space */
1077 KdpReadIoSpace(&ManipulateState
, &Data
, Context
);
1080 case DbgKdWriteIoSpaceApi
:
1082 /* Write I/O Space */
1083 KdpWriteIoSpace(&ManipulateState
, &Data
, Context
);
1086 case DbgKdRebootApi
:
1088 /* Reboot the system */
1089 HalReturnToFirmware(HalRebootRoutine
);
1092 case DbgKdContinueApi2
:
1094 /* Check if caller reports success */
1095 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
1097 /* Update the state */
1098 KdpGetStateChange(&ManipulateState
, Context
);
1099 return ContinueSuccess
;
1103 /* Return an error */
1104 return ContinueError
;
1107 case DbgKdReadPhysicalMemoryApi
:
1109 /* Read physical memory */
1110 KdpReadPhysicalmemory(&ManipulateState
, &Data
, Context
);
1113 case DbgKdWritePhysicalMemoryApi
:
1115 /* Write physical memory */
1116 KdpWritePhysicalmemory(&ManipulateState
, &Data
, Context
);
1119 case DbgKdQuerySpecialCallsApi
:
1122 KdpDprintf("DbgKdQuerySpecialCallsApi called\n");
1126 case DbgKdSetSpecialCallApi
:
1129 KdpDprintf("DbgKdSetSpecialCallApi called\n");
1133 case DbgKdClearSpecialCallsApi
:
1136 KdpDprintf("DbgKdClearSpecialCallsApi called\n");
1140 case DbgKdSetInternalBreakPointApi
:
1143 KdpDprintf("DbgKdSetInternalBreakPointApi called\n");
1147 case DbgKdGetInternalBreakPointApi
:
1150 KdpDprintf("DbgKdGetInternalBreakPointApi called\n");
1154 case DbgKdReadIoSpaceExtendedApi
:
1156 /* Read I/O Space */
1157 KdpReadIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1160 case DbgKdWriteIoSpaceExtendedApi
:
1162 /* Write I/O Space */
1163 KdpWriteIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1166 case DbgKdGetVersionApi
:
1168 /* Get version data */
1169 KdpGetVersion(&ManipulateState
);
1172 case DbgKdWriteBreakPointExApi
:
1174 /* Write the breakpoint and check if it failed */
1175 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState
,
1179 /* Return an error */
1180 return ContinueError
;
1184 case DbgKdRestoreBreakPointExApi
:
1186 /* Restore the breakpoint */
1187 KdpRestoreBreakPointEx(&ManipulateState
, &Data
, Context
);
1190 case DbgKdCauseBugCheckApi
:
1192 /* Crash the system */
1193 KdpCauseBugCheck(&ManipulateState
);
1196 case DbgKdSwitchProcessor
:
1199 KdpDprintf("DbgKdSwitchProcessor called\n");
1203 case DbgKdPageInApi
:
1206 KdpDprintf("DbgKdPageInApi called\n");
1210 case DbgKdReadMachineSpecificRegister
:
1212 /* Read from the specified MSR */
1213 KdpReadMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1216 case DbgKdWriteMachineSpecificRegister
:
1218 /* Write to the specified MSR */
1219 KdpWriteMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1222 case DbgKdSearchMemoryApi
:
1225 KdpSearchMemory(&ManipulateState
, &Data
, Context
);
1228 case DbgKdGetBusDataApi
:
1230 /* Read from the bus */
1231 KdpGetBusData(&ManipulateState
, &Data
, Context
);
1234 case DbgKdSetBusDataApi
:
1236 /* Write to the bus */
1237 KdpSetBusData(&ManipulateState
, &Data
, Context
);
1240 case DbgKdCheckLowMemoryApi
:
1242 /* Check for memory corruption in the lower 4 GB */
1243 KdpCheckLowMemory(&ManipulateState
);
1246 case DbgKdClearAllInternalBreakpointsApi
:
1248 /* Just clear the counter */
1249 KdpNumInternalBreakpoints
= 0;
1252 case DbgKdFillMemoryApi
:
1255 KdpFillMemory(&ManipulateState
, &Data
, Context
);
1258 case DbgKdQueryMemoryApi
:
1261 KdpQueryMemory(&ManipulateState
, Context
);
1264 case DbgKdSwitchPartition
:
1267 KdpDprintf("DbgKdSwitchPartition called\n");
1271 /* Unsupported Message */
1274 /* Setup an empty message, with failure */
1275 KdpDprintf("Received Unhandled API %lx\n", ManipulateState
.ApiNumber
);
1277 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
1280 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1291 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
1292 IN PKD_SYMBOLS_INFO SymbolInfo
,
1294 IN OUT PCONTEXT Context
)
1297 STRING Data
, Header
;
1298 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
1299 KCONTINUE_STATUS Status
;
1301 /* Start wait loop */
1304 /* Build the architecture common parts of the message */
1305 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
1309 /* Now finish creating the structure */
1310 KdpSetContextState(&WaitStateChange
, Context
);
1312 /* Fill out load data */
1313 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
1314 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONG64
)(LONG_PTR
)SymbolInfo
->BaseOfDll
;
1315 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
1316 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
1317 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
1319 /* Check if we have a symbol name */
1322 /* Setup the information */
1323 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathName
->Length
;
1324 RtlCopyMemory(KdpPathBuffer
, PathName
->Buffer
, PathName
->Length
);
1325 Data
.Buffer
= KdpPathBuffer
;
1326 Data
.Length
= WaitStateChange
.u
.LoadSymbols
.PathNameLength
;
1332 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
1336 /* Setup the header */
1337 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
1338 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1340 /* Send the packet */
1341 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1345 } while (Status
== ContinueProcessorReselected
);
1353 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
1354 IN OUT PCONTEXT Context
,
1355 IN BOOLEAN SecondChanceException
)
1357 STRING Header
, Data
;
1358 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange
;
1359 KCONTINUE_STATUS Status
;
1361 /* Start report loop */
1364 /* Build the architecture common parts of the message */
1365 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
1367 /* Copy the Exception Record and set First Chance flag */
1368 CopyExceptionRecord(ExceptionRecord
,
1369 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
1370 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
1372 /* Now finish creating the structure */
1373 KdpSetContextState(&WaitStateChange
, Context
);
1375 /* Setup the actual header to send to KD */
1376 Header
.Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
1377 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1379 /* Setup the trace data */
1380 DumpTraceData(&Data
);
1382 /* Send State Change packet and wait for a reply */
1383 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1387 } while (Status
== ContinueProcessorReselected
);
1395 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
1396 IN PVOID DeferredContext
,
1397 IN PVOID SystemArgument1
,
1398 IN PVOID SystemArgument2
)
1400 LONG OldSlip
, NewSlip
, PendingSlip
;
1402 /* Get the current pending slip */
1403 PendingSlip
= KdpTimeSlipPending
;
1406 /* Save the old value and either disable or enable it now. */
1407 OldSlip
= PendingSlip
;
1408 NewSlip
= OldSlip
> 1 ? 1 : 0;
1410 /* Try to change the value */
1411 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1413 OldSlip
) != OldSlip
);
1415 /* If the New Slip value is 1, then do the Time Slipping */
1416 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1421 KdpTimeSlipWork(IN PVOID Context
)
1424 LARGE_INTEGER DueTime
;
1426 /* Update the System time from the CMOS */
1427 ExAcquireTimeRefreshLock(FALSE
);
1428 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1429 ExReleaseTimeRefreshLock();
1431 /* Check if we have a registered Time Slip Event and signal it */
1432 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
1433 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
1434 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
1436 /* Delay the DPC until it runs next time */
1437 DueTime
.QuadPart
= -1800000000;
1438 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1443 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1444 IN OUT PCONTEXT ContextRecord
,
1445 IN BOOLEAN SecondChanceException
)
1449 /* Save the port data */
1452 /* Report a state change */
1453 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1455 SecondChanceException
);
1457 /* Restore the port data and return */
1464 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1466 LARGE_INTEGER Null
= {{0}};
1468 /* Check if interrupts were disabled */
1469 if (!KeGetTrapFrameInterruptState(TrapFrame
))
1471 /* Nothing to return */
1475 /* Otherwise, do the call */
1476 return KeQueryPerformanceCounter(NULL
);
1481 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1482 IN PKEXCEPTION_FRAME ExceptionFrame
)
1486 /* Check if we have a trap frame */
1489 /* Calculate the time difference for the enter */
1490 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1491 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1492 KdTimerStart
.QuadPart
;
1496 /* No trap frame, so can't calculate */
1497 KdTimerStop
.QuadPart
= 0;
1500 /* Save the current IRQL */
1501 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1503 /* Freeze all CPUs */
1504 Entered
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1506 /* Lock the port, save the state and set debugger entered */
1507 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1509 KdEnteredDebugger
= TRUE
;
1511 /* Check freeze flag */
1512 if (KiFreezeFlag
& 1)
1514 /* Print out errror */
1515 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1518 /* Check processor state */
1519 if (KiFreezeFlag
& 2)
1521 /* Print out errror */
1522 KdpDprintf("Some processors not frozen in debugger!\n");
1525 /* Make sure we acquired the port */
1526 if (!KdpPortLocked
) KdpDprintf("Port lock was not acquired!\n");
1528 /* Return enter state */
1534 KdExitDebugger(IN BOOLEAN Entered
)
1538 /* Restore the state and unlock the port */
1540 if (KdpPortLocked
) KdpPortUnlock();
1542 /* Unfreeze the CPUs */
1543 KeThawExecution(Entered
);
1545 /* Compare time with the one from KdEnterDebugger */
1546 if (!KdTimerStop
.QuadPart
)
1548 /* We didn't get a trap frame earlier in so never got the time */
1549 KdTimerStart
= KdTimerStop
;
1553 /* Query the timer */
1554 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1557 /* Check if a Time Slip was on queue */
1558 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1561 /* Queue a DPC for the time slip */
1562 InterlockedIncrement(&KdpTimeSlipPending
);
1563 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
);
1569 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock
)
1573 #if defined(__GNUC__)
1574 /* Make gcc happy */
1575 OldIrql
= PASSIVE_LEVEL
;
1578 /* Check if we need to acquire the lock */
1582 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1586 /* Check if we're not disabled */
1587 if (!KdDisableCount
)
1589 /* Check if we had locked the port before */
1593 KeLowerIrql(OldIrql
);
1597 /* Fail: We're already enabled */
1598 return STATUS_INVALID_PARAMETER
;
1601 /* Decrease the disable count */
1602 if (!(--KdDisableCount
))
1604 /* We're now enabled again! Were we enabled before, too? */
1605 if (KdPreviouslyEnabled
)
1607 /* Reinitialize the Debugger */
1608 KdInitSystem(0, NULL
) ;
1609 KdpRestoreAllBreakpoints();
1613 /* Check if we had locked the port before */
1616 /* Yes, now unlock it */
1617 KeLowerIrql(OldIrql
);
1622 return STATUS_SUCCESS
;
1625 /* PUBLIC FUNCTIONS **********************************************************/
1632 KdEnableDebugger(VOID
)
1634 /* Use the internal routine */
1635 KdpDprintf("KdEnableDebugger called\n");
1637 return KdEnableDebuggerWithLock(TRUE
);
1645 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
1646 IN PVOID InputBuffer
,
1647 IN ULONG InputBufferLength
,
1648 OUT PVOID OutputBuffer
,
1649 IN ULONG OutputBufferLength
,
1650 IN OUT PULONG ReturnLength
,
1651 IN KPROCESSOR_MODE PreviousMode
)
1654 return STATUS_SUCCESS
;
1662 KdChangeOption(IN KD_OPTION Option
,
1663 IN ULONG InBufferBytes OPTIONAL
,
1665 IN ULONG OutBufferBytes OPTIONAL
,
1666 OUT PVOID OutBuffer
,
1667 OUT PULONG OutBufferNeeded OPTIONAL
)
1670 return STATUS_SUCCESS
;
1678 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
1681 return STATUS_SUCCESS
;
1689 KdDisableDebugger(VOID
)
1692 return STATUS_SUCCESS
;
1700 KdRefreshDebuggerNotPresent(VOID
)
1703 return KdDebuggerNotPresent
;
1708 NtQueryDebugFilterState(ULONG ComponentId
,
1712 return STATUS_SUCCESS
;
1717 NtSetDebugFilterState(ULONG ComponentId
,
1722 return STATUS_SUCCESS
;