Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenkdmain.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel 00004 * FILE: ntoskrnl/kd/kdinit.c 00005 * PURPOSE: Kernel Debugger Initialization 00006 * 00007 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 00008 */ 00009 00010 #include <ntoskrnl.h> 00011 #define NDEBUG 00012 #include <debug.h> 00013 00014 /* VARIABLES ***************************************************************/ 00015 00016 BOOLEAN KdDebuggerEnabled = FALSE; 00017 BOOLEAN KdEnteredDebugger = FALSE; 00018 BOOLEAN KdDebuggerNotPresent = TRUE; 00019 BOOLEAN KdBreakAfterSymbolLoad = FALSE; 00020 BOOLEAN KdpBreakPending = FALSE; 00021 BOOLEAN KdPitchDebugger = TRUE; 00022 BOOLEAN KdIgnoreUmExceptions = FALSE; 00023 KD_CONTEXT KdpContext; 00024 ULONG Kd_WIN2000_Mask; 00025 VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads); 00026 00027 typedef struct 00028 { 00029 ULONG ComponentId; 00030 ULONG Level; 00031 } KD_COMPONENT_DATA; 00032 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128 00033 KD_COMPONENT_DATA KdComponentTable[MAX_KD_COMPONENT_TABLE_ENTRIES]; 00034 ULONG KdComponentTableEntries = 0; 00035 00036 ULONG Kd_DEFAULT_MASK = 1 << DPFLTR_ERROR_LEVEL; 00037 00038 /* PRIVATE FUNCTIONS *********************************************************/ 00039 00040 ULONG 00041 NTAPI 00042 KdpServiceDispatcher(ULONG Service, 00043 PVOID Buffer1, 00044 ULONG Buffer1Length) 00045 { 00046 ULONG Result = 0; 00047 00048 switch (Service) 00049 { 00050 case BREAKPOINT_PRINT: /* DbgPrint */ 00051 Result = KdpPrintString(Buffer1, Buffer1Length); 00052 break; 00053 00054 #if DBG 00055 case ' soR': /* ROS-INTERNAL */ 00056 { 00057 switch ((ULONG_PTR)Buffer1) 00058 { 00059 case DumpAllThreads: 00060 PspDumpThreads(TRUE); 00061 break; 00062 00063 case DumpUserThreads: 00064 PspDumpThreads(FALSE); 00065 break; 00066 00067 case KdSpare3: 00068 MmDumpArmPfnDatabase(FALSE); 00069 break; 00070 00071 default: 00072 break; 00073 } 00074 break; 00075 } 00076 00077 /* Register a debug callback */ 00078 case 'CsoR': 00079 { 00080 switch (Buffer1Length) 00081 { 00082 case ID_Win32PreServiceHook: 00083 KeWin32PreServiceHook = Buffer1; 00084 break; 00085 00086 case ID_Win32PostServiceHook: 00087 KeWin32PostServiceHook = Buffer1; 00088 break; 00089 00090 } 00091 break; 00092 } 00093 00094 /* Special case for stack frame dumps */ 00095 case 'DsoR': 00096 { 00097 KeRosDumpStackFrames((PULONG)Buffer1, Buffer1Length); 00098 break; 00099 } 00100 #endif 00101 default: 00102 HalDisplayString ("Invalid debug service call!\n"); 00103 break; 00104 } 00105 00106 return Result; 00107 } 00108 00109 BOOLEAN 00110 NTAPI 00111 KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame, 00112 IN PKEXCEPTION_FRAME ExceptionFrame, 00113 IN PEXCEPTION_RECORD ExceptionRecord, 00114 IN PCONTEXT Context, 00115 IN KPROCESSOR_MODE PreviousMode, 00116 IN BOOLEAN SecondChance) 00117 { 00118 KD_CONTINUE_TYPE Return = kdHandleException; 00119 ULONG ExceptionCommand = ExceptionRecord->ExceptionInformation[0]; 00120 00121 /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */ 00122 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00123 (ExceptionRecord->NumberParameters > 0) && 00124 ((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) || 00125 (ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) || 00126 (ExceptionCommand == BREAKPOINT_COMMAND_STRING) || 00127 (ExceptionCommand == BREAKPOINT_PRINT) || 00128 (ExceptionCommand == BREAKPOINT_PROMPT))) 00129 { 00130 /* Check if this is a debug print */ 00131 if (ExceptionCommand == BREAKPOINT_PRINT) 00132 { 00133 /* Print the string */ 00134 KdpServiceDispatcher(BREAKPOINT_PRINT, 00135 (PVOID)ExceptionRecord->ExceptionInformation[1], 00136 ExceptionRecord->ExceptionInformation[2]); 00137 00138 /* Return success */ 00139 KeSetContextReturnRegister(Context, STATUS_SUCCESS); 00140 } 00141 #ifdef KDBG 00142 else if (ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) 00143 { 00144 PLDR_DATA_TABLE_ENTRY LdrEntry; 00145 00146 /* Load symbols. Currently implemented only for KDBG! */ 00147 if(KdbpSymFindModule(((PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2])->BaseOfDll, NULL, -1, &LdrEntry)) 00148 KdbSymProcessSymbols(LdrEntry); 00149 } 00150 else if (ExceptionCommand == BREAKPOINT_PROMPT) 00151 { 00152 ULONG ReturnValue; 00153 LPSTR OutString; 00154 USHORT OutStringLength; 00155 00156 /* Get the response string and length */ 00157 OutString = (LPSTR)Context->Ebx; 00158 OutStringLength = (USHORT)Context->Edi; 00159 00160 /* Call KDBG */ 00161 ReturnValue = KdpPrompt((LPSTR)ExceptionRecord-> 00162 ExceptionInformation[1], 00163 (USHORT)ExceptionRecord-> 00164 ExceptionInformation[2], 00165 OutString, 00166 OutStringLength); 00167 00168 /* Return the number of characters that we received */ 00169 Context->Eax = ReturnValue; 00170 } 00171 #endif 00172 00173 /* This we can handle: simply bump the Program Counter */ 00174 KeSetContextPc(Context, KeGetContextPc(Context) + KD_BREAKPOINT_SIZE); 00175 return TRUE; 00176 } 00177 00178 #ifdef KDBG 00179 /* Check if this is an assertion failure */ 00180 if (ExceptionRecord->ExceptionCode == STATUS_ASSERTION_FAILURE) 00181 { 00182 /* Warn about it */ 00183 DbgPrint("\n!!! Assertion Failure at Address 0x%p !!!\n\n", 00184 (PVOID)Context->Eip); 00185 00186 /* Bump EIP to the instruction following the int 2C and return */ 00187 Context->Eip += 2; 00188 return TRUE; 00189 } 00190 #endif 00191 00192 /* Get out of here if the Debugger isn't connected */ 00193 if (KdDebuggerNotPresent) return FALSE; 00194 00195 #ifdef KDBG 00196 /* Call KDBG if available */ 00197 Return = KdbEnterDebuggerException(ExceptionRecord, 00198 PreviousMode, 00199 Context, 00200 TrapFrame, 00201 !SecondChance); 00202 #else /* not KDBG */ 00203 if (WrapperInitRoutine) 00204 { 00205 /* Call GDB */ 00206 Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord, 00207 Context, 00208 TrapFrame); 00209 } 00210 #endif /* not KDBG */ 00211 00212 /* Debugger didn't handle it, please handle! */ 00213 if (Return == kdHandleException) return FALSE; 00214 00215 /* Debugger handled it */ 00216 return TRUE; 00217 } 00218 00219 BOOLEAN 00220 NTAPI 00221 KdpCallGdb(IN PKTRAP_FRAME TrapFrame, 00222 IN PEXCEPTION_RECORD ExceptionRecord, 00223 IN PCONTEXT Context) 00224 { 00225 KD_CONTINUE_TYPE Return = kdDoNotHandleException; 00226 00227 /* Get out of here if the Debugger isn't connected */ 00228 if (KdDebuggerNotPresent) return FALSE; 00229 00230 /* FIXME: 00231 * Right now, the GDB wrapper seems to handle exceptions differntly 00232 * from KDGB and both are called at different times, while the GDB 00233 * one is only called once and that's it. I don't really have the knowledge 00234 * to fix the GDB stub, so until then, we'll be using this hack 00235 */ 00236 if (WrapperInitRoutine) 00237 { 00238 Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord, 00239 Context, 00240 TrapFrame); 00241 } 00242 00243 /* Debugger didn't handle it, please handle! */ 00244 if (Return == kdHandleException) return FALSE; 00245 00246 /* Debugger handled it */ 00247 return TRUE; 00248 } 00249 00250 BOOLEAN 00251 NTAPI 00252 KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord, 00253 IN PCONTEXT Context, 00254 IN KPROCESSOR_MODE PreviousMode) 00255 { 00256 /* KDBG has its own mechanism for ignoring user mode exceptions */ 00257 return FALSE; 00258 } 00259 00260 /* PUBLIC FUNCTIONS *********************************************************/ 00261 00262 /* 00263 * @implemented 00264 */ 00265 BOOLEAN 00266 NTAPI 00267 KdRefreshDebuggerNotPresent(VOID) 00268 { 00269 UNIMPLEMENTED; 00270 00271 /* Just return whatever was set previously -- FIXME! */ 00272 return KdDebuggerNotPresent; 00273 } 00274 00275 /* 00276 * @implemented 00277 */ 00278 NTSTATUS 00279 NTAPI 00280 KdDisableDebugger(VOID) 00281 { 00282 KIRQL OldIrql; 00283 00284 /* Raise IRQL */ 00285 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00286 00287 /* TODO: Disable any breakpoints */ 00288 00289 /* Disable the Debugger */ 00290 KdDebuggerEnabled = FALSE; 00291 00292 /* Lower the IRQL */ 00293 KeLowerIrql(OldIrql); 00294 00295 /* Return success */ 00296 return STATUS_SUCCESS; 00297 } 00298 00299 /* 00300 * @implemented 00301 */ 00302 NTSTATUS 00303 NTAPI 00304 KdEnableDebugger(VOID) 00305 { 00306 KIRQL OldIrql; 00307 00308 /* Raise IRQL */ 00309 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00310 00311 /* TODO: Re-enable any breakpoints */ 00312 00313 /* Enable the Debugger */ 00314 KdDebuggerEnabled = TRUE; 00315 00316 /* Lower the IRQL */ 00317 KeLowerIrql(OldIrql); 00318 00319 /* Return success */ 00320 return STATUS_SUCCESS; 00321 } 00322 00323 /* 00324 * @implemented 00325 */ 00326 BOOLEAN 00327 NTAPI 00328 KdPollBreakIn(VOID) 00329 { 00330 return KdpBreakPending; 00331 } 00332 00333 /* 00334 * @unimplemented 00335 */ 00336 NTSTATUS 00337 NTAPI 00338 KdPowerTransition(ULONG PowerState) 00339 { 00340 UNIMPLEMENTED; 00341 return STATUS_NOT_IMPLEMENTED; 00342 } 00343 00344 /* 00345 * @unimplemented 00346 */ 00347 NTSTATUS 00348 NTAPI 00349 KdChangeOption(IN KD_OPTION Option, 00350 IN ULONG InBufferLength OPTIONAL, 00351 IN PVOID InBuffer, 00352 IN ULONG OutBufferLength OPTIONAL, 00353 OUT PVOID OutBuffer, 00354 OUT PULONG OutBufferRequiredLength OPTIONAL) 00355 { 00356 UNIMPLEMENTED; 00357 return STATUS_NOT_IMPLEMENTED; 00358 } 00359 00360 00361 NTSTATUS 00362 NTAPI 00363 NtQueryDebugFilterState(IN ULONG ComponentId, 00364 IN ULONG Level) 00365 { 00366 ULONG i; 00367 00368 /* Convert Level to mask if it isn't already one */ 00369 if (Level < 32) 00370 Level = 1 << Level; 00371 00372 /* Check if it is not the default component */ 00373 if (ComponentId != DPFLTR_DEFAULT_ID) 00374 { 00375 /* No, search for an existing entry in the table */ 00376 for (i = 0; i < KdComponentTableEntries; i++) 00377 { 00378 /* Check if it is the right component */ 00379 if (ComponentId == KdComponentTable[i].ComponentId) 00380 { 00381 /* Check if mask are matching */ 00382 return (Level & KdComponentTable[i].Level) ? TRUE : FALSE; 00383 } 00384 } 00385 } 00386 00387 /* Entry not found in the table, use default mask */ 00388 return (Level & Kd_DEFAULT_MASK) ? TRUE : FALSE; 00389 } 00390 00391 NTSTATUS 00392 NTAPI 00393 NtSetDebugFilterState(IN ULONG ComponentId, 00394 IN ULONG Level, 00395 IN BOOLEAN State) 00396 { 00397 ULONG i; 00398 00399 /* Convert Level to mask if it isn't already one */ 00400 if (Level < 32) 00401 Level = 1 << Level; 00402 Level &= ~DPFLTR_MASK; 00403 00404 /* Check if it is the default component */ 00405 if (ComponentId == DPFLTR_DEFAULT_ID) 00406 { 00407 /* Yes, modify the default mask */ 00408 if (State) 00409 Kd_DEFAULT_MASK |= Level; 00410 else 00411 Kd_DEFAULT_MASK &= ~Level; 00412 00413 return STATUS_SUCCESS; 00414 } 00415 00416 /* Search for an existing entry */ 00417 for (i = 0; i < KdComponentTableEntries; i++ ) 00418 { 00419 if (ComponentId == KdComponentTable[i].ComponentId) 00420 break; 00421 } 00422 00423 /* Check if we have found an existing entry */ 00424 if (i == KdComponentTableEntries) 00425 { 00426 /* Check if we have enough space in the table */ 00427 if (i == MAX_KD_COMPONENT_TABLE_ENTRIES) 00428 return STATUS_INVALID_PARAMETER_1; 00429 00430 /* Add a new entry */ 00431 ++KdComponentTableEntries; 00432 KdComponentTable[i].ComponentId = ComponentId; 00433 KdComponentTable[i].Level = Kd_DEFAULT_MASK; 00434 } 00435 00436 /* Update entry table */ 00437 if (State) 00438 KdComponentTable[i].Level |= Level; 00439 else 00440 KdComponentTable[i].Level &= ~Level; 00441 00442 return STATUS_SUCCESS; 00443 } 00444 00445 /* 00446 * @unimplemented 00447 */ 00448 NTSTATUS 00449 NTAPI 00450 KdSystemDebugControl(IN SYSDBG_COMMAND Command, 00451 IN PVOID InputBuffer, 00452 IN ULONG InputBufferLength, 00453 OUT PVOID OutputBuffer, 00454 IN ULONG OutputBufferLength, 00455 IN OUT PULONG ReturnLength, 00456 IN KPROCESSOR_MODE PreviousMode) 00457 { 00458 /* HACK */ 00459 return KdpServiceDispatcher(Command, InputBuffer, InputBufferLength); 00460 } 00461 00462 PKDEBUG_ROUTINE KiDebugRoutine = KdpEnterDebuggerException; 00463 00464 /* EOF */ Generated on Sat May 26 2012 04:36:14 for ReactOS by
1.7.6.1
|