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)
7 * Stefan Ginsberg (stefan.ginsberg@reactos.org)
10 /* INCLUDES ******************************************************************/
16 /* PRIVATE FUNCTIONS *********************************************************/
20 KdpCopyMemoryChunks(IN ULONG64 Address
,
25 OUT PULONG ActualSize OPTIONAL
)
30 /* Check if this is physical or virtual copy */
31 if (Flags
& MMDBG_COPY_PHYSICAL
)
33 /* Fail physical memory read/write for now */
34 if (Flags
& MMDBG_COPY_WRITE
)
36 KdpDprintf("KdpCopyMemoryChunks: Failing write for Physical Address 0x%I64x Length: %x\n",
42 KdpDprintf("KdpCopyMemoryChunks: Failing read for Physical Address 0x%I64x Length: %x\n",
49 Status
= STATUS_UNSUCCESSFUL
;
53 /* Protect against NULL */
56 if (ActualSize
) *ActualSize
= 0;
57 return STATUS_UNSUCCESSFUL
;
60 /* Check if this is read or write */
61 if (Flags
& MMDBG_COPY_WRITE
)
64 RtlCopyMemory((PVOID
)(ULONG_PTR
)Address
,
72 (PVOID
)(ULONG_PTR
)Address
,
76 /* Set size and status */
78 Status
= STATUS_SUCCESS
;
81 /* Return the actual length if requested */
82 if (ActualSize
) *ActualSize
= Length
;
90 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
93 PDBGKD_QUERY_MEMORY Memory
= &State
->u
.QueryMemory
;
95 NTSTATUS Status
= STATUS_SUCCESS
;
97 /* Validate the address space */
98 if (Memory
->AddressSpace
== DBGKD_QUERY_MEMORY_VIRTUAL
)
100 /* Check if this is process memory */
101 if ((PVOID
)(ULONG_PTR
)Memory
->Address
< MmHighestUserAddress
)
104 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_PROCESS
;
108 /* FIXME: Check if it's session space */
109 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_KERNEL
;
113 Memory
->Flags
= DBGKD_QUERY_MEMORY_READ
|
114 DBGKD_QUERY_MEMORY_WRITE
|
115 DBGKD_QUERY_MEMORY_EXECUTE
;
120 Status
= STATUS_INVALID_PARAMETER
;
123 /* Return structure */
124 State
->ReturnStatus
= Status
;
125 Memory
->Reserved
= 0;
128 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
129 Header
.Buffer
= (PCHAR
)State
;
131 /* Send the packet */
132 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
140 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
145 KdpDprintf("KdpSearchMemory called\n");
151 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
156 KdpDprintf("KdpFillMemory called\n");
162 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
166 PDBGKD_WRITE_BREAKPOINT64 Breakpoint
= &State
->u
.WriteBreakPoint
;
170 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
171 Header
.Buffer
= (PCHAR
)State
;
172 ASSERT(Data
->Length
== 0);
174 /* Create the breakpoint */
175 Breakpoint
->BreakPointHandle
=
176 KdpAddBreakpoint((PVOID
)(ULONG_PTR
)Breakpoint
->BreakPointAddress
);
177 if (!Breakpoint
->BreakPointHandle
)
180 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
185 State
->ReturnStatus
= STATUS_SUCCESS
;
188 /* Send the packet */
189 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
197 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
201 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
204 /* Fill out the header */
205 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
206 Header
.Buffer
= (PCHAR
)State
;
207 ASSERT(Data
->Length
== 0);
209 /* Get the version block */
210 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
213 State
->ReturnStatus
= STATUS_SUCCESS
;
218 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
221 /* Send the packet */
222 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
230 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
235 KdpDprintf("KdpWriteBreakPointEx called\n");
237 return STATUS_UNSUCCESSFUL
;
242 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
247 KdpDprintf("KdpRestoreBreakPointEx called\n");
253 DumpTraceData(IN PSTRING TraceData
)
255 /* Update the buffer */
256 TraceDataBuffer
[0] = TraceDataBufferPosition
;
258 /* Setup the trace data */
259 TraceData
->Length
= TraceDataBufferPosition
* sizeof(ULONG
);
260 TraceData
->Buffer
= (PCHAR
)TraceDataBuffer
;
262 /* Reset the buffer location */
263 TraceDataBufferPosition
= 1;
268 KdpSetCommonState(IN ULONG NewState
,
270 IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
)
272 USHORT InstructionCount
;
273 BOOLEAN HadBreakpoints
;
275 /* Setup common stuff available for all CPU architectures */
276 WaitStateChange
->NewState
= NewState
;
277 WaitStateChange
->ProcessorLevel
= KeProcessorLevel
;
278 WaitStateChange
->Processor
= (USHORT
)KeGetCurrentPrcb()->Number
;
279 WaitStateChange
->NumberProcessors
= (ULONG
)KeNumberProcessors
;
280 WaitStateChange
->Thread
= (ULONG64
)(LONG_PTR
)KeGetCurrentThread();
281 WaitStateChange
->ProgramCounter
= (ULONG64
)(LONG_PTR
)KeGetContextPc(Context
);
283 /* Zero out the entire Control Report */
284 RtlZeroMemory(&WaitStateChange
->AnyControlReport
,
285 sizeof(DBGKD_ANY_CONTROL_REPORT
));
287 /* Now copy the instruction stream and set the count */
288 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
289 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
291 InstructionCount
= DBGKD_MAXSTREAM
;
292 WaitStateChange
->ControlReport
.InstructionCount
= InstructionCount
;
294 /* Clear all the breakpoints in this region */
296 KdpDeleteBreakpointRange((PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
297 (PVOID
)((ULONG_PTR
)WaitStateChange
->ProgramCounter
+
298 WaitStateChange
->ControlReport
.InstructionCount
- 1));
301 /* Copy the instruction stream again, this time without breakpoints */
302 RtlCopyMemory(&WaitStateChange
->ControlReport
.InstructionStream
[0],
303 (PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
304 WaitStateChange
->ControlReport
.InstructionCount
);
310 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State
)
314 /* Fill out the header */
315 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
316 Header
.Buffer
= (PCHAR
)State
;
318 /* Get the version block */
319 KdpSysGetVersion(&State
->u
.GetVersion64
);
321 /* Fill out the state */
322 State
->ApiNumber
= DbgKdGetVersionApi
;
323 State
->ReturnStatus
= STATUS_SUCCESS
;
325 /* Send the packet */
326 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
334 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
338 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
340 ULONG Length
= ReadMemory
->TransferCount
;
342 /* Setup the header */
343 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
344 Header
.Buffer
= (PCHAR
)State
;
345 ASSERT(Data
->Length
== 0);
347 /* Validate length */
348 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
350 /* Overflow, set it to maximum possible */
351 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
355 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
362 /* Return the actual length read */
363 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
365 /* Send the packet */
366 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
374 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
378 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
381 /* Setup the header */
382 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
383 Header
.Buffer
= (PCHAR
)State
;
386 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
392 &WriteMemory
->ActualBytesWritten
);
394 /* Send the packet */
395 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
403 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
407 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
409 ULONG Length
= ReadMemory
->TransferCount
;
410 ULONG Flags
, CacheFlags
;
412 /* Setup the header */
413 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
414 Header
.Buffer
= (PCHAR
)State
;
415 ASSERT(Data
->Length
== 0);
417 /* Validate length */
418 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
420 /* Overflow, set it to maximum possible */
421 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
424 /* Start with the default flags */
425 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_PHYSICAL
;
427 /* Get the caching flags and check if a type is specified */
428 CacheFlags
= ReadMemory
->ActualBytesRead
;
429 if (CacheFlags
== DBGKD_CACHING_CACHED
)
432 Flags
|= MMDBG_COPY_CACHED
;
434 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
437 Flags
|= MMDBG_COPY_UNCACHED
;
439 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
442 Flags
|= DBGKD_CACHING_WRITE_COMBINED
;
446 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
453 /* Return the actual length read */
454 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
456 /* Send the packet */
457 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
465 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
469 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
471 ULONG Flags
, CacheFlags
;
473 /* Setup the header */
474 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
475 Header
.Buffer
= (PCHAR
)State
;
477 /* Start with the default flags */
478 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_WRITE
| MMDBG_COPY_PHYSICAL
;
480 /* Get the caching flags and check if a type is specified */
481 CacheFlags
= WriteMemory
->ActualBytesWritten
;
482 if (CacheFlags
== DBGKD_CACHING_CACHED
)
485 Flags
|= MMDBG_COPY_CACHED
;
487 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
490 Flags
|= MMDBG_COPY_UNCACHED
;
492 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
495 Flags
|= DBGKD_CACHING_WRITE_COMBINED
;
499 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
504 &WriteMemory
->ActualBytesWritten
);
506 /* Send the packet */
507 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
515 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
519 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
523 /* Setup the header */
524 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
525 Header
.Buffer
= (PCHAR
)State
;
526 ASSERT(Data
->Length
== 0);
528 /* Check the length requested */
529 Length
= ReadMemory
->TransferCount
;
530 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
532 /* Use maximum allowed */
533 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
536 /* Call the internal routine */
537 State
->ReturnStatus
= KdpSysReadControlSpace(State
->Processor
,
538 ReadMemory
->TargetBaseAddress
,
543 /* Return the actual length read */
544 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
547 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
555 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
559 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
562 /* Setup the header */
563 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
564 Header
.Buffer
= (PCHAR
)State
;
566 /* Call the internal routine */
567 State
->ReturnStatus
= KdpSysWriteControlSpace(State
->Processor
,
568 WriteMemory
->TargetBaseAddress
,
571 &WriteMemory
->ActualBytesWritten
);
574 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
582 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
589 /* Setup the header */
590 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
591 Header
.Buffer
= (PCHAR
)State
;
592 ASSERT(Data
->Length
== 0);
594 /* Make sure that this is a valid request */
595 if (State
->Processor
< KeNumberProcessors
)
597 /* Check if the request is for this CPU */
598 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
600 /* We're just copying our own context */
601 ControlStart
= Context
;
605 /* SMP not yet handled */
606 KdpDprintf("KdpGetContext: SMP UNHANDLED\n");
611 /* Copy the memory */
612 RtlCopyMemory(Data
->Buffer
, ControlStart
, sizeof(CONTEXT
));
613 Data
->Length
= sizeof(CONTEXT
);
616 State
->ReturnStatus
= STATUS_SUCCESS
;
620 /* Invalid request */
621 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
625 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
633 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
640 /* Setup the header */
641 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
642 Header
.Buffer
= (PCHAR
)State
;
643 ASSERT(Data
->Length
== sizeof(CONTEXT
));
645 /* Make sure that this is a valid request */
646 if (State
->Processor
< KeNumberProcessors
)
648 /* Check if the request is for this CPU */
649 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
651 /* We're just copying our own context */
652 ControlStart
= Context
;
656 /* SMP not yet handled */
657 KdpDprintf("KdpSetContext: SMP UNHANDLED\n");
662 /* Copy the memory */
663 RtlCopyMemory(ControlStart
, Data
->Buffer
, sizeof(CONTEXT
));
666 State
->ReturnStatus
= STATUS_SUCCESS
;
670 /* Invalid request */
671 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
675 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
683 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State
)
685 /* Crash with the special code */
686 KeBugCheck(MANUALLY_INITIATED_CRASH
);
691 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
696 PDBGKD_READ_WRITE_MSR ReadMsr
= &State
->u
.ReadWriteMsr
;
697 LARGE_INTEGER MsrValue
;
699 /* Setup the header */
700 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
701 Header
.Buffer
= (PCHAR
)State
;
702 ASSERT(Data
->Length
== 0);
704 /* Call the internal routine */
705 State
->ReturnStatus
= KdpSysReadMsr(ReadMsr
->Msr
,
708 /* Return the data */
709 ReadMsr
->DataValueLow
= MsrValue
.LowPart
;
710 ReadMsr
->DataValueHigh
= MsrValue
.HighPart
;
713 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
721 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
726 PDBGKD_READ_WRITE_MSR WriteMsr
= &State
->u
.ReadWriteMsr
;
727 LARGE_INTEGER MsrValue
;
729 /* Setup the header */
730 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
731 Header
.Buffer
= (PCHAR
)State
;
732 ASSERT(Data
->Length
== 0);
734 /* Call the internal routine */
735 MsrValue
.LowPart
= WriteMsr
->DataValueLow
;
736 MsrValue
.HighPart
= WriteMsr
->DataValueHigh
;
737 State
->ReturnStatus
= KdpSysWriteMsr(WriteMsr
->Msr
,
741 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
749 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
754 PDBGKD_GET_SET_BUS_DATA GetBusData
= &State
->u
.GetSetBusData
;
757 /* Setup the header */
758 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
759 Header
.Buffer
= (PCHAR
)State
;
760 ASSERT(Data
->Length
== 0);
762 /* Check the length requested */
763 Length
= GetBusData
->Length
;
764 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
766 /* Use maximum allowed */
767 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
770 /* Call the internal routine */
771 State
->ReturnStatus
= KdpSysReadBusData(GetBusData
->BusDataType
,
772 GetBusData
->BusNumber
,
773 GetBusData
->SlotNumber
,
779 /* Return the actual length read */
780 Data
->Length
= GetBusData
->Length
= Length
;
783 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
791 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
796 PDBGKD_GET_SET_BUS_DATA SetBusData
= &State
->u
.GetSetBusData
;
799 /* Setup the header */
800 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
801 Header
.Buffer
= (PCHAR
)State
;
803 /* Call the internal routine */
804 State
->ReturnStatus
= KdpSysWriteBusData(SetBusData
->BusDataType
,
805 SetBusData
->BusNumber
,
806 SetBusData
->SlotNumber
,
812 /* Return the actual length written */
813 SetBusData
->Length
= Length
;
816 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
824 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
829 PDBGKD_READ_WRITE_IO64 ReadIo
= &State
->u
.ReadWriteIo
;
831 /* Setup the header */
832 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
833 Header
.Buffer
= (PCHAR
)State
;
834 ASSERT(Data
->Length
== 0);
837 * Clear the value so 1 or 2 byte reads
838 * don't leave the higher bits unmodified
840 ReadIo
->DataValue
= 0;
842 /* Call the internal routine */
843 State
->ReturnStatus
= KdpSysReadIoSpace(Isa
,
852 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
860 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
865 PDBGKD_READ_WRITE_IO64 WriteIo
= &State
->u
.ReadWriteIo
;
867 /* Setup the header */
868 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
869 Header
.Buffer
= (PCHAR
)State
;
870 ASSERT(Data
->Length
== 0);
872 /* Call the internal routine */
873 State
->ReturnStatus
= KdpSysWriteIoSpace(Isa
,
882 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
890 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
895 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended
= &State
->u
.
898 /* Setup the header */
899 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
900 Header
.Buffer
= (PCHAR
)State
;
901 ASSERT(Data
->Length
== 0);
904 * Clear the value so 1 or 2 byte reads
905 * don't leave the higher bits unmodified
907 ReadIoExtended
->DataValue
= 0;
909 /* Call the internal routine */
910 State
->ReturnStatus
= KdpSysReadIoSpace(ReadIoExtended
->InterfaceType
,
911 ReadIoExtended
->BusNumber
,
912 ReadIoExtended
->AddressSpace
,
913 ReadIoExtended
->IoAddress
,
914 &ReadIoExtended
->DataValue
,
915 ReadIoExtended
->DataSize
,
916 &ReadIoExtended
->DataSize
);
919 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
927 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
932 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended
= &State
->u
.
935 /* Setup the header */
936 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
937 Header
.Buffer
= (PCHAR
)State
;
938 ASSERT(Data
->Length
== 0);
940 /* Call the internal routine */
941 State
->ReturnStatus
= KdpSysReadIoSpace(WriteIoExtended
->InterfaceType
,
942 WriteIoExtended
->BusNumber
,
943 WriteIoExtended
->AddressSpace
,
944 WriteIoExtended
->IoAddress
,
945 &WriteIoExtended
->DataValue
,
946 WriteIoExtended
->DataSize
,
947 &WriteIoExtended
->DataSize
);
950 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
958 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State
)
962 /* Setup the header */
963 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
964 Header
.Buffer
= (PCHAR
)State
;
966 /* Call the internal routine */
967 State
->ReturnStatus
= KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE
);
970 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
978 KdpSendWaitContinue(IN ULONG PacketType
,
979 IN PSTRING SendHeader
,
980 IN PSTRING SendData OPTIONAL
,
981 IN OUT PCONTEXT Context
)
984 DBGKD_MANIPULATE_STATE64 ManipulateState
;
988 /* Setup the Manipulate State structure */
989 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
990 Header
.Buffer
= (PCHAR
)&ManipulateState
;
991 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
992 Data
.Buffer
= KdpMessageBuffer
;
993 //KdpContextSent = FALSE;
996 /* Send the Packet */
997 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
999 /* If the debugger isn't present anymore, just return success */
1000 if (KdDebuggerNotPresent
) return ContinueSuccess
;
1002 /* Main processing Loop */
1008 /* Wait to get a reply to our packet */
1009 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1015 /* If we got a resend request, do it */
1016 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
1017 } while (RecvCode
== KdPacketTimedOut
);
1019 /* Now check what API we got */
1020 switch (ManipulateState
.ApiNumber
)
1022 case DbgKdReadVirtualMemoryApi
:
1024 /* Read virtual memory */
1025 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
1028 case DbgKdWriteVirtualMemoryApi
:
1030 /* Write virtual memory */
1031 KdpWriteVirtualMemory(&ManipulateState
, &Data
, Context
);
1034 case DbgKdGetContextApi
:
1036 /* Get the current context */
1037 KdpGetContext(&ManipulateState
, &Data
, Context
);
1040 case DbgKdSetContextApi
:
1042 /* Set a new context */
1043 KdpSetContext(&ManipulateState
, &Data
, Context
);
1046 case DbgKdWriteBreakPointApi
:
1048 /* Write the breakpoint */
1049 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
1052 case DbgKdRestoreBreakPointApi
:
1054 /* Restore the breakpoint */
1055 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
1058 case DbgKdContinueApi
:
1060 /* Simply continue */
1061 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
1063 case DbgKdReadControlSpaceApi
:
1065 /* Read control space */
1066 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
1069 case DbgKdWriteControlSpaceApi
:
1071 /* Write control space */
1072 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
1075 case DbgKdReadIoSpaceApi
:
1077 /* Read I/O Space */
1078 KdpReadIoSpace(&ManipulateState
, &Data
, Context
);
1081 case DbgKdWriteIoSpaceApi
:
1083 /* Write I/O Space */
1084 KdpWriteIoSpace(&ManipulateState
, &Data
, Context
);
1087 case DbgKdRebootApi
:
1089 /* Reboot the system */
1090 HalReturnToFirmware(HalRebootRoutine
);
1093 case DbgKdContinueApi2
:
1095 /* Check if caller reports success */
1096 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
1098 /* Update the state */
1099 KdpGetStateChange(&ManipulateState
, Context
);
1100 return ContinueSuccess
;
1104 /* Return an error */
1105 return ContinueError
;
1108 case DbgKdReadPhysicalMemoryApi
:
1110 /* Read physical memory */
1111 KdpReadPhysicalmemory(&ManipulateState
, &Data
, Context
);
1114 case DbgKdWritePhysicalMemoryApi
:
1116 /* Write physical memory */
1117 KdpWritePhysicalmemory(&ManipulateState
, &Data
, Context
);
1120 case DbgKdQuerySpecialCallsApi
:
1123 KdpDprintf("DbgKdQuerySpecialCallsApi called\n");
1127 case DbgKdSetSpecialCallApi
:
1130 KdpDprintf("DbgKdSetSpecialCallApi called\n");
1134 case DbgKdClearSpecialCallsApi
:
1137 KdpDprintf("DbgKdClearSpecialCallsApi called\n");
1141 case DbgKdSetInternalBreakPointApi
:
1144 KdpDprintf("DbgKdSetInternalBreakPointApi called\n");
1148 case DbgKdGetInternalBreakPointApi
:
1151 KdpDprintf("DbgKdGetInternalBreakPointApi called\n");
1155 case DbgKdReadIoSpaceExtendedApi
:
1157 /* Read I/O Space */
1158 KdpReadIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1161 case DbgKdWriteIoSpaceExtendedApi
:
1163 /* Write I/O Space */
1164 KdpWriteIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1167 case DbgKdGetVersionApi
:
1169 /* Get version data */
1170 KdpGetVersion(&ManipulateState
);
1173 case DbgKdWriteBreakPointExApi
:
1175 /* Write the breakpoint and check if it failed */
1176 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState
,
1180 /* Return an error */
1181 return ContinueError
;
1185 case DbgKdRestoreBreakPointExApi
:
1187 /* Restore the breakpoint */
1188 KdpRestoreBreakPointEx(&ManipulateState
, &Data
, Context
);
1191 case DbgKdCauseBugCheckApi
:
1193 /* Crash the system */
1194 KdpCauseBugCheck(&ManipulateState
);
1197 case DbgKdSwitchProcessor
:
1200 KdpDprintf("DbgKdSwitchProcessor called\n");
1204 case DbgKdPageInApi
:
1207 KdpDprintf("DbgKdPageInApi called\n");
1211 case DbgKdReadMachineSpecificRegister
:
1213 /* Read from the specified MSR */
1214 KdpReadMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1217 case DbgKdWriteMachineSpecificRegister
:
1219 /* Write to the specified MSR */
1220 KdpWriteMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1223 case DbgKdSearchMemoryApi
:
1226 KdpSearchMemory(&ManipulateState
, &Data
, Context
);
1229 case DbgKdGetBusDataApi
:
1231 /* Read from the bus */
1232 KdpGetBusData(&ManipulateState
, &Data
, Context
);
1235 case DbgKdSetBusDataApi
:
1237 /* Write to the bus */
1238 KdpSetBusData(&ManipulateState
, &Data
, Context
);
1241 case DbgKdCheckLowMemoryApi
:
1243 /* Check for memory corruption in the lower 4 GB */
1244 KdpCheckLowMemory(&ManipulateState
);
1247 case DbgKdClearAllInternalBreakpointsApi
:
1249 /* Just clear the counter */
1250 KdpNumInternalBreakpoints
= 0;
1253 case DbgKdFillMemoryApi
:
1256 KdpFillMemory(&ManipulateState
, &Data
, Context
);
1259 case DbgKdQueryMemoryApi
:
1262 KdpQueryMemory(&ManipulateState
, Context
);
1265 case DbgKdSwitchPartition
:
1268 KdpDprintf("DbgKdSwitchPartition called\n");
1272 /* Unsupported Message */
1275 /* Setup an empty message, with failure */
1276 KdpDprintf("Received Unhandled API %lx\n", ManipulateState
.ApiNumber
);
1278 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
1281 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1292 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
1293 IN PKD_SYMBOLS_INFO SymbolInfo
,
1295 IN OUT PCONTEXT Context
)
1298 STRING Data
, Header
;
1299 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1300 KCONTINUE_STATUS Status
;
1302 /* Start wait loop */
1305 /* Build the architecture common parts of the message */
1306 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
1310 /* Now finish creating the structure */
1311 KdpSetContextState(&WaitStateChange
, Context
);
1313 /* Fill out load data */
1314 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
1315 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONG64
)(LONG_PTR
)SymbolInfo
->BaseOfDll
;
1316 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
1317 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
1318 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
1320 /* Check if we have a symbol name */
1323 /* Setup the information */
1324 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathName
->Length
;
1325 RtlCopyMemory(KdpPathBuffer
, PathName
->Buffer
, PathName
->Length
);
1326 Data
.Buffer
= KdpPathBuffer
;
1327 Data
.Length
= WaitStateChange
.u
.LoadSymbols
.PathNameLength
;
1333 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
1337 /* Setup the header */
1338 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1339 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1341 /* Send the packet */
1342 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1346 } while (Status
== ContinueProcessorReselected
);
1354 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
1355 IN OUT PCONTEXT Context
,
1356 IN BOOLEAN SecondChanceException
)
1358 STRING Header
, Data
;
1359 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1360 KCONTINUE_STATUS Status
;
1362 /* Start report loop */
1365 /* Build the architecture common parts of the message */
1366 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
1368 /* Copy the Exception Record and set First Chance flag */
1369 #if !defined(_WIN64)
1370 ExceptionRecord32To64((PEXCEPTION_RECORD32
)ExceptionRecord
,
1371 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
1373 RtlCopyMemory(&WaitStateChange
.u
.Exception
.ExceptionRecord
,
1375 sizeof(EXCEPTION_RECORD
));
1377 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
1379 /* Now finish creating the structure */
1380 KdpSetContextState(&WaitStateChange
, Context
);
1382 /* Setup the actual header to send to KD */
1383 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1384 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1386 /* Setup the trace data */
1387 DumpTraceData(&Data
);
1389 /* Send State Change packet and wait for a reply */
1390 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1394 } while (Status
== ContinueProcessorReselected
);
1402 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
1403 IN PVOID DeferredContext
,
1404 IN PVOID SystemArgument1
,
1405 IN PVOID SystemArgument2
)
1407 LONG OldSlip
, NewSlip
, PendingSlip
;
1409 /* Get the current pending slip */
1410 PendingSlip
= KdpTimeSlipPending
;
1413 /* Save the old value and either disable or enable it now. */
1414 OldSlip
= PendingSlip
;
1415 NewSlip
= OldSlip
> 1 ? 1 : 0;
1417 /* Try to change the value */
1418 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1420 OldSlip
) != OldSlip
);
1422 /* If the New Slip value is 1, then do the Time Slipping */
1423 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1428 KdpTimeSlipWork(IN PVOID Context
)
1431 LARGE_INTEGER DueTime
;
1433 /* Update the System time from the CMOS */
1434 ExAcquireTimeRefreshLock(FALSE
);
1435 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1436 ExReleaseTimeRefreshLock();
1438 /* Check if we have a registered Time Slip Event and signal it */
1439 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
1440 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
1441 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
1443 /* Delay the DPC until it runs next time */
1444 DueTime
.QuadPart
= -1800000000;
1445 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1450 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1451 IN OUT PCONTEXT ContextRecord
,
1452 IN BOOLEAN SecondChanceException
)
1456 /* Save the port data */
1459 /* Report a state change */
1460 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1462 SecondChanceException
);
1464 /* Restore the port data and return */
1471 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1473 LARGE_INTEGER Null
= {{0}};
1475 /* Check if interrupts were disabled */
1476 if (!KeGetTrapFrameInterruptState(TrapFrame
))
1478 /* Nothing to return */
1482 /* Otherwise, do the call */
1483 return KeQueryPerformanceCounter(NULL
);
1488 KdpAllowDisable(VOID
)
1490 /* Check if we are on MP */
1491 if (KeNumberProcessors
> 1)
1494 KdpDprintf("KdpAllowDisable: SMP UNHANDLED\n");
1499 return STATUS_SUCCESS
;
1504 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1505 IN PKEXCEPTION_FRAME ExceptionFrame
)
1509 /* Check if we have a trap frame */
1512 /* Calculate the time difference for the enter */
1513 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1514 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1515 KdTimerStart
.QuadPart
;
1519 /* No trap frame, so can't calculate */
1520 KdTimerStop
.QuadPart
= 0;
1523 /* Save the current IRQL */
1524 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1526 /* Freeze all CPUs */
1527 Entered
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1529 /* Lock the port, save the state and set debugger entered */
1530 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1532 KdEnteredDebugger
= TRUE
;
1534 /* Check freeze flag */
1535 if (KiFreezeFlag
& 1)
1537 /* Print out errror */
1538 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1541 /* Check processor state */
1542 if (KiFreezeFlag
& 2)
1544 /* Print out errror */
1545 KdpDprintf("Some processors not frozen in debugger!\n");
1548 /* Make sure we acquired the port */
1549 if (!KdpPortLocked
) KdpDprintf("Port lock was not acquired!\n");
1551 /* Return enter state */
1557 KdExitDebugger(IN BOOLEAN Entered
)
1561 /* Restore the state and unlock the port */
1563 if (KdpPortLocked
) KdpPortUnlock();
1565 /* Unfreeze the CPUs */
1566 KeThawExecution(Entered
);
1568 /* Compare time with the one from KdEnterDebugger */
1569 if (!KdTimerStop
.QuadPart
)
1571 /* We didn't get a trap frame earlier in so never got the time */
1572 KdTimerStart
= KdTimerStop
;
1576 /* Query the timer */
1577 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1580 /* Check if a Time Slip was on queue */
1581 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1584 /* Queue a DPC for the time slip */
1585 InterlockedIncrement(&KdpTimeSlipPending
);
1586 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
);
1592 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock
)
1596 #if defined(__GNUC__)
1597 /* Make gcc happy */
1598 OldIrql
= PASSIVE_LEVEL
;
1601 /* Check if enabling the debugger is blocked */
1604 /* It is, fail the enable */
1605 return STATUS_ACCESS_DENIED
;
1608 /* Check if we need to acquire the lock */
1612 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1616 /* Check if we're not disabled */
1617 if (!KdDisableCount
)
1619 /* Check if we had locked the port before */
1623 KeLowerIrql(OldIrql
);
1626 /* Fail: We're already enabled */
1627 return STATUS_INVALID_PARAMETER
;
1632 * This can only happen if we are called from a bugcheck
1633 * and were never initialized, so initialize the debugger now.
1635 KdInitSystem(0, NULL
);
1637 /* Return success since we initialized */
1638 return STATUS_SUCCESS
;
1642 /* Decrease the disable count */
1643 if (!(--KdDisableCount
))
1645 /* We're now enabled again! Were we enabled before, too? */
1646 if (KdPreviouslyEnabled
)
1648 /* Reinitialize the Debugger */
1649 KdInitSystem(0, NULL
) ;
1650 KdpRestoreAllBreakpoints();
1654 /* Check if we had locked the port before */
1657 /* Yes, now unlock it */
1658 KeLowerIrql(OldIrql
);
1663 return STATUS_SUCCESS
;
1668 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock
)
1673 #if defined(__GNUC__)
1674 /* Make gcc happy */
1675 OldIrql
= PASSIVE_LEVEL
;
1679 * If enabling the debugger is blocked
1680 * then there is nothing to disable (duh)
1685 return STATUS_ACCESS_DENIED
;
1688 /* Check if we need to acquire the lock */
1692 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1696 /* Check if we're not disabled */
1697 if (!KdDisableCount
)
1699 /* Check if the debugger was never actually initialized */
1700 if (!(KdDebuggerEnabled
) && !(KdPitchDebugger
))
1702 /* It wasn't, so don't re-enable it later */
1703 KdPreviouslyEnabled
= FALSE
;
1707 /* It was, so we will re-enable it later */
1708 KdPreviouslyEnabled
= TRUE
;
1711 /* Check if we were called from the exported API and are enabled */
1712 if ((NeedLock
) && (KdPreviouslyEnabled
))
1714 /* Check if it is safe to disable the debugger */
1715 Status
= KdpAllowDisable();
1716 if (!NT_SUCCESS(Status
))
1718 /* Release the lock and fail */
1719 KeLowerIrql(OldIrql
);
1725 /* Only disable the debugger if it is enabled */
1726 if (KdDebuggerEnabled
)
1729 * Disable the debugger; suspend breakpoints
1730 * and reset the debug stub
1732 KdpSuspendAllBreakPoints();
1733 KiDebugRoutine
= KdpStub
;
1735 /* We are disabled now */
1736 KdDebuggerEnabled
= FALSE
;
1737 #undef KdDebuggerEnabled
1738 SharedUserData
->KdDebuggerEnabled
= FALSE
;
1739 #define KdDebuggerEnabled _KdDebuggerEnabled
1743 /* Increment the disable count */
1746 /* Check if we had locked the port before */
1749 /* Yes, now unlock it */
1750 KeLowerIrql(OldIrql
);
1755 return STATUS_SUCCESS
;
1758 /* PUBLIC FUNCTIONS **********************************************************/
1765 KdEnableDebugger(VOID
)
1767 /* Use the internal routine */
1768 return KdEnableDebuggerWithLock(TRUE
);
1776 KdDisableDebugger(VOID
)
1778 /* Use the internal routine */
1779 return KdDisableDebuggerWithLock(TRUE
);
1787 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
1788 IN PVOID InputBuffer
,
1789 IN ULONG InputBufferLength
,
1790 OUT PVOID OutputBuffer
,
1791 IN ULONG OutputBufferLength
,
1792 IN OUT PULONG ReturnLength
,
1793 IN KPROCESSOR_MODE PreviousMode
)
1796 return STATUS_SUCCESS
;
1804 KdChangeOption(IN KD_OPTION Option
,
1805 IN ULONG InBufferBytes OPTIONAL
,
1807 IN ULONG OutBufferBytes OPTIONAL
,
1808 OUT PVOID OutBuffer
,
1809 OUT PULONG OutBufferNeeded OPTIONAL
)
1812 return STATUS_SUCCESS
;
1820 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
1823 return STATUS_SUCCESS
;
1831 KdRefreshDebuggerNotPresent(VOID
)
1834 return KdDebuggerNotPresent
;
1842 NtQueryDebugFilterState(IN ULONG ComponentId
,
1846 return STATUS_SUCCESS
;
1854 NtSetDebugFilterState(IN ULONG ComponentId
,
1859 return STATUS_SUCCESS
;