2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/kd/kdmain.c
5 * PURPOSE: Kernel Debugger Initialization
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
14 /* VARIABLES ***************************************************************/
16 BOOLEAN KdDebuggerEnabled
= FALSE
;
17 BOOLEAN KdEnteredDebugger
= FALSE
;
18 BOOLEAN KdDebuggerNotPresent
= TRUE
;
19 BOOLEAN KdBreakAfterSymbolLoad
= FALSE
;
20 BOOLEAN KdPitchDebugger
= TRUE
;
21 BOOLEAN KdIgnoreUmExceptions
= FALSE
;
22 KD_CONTEXT KdpContext
;
23 ULONG Kd_WIN2000_Mask
;
24 LONG KdpTimeSlipPending
;
25 KDDEBUGGER_DATA64 KdDebuggerDataBlock
;
26 VOID NTAPI
PspDumpThreads(BOOLEAN SystemThreads
);
33 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128
34 KD_COMPONENT_DATA KdpComponentTable
[MAX_KD_COMPONENT_TABLE_ENTRIES
];
35 ULONG KdComponentTableEntries
= 0;
37 ULONG Kd_DEFAULT_MASK
= 1 << DPFLTR_ERROR_LEVEL
;
39 /* PRIVATE FUNCTIONS *********************************************************/
43 KdpServiceDispatcher(ULONG Service
,
46 KPROCESSOR_MODE PreviousMode
)
52 case BREAKPOINT_PRINT
: /* DbgPrint */
53 Result
= KdpPrintString(Buffer1
, Buffer1Length
, PreviousMode
);
57 case ' soR': /* ROS-INTERNAL */
59 switch ((ULONG_PTR
)Buffer1
)
66 PspDumpThreads(FALSE
);
70 MmDumpArmPfnDatabase(FALSE
);
79 #if defined(_M_IX86) && !defined(_WINKD_) // See ke/i386/traphdlr.c
80 /* Register a debug callback */
83 switch (Buffer1Length
)
85 case ID_Win32PreServiceHook
:
86 KeWin32PreServiceHook
= Buffer1
;
89 case ID_Win32PostServiceHook
:
90 KeWin32PostServiceHook
= Buffer1
;
98 /* Special case for stack frame dumps */
101 KeRosDumpStackFrames((PULONG
)Buffer1
, Buffer1Length
);
106 /* Register KDBG CLI callback */
109 Result
= KdbRegisterCliCallback(Buffer1
, Buffer1Length
);
115 DPRINT1("Invalid debug service call!\n");
116 HalDisplayString("Invalid debug service call!\r\n");
125 KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame
,
126 IN PKEXCEPTION_FRAME ExceptionFrame
,
127 IN PEXCEPTION_RECORD ExceptionRecord
,
129 IN KPROCESSOR_MODE PreviousMode
,
130 IN BOOLEAN SecondChance
)
132 KD_CONTINUE_TYPE Return
= kdHandleException
;
133 ULONG ExceptionCommand
= ExceptionRecord
->ExceptionInformation
[0];
135 /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
136 if ((ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
) &&
137 (ExceptionRecord
->NumberParameters
> 0) &&
138 ((ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
) ||
139 (ExceptionCommand
== BREAKPOINT_UNLOAD_SYMBOLS
) ||
140 (ExceptionCommand
== BREAKPOINT_COMMAND_STRING
) ||
141 (ExceptionCommand
== BREAKPOINT_PRINT
) ||
142 (ExceptionCommand
== BREAKPOINT_PROMPT
)))
144 /* Check if this is a debug print */
145 if (ExceptionCommand
== BREAKPOINT_PRINT
)
147 /* Print the string */
148 KdpServiceDispatcher(BREAKPOINT_PRINT
,
149 (PVOID
)ExceptionRecord
->ExceptionInformation
[1],
150 ExceptionRecord
->ExceptionInformation
[2],
154 KeSetContextReturnRegister(Context
, STATUS_SUCCESS
);
157 else if (ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
)
159 PKD_SYMBOLS_INFO SymbolsInfo
;
160 KD_SYMBOLS_INFO CapturedSymbolsInfo
;
161 PLDR_DATA_TABLE_ENTRY LdrEntry
;
163 SymbolsInfo
= (PKD_SYMBOLS_INFO
)ExceptionRecord
->ExceptionInformation
[2];
164 if (PreviousMode
!= KernelMode
)
168 ProbeForRead(SymbolsInfo
,
169 sizeof(*SymbolsInfo
),
171 RtlCopyMemory(&CapturedSymbolsInfo
,
173 sizeof(*SymbolsInfo
));
174 SymbolsInfo
= &CapturedSymbolsInfo
;
176 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
183 if (SymbolsInfo
!= NULL
)
185 /* Load symbols. Currently implemented only for KDBG! */
186 if (KdbpSymFindModule(SymbolsInfo
->BaseOfDll
, NULL
, -1, &LdrEntry
))
188 KdbSymProcessSymbols(LdrEntry
);
192 else if (ExceptionCommand
== BREAKPOINT_PROMPT
)
196 USHORT OutStringLength
;
198 /* Get the response string and length */
199 OutString
= (LPSTR
)Context
->Ebx
;
200 OutStringLength
= (USHORT
)Context
->Edi
;
203 ReturnValue
= KdpPrompt((LPSTR
)ExceptionRecord
->
204 ExceptionInformation
[1],
205 (USHORT
)ExceptionRecord
->
206 ExceptionInformation
[2],
213 /* Return the number of characters that we received */
214 Context
->Eax
= ReturnValue
;
218 /* This we can handle: simply bump the Program Counter */
219 KeSetContextPc(Context
, KeGetContextPc(Context
) + KD_BREAKPOINT_SIZE
);
224 /* Check if this is an assertion failure */
225 if (ExceptionRecord
->ExceptionCode
== STATUS_ASSERTION_FAILURE
)
227 /* Bump EIP to the instruction following the int 2C */
232 /* Get out of here if the Debugger isn't connected */
233 if (KdDebuggerNotPresent
) return FALSE
;
236 /* Call KDBG if available */
237 Return
= KdbEnterDebuggerException(ExceptionRecord
,
243 if (WrapperInitRoutine
)
246 Return
= WrapperTable
.KdpExceptionRoutine(ExceptionRecord
,
250 #endif /* not KDBG */
252 /* Debugger didn't handle it, please handle! */
253 if (Return
== kdHandleException
) return FALSE
;
255 /* Debugger handled it */
261 KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord
,
263 IN KPROCESSOR_MODE PreviousMode
)
265 /* KDBG has its own mechanism for ignoring user mode exceptions */
269 /* PUBLIC FUNCTIONS *********************************************************/
273 KdUpdateDataBlock(VOID
)
282 KdRefreshDebuggerNotPresent(VOID
)
286 /* Just return whatever was set previously -- FIXME! */
287 return KdDebuggerNotPresent
;
295 KdDisableDebugger(VOID
)
300 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
302 /* TODO: Disable any breakpoints */
304 /* Disable the Debugger */
305 KdDebuggerEnabled
= FALSE
;
306 SharedUserData
->KdDebuggerEnabled
= FALSE
;
309 KeLowerIrql(OldIrql
);
312 return STATUS_SUCCESS
;
317 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock
)
319 return STATUS_ACCESS_DENIED
;
327 KdEnableDebugger(VOID
)
332 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
334 /* TODO: Re-enable any breakpoints */
336 /* Enable the Debugger */
337 KdDebuggerEnabled
= TRUE
;
338 SharedUserData
->KdDebuggerEnabled
= TRUE
;
341 KeLowerIrql(OldIrql
);
344 return STATUS_SUCCESS
;
362 KdPowerTransition(ULONG PowerState
)
365 return STATUS_NOT_IMPLEMENTED
;
373 KdChangeOption(IN KD_OPTION Option
,
374 IN ULONG InBufferLength OPTIONAL
,
376 IN ULONG OutBufferLength OPTIONAL
,
378 OUT PULONG OutBufferRequiredLength OPTIONAL
)
381 return STATUS_NOT_IMPLEMENTED
;
387 NtQueryDebugFilterState(IN ULONG ComponentId
,
392 /* Convert Level to mask if it isn't already one */
396 /* Check if it is not the default component */
397 if (ComponentId
!= MAXULONG
)
399 /* No, search for an existing entry in the table */
400 for (i
= 0; i
< KdComponentTableEntries
; i
++)
402 /* Check if it is the right component */
403 if (ComponentId
== KdpComponentTable
[i
].ComponentId
)
405 /* Check if mask are matching */
406 return (Level
& KdpComponentTable
[i
].Level
) ? TRUE
: FALSE
;
411 /* Entry not found in the table, use default mask */
412 return (Level
& Kd_DEFAULT_MASK
) ? TRUE
: FALSE
;
417 NtSetDebugFilterState(IN ULONG ComponentId
,
423 /* Convert Level to mask if it isn't already one */
426 Level
&= ~DPFLTR_MASK
;
428 /* Check if it is the default component */
429 if (ComponentId
== MAXULONG
)
431 /* Yes, modify the default mask */
433 Kd_DEFAULT_MASK
|= Level
;
435 Kd_DEFAULT_MASK
&= ~Level
;
437 return STATUS_SUCCESS
;
440 /* Search for an existing entry */
441 for (i
= 0; i
< KdComponentTableEntries
; i
++ )
443 if (ComponentId
== KdpComponentTable
[i
].ComponentId
)
447 /* Check if we have found an existing entry */
448 if (i
== KdComponentTableEntries
)
450 /* Check if we have enough space in the table */
451 if (i
== MAX_KD_COMPONENT_TABLE_ENTRIES
)
452 return STATUS_INVALID_PARAMETER_1
;
454 /* Add a new entry */
455 ++KdComponentTableEntries
;
456 KdpComponentTable
[i
].ComponentId
= ComponentId
;
457 KdpComponentTable
[i
].Level
= Kd_DEFAULT_MASK
;
460 /* Update entry table */
462 KdpComponentTable
[i
].Level
|= Level
;
464 KdpComponentTable
[i
].Level
&= ~Level
;
466 return STATUS_SUCCESS
;
474 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
475 IN PVOID InputBuffer
,
476 IN ULONG InputBufferLength
,
477 OUT PVOID OutputBuffer
,
478 IN ULONG OutputBufferLength
,
479 IN OUT PULONG ReturnLength
,
480 IN KPROCESSOR_MODE PreviousMode
)
483 return KdpServiceDispatcher(Command
,
489 PKDEBUG_ROUTINE KiDebugRoutine
= KdpEnterDebuggerException
;