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
= 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
= 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 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
438 /* Send the packet */
439 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
447 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
451 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
454 /* Setup the header */
455 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
456 Header
.Buffer
= (PCHAR
)State
;
459 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
465 &WriteMemory
->ActualBytesWritten
);
467 /* Send the packet */
468 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
476 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
480 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
482 ULONG Length
= ReadMemory
->TransferCount
;
483 ULONG Flags
, CacheFlags
;
485 /* Setup the header */
486 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
487 Header
.Buffer
= (PCHAR
)State
;
488 ASSERT(Data
->Length
== 0);
490 /* Validate length */
491 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
493 /* Overflow, set it to maximum possible */
494 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
497 /* Start with the default flags */
498 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_PHYSICAL
;
500 /* Get the caching flags and check if a type is specified */
501 CacheFlags
= ReadMemory
->ActualBytesRead
;
502 if (CacheFlags
== DBGKD_CACHING_CACHED
)
505 Flags
|= MMDBG_COPY_CACHED
;
507 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
510 Flags
|= MMDBG_COPY_UNCACHED
;
512 else if (CacheFlags
== DBGKD_CACHING_WRITE_COMBINED
)
515 Flags
|= MMDBG_COPY_WRITE_COMBINED
;
519 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
526 /* Return the actual length read */
527 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
529 /* Send the packet */
530 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
538 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
542 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
544 ULONG Flags
, CacheFlags
;
546 /* Setup the header */
547 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
548 Header
.Buffer
= (PCHAR
)State
;
550 /* Start with the default flags */
551 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_WRITE
| MMDBG_COPY_PHYSICAL
;
553 /* Get the caching flags and check if a type is specified */
554 CacheFlags
= WriteMemory
->ActualBytesWritten
;
555 if (CacheFlags
== DBGKD_CACHING_CACHED
)
558 Flags
|= MMDBG_COPY_CACHED
;
560 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
563 Flags
|= MMDBG_COPY_UNCACHED
;
565 else if (CacheFlags
== DBGKD_CACHING_WRITE_COMBINED
)
568 Flags
|= MMDBG_COPY_WRITE_COMBINED
;
572 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
577 &WriteMemory
->ActualBytesWritten
);
579 /* Send the packet */
580 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
588 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
592 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
596 /* Setup the header */
597 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
598 Header
.Buffer
= (PCHAR
)State
;
599 ASSERT(Data
->Length
== 0);
601 /* Check the length requested */
602 Length
= ReadMemory
->TransferCount
;
603 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
605 /* Use maximum allowed */
606 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
609 /* Call the internal routine */
610 State
->ReturnStatus
= KdpSysReadControlSpace(State
->Processor
,
611 ReadMemory
->TargetBaseAddress
,
616 /* Return the actual length read */
617 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
620 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
628 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
632 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
635 /* Setup the header */
636 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
637 Header
.Buffer
= (PCHAR
)State
;
639 /* Call the internal routine */
640 State
->ReturnStatus
= KdpSysWriteControlSpace(State
->Processor
,
641 WriteMemory
->TargetBaseAddress
,
644 &WriteMemory
->ActualBytesWritten
);
647 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
655 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
660 PCONTEXT TargetContext
;
662 /* Setup the header */
663 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
664 Header
.Buffer
= (PCHAR
)State
;
665 ASSERT(Data
->Length
== 0);
667 /* Make sure that this is a valid request */
668 if (State
->Processor
< KeNumberProcessors
)
670 /* Check if the request is for this CPU */
671 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
673 /* We're just copying our own context */
674 TargetContext
= Context
;
678 /* Get the context from the PRCB array */
679 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
680 ProcessorState
.ContextFrame
;
683 /* Copy it over to the debugger */
684 RtlCopyMemory(Data
->Buffer
, TargetContext
, sizeof(CONTEXT
));
685 Data
->Length
= sizeof(CONTEXT
);
687 /* Let the debugger set the context now */
688 KdpContextSent
= TRUE
;
691 State
->ReturnStatus
= STATUS_SUCCESS
;
695 /* Invalid request */
696 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
700 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
708 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
713 PCONTEXT TargetContext
;
715 /* Setup the header */
716 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
717 Header
.Buffer
= (PCHAR
)State
;
718 ASSERT(Data
->Length
== sizeof(CONTEXT
));
720 /* Make sure that this is a valid request */
721 if ((State
->Processor
< KeNumberProcessors
) && (KdpContextSent
== TRUE
))
723 /* Check if the request is for this CPU */
724 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
726 /* We're just copying our own context */
727 TargetContext
= Context
;
731 /* Get the context from the PRCB array */
732 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
733 ProcessorState
.ContextFrame
;
736 /* Copy the new context to it */
737 RtlCopyMemory(TargetContext
, Data
->Buffer
, sizeof(CONTEXT
));
740 State
->ReturnStatus
= STATUS_SUCCESS
;
744 /* Invalid request */
745 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
749 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
757 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State
)
759 /* Crash with the special code */
760 KeBugCheck(MANUALLY_INITIATED_CRASH
);
765 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
770 PDBGKD_READ_WRITE_MSR ReadMsr
= &State
->u
.ReadWriteMsr
;
771 LARGE_INTEGER MsrValue
;
773 /* Setup the header */
774 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
775 Header
.Buffer
= (PCHAR
)State
;
776 ASSERT(Data
->Length
== 0);
778 /* Call the internal routine */
779 State
->ReturnStatus
= KdpSysReadMsr(ReadMsr
->Msr
,
782 /* Return the data */
783 ReadMsr
->DataValueLow
= MsrValue
.LowPart
;
784 ReadMsr
->DataValueHigh
= MsrValue
.HighPart
;
787 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
795 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
800 PDBGKD_READ_WRITE_MSR WriteMsr
= &State
->u
.ReadWriteMsr
;
801 LARGE_INTEGER MsrValue
;
803 /* Setup the header */
804 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
805 Header
.Buffer
= (PCHAR
)State
;
806 ASSERT(Data
->Length
== 0);
808 /* Call the internal routine */
809 MsrValue
.LowPart
= WriteMsr
->DataValueLow
;
810 MsrValue
.HighPart
= WriteMsr
->DataValueHigh
;
811 State
->ReturnStatus
= KdpSysWriteMsr(WriteMsr
->Msr
,
815 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
823 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
828 PDBGKD_GET_SET_BUS_DATA GetBusData
= &State
->u
.GetSetBusData
;
831 /* Setup the header */
832 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
833 Header
.Buffer
= (PCHAR
)State
;
834 ASSERT(Data
->Length
== 0);
836 /* Check the length requested */
837 Length
= GetBusData
->Length
;
838 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
840 /* Use maximum allowed */
841 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
844 /* Call the internal routine */
845 State
->ReturnStatus
= KdpSysReadBusData(GetBusData
->BusDataType
,
846 GetBusData
->BusNumber
,
847 GetBusData
->SlotNumber
,
853 /* Return the actual length read */
854 Data
->Length
= GetBusData
->Length
= Length
;
857 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
865 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
870 PDBGKD_GET_SET_BUS_DATA SetBusData
= &State
->u
.GetSetBusData
;
873 /* Setup the header */
874 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
875 Header
.Buffer
= (PCHAR
)State
;
877 /* Call the internal routine */
878 State
->ReturnStatus
= KdpSysWriteBusData(SetBusData
->BusDataType
,
879 SetBusData
->BusNumber
,
880 SetBusData
->SlotNumber
,
886 /* Return the actual length written */
887 SetBusData
->Length
= Length
;
890 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
898 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
903 PDBGKD_READ_WRITE_IO64 ReadIo
= &State
->u
.ReadWriteIo
;
905 /* Setup the header */
906 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
907 Header
.Buffer
= (PCHAR
)State
;
908 ASSERT(Data
->Length
== 0);
911 * Clear the value so 1 or 2 byte reads
912 * don't leave the higher bits unmodified
914 ReadIo
->DataValue
= 0;
916 /* Call the internal routine */
917 State
->ReturnStatus
= KdpSysReadIoSpace(Isa
,
926 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
934 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
939 PDBGKD_READ_WRITE_IO64 WriteIo
= &State
->u
.ReadWriteIo
;
941 /* Setup the header */
942 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
943 Header
.Buffer
= (PCHAR
)State
;
944 ASSERT(Data
->Length
== 0);
946 /* Call the internal routine */
947 State
->ReturnStatus
= KdpSysWriteIoSpace(Isa
,
956 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
964 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
969 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended
= &State
->u
.
972 /* Setup the header */
973 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
974 Header
.Buffer
= (PCHAR
)State
;
975 ASSERT(Data
->Length
== 0);
978 * Clear the value so 1 or 2 byte reads
979 * don't leave the higher bits unmodified
981 ReadIoExtended
->DataValue
= 0;
983 /* Call the internal routine */
984 State
->ReturnStatus
= KdpSysReadIoSpace(ReadIoExtended
->InterfaceType
,
985 ReadIoExtended
->BusNumber
,
986 ReadIoExtended
->AddressSpace
,
987 ReadIoExtended
->IoAddress
,
988 &ReadIoExtended
->DataValue
,
989 ReadIoExtended
->DataSize
,
990 &ReadIoExtended
->DataSize
);
993 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1001 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
1003 IN PCONTEXT Context
)
1006 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended
= &State
->u
.
1007 ReadWriteIoExtended
;
1009 /* Setup the header */
1010 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1011 Header
.Buffer
= (PCHAR
)State
;
1012 ASSERT(Data
->Length
== 0);
1014 /* Call the internal routine */
1015 State
->ReturnStatus
= KdpSysReadIoSpace(WriteIoExtended
->InterfaceType
,
1016 WriteIoExtended
->BusNumber
,
1017 WriteIoExtended
->AddressSpace
,
1018 WriteIoExtended
->IoAddress
,
1019 &WriteIoExtended
->DataValue
,
1020 WriteIoExtended
->DataSize
,
1021 &WriteIoExtended
->DataSize
);
1023 /* Send the reply */
1024 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1032 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State
)
1036 /* Setup the header */
1037 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1038 Header
.Buffer
= (PCHAR
)State
;
1040 /* Call the internal routine */
1041 State
->ReturnStatus
= KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE
);
1043 /* Send the reply */
1044 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1052 KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State
)
1057 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
1059 /* Setup the packet */
1060 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1061 Header
.Buffer
= (PCHAR
)State
;
1064 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1072 KdpSendWaitContinue(IN ULONG PacketType
,
1073 IN PSTRING SendHeader
,
1074 IN PSTRING SendData OPTIONAL
,
1075 IN OUT PCONTEXT Context
)
1077 STRING Data
, Header
;
1078 DBGKD_MANIPULATE_STATE64 ManipulateState
;
1082 /* Setup the Manipulate State structure */
1083 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
1084 Header
.Buffer
= (PCHAR
)&ManipulateState
;
1085 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
1086 Data
.Buffer
= KdpMessageBuffer
;
1089 * Reset the context state to ensure the debugger has received
1090 * the current context before it sets it
1092 KdpContextSent
= FALSE
;
1095 /* Send the Packet */
1096 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
1098 /* If the debugger isn't present anymore, just return success */
1099 if (KdDebuggerNotPresent
) return ContinueSuccess
;
1101 /* Main processing Loop */
1107 /* Wait to get a reply to our packet */
1108 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1114 /* If we got a resend request, do it */
1115 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
1116 } while (RecvCode
== KdPacketTimedOut
);
1118 /* Now check what API we got */
1119 switch (ManipulateState
.ApiNumber
)
1121 case DbgKdReadVirtualMemoryApi
:
1123 /* Read virtual memory */
1124 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
1127 case DbgKdWriteVirtualMemoryApi
:
1129 /* Write virtual memory */
1130 KdpWriteVirtualMemory(&ManipulateState
, &Data
, Context
);
1133 case DbgKdGetContextApi
:
1135 /* Get the current context */
1136 KdpGetContext(&ManipulateState
, &Data
, Context
);
1139 case DbgKdSetContextApi
:
1141 /* Set a new context */
1142 KdpSetContext(&ManipulateState
, &Data
, Context
);
1145 case DbgKdWriteBreakPointApi
:
1147 /* Write the breakpoint */
1148 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
1151 case DbgKdRestoreBreakPointApi
:
1153 /* Restore the breakpoint */
1154 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
1157 case DbgKdContinueApi
:
1159 /* Simply continue */
1160 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
1162 case DbgKdReadControlSpaceApi
:
1164 /* Read control space */
1165 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
1168 case DbgKdWriteControlSpaceApi
:
1170 /* Write control space */
1171 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
1174 case DbgKdReadIoSpaceApi
:
1176 /* Read I/O Space */
1177 KdpReadIoSpace(&ManipulateState
, &Data
, Context
);
1180 case DbgKdWriteIoSpaceApi
:
1182 /* Write I/O Space */
1183 KdpWriteIoSpace(&ManipulateState
, &Data
, Context
);
1186 case DbgKdRebootApi
:
1188 /* Reboot the system */
1189 HalReturnToFirmware(HalRebootRoutine
);
1192 case DbgKdContinueApi2
:
1194 /* Check if caller reports success */
1195 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
1197 /* Update the state */
1198 KdpGetStateChange(&ManipulateState
, Context
);
1199 return ContinueSuccess
;
1203 /* Return an error */
1204 return ContinueError
;
1207 case DbgKdReadPhysicalMemoryApi
:
1209 /* Read physical memory */
1210 KdpReadPhysicalmemory(&ManipulateState
, &Data
, Context
);
1213 case DbgKdWritePhysicalMemoryApi
:
1215 /* Write physical memory */
1216 KdpWritePhysicalmemory(&ManipulateState
, &Data
, Context
);
1219 case DbgKdQuerySpecialCallsApi
:
1220 case DbgKdSetSpecialCallApi
:
1221 case DbgKdClearSpecialCallsApi
:
1224 KdpDprintf("Special Call support is unimplemented!\n");
1225 KdpNotSupported(&ManipulateState
);
1228 case DbgKdSetInternalBreakPointApi
:
1229 case DbgKdGetInternalBreakPointApi
:
1232 KdpDprintf("Internal Breakpoint support is unimplemented!\n");
1233 KdpNotSupported(&ManipulateState
);
1236 case DbgKdReadIoSpaceExtendedApi
:
1238 /* Read I/O Space */
1239 KdpReadIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1242 case DbgKdWriteIoSpaceExtendedApi
:
1244 /* Write I/O Space */
1245 KdpWriteIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1248 case DbgKdGetVersionApi
:
1250 /* Get version data */
1251 KdpGetVersion(&ManipulateState
);
1254 case DbgKdWriteBreakPointExApi
:
1256 /* Write the breakpoint and check if it failed */
1257 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState
,
1261 /* Return an error */
1262 return ContinueError
;
1266 case DbgKdRestoreBreakPointExApi
:
1268 /* Restore the breakpoint */
1269 KdpRestoreBreakPointEx(&ManipulateState
, &Data
, Context
);
1272 case DbgKdCauseBugCheckApi
:
1274 /* Crash the system */
1275 KdpCauseBugCheck(&ManipulateState
);
1278 case DbgKdSwitchProcessor
:
1281 KdpDprintf("Processor Switch support is unimplemented!\n");
1282 KdpNotSupported(&ManipulateState
);
1285 case DbgKdPageInApi
:
1288 KdpDprintf("Page-In support is unimplemented!\n");
1289 KdpNotSupported(&ManipulateState
);
1292 case DbgKdReadMachineSpecificRegister
:
1294 /* Read from the specified MSR */
1295 KdpReadMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1298 case DbgKdWriteMachineSpecificRegister
:
1300 /* Write to the specified MSR */
1301 KdpWriteMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1304 case DbgKdSearchMemoryApi
:
1307 KdpSearchMemory(&ManipulateState
, &Data
, Context
);
1310 case DbgKdGetBusDataApi
:
1312 /* Read from the bus */
1313 KdpGetBusData(&ManipulateState
, &Data
, Context
);
1316 case DbgKdSetBusDataApi
:
1318 /* Write to the bus */
1319 KdpSetBusData(&ManipulateState
, &Data
, Context
);
1322 case DbgKdCheckLowMemoryApi
:
1324 /* Check for memory corruption in the lower 4 GB */
1325 KdpCheckLowMemory(&ManipulateState
);
1328 case DbgKdClearAllInternalBreakpointsApi
:
1330 /* Just clear the counter */
1331 KdpNumInternalBreakpoints
= 0;
1334 case DbgKdFillMemoryApi
:
1337 KdpFillMemory(&ManipulateState
, &Data
, Context
);
1340 case DbgKdQueryMemoryApi
:
1343 KdpQueryMemory(&ManipulateState
, Context
);
1346 case DbgKdSwitchPartition
:
1349 KdpDprintf("Partition Switch support is unimplemented!\n");
1350 KdpNotSupported(&ManipulateState
);
1353 /* Unsupported Message */
1356 /* Setup an empty message, with failure */
1357 KdpDprintf("Received Unhandled API %lx\n", ManipulateState
.ApiNumber
);
1359 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
1362 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1373 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
1374 IN PKD_SYMBOLS_INFO SymbolInfo
,
1376 IN OUT PCONTEXT Context
)
1379 STRING Data
, Header
;
1380 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1381 ULONG PathNameLength
;
1382 KCONTINUE_STATUS Status
;
1384 /* Start wait loop */
1387 /* Build the architecture common parts of the message */
1388 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
1392 /* Now finish creating the structure */
1393 KdpSetContextState(&WaitStateChange
, Context
);
1395 /* Fill out load data */
1396 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
1397 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONG64
)(LONG_PTR
)SymbolInfo
->BaseOfDll
;
1398 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
1399 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
1400 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
1402 /* Check if we have a path name */
1405 /* Copy it to the path buffer */
1406 KdpCopyMemoryChunks((ULONG_PTR
)PathName
->Buffer
,
1413 /* Null terminate */
1414 KdpPathBuffer
[PathNameLength
++] = ANSI_NULL
;
1416 /* Set the path length */
1417 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathNameLength
;
1419 /* Set up the data */
1420 Data
.Buffer
= KdpPathBuffer
;
1421 Data
.Length
= PathNameLength
;
1427 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
1431 /* Setup the header */
1432 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1433 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1435 /* Send the packet */
1436 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1440 } while (Status
== ContinueProcessorReselected
);
1445 KdpReportCommandStringStateChange(IN PSTRING NameString
,
1446 IN PSTRING CommandString
,
1447 IN OUT PCONTEXT Context
)
1449 STRING Header
, Data
;
1450 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1451 ULONG Length
, ActualLength
, TotalLength
;
1452 KCONTINUE_STATUS Status
;
1454 /* Start wait loop */
1457 /* Build the architecture common parts of the message */
1458 KdpSetCommonState(DbgKdCommandStringStateChange
,
1462 /* Set the context */
1463 KdpSetContextState(&WaitStateChange
, Context
);
1465 /* Clear the command string structure */
1466 RtlZeroMemory(&WaitStateChange
.u
.CommandString
,
1467 sizeof(DBGKD_COMMAND_STRING
));
1469 /* Normalize name string to max */
1470 Length
= min(128 - 1, NameString
->Length
);
1472 /* Copy it to the message buffer */
1473 KdpCopyMemoryChunks((ULONG_PTR
)NameString
->Buffer
,
1480 /* Null terminate and calculate the total length */
1481 TotalLength
= ActualLength
;
1482 KdpMessageBuffer
[TotalLength
++] = ANSI_NULL
;
1484 /* Check if the command string is too long */
1485 Length
= CommandString
->Length
;
1486 if (Length
> (PACKET_MAX_SIZE
-
1487 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
) - TotalLength
))
1489 /* Use maximum possible size */
1490 Length
= (PACKET_MAX_SIZE
-
1491 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
) - TotalLength
);
1494 /* Copy it to the message buffer */
1495 KdpCopyMemoryChunks((ULONG_PTR
)CommandString
->Buffer
,
1496 KdpMessageBuffer
+ TotalLength
,
1502 /* Null terminate and calculate the total length */
1503 TotalLength
+= ActualLength
;
1504 KdpMessageBuffer
[TotalLength
++] = ANSI_NULL
;
1506 /* Now set up the header and the data */
1507 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1508 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1509 Data
.Length
= TotalLength
;
1510 Data
.Buffer
= KdpMessageBuffer
;
1512 /* Send State Change packet and wait for a reply */
1513 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1517 } while (Status
== ContinueProcessorReselected
);
1522 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
1523 IN OUT PCONTEXT Context
,
1524 IN BOOLEAN SecondChanceException
)
1526 STRING Header
, Data
;
1527 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1528 KCONTINUE_STATUS Status
;
1530 /* Start report loop */
1533 /* Build the architecture common parts of the message */
1534 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
1536 /* Copy the Exception Record and set First Chance flag */
1537 #if !defined(_WIN64)
1538 ExceptionRecord32To64((PEXCEPTION_RECORD32
)ExceptionRecord
,
1539 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
1541 RtlCopyMemory(&WaitStateChange
.u
.Exception
.ExceptionRecord
,
1543 sizeof(EXCEPTION_RECORD
));
1545 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
1547 /* Now finish creating the structure */
1548 KdpSetContextState(&WaitStateChange
, Context
);
1550 /* Setup the actual header to send to KD */
1551 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1552 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1554 /* Setup the trace data */
1555 DumpTraceData(&Data
);
1557 /* Send State Change packet and wait for a reply */
1558 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1562 } while (Status
== ContinueProcessorReselected
);
1570 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
1571 IN PVOID DeferredContext
,
1572 IN PVOID SystemArgument1
,
1573 IN PVOID SystemArgument2
)
1575 LONG OldSlip
, NewSlip
, PendingSlip
;
1577 /* Get the current pending slip */
1578 PendingSlip
= KdpTimeSlipPending
;
1581 /* Save the old value and either disable or enable it now. */
1582 OldSlip
= PendingSlip
;
1583 NewSlip
= OldSlip
> 1 ? 1 : 0;
1585 /* Try to change the value */
1586 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1588 OldSlip
) != OldSlip
);
1590 /* If the New Slip value is 1, then do the Time Slipping */
1591 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1596 KdpTimeSlipWork(IN PVOID Context
)
1599 LARGE_INTEGER DueTime
;
1601 /* Update the System time from the CMOS */
1602 ExAcquireTimeRefreshLock(FALSE
);
1603 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1604 ExReleaseTimeRefreshLock();
1606 /* Check if we have a registered Time Slip Event and signal it */
1607 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
1608 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
1609 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
1611 /* Delay the DPC until it runs next time */
1612 DueTime
.QuadPart
= -1800000000;
1613 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1618 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1619 IN OUT PCONTEXT ContextRecord
,
1620 IN BOOLEAN SecondChanceException
)
1624 /* Save the port data */
1627 /* Report a state change */
1628 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1630 SecondChanceException
);
1632 /* Restore the port data and return */
1639 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1641 LARGE_INTEGER Null
= {{0}};
1643 /* Check if interrupts were disabled */
1644 if (!KeGetTrapFrameInterruptState(TrapFrame
))
1646 /* Nothing to return */
1650 /* Otherwise, do the call */
1651 return KeQueryPerformanceCounter(NULL
);
1656 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1657 IN PKEXCEPTION_FRAME ExceptionFrame
)
1661 /* Check if we have a trap frame */
1664 /* Calculate the time difference for the enter */
1665 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1666 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1667 KdTimerStart
.QuadPart
;
1671 /* No trap frame, so can't calculate */
1672 KdTimerStop
.QuadPart
= 0;
1675 /* Save the current IRQL */
1676 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1678 /* Freeze all CPUs */
1679 Enable
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1681 /* Lock the port, save the state and set debugger entered */
1682 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1684 KdEnteredDebugger
= TRUE
;
1686 /* Check freeze flag */
1687 if (KiFreezeFlag
& 1)
1689 /* Print out errror */
1690 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1693 /* Check processor state */
1694 if (KiFreezeFlag
& 2)
1696 /* Print out errror */
1697 KdpDprintf("Some processors not frozen in debugger!\n");
1700 /* Make sure we acquired the port */
1701 if (!KdpPortLocked
) KdpDprintf("Port lock was not acquired!\n");
1703 /* Return if interrupts needs to be re-enabled */
1709 KdExitDebugger(IN BOOLEAN Enable
)
1713 /* Restore the state and unlock the port */
1715 if (KdpPortLocked
) KdpPortUnlock();
1717 /* Unfreeze the CPUs */
1718 KeThawExecution(Enable
);
1720 /* Compare time with the one from KdEnterDebugger */
1721 if (!KdTimerStop
.QuadPart
)
1723 /* We didn't get a trap frame earlier in so never got the time */
1724 KdTimerStart
= KdTimerStop
;
1728 /* Query the timer */
1729 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1732 /* Check if a Time Slip was on queue */
1733 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1736 /* Queue a DPC for the time slip */
1737 InterlockedIncrement(&KdpTimeSlipPending
);
1738 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
);
1744 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock
)
1748 #if defined(__GNUC__)
1749 /* Make gcc happy */
1750 OldIrql
= PASSIVE_LEVEL
;
1753 /* Check if enabling the debugger is blocked */
1756 /* It is, fail the enable */
1757 return STATUS_ACCESS_DENIED
;
1760 /* Check if we need to acquire the lock */
1764 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1768 /* Check if we're not disabled */
1769 if (!KdDisableCount
)
1771 /* Check if we had locked the port before */
1775 KeLowerIrql(OldIrql
);
1778 /* Fail: We're already enabled */
1779 return STATUS_INVALID_PARAMETER
;
1784 * This can only happen if we are called from a bugcheck
1785 * and were never initialized, so initialize the debugger now.
1787 KdInitSystem(0, NULL
);
1789 /* Return success since we initialized */
1790 return STATUS_SUCCESS
;
1794 /* Decrease the disable count */
1795 if (!(--KdDisableCount
))
1797 /* We're now enabled again! Were we enabled before, too? */
1798 if (KdPreviouslyEnabled
)
1800 /* Reinitialize the Debugger */
1801 KdInitSystem(0, NULL
) ;
1802 KdpRestoreAllBreakpoints();
1806 /* Check if we had locked the port before */
1809 /* Yes, now unlock it */
1810 KeLowerIrql(OldIrql
);
1815 return STATUS_SUCCESS
;
1820 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock
)
1825 #if defined(__GNUC__)
1826 /* Make gcc happy */
1827 OldIrql
= PASSIVE_LEVEL
;
1831 * If enabling the debugger is blocked
1832 * then there is nothing to disable (duh)
1837 return STATUS_ACCESS_DENIED
;
1840 /* Check if we need to acquire the lock */
1844 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1848 /* Check if we're not disabled */
1849 if (!KdDisableCount
)
1851 /* Check if the debugger was never actually initialized */
1852 if (!(KdDebuggerEnabled
) && !(KdPitchDebugger
))
1854 /* It wasn't, so don't re-enable it later */
1855 KdPreviouslyEnabled
= FALSE
;
1859 /* It was, so we will re-enable it later */
1860 KdPreviouslyEnabled
= TRUE
;
1863 /* Check if we were called from the exported API and are enabled */
1864 if ((NeedLock
) && (KdPreviouslyEnabled
))
1866 /* Check if it is safe to disable the debugger */
1867 Status
= KdpAllowDisable();
1868 if (!NT_SUCCESS(Status
))
1870 /* Release the lock and fail */
1871 KeLowerIrql(OldIrql
);
1877 /* Only disable the debugger if it is enabled */
1878 if (KdDebuggerEnabled
)
1881 * Disable the debugger; suspend breakpoints
1882 * and reset the debug stub
1884 KdpSuspendAllBreakPoints();
1885 KiDebugRoutine
= KdpStub
;
1887 /* We are disabled now */
1888 KdDebuggerEnabled
= FALSE
;
1889 #undef KdDebuggerEnabled
1890 SharedUserData
->KdDebuggerEnabled
= FALSE
;
1891 #define KdDebuggerEnabled _KdDebuggerEnabled
1895 /* Increment the disable count */
1898 /* Check if we had locked the port before */
1901 /* Yes, now unlock it */
1902 KeLowerIrql(OldIrql
);
1907 return STATUS_SUCCESS
;
1910 /* PUBLIC FUNCTIONS **********************************************************/
1917 KdEnableDebugger(VOID
)
1919 /* Use the internal routine */
1920 return KdEnableDebuggerWithLock(TRUE
);
1928 KdDisableDebugger(VOID
)
1930 /* Use the internal routine */
1931 return KdDisableDebuggerWithLock(TRUE
);
1939 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
1940 IN PVOID InputBuffer
,
1941 IN ULONG InputBufferLength
,
1942 OUT PVOID OutputBuffer
,
1943 IN ULONG OutputBufferLength
,
1944 IN OUT PULONG ReturnLength
,
1945 IN KPROCESSOR_MODE PreviousMode
)
1947 /* Local kernel debugging is not yet supported */
1948 DbgPrint("KdSystemDebugControl is unimplemented!\n");
1949 return STATUS_NOT_IMPLEMENTED
;
1957 KdChangeOption(IN KD_OPTION Option
,
1958 IN ULONG InBufferBytes OPTIONAL
,
1960 IN ULONG OutBufferBytes OPTIONAL
,
1961 OUT PVOID OutBuffer
,
1962 OUT PULONG OutBufferNeeded OPTIONAL
)
1964 /* Fail if there is no debugger */
1965 if (KdPitchDebugger
)
1967 /* No debugger, no options */
1968 return STATUS_DEBUGGER_INACTIVE
;
1971 /* Do we recognize this option? */
1972 if (Option
!= KD_OPTION_SET_BLOCK_ENABLE
)
1974 /* We don't, clear the output length and fail */
1975 if (OutBufferNeeded
) *OutBufferNeeded
= 0;
1976 return STATUS_INVALID_INFO_CLASS
;
1979 /* Verify parameters */
1980 if ((InBufferBytes
!= sizeof(BOOLEAN
)) ||
1981 (OutBufferBytes
!= 0) ||
1982 (OutBuffer
!= NULL
))
1984 /* Invalid parameters for this option, fail */
1985 return STATUS_INVALID_PARAMETER
;
1989 * Check if the high bit is set, meaning we don't
1990 * allow the debugger to be enabled
1992 if (KdBlockEnable
& 0x80)
1994 /* Fail regardless of what state the caller tried to set */
1995 return STATUS_ACCESS_VIOLATION
;
1998 /* Set the new block enable state */
1999 KdBlockEnable
= *(PBOOLEAN
)InBuffer
;
2001 /* No output buffer required for this option */
2002 if (OutBufferNeeded
) *OutBufferNeeded
= 0;
2005 return STATUS_SUCCESS
;
2013 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
2015 /* Check what power state this is */
2016 if (NewState
== PowerDeviceD0
)
2018 /* Wake up the debug port */
2020 return STATUS_SUCCESS
;
2022 else if ((NewState
== PowerDeviceD1
) ||
2023 (NewState
== PowerDeviceD2
) ||
2024 (NewState
== PowerDeviceD3
))
2026 /* Power down the debug port */
2028 return STATUS_SUCCESS
;
2032 /* Invalid state! */
2033 return STATUS_INVALID_PARAMETER_1
;
2042 KdRefreshDebuggerNotPresent(VOID
)
2044 BOOLEAN Enable
, DebuggerNotPresent
;
2046 /* Check if the debugger is completely disabled */
2047 if (KdPitchDebugger
)
2049 /* Don't try to refresh then -- fail early */
2053 /* Enter the debugger */
2054 Enable
= KdEnterDebugger(NULL
, NULL
);
2057 * Attempt to send a string to the debugger to refresh the
2060 KdpDprintf("KDTARGET: Refreshing KD connection\n");
2062 /* Save the state while we are holding the lock */
2063 DebuggerNotPresent
= KdDebuggerNotPresent
;
2065 /* Exit the debugger and return the state */
2066 KdExitDebugger(Enable
);
2067 return DebuggerNotPresent
;
2075 NtQueryDebugFilterState(IN ULONG ComponentId
,
2080 /* Check if the ID fits in the component table */
2081 if (ComponentId
< KdComponentTableSize
)
2083 /* It does, so get the mask from there */
2084 Mask
= KdComponentTable
[ComponentId
];
2086 else if (ComponentId
== MAXULONG
)
2089 * This is the internal ID used for DbgPrint messages without ID and
2090 * Level. Use the system-wide mask for those.
2092 Mask
= &Kd_WIN2000_Mask
;
2096 /* Invalid ID, fail */
2097 return STATUS_INVALID_PARAMETER_1
;
2100 /* Convert Level to bit field if necessary */
2101 if (Level
< 32) Level
= 1 << Level
;
2103 /* Determine if this Level is filtered out */
2104 if ((Kd_WIN2000_Mask
& Level
) ||
2107 /* This mask will get through to the debugger */
2108 return (NTSTATUS
)TRUE
;
2112 /* This mask is filtered out */
2113 return (NTSTATUS
)FALSE
;
2122 NtSetDebugFilterState(IN ULONG ComponentId
,
2128 /* Modifying debug filters requires the debug privilege */
2129 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
,
2130 ExGetPreviousMode()))
2133 return STATUS_ACCESS_DENIED
;
2136 /* Check if the ID fits in the component table */
2137 if (ComponentId
< KdComponentTableSize
)
2139 /* It does, so get the mask from there */
2140 Mask
= KdComponentTable
[ComponentId
];
2142 else if (ComponentId
== MAXULONG
)
2145 * This is the internal ID used for DbgPrint messages without ID and
2146 * Level. Use the system-wide mask for those.
2148 Mask
= &Kd_WIN2000_Mask
;
2152 /* Invalid ID, fail */
2153 return STATUS_INVALID_PARAMETER_1
;
2156 /* Convert Level to bit field if required */
2157 if (Level
< 32) Level
= 1 << Level
;
2159 /* Check what kind of operation this is */
2167 /* Remove the Level */
2172 return STATUS_SUCCESS
;