2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/kd/kdinit.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 KiEnableTimerWatchdog
= FALSE
;
20 BOOLEAN KdBreakAfterSymbolLoad
= FALSE
;
21 BOOLEAN KdpBreakPending
;
22 BOOLEAN KdPitchDebugger
= TRUE
;
23 VOID NTAPI
PspDumpThreads(BOOLEAN SystemThreads
);
30 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128
31 KD_COMPONENT_DATA KdComponentTable
[MAX_KD_COMPONENT_TABLE_ENTRIES
];
32 ULONG KdComponentTableEntries
= 0;
34 ULONG Kd_DEFAULT_MASK
= 1 << DPFLTR_ERROR_LEVEL
;
36 /* PRIVATE FUNCTIONS *********************************************************/
40 KdpServiceDispatcher(ULONG Service
,
48 case BREAKPOINT_PRINT
: /* DbgPrint */
49 Result
= KdpPrintString(Buffer1
, Buffer1Length
);
53 case ' soR': /* ROS-INTERNAL */
55 switch ((ULONG
)Buffer1
)
58 KeBugCheck(MANUALLY_INITIATED_CRASH
);
66 PspDumpThreads(FALSE
);
73 case ThatsWhatSheSaid
:
83 /* Special case for stack frame dumps */
86 KeRosDumpStackFrames((PULONG
)Buffer1
, Buffer1Length
);
91 HalDisplayString ("Invalid debug service call!\n");
100 KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame
,
101 IN PKEXCEPTION_FRAME ExceptionFrame
,
102 IN PEXCEPTION_RECORD ExceptionRecord
,
104 IN KPROCESSOR_MODE PreviousMode
,
105 IN BOOLEAN SecondChance
)
107 KD_CONTINUE_TYPE Return
= kdHandleException
;
108 ULONG ExceptionCommand
= ExceptionRecord
->ExceptionInformation
[0];
113 /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
114 if ((ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
) &&
115 (ExceptionRecord
->NumberParameters
> 0) &&
116 ((ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
) ||
117 (ExceptionCommand
== BREAKPOINT_UNLOAD_SYMBOLS
) ||
118 (ExceptionCommand
== BREAKPOINT_COMMAND_STRING
) ||
119 (ExceptionCommand
== BREAKPOINT_PRINT
)))
121 /* Check if this is a debug print */
122 if (ExceptionCommand
== BREAKPOINT_PRINT
)
124 /* Print the string */
125 KdpServiceDispatcher(BREAKPOINT_PRINT
,
126 (PVOID
)ExceptionRecord
->ExceptionInformation
[1],
127 ExceptionRecord
->ExceptionInformation
[2]);
129 Context
->Eax
= STATUS_SUCCESS
;
131 Context
->R0
= STATUS_SUCCESS
;
133 #error Please be portable when modifying code
136 else if (ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
)
138 /* Load symbols. Currently implemented only for KDBG! */
139 KDB_SYMBOLFILE_HOOK((PANSI_STRING
)ExceptionRecord
->ExceptionInformation
[1],
140 (PKD_SYMBOLS_INFO
)ExceptionRecord
->ExceptionInformation
[2]);
143 /* This we can handle: simply bump EIP */
147 Context
->Pc
+= sizeof(ULONG
);
152 /* Get out of here if the Debugger isn't connected */
153 if (KdDebuggerNotPresent
) return FALSE
;
155 /* Save old EIP value */
157 EipOld
= Context
->Eip
;
161 /* Call KDBG if available */
162 Return
= KdbEnterDebuggerException(ExceptionRecord
,
168 if (WrapperInitRoutine
)
171 Return
= WrapperTable
.KdpExceptionRoutine(ExceptionRecord
,
175 #endif /* not KDBG */
177 /* Bump EIP over int 3 if debugger did not already change it */
178 if (ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
)
180 //DPRINT1("Address: %p. Return: %d\n", EipOld, Return);
183 /* Debugger didn't handle it, please handle! */
184 if (Return
== kdHandleException
) return FALSE
;
186 /* Debugger handled it */
192 KdpCallGdb(IN PKTRAP_FRAME TrapFrame
,
193 IN PEXCEPTION_RECORD ExceptionRecord
,
196 KD_CONTINUE_TYPE Return
= kdDoNotHandleException
;
198 /* Get out of here if the Debugger isn't connected */
199 if (KdDebuggerNotPresent
) return FALSE
;
202 * Right now, the GDB wrapper seems to handle exceptions differntly
203 * from KDGB and both are called at different times, while the GDB
204 * one is only called once and that's it. I don't really have the knowledge
205 * to fix the GDB stub, so until then, we'll be using this hack
207 if (WrapperInitRoutine
)
209 Return
= WrapperTable
.KdpExceptionRoutine(ExceptionRecord
,
214 /* Debugger didn't handle it, please handle! */
215 if (Return
== kdHandleException
) return FALSE
;
217 /* Debugger handled it */
221 /* PUBLIC FUNCTIONS *********************************************************/
228 KdRefreshDebuggerNotPresent(VOID
)
232 /* Just return whatever was set previously -- FIXME! */
233 return KdDebuggerNotPresent
;
241 KdDisableDebugger(VOID
)
246 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
248 /* TODO: Disable any breakpoints */
250 /* Disable the Debugger */
251 KdDebuggerEnabled
= FALSE
;
254 KeLowerIrql(OldIrql
);
257 return STATUS_SUCCESS
;
265 KdEnableDebugger(VOID
)
270 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
272 /* TODO: Re-enable any breakpoints */
274 /* Enable the Debugger */
275 KdDebuggerEnabled
= TRUE
;
278 KeLowerIrql(OldIrql
);
281 return STATUS_SUCCESS
;
291 return KdpBreakPending
;
299 KdPowerTransition(ULONG PowerState
)
302 return STATUS_NOT_IMPLEMENTED
;
310 KdChangeOption(IN KD_OPTION Option
,
311 IN ULONG InBufferLength OPTIONAL
,
313 IN ULONG OutBufferLength OPTIONAL
,
315 OUT PULONG OutBufferRequiredLength OPTIONAL
)
318 return STATUS_NOT_IMPLEMENTED
;
324 NtQueryDebugFilterState(IN ULONG ComponentId
,
329 /* Convert Level to mask if it isn't already one */
333 /* Check if it is not the default component */
334 if (ComponentId
!= DPFLTR_DEFAULT_ID
)
336 /* No, search for an existing entry in the table */
337 for (i
= 0; i
< KdComponentTableEntries
; i
++)
339 /* Check if it is the right component */
340 if (ComponentId
== KdComponentTable
[i
].ComponentId
)
342 /* Check if mask are matching */
343 return (Level
& KdComponentTable
[i
].Level
) != 0;
348 /* Entry not found in the table, use default mask */
349 return (Level
& Kd_DEFAULT_MASK
) != 0;
354 NtSetDebugFilterState(IN ULONG ComponentId
,
360 /* Convert Level to mask if it isn't already one */
363 Level
&= ~DPFLTR_MASK
;
365 /* Check if it is the default component */
366 if (ComponentId
== DPFLTR_DEFAULT_ID
)
368 /* Yes, modify the default mask */
370 Kd_DEFAULT_MASK
|= Level
;
372 Kd_DEFAULT_MASK
&= ~Level
;
374 return STATUS_SUCCESS
;
377 /* Search for an existing entry */
378 for (i
= 0; i
< KdComponentTableEntries
; i
++ )
380 if (ComponentId
== KdComponentTable
[i
].ComponentId
)
384 /* Check if we have found an existing entry */
385 if (i
== KdComponentTableEntries
)
387 /* Check if we have enough space in the table */
388 if (i
== MAX_KD_COMPONENT_TABLE_ENTRIES
)
389 return STATUS_INVALID_PARAMETER_1
;
391 /* Add a new entry */
392 ++KdComponentTableEntries
;
393 KdComponentTable
[i
].ComponentId
= ComponentId
;
394 KdComponentTable
[i
].Level
= Kd_DEFAULT_MASK
;
397 /* Update entry table */
399 KdComponentTable
[i
].Level
|= Level
;
401 KdComponentTable
[i
].Level
&= ~Level
;
403 return STATUS_SUCCESS
;
411 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
412 IN PVOID InputBuffer
,
413 IN ULONG InputBufferLength
,
414 OUT PVOID OutputBuffer
,
415 IN ULONG OutputBufferLength
,
416 IN OUT PULONG ReturnLength
,
417 IN KPROCESSOR_MODE PreviousMode
)
420 return KdpServiceDispatcher(Command
, InputBuffer
, InputBufferLength
);
423 PKDEBUG_ROUTINE KiDebugRoutine
= KdpEnterDebuggerException
;