2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/kd/kdinit.c
5 * PURPOSE: Kernel Debugger Initializtion
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 TAG('R', 'o', 's', ' '): /* ROS-INTERNAL */
55 switch ((ULONG_PTR
)Buffer1
)
57 case DumpNonPagedPool
:
58 MiDebugDumpNonPagedPool(FALSE
);
62 KeBugCheck(MANUALLY_INITIATED_CRASH
);
65 case DumpNonPagedPoolStats
:
66 MiDebugDumpNonPagedPoolStats(FALSE
);
69 case DumpNewNonPagedPool
:
70 MiDebugDumpNonPagedPool(TRUE
);
73 case DumpNewNonPagedPoolStats
:
74 MiDebugDumpNonPagedPoolStats(TRUE
);
82 PspDumpThreads(FALSE
);
95 HalDisplayString ("Invalid debug service call!\n");
104 KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame
,
105 IN PKEXCEPTION_FRAME ExceptionFrame
,
106 IN PEXCEPTION_RECORD ExceptionRecord
,
108 IN KPROCESSOR_MODE PreviousMode
,
109 IN BOOLEAN SecondChance
)
111 KD_CONTINUE_TYPE Return
;
112 ULONG ExceptionCommand
= ExceptionRecord
->ExceptionInformation
[0];
117 /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
118 if ((ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
) &&
119 (ExceptionRecord
->NumberParameters
> 0) &&
120 ((ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
) ||
121 (ExceptionCommand
== BREAKPOINT_UNLOAD_SYMBOLS
) ||
122 (ExceptionCommand
== BREAKPOINT_COMMAND_STRING
) ||
123 (ExceptionCommand
== BREAKPOINT_PRINT
)))
125 /* Check if this is a debug print */
126 if (ExceptionCommand
== BREAKPOINT_PRINT
)
128 /* Print the string */
129 KdpServiceDispatcher(BREAKPOINT_PRINT
,
130 (PVOID
)ExceptionRecord
->ExceptionInformation
[1],
131 ExceptionRecord
->ExceptionInformation
[2]);
133 else if (ExceptionCommand
== BREAKPOINT_LOAD_SYMBOLS
)
135 /* Load symbols. Currently implemented only for KDBG! */
136 KDB_SYMBOLFILE_HOOK((PANSI_STRING
)ExceptionRecord
->ExceptionInformation
[1],
137 (PKD_SYMBOLS_INFO
)ExceptionRecord
->ExceptionInformation
[2]);
140 /* This we can handle: simply bump EIP */
144 Context
->Pc
+= sizeof(ULONG
);
149 /* Get out of here if the Debugger isn't connected */
150 if (KdDebuggerNotPresent
) return FALSE
;
152 /* Save old EIP value */
154 EipOld
= Context
->Eip
;
157 /* Call KDBG if available */
158 Return
= KdbEnterDebuggerException(ExceptionRecord
,
164 /* Bump EIP over int 3 if debugger did not already change it */
165 if (ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
)
167 //DPRINT1("Address: %p. Return: %d\n", EipOld, Return);
170 /* Debugger didn't handle it, please handle! */
171 if (Return
== kdHandleException
) return FALSE
;
173 /* Debugger handled it */
179 KdpCallGdb(IN PKTRAP_FRAME TrapFrame
,
180 IN PEXCEPTION_RECORD ExceptionRecord
,
183 KD_CONTINUE_TYPE Return
= kdDoNotHandleException
;
185 /* Get out of here if the Debugger isn't connected */
186 if (KdDebuggerNotPresent
) return FALSE
;
189 * Right now, the GDB wrapper seems to handle exceptions differntly
190 * from KDGB and both are called at different times, while the GDB
191 * one is only called once and that's it. I don't really have the knowledge
192 * to fix the GDB stub, so until then, we'll be using this hack
194 if (WrapperInitRoutine
)
196 Return
= WrapperTable
.KdpExceptionRoutine(ExceptionRecord
,
201 /* Debugger didn't handle it, please handle! */
202 if (Return
== kdHandleException
) return FALSE
;
204 /* Debugger handled it */
208 /* PUBLIC FUNCTIONS *********************************************************/
215 KdRefreshDebuggerNotPresent(VOID
)
219 /* Just return whatever was set previously -- FIXME! */
220 return KdDebuggerNotPresent
;
228 KdDisableDebugger(VOID
)
233 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
235 /* TODO: Disable any breakpoints */
237 /* Disable the Debugger */
238 KdDebuggerEnabled
= FALSE
;
241 KeLowerIrql(OldIrql
);
244 return STATUS_SUCCESS
;
252 KdEnableDebugger(VOID
)
257 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
259 /* TODO: Re-enable any breakpoints */
261 /* Enable the Debugger */
262 KdDebuggerEnabled
= TRUE
;
265 KeLowerIrql(OldIrql
);
268 return STATUS_SUCCESS
;
278 return KdpBreakPending
;
286 KdPowerTransition(ULONG PowerState
)
289 return STATUS_NOT_IMPLEMENTED
;
297 KdChangeOption(IN KD_OPTION Option
,
298 IN ULONG InBufferLength OPTIONAL
,
300 IN ULONG OutBufferLength OPTIONAL
,
302 OUT PULONG OutBufferRequiredLength OPTIONAL
)
305 return STATUS_NOT_IMPLEMENTED
;
311 NtQueryDebugFilterState(IN ULONG ComponentId
,
316 /* Convert Level to mask if it isn't already one */
320 /* Check if it is not the default component */
321 if (ComponentId
!= DPFLTR_DEFAULT_ID
)
323 /* No, search for an existing entry in the table */
324 for (i
= 0; i
< KdComponentTableEntries
; i
++)
326 /* Check if it is the right component */
327 if (ComponentId
== KdComponentTable
[i
].ComponentId
)
329 /* Check if mask are matching */
330 return (Level
& KdComponentTable
[i
].Level
) != 0;
335 /* Entry not found in the table, use default mask */
336 return (Level
& Kd_DEFAULT_MASK
) != 0;
341 NtSetDebugFilterState(IN ULONG ComponentId
,
347 /* Convert Level to mask if it isn't already one */
350 Level
&= ~DPFLTR_MASK
;
352 /* Check if it is the default component */
353 if (ComponentId
== DPFLTR_DEFAULT_ID
)
355 /* Yes, modify the default mask */
357 Kd_DEFAULT_MASK
|= Level
;
359 Kd_DEFAULT_MASK
&= ~Level
;
361 return STATUS_SUCCESS
;
364 /* Search for an existing entry */
365 for (i
= 0; i
< KdComponentTableEntries
; i
++ )
367 if (ComponentId
== KdComponentTable
[i
].ComponentId
)
371 /* Check if we have found an existing entry */
372 if (i
== KdComponentTableEntries
)
374 /* Check if we have enough space in the table */
375 if (i
== MAX_KD_COMPONENT_TABLE_ENTRIES
)
376 return STATUS_INVALID_PARAMETER_1
;
378 /* Add a new entry */
379 ++KdComponentTableEntries
;
380 KdComponentTable
[i
].ComponentId
= ComponentId
;
381 KdComponentTable
[i
].Level
= Kd_DEFAULT_MASK
;
384 /* Update entry table */
386 KdComponentTable
[i
].Level
|= Level
;
388 KdComponentTable
[i
].Level
&= ~Level
;
390 return STATUS_SUCCESS
;
398 KdSystemDebugControl(IN SYSDBG_COMMAND Command
,
399 IN PVOID InputBuffer
,
400 IN ULONG InputBufferLength
,
401 OUT PVOID OutputBuffer
,
402 IN ULONG OutputBufferLength
,
403 IN OUT PULONG ReturnLength
,
404 IN KPROCESSOR_MODE PreviousMode
)
407 return KdpServiceDispatcher(Command
, InputBuffer
, InputBufferLength
);
410 PKDEBUG_ROUTINE KiDebugRoutine
= KdpEnterDebuggerException
;