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
)
28 ULONG RemainingLength
, CopyChunk
;
30 /* Check if we didn't get a chunk size or if it is too big */
33 /* Default to 4 byte chunks */
36 else if (ChunkSize
> MMDBG_COPY_MAX_SIZE
)
38 /* Normalize to maximum size */
39 ChunkSize
= MMDBG_COPY_MAX_SIZE
;
42 /* Copy the whole range in aligned chunks */
43 RemainingLength
= TotalSize
;
45 while (RemainingLength
> 0)
48 * Determine the best chunk size for this round.
49 * The ideal size is aligned, isn't larger than the
50 * the remaining length and respects the chunk limit.
52 while (((CopyChunk
* 2) <= RemainingLength
) &&
53 (CopyChunk
< ChunkSize
) &&
54 ((Address
& ((CopyChunk
* 2) - 1)) == 0))
61 * The chunk size can be larger than the remaining size if this isn't
62 * the first round, so check if we need to shrink it back
64 while (CopyChunk
> RemainingLength
)
71 Status
= MmDbgCopyMemory(Address
,
75 if (!NT_SUCCESS(Status
))
77 /* Copy failed, break out */
81 /* Update pointers and length for the next run */
82 Address
= Address
+ CopyChunk
;
83 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CopyChunk
);
84 RemainingLength
= RemainingLength
- CopyChunk
;
88 * Return the size we managed to copy
89 * and return success if we could copy the whole range
91 if (ActualSize
) *ActualSize
= TotalSize
- RemainingLength
;
92 return RemainingLength
== 0 ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
97 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
100 PDBGKD_QUERY_MEMORY Memory
= &State
->u
.QueryMemory
;
102 NTSTATUS Status
= STATUS_SUCCESS
;
104 /* Validate the address space */
105 if (Memory
->AddressSpace
== DBGKD_QUERY_MEMORY_VIRTUAL
)
107 /* Check if this is process memory */
108 if ((PVOID
)(ULONG_PTR
)Memory
->Address
< MmHighestUserAddress
)
111 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_PROCESS
;
115 /* Check if it's session space */
116 if (MmIsSessionAddress((PVOID
)(ULONG_PTR
)Memory
->Address
))
119 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_SESSION
;
123 /* Not session space but some other kernel memory */
124 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_KERNEL
;
129 Memory
->Flags
= DBGKD_QUERY_MEMORY_READ
|
130 DBGKD_QUERY_MEMORY_WRITE
|
131 DBGKD_QUERY_MEMORY_EXECUTE
;
136 Status
= STATUS_INVALID_PARAMETER
;
139 /* Return structure */
140 State
->ReturnStatus
= Status
;
141 Memory
->Reserved
= 0;
144 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
145 Header
.Buffer
= (PCHAR
)State
;
147 /* Send the packet */
148 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
156 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
160 //PDBGKD_SEARCH_MEMORY SearchMemory = &State->u.SearchMemory;
164 KdpDprintf("Memory Search support is unimplemented!\n");
166 /* Send a failure packet */
167 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
168 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
169 Header
.Buffer
= (PCHAR
)State
;
170 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
178 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
182 //PDBGKD_FILL_MEMORY FillMemory = &State->u.FillMemory;
186 KdpDprintf("Memory Fill support is unimplemented!\n");
188 /* Send a failure packet */
189 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
190 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
191 Header
.Buffer
= (PCHAR
)State
;
192 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
200 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
204 PDBGKD_WRITE_BREAKPOINT64 Breakpoint
= &State
->u
.WriteBreakPoint
;
208 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
209 Header
.Buffer
= (PCHAR
)State
;
210 ASSERT(Data
->Length
== 0);
212 /* Create the breakpoint */
213 Breakpoint
->BreakPointHandle
=
214 KdpAddBreakpoint((PVOID
)(ULONG_PTR
)Breakpoint
->BreakPointAddress
);
215 if (!Breakpoint
->BreakPointHandle
)
218 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
223 State
->ReturnStatus
= STATUS_SUCCESS
;
226 /* Send the packet */
227 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
235 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
239 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
242 /* Fill out the header */
243 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
244 Header
.Buffer
= (PCHAR
)State
;
245 ASSERT(Data
->Length
== 0);
247 /* Get the version block */
248 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
251 State
->ReturnStatus
= STATUS_SUCCESS
;
256 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
259 /* Send the packet */
260 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
268 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
272 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
276 KdpDprintf("Extended Breakpoint Write support is unimplemented!\n");
278 /* Send a failure packet */
279 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
280 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
281 Header
.Buffer
= (PCHAR
)State
;
282 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
286 return STATUS_UNSUCCESSFUL
;
291 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
295 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
299 KdpDprintf("Extended Breakpoint Restore support is unimplemented!\n");
301 /* Send a failure packet */
302 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
303 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
304 Header
.Buffer
= (PCHAR
)State
;
305 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
313 DumpTraceData(IN PSTRING TraceData
)
315 /* Update the buffer */
316 TraceDataBuffer
[0] = TraceDataBufferPosition
;
318 /* Setup the trace data */
319 TraceData
->Length
= (USHORT
)(TraceDataBufferPosition
* sizeof(ULONG
));
320 TraceData
->Buffer
= (PCHAR
)TraceDataBuffer
;
322 /* Reset the buffer location */
323 TraceDataBufferPosition
= 1;
328 KdpSetCommonState(IN ULONG NewState
,
330 IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
)
332 ULONG InstructionCount
;
333 BOOLEAN HadBreakpoints
;
335 /* Setup common stuff available for all CPU architectures */
336 WaitStateChange
->NewState
= NewState
;
337 WaitStateChange
->ProcessorLevel
= KeProcessorLevel
;
338 WaitStateChange
->Processor
= (USHORT
)KeGetCurrentPrcb()->Number
;
339 WaitStateChange
->NumberProcessors
= (ULONG
)KeNumberProcessors
;
340 WaitStateChange
->Thread
= (ULONG64
)(LONG_PTR
)KeGetCurrentThread();
341 WaitStateChange
->ProgramCounter
= (ULONG64
)(LONG_PTR
)KeGetContextPc(Context
);
343 /* Zero out the entire Control Report */
344 RtlZeroMemory(&WaitStateChange
->AnyControlReport
,
345 sizeof(DBGKD_ANY_CONTROL_REPORT
));
347 /* Now copy the instruction stream and set the count */
348 KdpCopyMemoryChunks((ULONG_PTR
)WaitStateChange
->ProgramCounter
,
349 &WaitStateChange
->ControlReport
.InstructionStream
[0],
354 WaitStateChange
->ControlReport
.InstructionCount
= (USHORT
)InstructionCount
;
356 /* Clear all the breakpoints in this region */
358 KdpDeleteBreakpointRange((PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
359 (PVOID
)((ULONG_PTR
)WaitStateChange
->ProgramCounter
+
360 WaitStateChange
->ControlReport
.InstructionCount
- 1));
363 /* Copy the instruction stream again, this time without breakpoints */
364 KdpCopyMemoryChunks((ULONG_PTR
)WaitStateChange
->ProgramCounter
,
365 &WaitStateChange
->ControlReport
.InstructionStream
[0],
375 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version
)
377 /* Copy the version block */
378 RtlCopyMemory(Version
, &KdVersionBlock
, sizeof(DBGKD_GET_VERSION64
));
383 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State
)
387 /* Fill out the header */
388 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
389 Header
.Buffer
= (PCHAR
)State
;
391 /* Get the version block */
392 KdpSysGetVersion(&State
->u
.GetVersion64
);
394 /* Fill out the state */
395 State
->ApiNumber
= DbgKdGetVersionApi
;
396 State
->ReturnStatus
= STATUS_SUCCESS
;
398 /* Send the packet */
399 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
407 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
411 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
413 ULONG Length
= ReadMemory
->TransferCount
;
415 /* Setup the header */
416 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
417 Header
.Buffer
= (PCHAR
)State
;
418 ASSERT(Data
->Length
== 0);
420 /* Validate length */
421 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
423 /* Overflow, set it to maximum possible */
424 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
428 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
435 /* Return the actual length read */
436 ReadMemory
->ActualBytesRead
= Length
;
437 Data
->Length
= (USHORT
)Length
;
439 /* Send the packet */
440 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
448 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
452 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
455 /* Setup the header */
456 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
457 Header
.Buffer
= (PCHAR
)State
;
460 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
466 &WriteMemory
->ActualBytesWritten
);
468 /* Send the packet */
469 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
477 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
481 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
483 ULONG Length
= ReadMemory
->TransferCount
;
484 ULONG Flags
, CacheFlags
;
486 /* Setup the header */
487 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
488 Header
.Buffer
= (PCHAR
)State
;
489 ASSERT(Data
->Length
== 0);
491 /* Validate length */
492 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
494 /* Overflow, set it to maximum possible */
495 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
498 /* Start with the default flags */
499 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_PHYSICAL
;
501 /* Get the caching flags and check if a type is specified */
502 CacheFlags
= ReadMemory
->ActualBytesRead
;
503 if (CacheFlags
== DBGKD_CACHING_CACHED
)
506 Flags
|= MMDBG_COPY_CACHED
;
508 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
511 Flags
|= MMDBG_COPY_UNCACHED
;
513 else if (CacheFlags
== DBGKD_CACHING_WRITE_COMBINED
)
516 Flags
|= MMDBG_COPY_WRITE_COMBINED
;
520 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
527 /* Return the actual length read */
528 ReadMemory
->ActualBytesRead
= Length
;
529 Data
->Length
= (USHORT
)Length
;
531 /* Send the packet */
532 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
540 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
544 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
546 ULONG Flags
, CacheFlags
;
548 /* Setup the header */
549 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
550 Header
.Buffer
= (PCHAR
)State
;
552 /* Start with the default flags */
553 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_WRITE
| MMDBG_COPY_PHYSICAL
;
555 /* Get the caching flags and check if a type is specified */
556 CacheFlags
= WriteMemory
->ActualBytesWritten
;
557 if (CacheFlags
== DBGKD_CACHING_CACHED
)
560 Flags
|= MMDBG_COPY_CACHED
;
562 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
565 Flags
|= MMDBG_COPY_UNCACHED
;
567 else if (CacheFlags
== DBGKD_CACHING_WRITE_COMBINED
)
570 Flags
|= MMDBG_COPY_WRITE_COMBINED
;
574 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
579 &WriteMemory
->ActualBytesWritten
);
581 /* Send the packet */
582 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
590 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
594 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
598 /* Setup the header */
599 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
600 Header
.Buffer
= (PCHAR
)State
;
601 ASSERT(Data
->Length
== 0);
603 /* Check the length requested */
604 Length
= ReadMemory
->TransferCount
;
605 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
607 /* Use maximum allowed */
608 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
611 /* Call the internal routine */
612 State
->ReturnStatus
= KdpSysReadControlSpace(State
->Processor
,
613 ReadMemory
->TargetBaseAddress
,
618 /* Return the actual length read */
619 ReadMemory
->ActualBytesRead
= Length
;
620 Data
->Length
= (USHORT
)Length
;
623 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
631 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
635 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
638 /* Setup the header */
639 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
640 Header
.Buffer
= (PCHAR
)State
;
642 /* Call the internal routine */
643 State
->ReturnStatus
= KdpSysWriteControlSpace(State
->Processor
,
644 WriteMemory
->TargetBaseAddress
,
647 &WriteMemory
->ActualBytesWritten
);
650 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
658 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
663 PCONTEXT TargetContext
;
665 /* Setup the header */
666 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
667 Header
.Buffer
= (PCHAR
)State
;
668 ASSERT(Data
->Length
== 0);
670 /* Make sure that this is a valid request */
671 if (State
->Processor
< KeNumberProcessors
)
673 /* Check if the request is for this CPU */
674 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
676 /* We're just copying our own context */
677 TargetContext
= Context
;
681 /* Get the context from the PRCB array */
682 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
683 ProcessorState
.ContextFrame
;
686 /* Copy it over to the debugger */
687 RtlCopyMemory(Data
->Buffer
, TargetContext
, sizeof(CONTEXT
));
688 Data
->Length
= sizeof(CONTEXT
);
690 /* Let the debugger set the context now */
691 KdpContextSent
= TRUE
;
694 State
->ReturnStatus
= STATUS_SUCCESS
;
698 /* Invalid request */
699 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
703 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
711 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
716 PCONTEXT TargetContext
;
718 /* Setup the header */
719 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
720 Header
.Buffer
= (PCHAR
)State
;
721 ASSERT(Data
->Length
== sizeof(CONTEXT
));
723 /* Make sure that this is a valid request */
724 if ((State
->Processor
< KeNumberProcessors
) && (KdpContextSent
== TRUE
))
726 /* Check if the request is for this CPU */
727 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
729 /* We're just copying our own context */
730 TargetContext
= Context
;
734 /* Get the context from the PRCB array */
735 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
736 ProcessorState
.ContextFrame
;
739 /* Copy the new context to it */
740 RtlCopyMemory(TargetContext
, Data
->Buffer
, sizeof(CONTEXT
));
743 State
->ReturnStatus
= STATUS_SUCCESS
;
747 /* Invalid request */
748 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
752 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
760 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State
)
762 /* Crash with the special code */
763 KeBugCheck(MANUALLY_INITIATED_CRASH
);
768 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
773 PDBGKD_READ_WRITE_MSR ReadMsr
= &State
->u
.ReadWriteMsr
;
774 LARGE_INTEGER MsrValue
;
776 /* Setup the header */
777 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
778 Header
.Buffer
= (PCHAR
)State
;
779 ASSERT(Data
->Length
== 0);
781 /* Call the internal routine */
782 State
->ReturnStatus
= KdpSysReadMsr(ReadMsr
->Msr
,
785 /* Return the data */
786 ReadMsr
->DataValueLow
= MsrValue
.LowPart
;
787 ReadMsr
->DataValueHigh
= MsrValue
.HighPart
;
790 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
798 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
803 PDBGKD_READ_WRITE_MSR WriteMsr
= &State
->u
.ReadWriteMsr
;
804 LARGE_INTEGER MsrValue
;
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 MsrValue
.LowPart
= WriteMsr
->DataValueLow
;
813 MsrValue
.HighPart
= WriteMsr
->DataValueHigh
;
814 State
->ReturnStatus
= KdpSysWriteMsr(WriteMsr
->Msr
,
818 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
826 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
831 PDBGKD_GET_SET_BUS_DATA GetBusData
= &State
->u
.GetSetBusData
;
834 /* Setup the header */
835 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
836 Header
.Buffer
= (PCHAR
)State
;
837 ASSERT(Data
->Length
== 0);
839 /* Check the length requested */
840 Length
= GetBusData
->Length
;
841 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
843 /* Use maximum allowed */
844 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
847 /* Call the internal routine */
848 State
->ReturnStatus
= KdpSysReadBusData(GetBusData
->BusDataType
,
849 GetBusData
->BusNumber
,
850 GetBusData
->SlotNumber
,
856 /* Return the actual length read */
857 GetBusData
->Length
= Length
;
858 Data
->Length
= (USHORT
)Length
;
861 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
869 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
874 PDBGKD_GET_SET_BUS_DATA SetBusData
= &State
->u
.GetSetBusData
;
877 /* Setup the header */
878 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
879 Header
.Buffer
= (PCHAR
)State
;
881 /* Call the internal routine */
882 State
->ReturnStatus
= KdpSysWriteBusData(SetBusData
->BusDataType
,
883 SetBusData
->BusNumber
,
884 SetBusData
->SlotNumber
,
890 /* Return the actual length written */
891 SetBusData
->Length
= Length
;
894 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
902 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
907 PDBGKD_READ_WRITE_IO64 ReadIo
= &State
->u
.ReadWriteIo
;
909 /* Setup the header */
910 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
911 Header
.Buffer
= (PCHAR
)State
;
912 ASSERT(Data
->Length
== 0);
915 * Clear the value so 1 or 2 byte reads
916 * don't leave the higher bits unmodified
918 ReadIo
->DataValue
= 0;
920 /* Call the internal routine */
921 State
->ReturnStatus
= KdpSysReadIoSpace(Isa
,
930 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
938 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
943 PDBGKD_READ_WRITE_IO64 WriteIo
= &State
->u
.ReadWriteIo
;
945 /* Setup the header */
946 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
947 Header
.Buffer
= (PCHAR
)State
;
948 ASSERT(Data
->Length
== 0);
950 /* Call the internal routine */
951 State
->ReturnStatus
= KdpSysWriteIoSpace(Isa
,
960 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
968 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
973 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended
= &State
->u
.
976 /* Setup the header */
977 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
978 Header
.Buffer
= (PCHAR
)State
;
979 ASSERT(Data
->Length
== 0);
982 * Clear the value so 1 or 2 byte reads
983 * don't leave the higher bits unmodified
985 ReadIoExtended
->DataValue
= 0;
987 /* Call the internal routine */
988 State
->ReturnStatus
= KdpSysReadIoSpace(ReadIoExtended
->InterfaceType
,
989 ReadIoExtended
->BusNumber
,
990 ReadIoExtended
->AddressSpace
,
991 ReadIoExtended
->IoAddress
,
992 &ReadIoExtended
->DataValue
,
993 ReadIoExtended
->DataSize
,
994 &ReadIoExtended
->DataSize
);
997 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1005 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
1007 IN PCONTEXT Context
)
1010 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended
= &State
->u
.
1011 ReadWriteIoExtended
;
1013 /* Setup the header */
1014 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1015 Header
.Buffer
= (PCHAR
)State
;
1016 ASSERT(Data
->Length
== 0);
1018 /* Call the internal routine */
1019 State
->ReturnStatus
= KdpSysReadIoSpace(WriteIoExtended
->InterfaceType
,
1020 WriteIoExtended
->BusNumber
,
1021 WriteIoExtended
->AddressSpace
,
1022 WriteIoExtended
->IoAddress
,
1023 &WriteIoExtended
->DataValue
,
1024 WriteIoExtended
->DataSize
,
1025 &WriteIoExtended
->DataSize
);
1027 /* Send the reply */
1028 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1036 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State
)
1040 /* Setup the header */
1041 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1042 Header
.Buffer
= (PCHAR
)State
;
1044 /* Call the internal routine */
1045 State
->ReturnStatus
= KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE
);
1047 /* Send the reply */
1048 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1056 KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State
)
1061 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
1063 /* Setup the packet */
1064 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1065 Header
.Buffer
= (PCHAR
)State
;
1068 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1076 KdpSendWaitContinue(IN ULONG PacketType
,
1077 IN PSTRING SendHeader
,
1078 IN PSTRING SendData OPTIONAL
,
1079 IN OUT PCONTEXT Context
)
1081 STRING Data
, Header
;
1082 DBGKD_MANIPULATE_STATE64 ManipulateState
;
1086 /* Setup the Manipulate State structure */
1087 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
1088 Header
.Buffer
= (PCHAR
)&ManipulateState
;
1089 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
1090 Data
.Buffer
= KdpMessageBuffer
;
1093 * Reset the context state to ensure the debugger has received
1094 * the current context before it sets it
1096 KdpContextSent
= FALSE
;
1099 /* Send the Packet */
1100 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
1102 /* If the debugger isn't present anymore, just return success */
1103 if (KdDebuggerNotPresent
) return ContinueSuccess
;
1105 /* Main processing Loop */
1111 /* Wait to get a reply to our packet */
1112 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1118 /* If we got a resend request, do it */
1119 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
1120 } while (RecvCode
== KdPacketTimedOut
);
1122 /* Now check what API we got */
1123 switch (ManipulateState
.ApiNumber
)
1125 case DbgKdReadVirtualMemoryApi
:
1127 /* Read virtual memory */
1128 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
1131 case DbgKdWriteVirtualMemoryApi
:
1133 /* Write virtual memory */
1134 KdpWriteVirtualMemory(&ManipulateState
, &Data
, Context
);
1137 case DbgKdGetContextApi
:
1139 /* Get the current context */
1140 KdpGetContext(&ManipulateState
, &Data
, Context
);
1143 case DbgKdSetContextApi
:
1145 /* Set a new context */
1146 KdpSetContext(&ManipulateState
, &Data
, Context
);
1149 case DbgKdWriteBreakPointApi
:
1151 /* Write the breakpoint */
1152 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
1155 case DbgKdRestoreBreakPointApi
:
1157 /* Restore the breakpoint */
1158 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
1161 case DbgKdContinueApi
:
1163 /* Simply continue */
1164 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
1166 case DbgKdReadControlSpaceApi
:
1168 /* Read control space */
1169 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
1172 case DbgKdWriteControlSpaceApi
:
1174 /* Write control space */
1175 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
1178 case DbgKdReadIoSpaceApi
:
1180 /* Read I/O Space */
1181 KdpReadIoSpace(&ManipulateState
, &Data
, Context
);
1184 case DbgKdWriteIoSpaceApi
:
1186 /* Write I/O Space */
1187 KdpWriteIoSpace(&ManipulateState
, &Data
, Context
);
1190 case DbgKdRebootApi
:
1192 /* Reboot the system */
1193 HalReturnToFirmware(HalRebootRoutine
);
1196 case DbgKdContinueApi2
:
1198 /* Check if caller reports success */
1199 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
1201 /* Update the state */
1202 KdpGetStateChange(&ManipulateState
, Context
);
1203 return ContinueSuccess
;
1207 /* Return an error */
1208 return ContinueError
;
1211 case DbgKdReadPhysicalMemoryApi
:
1213 /* Read physical memory */
1214 KdpReadPhysicalmemory(&ManipulateState
, &Data
, Context
);
1217 case DbgKdWritePhysicalMemoryApi
:
1219 /* Write physical memory */
1220 KdpWritePhysicalmemory(&ManipulateState
, &Data
, Context
);
1223 case DbgKdQuerySpecialCallsApi
:
1224 case DbgKdSetSpecialCallApi
:
1225 case DbgKdClearSpecialCallsApi
:
1228 KdpDprintf("Special Call support is unimplemented!\n");
1229 KdpNotSupported(&ManipulateState
);
1232 case DbgKdSetInternalBreakPointApi
:
1233 case DbgKdGetInternalBreakPointApi
:
1236 KdpDprintf("Internal Breakpoint support is unimplemented!\n");
1237 KdpNotSupported(&ManipulateState
);
1240 case DbgKdReadIoSpaceExtendedApi
:
1242 /* Read I/O Space */
1243 KdpReadIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1246 case DbgKdWriteIoSpaceExtendedApi
:
1248 /* Write I/O Space */
1249 KdpWriteIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1252 case DbgKdGetVersionApi
:
1254 /* Get version data */
1255 KdpGetVersion(&ManipulateState
);
1258 case DbgKdWriteBreakPointExApi
:
1260 /* Write the breakpoint and check if it failed */
1261 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState
,
1265 /* Return an error */
1266 return ContinueError
;
1270 case DbgKdRestoreBreakPointExApi
:
1272 /* Restore the breakpoint */
1273 KdpRestoreBreakPointEx(&ManipulateState
, &Data
, Context
);
1276 case DbgKdCauseBugCheckApi
:
1278 /* Crash the system */
1279 KdpCauseBugCheck(&ManipulateState
);
1282 case DbgKdSwitchProcessor
:
1285 KdpDprintf("Processor Switch support is unimplemented!\n");
1286 KdpNotSupported(&ManipulateState
);
1289 case DbgKdPageInApi
:
1292 KdpDprintf("Page-In support is unimplemented!\n");
1293 KdpNotSupported(&ManipulateState
);
1296 case DbgKdReadMachineSpecificRegister
:
1298 /* Read from the specified MSR */
1299 KdpReadMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1302 case DbgKdWriteMachineSpecificRegister
:
1304 /* Write to the specified MSR */
1305 KdpWriteMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1308 case DbgKdSearchMemoryApi
:
1311 KdpSearchMemory(&ManipulateState
, &Data
, Context
);
1314 case DbgKdGetBusDataApi
:
1316 /* Read from the bus */
1317 KdpGetBusData(&ManipulateState
, &Data
, Context
);
1320 case DbgKdSetBusDataApi
:
1322 /* Write to the bus */
1323 KdpSetBusData(&ManipulateState
, &Data
, Context
);
1326 case DbgKdCheckLowMemoryApi
:
1328 /* Check for memory corruption in the lower 4 GB */
1329 KdpCheckLowMemory(&ManipulateState
);
1332 case DbgKdClearAllInternalBreakpointsApi
:
1334 /* Just clear the counter */
1335 KdpNumInternalBreakpoints
= 0;
1338 case DbgKdFillMemoryApi
:
1341 KdpFillMemory(&ManipulateState
, &Data
, Context
);
1344 case DbgKdQueryMemoryApi
:
1347 KdpQueryMemory(&ManipulateState
, Context
);
1350 case DbgKdSwitchPartition
:
1353 KdpDprintf("Partition Switch support is unimplemented!\n");
1354 KdpNotSupported(&ManipulateState
);
1357 /* Unsupported Message */
1360 /* Setup an empty message, with failure */
1361 KdpDprintf("Received Unhandled API %lx\n", ManipulateState
.ApiNumber
);
1363 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
1366 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1377 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
1378 IN PKD_SYMBOLS_INFO SymbolInfo
,
1380 IN OUT PCONTEXT Context
)
1383 STRING Data
, Header
;
1384 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1385 ULONG PathNameLength
;
1386 KCONTINUE_STATUS Status
;
1388 /* Start wait loop */
1391 /* Build the architecture common parts of the message */
1392 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
1396 /* Now finish creating the structure */
1397 KdpSetContextState(&WaitStateChange
, Context
);
1399 /* Fill out load data */
1400 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
1401 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONG64
)(LONG_PTR
)SymbolInfo
->BaseOfDll
;
1402 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
1403 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
1404 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
1406 /* Check if we have a path name */
1409 /* Copy it to the path buffer */
1410 KdpCopyMemoryChunks((ULONG_PTR
)PathName
->Buffer
,
1417 /* Null terminate */
1418 KdpPathBuffer
[PathNameLength
++] = ANSI_NULL
;
1420 /* Set the path length */
1421 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathNameLength
;
1423 /* Set up the data */
1424 Data
.Buffer
= KdpPathBuffer
;
1425 Data
.Length
= (USHORT
)PathNameLength
;
1431 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
1435 /* Setup the header */
1436 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1437 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1439 /* Send the packet */
1440 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1444 } while (Status
== ContinueProcessorReselected
);
1449 KdpReportCommandStringStateChange(IN PSTRING NameString
,
1450 IN PSTRING CommandString
,
1451 IN OUT PCONTEXT Context
)
1453 STRING Header
, Data
;
1454 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1455 ULONG Length
, ActualLength
, TotalLength
;
1456 KCONTINUE_STATUS Status
;
1458 /* Start wait loop */
1461 /* Build the architecture common parts of the message */
1462 KdpSetCommonState(DbgKdCommandStringStateChange
,
1466 /* Set the context */
1467 KdpSetContextState(&WaitStateChange
, Context
);
1469 /* Clear the command string structure */
1470 RtlZeroMemory(&WaitStateChange
.u
.CommandString
,
1471 sizeof(DBGKD_COMMAND_STRING
));
1473 /* Normalize name string to max */
1474 Length
= min(128 - 1, NameString
->Length
);
1476 /* Copy it to the message buffer */
1477 KdpCopyMemoryChunks((ULONG_PTR
)NameString
->Buffer
,
1484 /* Null terminate and calculate the total length */
1485 TotalLength
= ActualLength
;
1486 KdpMessageBuffer
[TotalLength
++] = ANSI_NULL
;
1488 /* Check if the command string is too long */
1489 Length
= CommandString
->Length
;
1490 if (Length
> (PACKET_MAX_SIZE
-
1491 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
) - TotalLength
))
1493 /* Use maximum possible size */
1494 Length
= (PACKET_MAX_SIZE
-
1495 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
) - TotalLength
);
1498 /* Copy it to the message buffer */
1499 KdpCopyMemoryChunks((ULONG_PTR
)CommandString
->Buffer
,
1500 KdpMessageBuffer
+ TotalLength
,
1506 /* Null terminate and calculate the total length */
1507 TotalLength
+= ActualLength
;
1508 KdpMessageBuffer
[TotalLength
++] = ANSI_NULL
;
1510 /* Now set up the header and the data */
1511 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1512 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1513 Data
.Length
= (USHORT
)TotalLength
;
1514 Data
.Buffer
= KdpMessageBuffer
;
1516 /* Send State Change packet and wait for a reply */
1517 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1521 } while (Status
== ContinueProcessorReselected
);
1526 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
1527 IN OUT PCONTEXT Context
,
1528 IN BOOLEAN SecondChanceException
)
1530 STRING Header
, Data
;
1531 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1532 KCONTINUE_STATUS Status
;
1534 /* Start report loop */
1537 /* Build the architecture common parts of the message */
1538 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
1540 /* Copy the Exception Record and set First Chance flag */
1541 #if !defined(_WIN64)
1542 ExceptionRecord32To64((PEXCEPTION_RECORD32
)ExceptionRecord
,
1543 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
1545 RtlCopyMemory(&WaitStateChange
.u
.Exception
.ExceptionRecord
,
1547 sizeof(EXCEPTION_RECORD
));
1549 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
1551 /* Now finish creating the structure */
1552 KdpSetContextState(&WaitStateChange
, Context
);
1554 /* Setup the actual header to send to KD */
1555 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1556 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1558 /* Setup the trace data */
1559 DumpTraceData(&Data
);
1561 /* Send State Change packet and wait for a reply */
1562 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1566 } while (Status
== ContinueProcessorReselected
);
1574 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
1575 IN PVOID DeferredContext
,
1576 IN PVOID SystemArgument1
,
1577 IN PVOID SystemArgument2
)
1579 LONG OldSlip
, NewSlip
, PendingSlip
;
1581 /* Get the current pending slip */
1582 PendingSlip
= KdpTimeSlipPending
;
1585 /* Save the old value and either disable or enable it now. */
1586 OldSlip
= PendingSlip
;
1587 NewSlip
= OldSlip
> 1 ? 1 : 0;
1589 /* Try to change the value */
1590 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1592 OldSlip
) != OldSlip
);
1594 /* If the New Slip value is 1, then do the Time Slipping */
1595 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1600 KdpTimeSlipWork(IN PVOID Context
)
1603 LARGE_INTEGER DueTime
;
1605 /* Update the System time from the CMOS */
1606 ExAcquireTimeRefreshLock(FALSE
);
1607 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1608 ExReleaseTimeRefreshLock();
1610 /* Check if we have a registered Time Slip Event and signal it */
1611 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
1612 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
1613 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
1615 /* Delay the DPC until it runs next time */
1616 DueTime
.QuadPart
= -1800000000;
1617 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1622 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1623 IN OUT PCONTEXT ContextRecord
,
1624 IN BOOLEAN SecondChanceException
)
1628 /* Save the port data */
1631 /* Report a state change */
1632 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1634 SecondChanceException
);
1636 /* Restore the port data and return */
1643 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1645 LARGE_INTEGER Null
= {{0}};
1647 /* Check if interrupts were disabled */
1648 if (!KeGetTrapFrameInterruptState(TrapFrame
))
1650 /* Nothing to return */
1654 /* Otherwise, do the call */
1655 return KeQueryPerformanceCounter(NULL
);
1660 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1661 IN PKEXCEPTION_FRAME ExceptionFrame
)
1665 /* Check if we have a trap frame */
1668 /* Calculate the time difference for the enter */
1669 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1670 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1671 KdTimerStart
.QuadPart
;
1675 /* No trap frame, so can't calculate */
1676 KdTimerStop
.QuadPart
= 0;
1679 /* Save the current IRQL */
1680 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1682 /* Freeze all CPUs */
1683 Enable
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1685 /* Lock the port, save the state and set debugger entered */
1686 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1688 KdEnteredDebugger
= TRUE
;
1690 /* Check freeze flag */
1691 if (KiFreezeFlag
& 1)
1693 /* Print out errror */
1694 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1697 /* Check processor state */
1698 if (KiFreezeFlag
& 2)
1700 /* Print out errror */
1701 KdpDprintf("Some processors not frozen in debugger!\n");
1704 /* Make sure we acquired the port */
1705 if (!KdpPortLocked
) KdpDprintf("Port lock was not acquired!\n");
1707 /* Return if interrupts needs to be re-enabled */
1713 KdExitDebugger(IN BOOLEAN Enable
)
1717 /* Restore the state and unlock the port */
1719 if (KdpPortLocked
) KdpPortUnlock();
1721 /* Unfreeze the CPUs */
1722 KeThawExecution(Enable
);
1724 /* Compare time with the one from KdEnterDebugger */
1725 if (!KdTimerStop
.QuadPart
)
1727 /* We didn't get a trap frame earlier in so never got the time */
1728 KdTimerStart
= KdTimerStop
;
1732 /* Query the timer */
1733 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1736 /* Check if a Time Slip was on queue */
1737 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1740 /* Queue a DPC for the time slip */
1741 InterlockedIncrement(&KdpTimeSlipPending
);
1742 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
);
1748 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock
)
1752 #if defined(__GNUC__)
1753 /* Make gcc happy */
1754 OldIrql
= PASSIVE_LEVEL
;
1757 /* Check if enabling the debugger is blocked */
1760 /* It is, fail the enable */
1761 return STATUS_ACCESS_DENIED
;
1764 /* Check if we need to acquire the lock */
1768 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1772 /* Check if we're not disabled */
1773 if (!KdDisableCount
)
1775 /* Check if we had locked the port before */
1779 KeLowerIrql(OldIrql
);
1782 /* Fail: We're already enabled */
1783 return STATUS_INVALID_PARAMETER
;
1788 * This can only happen if we are called from a bugcheck
1789 * and were never initialized, so initialize the debugger now.
1791 KdInitSystem(0, NULL
);
1793 /* Return success since we initialized */
1794 return STATUS_SUCCESS
;
1798 /* Decrease the disable count */
1799 if (!(--KdDisableCount
))
1801 /* We're now enabled again! Were we enabled before, too? */
1802 if (KdPreviouslyEnabled
)
1804 /* Reinitialize the Debugger */
1805 KdInitSystem(0, NULL
) ;
1806 KdpRestoreAllBreakpoints();
1810 /* Check if we had locked the port before */
1813 /* Yes, now unlock it */
1814 KeLowerIrql(OldIrql
);
1819 return STATUS_SUCCESS
;
1824 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock
)
1829 #if defined(__GNUC__)
1830 /* Make gcc happy */
1831 OldIrql
= PASSIVE_LEVEL
;
1835 * If enabling the debugger is blocked
1836 * then there is nothing to disable (duh)
1841 return STATUS_ACCESS_DENIED
;
1844 /* Check if we need to acquire the lock */
1848 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1852 /* Check if we're not disabled */
1853 if (!KdDisableCount
)
1855 /* Check if the debugger was never actually initialized */
1856 if (!(KdDebuggerEnabled
) && !(KdPitchDebugger
))
1858 /* It wasn't, so don't re-enable it later */
1859 KdPreviouslyEnabled
= FALSE
;
1863 /* It was, so we will re-enable it later */
1864 KdPreviouslyEnabled
= TRUE
;
1867 /* Check if we were called from the exported API and are enabled */
1868 if ((NeedLock
) && (KdPreviouslyEnabled
))
1870 /* Check if it is safe to disable the debugger */
1871 Status
= KdpAllowDisable();
1872 if (!NT_SUCCESS(Status
))
1874 /* Release the lock and fail */
1875 KeLowerIrql(OldIrql
);
1881 /* Only disable the debugger if it is enabled */
1882 if (KdDebuggerEnabled
)
1885 * Disable the debugger; suspend breakpoints
1886 * and reset the debug stub
1888 KdpSuspendAllBreakPoints();
1889 KiDebugRoutine
= KdpStub
;
1891 /* We are disabled now */
1892 KdDebuggerEnabled
= FALSE
;
1893 #undef KdDebuggerEnabled
1894 SharedUserData
->KdDebuggerEnabled
= FALSE
;
1895 #define KdDebuggerEnabled _KdDebuggerEnabled
1899 /* Increment the disable count */
1902 /* Check if we had locked the port before */
1905 /* Yes, now unlock it */
1906 KeLowerIrql(OldIrql
);
1911 return STATUS_SUCCESS
;
1914 /* PUBLIC FUNCTIONS **********************************************************/
1921 KdEnableDebugger(VOID
)
1923 /* Use the internal routine */
1924 return KdEnableDebuggerWithLock(TRUE
);
1932 KdDisableDebugger(VOID
)
1934 /* Use the internal routine */
1935 return KdDisableDebuggerWithLock(TRUE
);
1943 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
1944 IN PVOID InputBuffer
,
1945 IN ULONG InputBufferLength
,
1946 OUT PVOID OutputBuffer
,
1947 IN ULONG OutputBufferLength
,
1948 IN OUT PULONG ReturnLength
,
1949 IN KPROCESSOR_MODE PreviousMode
)
1951 /* Local kernel debugging is not yet supported */
1952 DbgPrint("KdSystemDebugControl is unimplemented!\n");
1953 return STATUS_NOT_IMPLEMENTED
;
1961 KdChangeOption(IN KD_OPTION Option
,
1962 IN ULONG InBufferBytes OPTIONAL
,
1964 IN ULONG OutBufferBytes OPTIONAL
,
1965 OUT PVOID OutBuffer
,
1966 OUT PULONG OutBufferNeeded OPTIONAL
)
1968 /* Fail if there is no debugger */
1969 if (KdPitchDebugger
)
1971 /* No debugger, no options */
1972 return STATUS_DEBUGGER_INACTIVE
;
1975 /* Do we recognize this option? */
1976 if (Option
!= KD_OPTION_SET_BLOCK_ENABLE
)
1978 /* We don't, clear the output length and fail */
1979 if (OutBufferNeeded
) *OutBufferNeeded
= 0;
1980 return STATUS_INVALID_INFO_CLASS
;
1983 /* Verify parameters */
1984 if ((InBufferBytes
!= sizeof(BOOLEAN
)) ||
1985 (OutBufferBytes
!= 0) ||
1986 (OutBuffer
!= NULL
))
1988 /* Invalid parameters for this option, fail */
1989 return STATUS_INVALID_PARAMETER
;
1993 * Check if the high bit is set, meaning we don't
1994 * allow the debugger to be enabled
1996 if (KdBlockEnable
& 0x80)
1998 /* Fail regardless of what state the caller tried to set */
1999 return STATUS_ACCESS_VIOLATION
;
2002 /* Set the new block enable state */
2003 KdBlockEnable
= *(PBOOLEAN
)InBuffer
;
2005 /* No output buffer required for this option */
2006 if (OutBufferNeeded
) *OutBufferNeeded
= 0;
2009 return STATUS_SUCCESS
;
2017 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
2019 /* Check what power state this is */
2020 if (NewState
== PowerDeviceD0
)
2022 /* Wake up the debug port */
2024 return STATUS_SUCCESS
;
2026 else if ((NewState
== PowerDeviceD1
) ||
2027 (NewState
== PowerDeviceD2
) ||
2028 (NewState
== PowerDeviceD3
))
2030 /* Power down the debug port */
2032 return STATUS_SUCCESS
;
2036 /* Invalid state! */
2037 return STATUS_INVALID_PARAMETER_1
;
2046 KdRefreshDebuggerNotPresent(VOID
)
2048 BOOLEAN Enable
, DebuggerNotPresent
;
2050 /* Check if the debugger is completely disabled */
2051 if (KdPitchDebugger
)
2053 /* Don't try to refresh then -- fail early */
2057 /* Enter the debugger */
2058 Enable
= KdEnterDebugger(NULL
, NULL
);
2061 * Attempt to send a string to the debugger to refresh the
2064 KdpDprintf("KDTARGET: Refreshing KD connection\n");
2066 /* Save the state while we are holding the lock */
2067 DebuggerNotPresent
= KdDebuggerNotPresent
;
2069 /* Exit the debugger and return the state */
2070 KdExitDebugger(Enable
);
2071 return DebuggerNotPresent
;
2079 NtQueryDebugFilterState(IN ULONG ComponentId
,
2084 /* Check if the ID fits in the component table */
2085 if (ComponentId
< KdComponentTableSize
)
2087 /* It does, so get the mask from there */
2088 Mask
= KdComponentTable
[ComponentId
];
2090 else if (ComponentId
== MAXULONG
)
2093 * This is the internal ID used for DbgPrint messages without ID and
2094 * Level. Use the system-wide mask for those.
2096 Mask
= &Kd_WIN2000_Mask
;
2100 /* Invalid ID, fail */
2101 return STATUS_INVALID_PARAMETER_1
;
2104 /* Convert Level to bit field if necessary */
2105 if (Level
< 32) Level
= 1 << Level
;
2107 /* Determine if this Level is filtered out */
2108 if ((Kd_WIN2000_Mask
& Level
) ||
2111 /* This mask will get through to the debugger */
2112 return (NTSTATUS
)TRUE
;
2116 /* This mask is filtered out */
2117 return (NTSTATUS
)FALSE
;
2126 NtSetDebugFilterState(IN ULONG ComponentId
,
2132 /* Modifying debug filters requires the debug privilege */
2133 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
,
2134 ExGetPreviousMode()))
2137 return STATUS_ACCESS_DENIED
;
2140 /* Check if the ID fits in the component table */
2141 if (ComponentId
< KdComponentTableSize
)
2143 /* It does, so get the mask from there */
2144 Mask
= KdComponentTable
[ComponentId
];
2146 else if (ComponentId
== MAXULONG
)
2149 * This is the internal ID used for DbgPrint messages without ID and
2150 * Level. Use the system-wide mask for those.
2152 Mask
= &Kd_WIN2000_Mask
;
2156 /* Invalid ID, fail */
2157 return STATUS_INVALID_PARAMETER_1
;
2160 /* Convert Level to bit field if required */
2161 if (Level
< 32) Level
= 1 << Level
;
2163 /* Check what kind of operation this is */
2171 /* Remove the Level */
2176 return STATUS_SUCCESS
;