- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception...
[reactos.git] / reactos / ntoskrnl / kd / kdmain.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/kd/kdinit.c
5 * PURPOSE: Kernel Debugger Initializtion
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 */
9
10 #include <ntoskrnl.h>
11 #define NDEBUG
12 #include <internal/debug.h>
13
14 /* VARIABLES ***************************************************************/
15
16 BOOLEAN KdDebuggerEnabled = FALSE;
17 BOOLEAN KdEnteredDebugger = FALSE;
18 BOOLEAN KdDebuggerNotPresent = TRUE;
19 BOOLEAN KiEnableTimerWatchdog = FALSE;
20 BOOLEAN KdBreakAfterSymbolLoad = FALSE;
21 BOOLEAN KdpBreakPending;
22 VOID STDCALL PspDumpThreads(BOOLEAN SystemThreads);
23
24 typedef struct
25 {
26 ULONG ComponentId;
27 ULONG Level;
28 } KD_COMPONENT_DATA;
29 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128
30 KD_COMPONENT_DATA KdComponentTable[MAX_KD_COMPONENT_TABLE_ENTRIES];
31 ULONG KdComponentTableEntries = 0;
32
33 /* PRIVATE FUNCTIONS *********************************************************/
34
35 ULONG
36 STDCALL
37 KdpServiceDispatcher(ULONG Service,
38 PVOID Buffer1,
39 ULONG Buffer1Length)
40 {
41 ULONG Result = 0;
42
43 switch (Service)
44 {
45 case BREAKPOINT_PRINT: /* DbgPrint */
46 Result = KdpPrintString(Buffer1, Buffer1Length);
47 break;
48
49 #ifdef DBG
50 case TAG('R', 'o', 's', ' '): /* ROS-INTERNAL */
51 {
52 switch ((ULONG)Buffer1)
53 {
54 case DumpNonPagedPool:
55 MiDebugDumpNonPagedPool(FALSE);
56 break;
57
58 case ManualBugCheck:
59 KEBUGCHECK(MANUALLY_INITIATED_CRASH);
60 break;
61
62 case DumpNonPagedPoolStats:
63 MiDebugDumpNonPagedPoolStats(FALSE);
64 break;
65
66 case DumpNewNonPagedPool:
67 MiDebugDumpNonPagedPool(TRUE);
68 break;
69
70 case DumpNewNonPagedPoolStats:
71 MiDebugDumpNonPagedPoolStats(TRUE);
72 break;
73
74 case DumpAllThreads:
75 PspDumpThreads(TRUE);
76 break;
77
78 case DumpUserThreads:
79 PspDumpThreads(FALSE);
80 break;
81
82 case EnterDebugger:
83 DbgBreakPoint();
84 break;
85
86 default:
87 break;
88 }
89 }
90 #endif
91 default:
92 HalDisplayString ("Invalid debug service call!\n");
93 break;
94 }
95
96 return Result;
97 }
98
99 BOOLEAN
100 NTAPI
101 KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame,
102 IN PKEXCEPTION_FRAME ExceptionFrame,
103 IN PEXCEPTION_RECORD ExceptionRecord,
104 IN PCONTEXT Context,
105 IN KPROCESSOR_MODE PreviousMode,
106 IN BOOLEAN SecondChance)
107 {
108 KD_CONTINUE_TYPE Return;
109
110 /* HACK (just like all this routine */
111 if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) Context->Eip++;
112
113 /* Get out of here if the Debugger isn't connected */
114 if (KdDebuggerNotPresent) return FALSE;
115
116 /* Call KDBG if available */
117 Return = KdbEnterDebuggerException(ExceptionRecord,
118 PreviousMode,
119 Context,
120 TrapFrame,
121 !SecondChance);
122
123 /* Convert return to BOOLEAN */
124 if (Return == kdContinue) return TRUE;
125 return FALSE;
126 }
127
128 BOOLEAN
129 NTAPI
130 KdpCallGdb(IN PKTRAP_FRAME TrapFrame,
131 IN PEXCEPTION_RECORD ExceptionRecord,
132 IN PCONTEXT Context)
133 {
134 KD_CONTINUE_TYPE Return = kdDoNotHandleException;
135
136 /* Get out of here if the Debugger isn't connected */
137 if (KdDebuggerNotPresent) return FALSE;
138
139 /* FIXME:
140 * Right now, the GDB wrapper seems to handle exceptions differntly
141 * from KDGB and both are called at different times, while the GDB
142 * one is only called once and that's it. I don't really have the knowledge
143 * to fix the GDB stub, so until then, we'll be using this hack
144 */
145 if (WrapperInitRoutine)
146 {
147 Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord,
148 Context,
149 TrapFrame);
150 }
151
152 /* Convert return to BOOLEAN */
153 if (Return == kdContinue) return TRUE;
154 return FALSE;
155 }
156
157 /* PUBLIC FUNCTIONS *********************************************************/
158
159 /*
160 * @implemented
161 */
162 NTSTATUS
163 STDCALL
164 KdDisableDebugger(VOID)
165 {
166 KIRQL OldIrql;
167
168 /* Raise IRQL */
169 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
170
171 /* TODO: Disable any breakpoints */
172
173 /* Disable the Debugger */
174 KdDebuggerEnabled = FALSE;
175
176 /* Lower the IRQL */
177 KeLowerIrql(OldIrql);
178
179 /* Return success */
180 return STATUS_SUCCESS;
181 }
182
183 /*
184 * @implemented
185 */
186 NTSTATUS
187 STDCALL
188 KdEnableDebugger(VOID)
189 {
190 KIRQL OldIrql;
191
192 /* Raise IRQL */
193 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
194
195 /* TODO: Re-enable any breakpoints */
196
197 /* Enable the Debugger */
198 KdDebuggerEnabled = TRUE;
199
200 /* Lower the IRQL */
201 KeLowerIrql(OldIrql);
202
203 /* Return success */
204 return STATUS_SUCCESS;
205 }
206
207 /*
208 * @implemented
209 */
210 BOOLEAN
211 STDCALL
212 KdPollBreakIn(VOID)
213 {
214 return KdpBreakPending;
215 }
216
217 /*
218 * @implemented
219 */
220 VOID
221 STDCALL
222 KeEnterKernelDebugger(VOID)
223 {
224 HalDisplayString("\n\n *** Entered kernel debugger ***\n");
225
226 /* Set the Variable */
227 KdEnteredDebugger = TRUE;
228
229 /* Halt the CPU */
230 for (;;) Ke386HaltProcessor();
231 }
232
233 /*
234 * @unimplemented
235 */
236 NTSTATUS
237 STDCALL
238 KdPowerTransition(ULONG PowerState)
239 {
240 UNIMPLEMENTED;
241 return STATUS_NOT_IMPLEMENTED;
242 }
243
244 /*
245 * @unimplemented
246 */
247 VOID
248 STDCALL
249 KdChangeOption(IN KD_OPTION Option,
250 IN ULONG InBufferLength OPTIONAL,
251 IN PVOID InBuffer,
252 IN ULONG OutBufferLength OPTIONAL,
253 OUT PVOID OutBuffer,
254 OUT PULONG OutBufferRequiredLength OPTIONAL)
255 {
256 UNIMPLEMENTED;
257 }
258
259
260 NTSTATUS
261 STDCALL
262 NtQueryDebugFilterState(IN ULONG ComponentId,
263 IN ULONG Level)
264 {
265 unsigned int i;
266
267 /* convert Level to mask if it isn't already one */
268 if ( Level < 32 )
269 Level = 1 << Level;
270
271 for ( i = 0; i < KdComponentTableEntries; i++ )
272 {
273 if ( ComponentId == KdComponentTable[i].ComponentId )
274 {
275 if ( Level & KdComponentTable[i].Level )
276 return TRUE;
277 break;
278 }
279 }
280 return FALSE;
281 }
282
283 NTSTATUS
284 STDCALL
285 NtSetDebugFilterState(IN ULONG ComponentId,
286 IN ULONG Level,
287 IN BOOLEAN State)
288 {
289 unsigned int i;
290 for ( i = 0; i < KdComponentTableEntries; i++ )
291 {
292 if ( ComponentId == KdComponentTable[i].ComponentId )
293 break;
294 }
295 if ( i == KdComponentTableEntries )
296 {
297 if ( i == MAX_KD_COMPONENT_TABLE_ENTRIES )
298 return STATUS_INVALID_PARAMETER_1;
299 ++KdComponentTableEntries;
300 KdComponentTable[i].ComponentId = ComponentId;
301 KdComponentTable[i].Level = 0;
302 }
303 if ( State )
304 KdComponentTable[i].Level |= Level;
305 else
306 KdComponentTable[i].Level &= ~Level;
307 return STATUS_SUCCESS;
308 }
309
310 PKDEBUG_ROUTINE KiDebugRoutine = KdpEnterDebuggerException;
311
312 /* EOF */