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 /* FIXME: Check if it's session space */
116 Memory
->AddressSpace
= DBGKD_QUERY_MEMORY_KERNEL
;
120 Memory
->Flags
= DBGKD_QUERY_MEMORY_READ
|
121 DBGKD_QUERY_MEMORY_WRITE
|
122 DBGKD_QUERY_MEMORY_EXECUTE
;
127 Status
= STATUS_INVALID_PARAMETER
;
130 /* Return structure */
131 State
->ReturnStatus
= Status
;
132 Memory
->Reserved
= 0;
135 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
136 Header
.Buffer
= (PCHAR
)State
;
138 /* Send the packet */
139 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
147 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
151 //PDBGKD_SEARCH_MEMORY SearchMemory = &State->u.SearchMemory;
155 KdpDprintf("Memory Search support is unimplemented!\n");
157 /* Send a failure packet */
158 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
159 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
160 Header
.Buffer
= (PCHAR
)State
;
161 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
169 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
173 //PDBGKD_FILL_MEMORY FillMemory = &State->u.FillMemory;
177 KdpDprintf("Memory Fill support is unimplemented!\n");
179 /* Send a failure packet */
180 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
181 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
182 Header
.Buffer
= (PCHAR
)State
;
183 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
191 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
195 PDBGKD_WRITE_BREAKPOINT64 Breakpoint
= &State
->u
.WriteBreakPoint
;
199 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
200 Header
.Buffer
= (PCHAR
)State
;
201 ASSERT(Data
->Length
== 0);
203 /* Create the breakpoint */
204 Breakpoint
->BreakPointHandle
=
205 KdpAddBreakpoint((PVOID
)(ULONG_PTR
)Breakpoint
->BreakPointAddress
);
206 if (!Breakpoint
->BreakPointHandle
)
209 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
214 State
->ReturnStatus
= STATUS_SUCCESS
;
217 /* Send the packet */
218 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
226 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State
,
230 PDBGKD_RESTORE_BREAKPOINT RestoreBp
= &State
->u
.RestoreBreakPoint
;
233 /* Fill out the header */
234 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
235 Header
.Buffer
= (PCHAR
)State
;
236 ASSERT(Data
->Length
== 0);
238 /* Get the version block */
239 if (KdpDeleteBreakpoint(RestoreBp
->BreakPointHandle
))
242 State
->ReturnStatus
= STATUS_SUCCESS
;
247 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
250 /* Send the packet */
251 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
259 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
263 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
267 KdpDprintf("Extended Breakpoint Write support is unimplemented!\n");
269 /* Send a failure packet */
270 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
271 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
272 Header
.Buffer
= (PCHAR
)State
;
273 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
277 return STATUS_UNSUCCESSFUL
;
282 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State
,
286 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
290 KdpDprintf("Extended Breakpoint Restore support is unimplemented!\n");
292 /* Send a failure packet */
293 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
294 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
295 Header
.Buffer
= (PCHAR
)State
;
296 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
304 DumpTraceData(IN PSTRING TraceData
)
306 /* Update the buffer */
307 TraceDataBuffer
[0] = TraceDataBufferPosition
;
309 /* Setup the trace data */
310 TraceData
->Length
= TraceDataBufferPosition
* sizeof(ULONG
);
311 TraceData
->Buffer
= (PCHAR
)TraceDataBuffer
;
313 /* Reset the buffer location */
314 TraceDataBufferPosition
= 1;
319 KdpSetCommonState(IN ULONG NewState
,
321 IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
)
323 ULONG InstructionCount
;
324 BOOLEAN HadBreakpoints
;
326 /* Setup common stuff available for all CPU architectures */
327 WaitStateChange
->NewState
= NewState
;
328 WaitStateChange
->ProcessorLevel
= KeProcessorLevel
;
329 WaitStateChange
->Processor
= (USHORT
)KeGetCurrentPrcb()->Number
;
330 WaitStateChange
->NumberProcessors
= (ULONG
)KeNumberProcessors
;
331 WaitStateChange
->Thread
= (ULONG64
)(LONG_PTR
)KeGetCurrentThread();
332 WaitStateChange
->ProgramCounter
= (ULONG64
)(LONG_PTR
)KeGetContextPc(Context
);
334 /* Zero out the entire Control Report */
335 RtlZeroMemory(&WaitStateChange
->AnyControlReport
,
336 sizeof(DBGKD_ANY_CONTROL_REPORT
));
338 /* Now copy the instruction stream and set the count */
339 KdpCopyMemoryChunks((ULONG_PTR
)WaitStateChange
->ProgramCounter
,
340 &WaitStateChange
->ControlReport
.InstructionStream
[0],
345 WaitStateChange
->ControlReport
.InstructionCount
= InstructionCount
;
347 /* Clear all the breakpoints in this region */
349 KdpDeleteBreakpointRange((PVOID
)(ULONG_PTR
)WaitStateChange
->ProgramCounter
,
350 (PVOID
)((ULONG_PTR
)WaitStateChange
->ProgramCounter
+
351 WaitStateChange
->ControlReport
.InstructionCount
- 1));
354 /* Copy the instruction stream again, this time without breakpoints */
355 KdpCopyMemoryChunks((ULONG_PTR
)WaitStateChange
->ProgramCounter
,
356 &WaitStateChange
->ControlReport
.InstructionStream
[0],
366 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version
)
368 /* Copy the version block */
369 RtlCopyMemory(Version
, &KdVersionBlock
, sizeof(DBGKD_GET_VERSION64
));
374 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State
)
378 /* Fill out the header */
379 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
380 Header
.Buffer
= (PCHAR
)State
;
382 /* Get the version block */
383 KdpSysGetVersion(&State
->u
.GetVersion64
);
385 /* Fill out the state */
386 State
->ApiNumber
= DbgKdGetVersionApi
;
387 State
->ReturnStatus
= STATUS_SUCCESS
;
389 /* Send the packet */
390 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
398 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
402 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
404 ULONG Length
= ReadMemory
->TransferCount
;
406 /* Setup the header */
407 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
408 Header
.Buffer
= (PCHAR
)State
;
409 ASSERT(Data
->Length
== 0);
411 /* Validate length */
412 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
414 /* Overflow, set it to maximum possible */
415 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
419 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
426 /* Return the actual length read */
427 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
429 /* Send the packet */
430 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
438 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State
,
442 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
445 /* Setup the header */
446 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
447 Header
.Buffer
= (PCHAR
)State
;
450 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
456 &WriteMemory
->ActualBytesWritten
);
458 /* Send the packet */
459 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
467 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
471 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
473 ULONG Length
= ReadMemory
->TransferCount
;
474 ULONG Flags
, CacheFlags
;
476 /* Setup the header */
477 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
478 Header
.Buffer
= (PCHAR
)State
;
479 ASSERT(Data
->Length
== 0);
481 /* Validate length */
482 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
484 /* Overflow, set it to maximum possible */
485 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
488 /* Start with the default flags */
489 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_PHYSICAL
;
491 /* Get the caching flags and check if a type is specified */
492 CacheFlags
= ReadMemory
->ActualBytesRead
;
493 if (CacheFlags
== DBGKD_CACHING_CACHED
)
496 Flags
|= MMDBG_COPY_CACHED
;
498 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
501 Flags
|= MMDBG_COPY_UNCACHED
;
503 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
506 Flags
|= DBGKD_CACHING_WRITE_COMBINED
;
510 State
->ReturnStatus
= KdpCopyMemoryChunks(ReadMemory
->TargetBaseAddress
,
517 /* Return the actual length read */
518 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
520 /* Send the packet */
521 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
529 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State
,
533 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
535 ULONG Flags
, CacheFlags
;
537 /* Setup the header */
538 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
539 Header
.Buffer
= (PCHAR
)State
;
541 /* Start with the default flags */
542 Flags
= MMDBG_COPY_UNSAFE
| MMDBG_COPY_WRITE
| MMDBG_COPY_PHYSICAL
;
544 /* Get the caching flags and check if a type is specified */
545 CacheFlags
= WriteMemory
->ActualBytesWritten
;
546 if (CacheFlags
== DBGKD_CACHING_CACHED
)
549 Flags
|= MMDBG_COPY_CACHED
;
551 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
554 Flags
|= MMDBG_COPY_UNCACHED
;
556 else if (CacheFlags
== DBGKD_CACHING_UNCACHED
)
559 Flags
|= DBGKD_CACHING_WRITE_COMBINED
;
563 State
->ReturnStatus
= KdpCopyMemoryChunks(WriteMemory
->TargetBaseAddress
,
568 &WriteMemory
->ActualBytesWritten
);
570 /* Send the packet */
571 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
579 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
583 PDBGKD_READ_MEMORY64 ReadMemory
= &State
->u
.ReadMemory
;
587 /* Setup the header */
588 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
589 Header
.Buffer
= (PCHAR
)State
;
590 ASSERT(Data
->Length
== 0);
592 /* Check the length requested */
593 Length
= ReadMemory
->TransferCount
;
594 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
596 /* Use maximum allowed */
597 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
600 /* Call the internal routine */
601 State
->ReturnStatus
= KdpSysReadControlSpace(State
->Processor
,
602 ReadMemory
->TargetBaseAddress
,
607 /* Return the actual length read */
608 Data
->Length
= ReadMemory
->ActualBytesRead
= Length
;
611 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
619 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
623 PDBGKD_WRITE_MEMORY64 WriteMemory
= &State
->u
.WriteMemory
;
626 /* Setup the header */
627 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
628 Header
.Buffer
= (PCHAR
)State
;
630 /* Call the internal routine */
631 State
->ReturnStatus
= KdpSysWriteControlSpace(State
->Processor
,
632 WriteMemory
->TargetBaseAddress
,
635 &WriteMemory
->ActualBytesWritten
);
638 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
646 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
651 PCONTEXT TargetContext
;
653 /* Setup the header */
654 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
655 Header
.Buffer
= (PCHAR
)State
;
656 ASSERT(Data
->Length
== 0);
658 /* Make sure that this is a valid request */
659 if (State
->Processor
< KeNumberProcessors
)
661 /* Check if the request is for this CPU */
662 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
664 /* We're just copying our own context */
665 TargetContext
= Context
;
669 /* Get the context from the PRCB array */
670 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
671 ProcessorState
.ContextFrame
;
675 RtlCopyMemory(Data
->Buffer
, TargetContext
, sizeof(CONTEXT
));
676 Data
->Length
= sizeof(CONTEXT
);
678 /* Let the debugger set the context now */
679 KdpContextSent
= TRUE
;
682 State
->ReturnStatus
= STATUS_SUCCESS
;
686 /* Invalid request */
687 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
691 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
699 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State
,
704 PCONTEXT TargetContext
;
706 /* Setup the header */
707 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
708 Header
.Buffer
= (PCHAR
)State
;
709 ASSERT(Data
->Length
== sizeof(CONTEXT
));
711 /* Make sure that this is a valid request */
712 if ((State
->Processor
< KeNumberProcessors
) && (KdpContextSent
== TRUE
))
714 /* Check if the request is for this CPU */
715 if (State
->Processor
== KeGetCurrentPrcb()->Number
)
717 /* We're just copying our own context */
718 TargetContext
= Context
;
722 /* Get the context from the PRCB array */
723 TargetContext
= &KiProcessorBlock
[State
->Processor
]->
724 ProcessorState
.ContextFrame
;
727 /* Get the context from the PRCB array */
728 RtlCopyMemory(TargetContext
, Data
->Buffer
, sizeof(CONTEXT
));
731 State
->ReturnStatus
= STATUS_SUCCESS
;
735 /* Invalid request */
736 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
740 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
748 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State
)
750 /* Crash with the special code */
751 KeBugCheck(MANUALLY_INITIATED_CRASH
);
756 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
761 PDBGKD_READ_WRITE_MSR ReadMsr
= &State
->u
.ReadWriteMsr
;
762 LARGE_INTEGER MsrValue
;
764 /* Setup the header */
765 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
766 Header
.Buffer
= (PCHAR
)State
;
767 ASSERT(Data
->Length
== 0);
769 /* Call the internal routine */
770 State
->ReturnStatus
= KdpSysReadMsr(ReadMsr
->Msr
,
773 /* Return the data */
774 ReadMsr
->DataValueLow
= MsrValue
.LowPart
;
775 ReadMsr
->DataValueHigh
= MsrValue
.HighPart
;
778 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
786 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State
,
791 PDBGKD_READ_WRITE_MSR WriteMsr
= &State
->u
.ReadWriteMsr
;
792 LARGE_INTEGER MsrValue
;
794 /* Setup the header */
795 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
796 Header
.Buffer
= (PCHAR
)State
;
797 ASSERT(Data
->Length
== 0);
799 /* Call the internal routine */
800 MsrValue
.LowPart
= WriteMsr
->DataValueLow
;
801 MsrValue
.HighPart
= WriteMsr
->DataValueHigh
;
802 State
->ReturnStatus
= KdpSysWriteMsr(WriteMsr
->Msr
,
806 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
814 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
819 PDBGKD_GET_SET_BUS_DATA GetBusData
= &State
->u
.GetSetBusData
;
822 /* Setup the header */
823 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
824 Header
.Buffer
= (PCHAR
)State
;
825 ASSERT(Data
->Length
== 0);
827 /* Check the length requested */
828 Length
= GetBusData
->Length
;
829 if (Length
> (PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
)))
831 /* Use maximum allowed */
832 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_MANIPULATE_STATE64
);
835 /* Call the internal routine */
836 State
->ReturnStatus
= KdpSysReadBusData(GetBusData
->BusDataType
,
837 GetBusData
->BusNumber
,
838 GetBusData
->SlotNumber
,
844 /* Return the actual length read */
845 Data
->Length
= GetBusData
->Length
= Length
;
848 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
856 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State
,
861 PDBGKD_GET_SET_BUS_DATA SetBusData
= &State
->u
.GetSetBusData
;
864 /* Setup the header */
865 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
866 Header
.Buffer
= (PCHAR
)State
;
868 /* Call the internal routine */
869 State
->ReturnStatus
= KdpSysWriteBusData(SetBusData
->BusDataType
,
870 SetBusData
->BusNumber
,
871 SetBusData
->SlotNumber
,
877 /* Return the actual length written */
878 SetBusData
->Length
= Length
;
881 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
889 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
894 PDBGKD_READ_WRITE_IO64 ReadIo
= &State
->u
.ReadWriteIo
;
896 /* Setup the header */
897 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
898 Header
.Buffer
= (PCHAR
)State
;
899 ASSERT(Data
->Length
== 0);
902 * Clear the value so 1 or 2 byte reads
903 * don't leave the higher bits unmodified
905 ReadIo
->DataValue
= 0;
907 /* Call the internal routine */
908 State
->ReturnStatus
= KdpSysReadIoSpace(Isa
,
917 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
925 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State
,
930 PDBGKD_READ_WRITE_IO64 WriteIo
= &State
->u
.ReadWriteIo
;
932 /* Setup the header */
933 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
934 Header
.Buffer
= (PCHAR
)State
;
935 ASSERT(Data
->Length
== 0);
937 /* Call the internal routine */
938 State
->ReturnStatus
= KdpSysWriteIoSpace(Isa
,
947 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
955 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
960 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended
= &State
->u
.
963 /* Setup the header */
964 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
965 Header
.Buffer
= (PCHAR
)State
;
966 ASSERT(Data
->Length
== 0);
969 * Clear the value so 1 or 2 byte reads
970 * don't leave the higher bits unmodified
972 ReadIoExtended
->DataValue
= 0;
974 /* Call the internal routine */
975 State
->ReturnStatus
= KdpSysReadIoSpace(ReadIoExtended
->InterfaceType
,
976 ReadIoExtended
->BusNumber
,
977 ReadIoExtended
->AddressSpace
,
978 ReadIoExtended
->IoAddress
,
979 &ReadIoExtended
->DataValue
,
980 ReadIoExtended
->DataSize
,
981 &ReadIoExtended
->DataSize
);
984 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
992 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State
,
997 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended
= &State
->u
.
1000 /* Setup the header */
1001 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1002 Header
.Buffer
= (PCHAR
)State
;
1003 ASSERT(Data
->Length
== 0);
1005 /* Call the internal routine */
1006 State
->ReturnStatus
= KdpSysReadIoSpace(WriteIoExtended
->InterfaceType
,
1007 WriteIoExtended
->BusNumber
,
1008 WriteIoExtended
->AddressSpace
,
1009 WriteIoExtended
->IoAddress
,
1010 &WriteIoExtended
->DataValue
,
1011 WriteIoExtended
->DataSize
,
1012 &WriteIoExtended
->DataSize
);
1014 /* Send the reply */
1015 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1023 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State
)
1027 /* Setup the header */
1028 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1029 Header
.Buffer
= (PCHAR
)State
;
1031 /* Call the internal routine */
1032 State
->ReturnStatus
= KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE
);
1034 /* Send the reply */
1035 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1043 KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State
)
1048 State
->ReturnStatus
= STATUS_UNSUCCESSFUL
;
1050 /* Setup the packet */
1051 Header
.Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1052 Header
.Buffer
= (PCHAR
)State
;
1055 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1063 KdpSendWaitContinue(IN ULONG PacketType
,
1064 IN PSTRING SendHeader
,
1065 IN PSTRING SendData OPTIONAL
,
1066 IN OUT PCONTEXT Context
)
1068 STRING Data
, Header
;
1069 DBGKD_MANIPULATE_STATE64 ManipulateState
;
1073 /* Setup the Manipulate State structure */
1074 Header
.MaximumLength
= sizeof(DBGKD_MANIPULATE_STATE64
);
1075 Header
.Buffer
= (PCHAR
)&ManipulateState
;
1076 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
1077 Data
.Buffer
= KdpMessageBuffer
;
1080 * Reset the context state to ensure the debugger has received
1081 * the current context before it sets it
1083 KdpContextSent
= FALSE
;
1086 /* Send the Packet */
1087 KdSendPacket(PacketType
, SendHeader
, SendData
, &KdpContext
);
1089 /* If the debugger isn't present anymore, just return success */
1090 if (KdDebuggerNotPresent
) return ContinueSuccess
;
1092 /* Main processing Loop */
1098 /* Wait to get a reply to our packet */
1099 RecvCode
= KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1105 /* If we got a resend request, do it */
1106 if (RecvCode
== KdPacketNeedsResend
) goto SendPacket
;
1107 } while (RecvCode
== KdPacketTimedOut
);
1109 /* Now check what API we got */
1110 switch (ManipulateState
.ApiNumber
)
1112 case DbgKdReadVirtualMemoryApi
:
1114 /* Read virtual memory */
1115 KdpReadVirtualMemory(&ManipulateState
, &Data
, Context
);
1118 case DbgKdWriteVirtualMemoryApi
:
1120 /* Write virtual memory */
1121 KdpWriteVirtualMemory(&ManipulateState
, &Data
, Context
);
1124 case DbgKdGetContextApi
:
1126 /* Get the current context */
1127 KdpGetContext(&ManipulateState
, &Data
, Context
);
1130 case DbgKdSetContextApi
:
1132 /* Set a new context */
1133 KdpSetContext(&ManipulateState
, &Data
, Context
);
1136 case DbgKdWriteBreakPointApi
:
1138 /* Write the breakpoint */
1139 KdpWriteBreakpoint(&ManipulateState
, &Data
, Context
);
1142 case DbgKdRestoreBreakPointApi
:
1144 /* Restore the breakpoint */
1145 KdpRestoreBreakpoint(&ManipulateState
, &Data
, Context
);
1148 case DbgKdContinueApi
:
1150 /* Simply continue */
1151 return NT_SUCCESS(ManipulateState
.u
.Continue
.ContinueStatus
);
1153 case DbgKdReadControlSpaceApi
:
1155 /* Read control space */
1156 KdpReadControlSpace(&ManipulateState
, &Data
, Context
);
1159 case DbgKdWriteControlSpaceApi
:
1161 /* Write control space */
1162 KdpWriteControlSpace(&ManipulateState
, &Data
, Context
);
1165 case DbgKdReadIoSpaceApi
:
1167 /* Read I/O Space */
1168 KdpReadIoSpace(&ManipulateState
, &Data
, Context
);
1171 case DbgKdWriteIoSpaceApi
:
1173 /* Write I/O Space */
1174 KdpWriteIoSpace(&ManipulateState
, &Data
, Context
);
1177 case DbgKdRebootApi
:
1179 /* Reboot the system */
1180 HalReturnToFirmware(HalRebootRoutine
);
1183 case DbgKdContinueApi2
:
1185 /* Check if caller reports success */
1186 if (NT_SUCCESS(ManipulateState
.u
.Continue2
.ContinueStatus
))
1188 /* Update the state */
1189 KdpGetStateChange(&ManipulateState
, Context
);
1190 return ContinueSuccess
;
1194 /* Return an error */
1195 return ContinueError
;
1198 case DbgKdReadPhysicalMemoryApi
:
1200 /* Read physical memory */
1201 KdpReadPhysicalmemory(&ManipulateState
, &Data
, Context
);
1204 case DbgKdWritePhysicalMemoryApi
:
1206 /* Write physical memory */
1207 KdpWritePhysicalmemory(&ManipulateState
, &Data
, Context
);
1210 case DbgKdQuerySpecialCallsApi
:
1211 case DbgKdSetSpecialCallApi
:
1212 case DbgKdClearSpecialCallsApi
:
1215 KdpDprintf("Special Call support is unimplemented!\n");
1216 KdpNotSupported(&ManipulateState
);
1219 case DbgKdSetInternalBreakPointApi
:
1220 case DbgKdGetInternalBreakPointApi
:
1223 KdpDprintf("Internal Breakpoint support is unimplemented!\n");
1224 KdpNotSupported(&ManipulateState
);
1227 case DbgKdReadIoSpaceExtendedApi
:
1229 /* Read I/O Space */
1230 KdpReadIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1233 case DbgKdWriteIoSpaceExtendedApi
:
1235 /* Write I/O Space */
1236 KdpWriteIoSpaceExtended(&ManipulateState
, &Data
, Context
);
1239 case DbgKdGetVersionApi
:
1241 /* Get version data */
1242 KdpGetVersion(&ManipulateState
);
1245 case DbgKdWriteBreakPointExApi
:
1247 /* Write the breakpoint and check if it failed */
1248 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState
,
1252 /* Return an error */
1253 return ContinueError
;
1257 case DbgKdRestoreBreakPointExApi
:
1259 /* Restore the breakpoint */
1260 KdpRestoreBreakPointEx(&ManipulateState
, &Data
, Context
);
1263 case DbgKdCauseBugCheckApi
:
1265 /* Crash the system */
1266 KdpCauseBugCheck(&ManipulateState
);
1269 case DbgKdSwitchProcessor
:
1272 KdpDprintf("Processor Switch support is unimplemented!\n");
1273 KdpNotSupported(&ManipulateState
);
1276 case DbgKdPageInApi
:
1279 KdpDprintf("Page-In support is unimplemented!\n");
1280 KdpNotSupported(&ManipulateState
);
1283 case DbgKdReadMachineSpecificRegister
:
1285 /* Read from the specified MSR */
1286 KdpReadMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1289 case DbgKdWriteMachineSpecificRegister
:
1291 /* Write to the specified MSR */
1292 KdpWriteMachineSpecificRegister(&ManipulateState
, &Data
, Context
);
1295 case DbgKdSearchMemoryApi
:
1298 KdpSearchMemory(&ManipulateState
, &Data
, Context
);
1301 case DbgKdGetBusDataApi
:
1303 /* Read from the bus */
1304 KdpGetBusData(&ManipulateState
, &Data
, Context
);
1307 case DbgKdSetBusDataApi
:
1309 /* Write to the bus */
1310 KdpSetBusData(&ManipulateState
, &Data
, Context
);
1313 case DbgKdCheckLowMemoryApi
:
1315 /* Check for memory corruption in the lower 4 GB */
1316 KdpCheckLowMemory(&ManipulateState
);
1319 case DbgKdClearAllInternalBreakpointsApi
:
1321 /* Just clear the counter */
1322 KdpNumInternalBreakpoints
= 0;
1325 case DbgKdFillMemoryApi
:
1328 KdpFillMemory(&ManipulateState
, &Data
, Context
);
1331 case DbgKdQueryMemoryApi
:
1334 KdpQueryMemory(&ManipulateState
, Context
);
1337 case DbgKdSwitchPartition
:
1340 KdpDprintf("Partition Switch support is unimplemented!\n");
1341 KdpNotSupported(&ManipulateState
);
1344 /* Unsupported Message */
1347 /* Setup an empty message, with failure */
1348 KdpDprintf("Received Unhandled API %lx\n", ManipulateState
.ApiNumber
);
1350 ManipulateState
.ReturnStatus
= STATUS_UNSUCCESSFUL
;
1353 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE
,
1364 KdpReportLoadSymbolsStateChange(IN PSTRING PathName
,
1365 IN PKD_SYMBOLS_INFO SymbolInfo
,
1367 IN OUT PCONTEXT Context
)
1370 STRING Data
, Header
;
1371 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1372 ULONG PathNameLength
;
1373 KCONTINUE_STATUS Status
;
1375 /* Start wait loop */
1378 /* Build the architecture common parts of the message */
1379 KdpSetCommonState(DbgKdLoadSymbolsStateChange
,
1383 /* Now finish creating the structure */
1384 KdpSetContextState(&WaitStateChange
, Context
);
1386 /* Fill out load data */
1387 WaitStateChange
.u
.LoadSymbols
.UnloadSymbols
= Unload
;
1388 WaitStateChange
.u
.LoadSymbols
.BaseOfDll
= (ULONG64
)(LONG_PTR
)SymbolInfo
->BaseOfDll
;
1389 WaitStateChange
.u
.LoadSymbols
.ProcessId
= SymbolInfo
->ProcessId
;
1390 WaitStateChange
.u
.LoadSymbols
.CheckSum
= SymbolInfo
->CheckSum
;
1391 WaitStateChange
.u
.LoadSymbols
.SizeOfImage
= SymbolInfo
->SizeOfImage
;
1393 /* Check if we have a path name */
1396 /* Copy it to the path buffer */
1397 KdpCopyMemoryChunks((ULONG_PTR
)PathName
->Buffer
,
1404 /* Null terminate */
1405 KdpPathBuffer
[PathNameLength
++] = ANSI_NULL
;
1407 /* Set the path length */
1408 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= PathNameLength
;
1410 /* Set up the data */
1411 Data
.Buffer
= KdpPathBuffer
;
1412 Data
.Length
= PathNameLength
;
1418 WaitStateChange
.u
.LoadSymbols
.PathNameLength
= 0;
1422 /* Setup the header */
1423 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1424 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1426 /* Send the packet */
1427 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1431 } while (Status
== ContinueProcessorReselected
);
1436 KdpReportCommandStringStateChange(IN PSTRING NameString
,
1437 IN PSTRING CommandString
,
1438 IN OUT PCONTEXT Context
)
1440 STRING Header
, Data
;
1441 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1442 ULONG Length
, ActualLength
, TotalLength
;
1443 KCONTINUE_STATUS Status
;
1445 /* Start wait loop */
1448 /* Build the architecture common parts of the message */
1449 KdpSetCommonState(DbgKdCommandStringStateChange
,
1453 /* Set the context */
1454 KdpSetContextState(&WaitStateChange
, Context
);
1456 /* Clear the command string structure */
1457 RtlZeroMemory(&WaitStateChange
.u
.CommandString
,
1458 sizeof(DBGKD_COMMAND_STRING
));
1460 /* Normalize name string to max */
1461 Length
= min(128 - 1, NameString
->Length
);
1463 /* Copy it to the message buffer */
1464 KdpCopyMemoryChunks((ULONG_PTR
)NameString
->Buffer
,
1471 /* Null terminate and calculate the total length */
1472 TotalLength
= ActualLength
;
1473 KdpMessageBuffer
[TotalLength
++] = ANSI_NULL
;
1475 /* Check if the command string is too long */
1476 Length
= CommandString
->Length
;
1477 if (Length
> (PACKET_MAX_SIZE
-
1478 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
) - TotalLength
))
1480 /* Use maximum possible size */
1481 Length
= (PACKET_MAX_SIZE
-
1482 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
) - TotalLength
);
1485 /* Copy it to the message buffer */
1486 KdpCopyMemoryChunks((ULONG_PTR
)CommandString
->Buffer
,
1487 KdpMessageBuffer
+ TotalLength
,
1493 /* Null terminate and calculate the total length */
1494 TotalLength
+= ActualLength
;
1495 KdpMessageBuffer
[TotalLength
++] = ANSI_NULL
;
1497 /* Now set up the header and the data */
1498 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1499 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1500 Data
.Length
= TotalLength
;
1501 Data
.Buffer
= KdpMessageBuffer
;
1503 /* Send State Change packet and wait for a reply */
1504 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1508 } while (Status
== ContinueProcessorReselected
);
1513 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord
,
1514 IN OUT PCONTEXT Context
,
1515 IN BOOLEAN SecondChanceException
)
1517 STRING Header
, Data
;
1518 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
;
1519 KCONTINUE_STATUS Status
;
1521 /* Start report loop */
1524 /* Build the architecture common parts of the message */
1525 KdpSetCommonState(DbgKdExceptionStateChange
, Context
, &WaitStateChange
);
1527 /* Copy the Exception Record and set First Chance flag */
1528 #if !defined(_WIN64)
1529 ExceptionRecord32To64((PEXCEPTION_RECORD32
)ExceptionRecord
,
1530 &WaitStateChange
.u
.Exception
.ExceptionRecord
);
1532 RtlCopyMemory(&WaitStateChange
.u
.Exception
.ExceptionRecord
,
1534 sizeof(EXCEPTION_RECORD
));
1536 WaitStateChange
.u
.Exception
.FirstChance
= !SecondChanceException
;
1538 /* Now finish creating the structure */
1539 KdpSetContextState(&WaitStateChange
, Context
);
1541 /* Setup the actual header to send to KD */
1542 Header
.Length
= sizeof(DBGKD_ANY_WAIT_STATE_CHANGE
);
1543 Header
.Buffer
= (PCHAR
)&WaitStateChange
;
1545 /* Setup the trace data */
1546 DumpTraceData(&Data
);
1548 /* Send State Change packet and wait for a reply */
1549 Status
= KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64
,
1553 } while (Status
== ContinueProcessorReselected
);
1561 KdpTimeSlipDpcRoutine(IN PKDPC Dpc
,
1562 IN PVOID DeferredContext
,
1563 IN PVOID SystemArgument1
,
1564 IN PVOID SystemArgument2
)
1566 LONG OldSlip
, NewSlip
, PendingSlip
;
1568 /* Get the current pending slip */
1569 PendingSlip
= KdpTimeSlipPending
;
1572 /* Save the old value and either disable or enable it now. */
1573 OldSlip
= PendingSlip
;
1574 NewSlip
= OldSlip
> 1 ? 1 : 0;
1576 /* Try to change the value */
1577 } while (InterlockedCompareExchange(&KdpTimeSlipPending
,
1579 OldSlip
) != OldSlip
);
1581 /* If the New Slip value is 1, then do the Time Slipping */
1582 if (NewSlip
) ExQueueWorkItem(&KdpTimeSlipWorkItem
, DelayedWorkQueue
);
1587 KdpTimeSlipWork(IN PVOID Context
)
1590 LARGE_INTEGER DueTime
;
1592 /* Update the System time from the CMOS */
1593 ExAcquireTimeRefreshLock(FALSE
);
1594 ExUpdateSystemTimeFromCmos(FALSE
, 0);
1595 ExReleaseTimeRefreshLock();
1597 /* Check if we have a registered Time Slip Event and signal it */
1598 KeAcquireSpinLock(&KdpTimeSlipEventLock
, &OldIrql
);
1599 if (KdpTimeSlipEvent
) KeSetEvent(KdpTimeSlipEvent
, 0, FALSE
);
1600 KeReleaseSpinLock(&KdpTimeSlipEventLock
, OldIrql
);
1602 /* Delay the DPC until it runs next time */
1603 DueTime
.QuadPart
= -1800000000;
1604 KeSetTimer(&KdpTimeSlipTimer
, DueTime
, &KdpTimeSlipDpc
);
1609 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord
,
1610 IN OUT PCONTEXT ContextRecord
,
1611 IN BOOLEAN SecondChanceException
)
1615 /* Save the port data */
1618 /* Report a state change */
1619 Status
= KdpReportExceptionStateChange(ExceptionRecord
,
1621 SecondChanceException
);
1623 /* Restore the port data and return */
1630 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame
)
1632 LARGE_INTEGER Null
= {{0}};
1634 /* Check if interrupts were disabled */
1635 if (!KeGetTrapFrameInterruptState(TrapFrame
))
1637 /* Nothing to return */
1641 /* Otherwise, do the call */
1642 return KeQueryPerformanceCounter(NULL
);
1647 KdpAllowDisable(VOID
)
1649 /* Check if we are on MP */
1650 if (KeNumberProcessors
> 1)
1653 KdpDprintf("KdpAllowDisable: SMP UNHANDLED\n");
1658 return STATUS_SUCCESS
;
1663 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame
,
1664 IN PKEXCEPTION_FRAME ExceptionFrame
)
1668 /* Check if we have a trap frame */
1671 /* Calculate the time difference for the enter */
1672 KdTimerStop
= KdpQueryPerformanceCounter(TrapFrame
);
1673 KdTimerDifference
.QuadPart
= KdTimerStop
.QuadPart
-
1674 KdTimerStart
.QuadPart
;
1678 /* No trap frame, so can't calculate */
1679 KdTimerStop
.QuadPart
= 0;
1682 /* Save the current IRQL */
1683 KeGetCurrentPrcb()->DebuggerSavedIRQL
= KeGetCurrentIrql();
1685 /* Freeze all CPUs */
1686 Entered
= KeFreezeExecution(TrapFrame
, ExceptionFrame
);
1688 /* Lock the port, save the state and set debugger entered */
1689 KdpPortLocked
= KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock
);
1691 KdEnteredDebugger
= TRUE
;
1693 /* Check freeze flag */
1694 if (KiFreezeFlag
& 1)
1696 /* Print out errror */
1697 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1700 /* Check processor state */
1701 if (KiFreezeFlag
& 2)
1703 /* Print out errror */
1704 KdpDprintf("Some processors not frozen in debugger!\n");
1707 /* Make sure we acquired the port */
1708 if (!KdpPortLocked
) KdpDprintf("Port lock was not acquired!\n");
1710 /* Return enter state */
1716 KdExitDebugger(IN BOOLEAN Entered
)
1720 /* Restore the state and unlock the port */
1722 if (KdpPortLocked
) KdpPortUnlock();
1724 /* Unfreeze the CPUs */
1725 KeThawExecution(Entered
);
1727 /* Compare time with the one from KdEnterDebugger */
1728 if (!KdTimerStop
.QuadPart
)
1730 /* We didn't get a trap frame earlier in so never got the time */
1731 KdTimerStart
= KdTimerStop
;
1735 /* Query the timer */
1736 KdTimerStart
= KeQueryPerformanceCounter(NULL
);
1739 /* Check if a Time Slip was on queue */
1740 TimeSlip
= InterlockedIncrement(&KdpTimeSlipPending
);
1743 /* Queue a DPC for the time slip */
1744 InterlockedIncrement(&KdpTimeSlipPending
);
1745 KeInsertQueueDpc(&KdpTimeSlipDpc
, NULL
, NULL
);
1751 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock
)
1755 #if defined(__GNUC__)
1756 /* Make gcc happy */
1757 OldIrql
= PASSIVE_LEVEL
;
1760 /* Check if enabling the debugger is blocked */
1763 /* It is, fail the enable */
1764 return STATUS_ACCESS_DENIED
;
1767 /* Check if we need to acquire the lock */
1771 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1775 /* Check if we're not disabled */
1776 if (!KdDisableCount
)
1778 /* Check if we had locked the port before */
1782 KeLowerIrql(OldIrql
);
1785 /* Fail: We're already enabled */
1786 return STATUS_INVALID_PARAMETER
;
1791 * This can only happen if we are called from a bugcheck
1792 * and were never initialized, so initialize the debugger now.
1794 KdInitSystem(0, NULL
);
1796 /* Return success since we initialized */
1797 return STATUS_SUCCESS
;
1801 /* Decrease the disable count */
1802 if (!(--KdDisableCount
))
1804 /* We're now enabled again! Were we enabled before, too? */
1805 if (KdPreviouslyEnabled
)
1807 /* Reinitialize the Debugger */
1808 KdInitSystem(0, NULL
) ;
1809 KdpRestoreAllBreakpoints();
1813 /* Check if we had locked the port before */
1816 /* Yes, now unlock it */
1817 KeLowerIrql(OldIrql
);
1822 return STATUS_SUCCESS
;
1827 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock
)
1832 #if defined(__GNUC__)
1833 /* Make gcc happy */
1834 OldIrql
= PASSIVE_LEVEL
;
1838 * If enabling the debugger is blocked
1839 * then there is nothing to disable (duh)
1844 return STATUS_ACCESS_DENIED
;
1847 /* Check if we need to acquire the lock */
1851 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1855 /* Check if we're not disabled */
1856 if (!KdDisableCount
)
1858 /* Check if the debugger was never actually initialized */
1859 if (!(KdDebuggerEnabled
) && !(KdPitchDebugger
))
1861 /* It wasn't, so don't re-enable it later */
1862 KdPreviouslyEnabled
= FALSE
;
1866 /* It was, so we will re-enable it later */
1867 KdPreviouslyEnabled
= TRUE
;
1870 /* Check if we were called from the exported API and are enabled */
1871 if ((NeedLock
) && (KdPreviouslyEnabled
))
1873 /* Check if it is safe to disable the debugger */
1874 Status
= KdpAllowDisable();
1875 if (!NT_SUCCESS(Status
))
1877 /* Release the lock and fail */
1878 KeLowerIrql(OldIrql
);
1884 /* Only disable the debugger if it is enabled */
1885 if (KdDebuggerEnabled
)
1888 * Disable the debugger; suspend breakpoints
1889 * and reset the debug stub
1891 KdpSuspendAllBreakPoints();
1892 KiDebugRoutine
= KdpStub
;
1894 /* We are disabled now */
1895 KdDebuggerEnabled
= FALSE
;
1896 #undef KdDebuggerEnabled
1897 SharedUserData
->KdDebuggerEnabled
= FALSE
;
1898 #define KdDebuggerEnabled _KdDebuggerEnabled
1902 /* Increment the disable count */
1905 /* Check if we had locked the port before */
1908 /* Yes, now unlock it */
1909 KeLowerIrql(OldIrql
);
1914 return STATUS_SUCCESS
;
1917 /* PUBLIC FUNCTIONS **********************************************************/
1924 KdEnableDebugger(VOID
)
1926 /* Use the internal routine */
1927 return KdEnableDebuggerWithLock(TRUE
);
1935 KdDisableDebugger(VOID
)
1937 /* Use the internal routine */
1938 return KdDisableDebuggerWithLock(TRUE
);
1946 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
1947 IN PVOID InputBuffer
,
1948 IN ULONG InputBufferLength
,
1949 OUT PVOID OutputBuffer
,
1950 IN ULONG OutputBufferLength
,
1951 IN OUT PULONG ReturnLength
,
1952 IN KPROCESSOR_MODE PreviousMode
)
1954 /* Local kernel debugging is not yet supported */
1955 DbgPrint("KdSystemDebugControl is unimplemented!\n");
1956 return STATUS_NOT_IMPLEMENTED
;
1964 KdChangeOption(IN KD_OPTION Option
,
1965 IN ULONG InBufferBytes OPTIONAL
,
1967 IN ULONG OutBufferBytes OPTIONAL
,
1968 OUT PVOID OutBuffer
,
1969 OUT PULONG OutBufferNeeded OPTIONAL
)
1971 /* Fail if there is no debugger */
1972 if (KdPitchDebugger
)
1974 /* No debugger, no options */
1975 return STATUS_DEBUGGER_INACTIVE
;
1978 /* Do we recognize this option? */
1979 if (Option
!= KD_OPTION_SET_BLOCK_ENABLE
)
1981 /* We don't, clear the output length and fail */
1982 if (OutBufferNeeded
) *OutBufferNeeded
= 0;
1983 return STATUS_INVALID_INFO_CLASS
;
1986 /* Verify parameters */
1987 if ((InBufferBytes
!= sizeof(BOOLEAN
)) ||
1988 (OutBufferBytes
!= 0) ||
1989 (OutBuffer
!= NULL
))
1991 /* Invalid parameters for this option, fail */
1992 return STATUS_INVALID_PARAMETER
;
1996 * Check if the high bit is set, meaning we don't
1997 * allow the debugger to be enabled
1999 if (KdBlockEnable
& 0x80)
2001 /* Fail regardless of what state the caller tried to set */
2002 return STATUS_ACCESS_VIOLATION
;
2005 /* Set the new block enable state */
2006 KdBlockEnable
= *(PBOOLEAN
)InBuffer
;
2008 /* No output buffer required for this option */
2009 if (OutBufferNeeded
) *OutBufferNeeded
= 0;
2012 return STATUS_SUCCESS
;
2020 KdPowerTransition(IN DEVICE_POWER_STATE NewState
)
2022 /* Check what power state this is */
2023 if (NewState
== PowerDeviceD0
)
2025 /* Wake up the debug port */
2027 return STATUS_SUCCESS
;
2029 else if ((NewState
== PowerDeviceD1
) ||
2030 (NewState
== PowerDeviceD2
) ||
2031 (NewState
== PowerDeviceD3
))
2033 /* Power down the debug port */
2035 return STATUS_SUCCESS
;
2039 /* Invalid state! */
2040 return STATUS_INVALID_PARAMETER_1
;
2049 KdRefreshDebuggerNotPresent(VOID
)
2051 BOOLEAN Entered
, DebuggerNotPresent
;
2053 /* Check if the debugger is completely disabled */
2054 if (KdPitchDebugger
)
2056 /* Don't try to refresh then -- fail early */
2060 /* Enter the debugger */
2061 Entered
= KdEnterDebugger(NULL
, NULL
);
2064 * Attempt to send a string to the debugger to refresh the
2067 KdpDprintf("KDTARGET: Refreshing KD connection\n");
2069 /* Save the state while we are holding the lock */
2070 DebuggerNotPresent
= KdDebuggerNotPresent
;
2072 /* Exit the debugger and return the state */
2073 KdExitDebugger(Entered
);
2074 return DebuggerNotPresent
;
2082 NtQueryDebugFilterState(IN ULONG ComponentId
,
2087 /* Check if the ID fits in the component table */
2088 if (ComponentId
< KdComponentTableSize
)
2090 /* It does, so get the mask from there */
2091 Mask
= KdComponentTable
[ComponentId
];
2093 else if (ComponentId
== MAXULONG
)
2096 * This is the internal ID used for DbgPrint messages without ID and
2097 * Level. Use the system-wide mask for those.
2099 Mask
= &Kd_WIN2000_Mask
;
2103 /* Invalid ID, fail */
2104 return STATUS_INVALID_PARAMETER_1
;
2107 /* Convert Level to bit field if necessary */
2108 if (Level
< 32) Level
= 1 << Level
;
2110 /* Determine if this Level is filtered out */
2111 if ((Kd_WIN2000_Mask
& Level
) ||
2114 /* This mask will get through to the debugger */
2115 return (NTSTATUS
)TRUE
;
2119 /* This mask is filtered out */
2120 return (NTSTATUS
)FALSE
;
2129 NtSetDebugFilterState(IN ULONG ComponentId
,
2135 /* Modifying debug filters requires the debug privilege */
2136 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
,
2137 ExGetPreviousMode()))
2140 return STATUS_ACCESS_DENIED
;
2143 /* Check if the ID fits in the component table */
2144 if (ComponentId
< KdComponentTableSize
)
2146 /* It does, so get the mask from there */
2147 Mask
= KdComponentTable
[ComponentId
];
2149 else if (ComponentId
== MAXULONG
)
2152 * This is the internal ID used for DbgPrint messages without ID and
2153 * Level. Use the system-wide mask for those.
2155 Mask
= &Kd_WIN2000_Mask
;
2159 /* Invalid ID, fail */
2160 return STATUS_INVALID_PARAMETER_1
;
2163 /* Convert Level to bit field if required */
2164 if (Level
< 32) Level
= 1 << Level
;
2166 /* Check what kind of operation this is */
2174 /* Remove the Level */
2179 return STATUS_SUCCESS
;