Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

kdtrap.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 kdtrap.c 00008 00009 Abstract: 00010 00011 This module contains code to implement the target side of the portable 00012 kernel debugger. 00013 00014 Author: 00015 00016 Bryan M. Willman (bryanwi) 25-Sep-90 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "kdp.h" 00023 00024 // 00025 // externs 00026 // 00027 extern PUCHAR KdpCopyDataToStack(PUCHAR, ULONG); 00028 00029 #ifdef ALLOC_PRAGMA 00030 #pragma alloc_text(PAGEKD, KdpTrap) 00031 #pragma alloc_text(PAGEKD, KdIsThisAKdTrap) 00032 #endif 00033 00034 00035 00036 00037 BOOLEAN 00038 KdpTrap ( 00039 IN PKTRAP_FRAME TrapFrame, 00040 IN PKEXCEPTION_FRAME ExceptionFrame, 00041 IN PEXCEPTION_RECORD ExceptionRecord, 00042 IN PCONTEXT ContextRecord, 00043 IN KPROCESSOR_MODE PreviousMode, 00044 IN BOOLEAN SecondChance 00045 ) 00046 00047 /*++ 00048 00049 Routine Description: 00050 00051 This routine is called whenever a exception is dispatched and the kernel 00052 debugger is active. 00053 00054 Arguments: 00055 00056 TrapFrame - Supplies a pointer to a trap frame that describes the 00057 trap. 00058 00059 ExceptionFrame - Supplies a pointer to a exception frame that describes 00060 the trap. 00061 00062 ExceptionRecord - Supplies a pointer to an exception record that 00063 describes the exception. 00064 00065 ContextRecord - Supplies the context at the time of the exception. 00066 00067 PreviousMode - Supplies the previous processor mode. 00068 00069 SecondChance - Supplies a boolean value that determines whether this is 00070 the second chance (TRUE) that the exception has been raised. 00071 00072 Return Value: 00073 00074 A value of TRUE is returned if the exception is handled. Otherwise a 00075 value of FALSE is returned. 00076 00077 --*/ 00078 00079 { 00080 00081 BOOLEAN Completion = FALSE; 00082 BOOLEAN Enable; 00083 BOOLEAN UnloadSymbols = FALSE; 00084 ULONG RetValue; 00085 STRING String, ReplyString; 00086 PUCHAR Buffer; 00087 PKD_SYMBOLS_INFO SymbolInfo; 00088 PVOID SavedEsp; 00089 PKPRCB Prcb; 00090 ULONG OldEip; 00091 00092 _asm { 00093 // 00094 // Save esp on ebp frame so c-runtime registers are restored correctly 00095 // 00096 00097 mov SavedEsp, esp 00098 } 00099 00100 // 00101 // Print, Prompt, Load symbols, Unload symbols, are all special 00102 // cases of STATUS_BREAKPOINT 00103 // 00104 00105 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00106 (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK)) { 00107 00108 // 00109 // We have one of the support functions. 00110 // 00111 00112 if (KdDebuggerNotPresent && 00113 ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_PROMPT) { 00114 ContextRecord->Eip++; 00115 return(TRUE); 00116 } 00117 00118 00119 // 00120 // Since some of these functions can be entered from user mode, 00121 // we hold off entering the debugger until the user mode buffers 00122 // are copied. (Because they may not be present in memory, and 00123 // they must be paged in before we raise Irql to the 00124 // Highest level.) 00125 // 00126 // 00127 00128 OldEip = ContextRecord->Eip; 00129 00130 switch (ExceptionRecord->ExceptionInformation[0]) { 00131 00132 // 00133 // ExceptionInformation[1] is PSTRING to print 00134 // 00135 00136 case BREAKPOINT_PRINT: 00137 00138 if (PreviousMode == UserMode) { 00139 00140 EXCEPTION_RECORD exr; 00141 // 00142 // Move user mode parameters to kernel stack 00143 // 00144 00145 try { 00146 String = *((PSTRING)ExceptionRecord->ExceptionInformation[1]); 00147 if (String.Length > 512) { 00148 break; 00149 } 00150 ProbeForRead(String.Buffer, String.Length, sizeof(UCHAR)); 00151 String.Buffer = 00152 KdpCopyDataToStack(String.Buffer, String.Length); 00153 00154 } except ((exr = *((GetExceptionInformation())->ExceptionRecord), EXCEPTION_EXECUTE_HANDLER)) { 00155 00156 // 00157 // If an exception occurs then don't handle 00158 // this DebugService request. 00159 // 00160 00161 break; 00162 } 00163 00164 } else { 00165 String = *((PSTRING)ExceptionRecord->ExceptionInformation[1]); 00166 } 00167 00168 KdLogDbgPrint(&String); 00169 00170 if ((NtGlobalFlag & FLG_DISABLE_DBGPRINT) == 0) { 00171 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); 00172 if (KdpPrintString(&String)) { 00173 ContextRecord->Eax = (ULONG)(STATUS_BREAKPOINT); 00174 } else { 00175 ContextRecord->Eax = STATUS_SUCCESS; 00176 } 00177 KdExitDebugger(Enable); 00178 } 00179 00180 Completion = TRUE; 00181 break; 00182 00183 // 00184 // ExceptionInformation[1] is prompt string, 00185 // ExceptionInformation[2] is return string 00186 // 00187 00188 case BREAKPOINT_PROMPT: 00189 if (PreviousMode == UserMode) { 00190 00191 // 00192 // Move user mode parameters to kernel stack 00193 // 00194 00195 00196 try { 00197 String = *((PSTRING)ExceptionRecord->ExceptionInformation[1]); 00198 if (String.Length > 512) { 00199 break; 00200 } 00201 ProbeForRead(String.Buffer, String.Length, sizeof(CHAR)); 00202 String.Buffer = 00203 KdpCopyDataToStack(String.Buffer, String.Length); 00204 00205 ReplyString = *((PSTRING)ExceptionRecord->ExceptionInformation[2]); 00206 if (ReplyString.MaximumLength > 512) { 00207 break; 00208 } 00209 ProbeForWrite(ReplyString.Buffer, 00210 ReplyString.MaximumLength, 00211 sizeof(CHAR)); 00212 Buffer = ReplyString.Buffer; 00213 ReplyString.Buffer = 00214 KdpCopyDataToStack( 00215 ReplyString.Buffer, 00216 ReplyString.MaximumLength 00217 ); 00218 00219 } except (EXCEPTION_EXECUTE_HANDLER) { 00220 00221 // 00222 // If an exception occurs then don't handle 00223 // this DebugService request. 00224 // 00225 00226 break; 00227 } 00228 } else { 00229 String = *((PSTRING)ExceptionRecord->ExceptionInformation[1]); 00230 ReplyString = *((PSTRING)ExceptionRecord->ExceptionInformation[2]); 00231 } 00232 00233 // 00234 // Prompt, keep prompting until no breakin seen. 00235 // 00236 00237 KdLogDbgPrint(&String); 00238 00239 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); 00240 do { 00241 RetValue = KdpPromptString(&String, &ReplyString); 00242 } while (RetValue == TRUE); 00243 00244 ContextRecord->Eax = ReplyString.Length; 00245 KdExitDebugger(Enable); 00246 00247 if (PreviousMode == UserMode) { 00248 00249 // 00250 // Restore user mode return parameters 00251 // 00252 00253 try { 00254 KdpQuickMoveMemory( 00255 Buffer, 00256 ReplyString.Buffer, 00257 ReplyString.Length 00258 ); 00259 } except (EXCEPTION_EXECUTE_HANDLER) { 00260 00261 // 00262 // If an exception occurs then don't handle 00263 // this DebugService request. 00264 // 00265 00266 break; 00267 } 00268 } 00269 00270 Completion = TRUE; 00271 break; 00272 00273 // 00274 // ExceptionInformation[1] is file name of new module 00275 // ExceptionInformaiton[2] is the base of the dll 00276 // 00277 00278 case BREAKPOINT_UNLOAD_SYMBOLS: 00279 UnloadSymbols = TRUE; 00280 00281 // 00282 // Fall through 00283 // 00284 00285 case BREAKPOINT_LOAD_SYMBOLS: 00286 00287 if (PreviousMode != KernelMode) { 00288 break; 00289 } 00290 00291 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); 00292 00293 // 00294 // Save and restore the processor context in case the 00295 // kernel debugger has been configured to stop on dll 00296 // loads. 00297 // 00298 00299 Prcb = KeGetCurrentPrcb(); 00300 KiSaveProcessorControlState(&Prcb->ProcessorState); 00301 RtlCopyMemory(&Prcb->ProcessorState.ContextFrame, 00302 ContextRecord, 00303 sizeof(CONTEXT)); 00304 00305 SymbolInfo = (PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2]; 00306 Completion = 00307 KdpReportLoadSymbolsStateChange((PSTRING)ExceptionRecord->ExceptionInformation[1], 00308 SymbolInfo, 00309 UnloadSymbols, 00310 &Prcb->ProcessorState.ContextFrame); 00311 00312 RtlCopyMemory(ContextRecord, 00313 &Prcb->ProcessorState.ContextFrame, 00314 sizeof (CONTEXT) ); 00315 00316 KiRestoreProcessorControlState(&Prcb->ProcessorState); 00317 00318 KdExitDebugger(Enable); 00319 break; 00320 00321 // 00322 // Unknown command 00323 // 00324 00325 default: 00326 // return FALSE 00327 break; 00328 } 00329 // 00330 // If the kernel debugger did not update the EIP, then increment 00331 // past the breakpoint instruction. 00332 // 00333 00334 if (ContextRecord->Eip == OldEip) { 00335 ContextRecord->Eip++; 00336 } 00337 00338 00339 } else { 00340 00341 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) || 00342 (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) || 00343 (NtGlobalFlag & FLG_STOP_ON_EXCEPTION) || 00344 SecondChance) { 00345 00346 if (!SecondChance && 00347 (ExceptionRecord->ExceptionCode == STATUS_PORT_DISCONNECTED || 00348 NT_SUCCESS( ExceptionRecord->ExceptionCode ) 00349 ) 00350 ) { 00351 // 00352 // User does not really want to see these either. 00353 // so do NOT report it to debugger. 00354 // 00355 00356 return FALSE; 00357 } 00358 00359 // 00360 // Report state change to kernel debugger on host 00361 // 00362 00363 00364 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); 00365 Prcb = KeGetCurrentPrcb(); 00366 KiSaveProcessorControlState(&Prcb->ProcessorState); 00367 RtlCopyMemory(&Prcb->ProcessorState.ContextFrame, 00368 ContextRecord, 00369 sizeof (CONTEXT)); 00370 00371 Completion = 00372 KdpReportExceptionStateChange(ExceptionRecord, 00373 &Prcb->ProcessorState.ContextFrame, 00374 SecondChance); 00375 00376 RtlCopyMemory(ContextRecord, 00377 &Prcb->ProcessorState.ContextFrame, 00378 sizeof(CONTEXT)); 00379 00380 KiRestoreProcessorControlState(&Prcb->ProcessorState); 00381 KdExitDebugger(Enable); 00382 00383 KdpControlCPressed = FALSE; 00384 00385 } else { 00386 00387 // 00388 // This is real exception that user doesn't want to see, 00389 // so do NOT report it to debugger. 00390 // 00391 00392 // return FALSE; 00393 } 00394 } 00395 00396 _asm { 00397 mov esp, SavedEsp 00398 } 00399 return Completion; 00400 00401 UNREFERENCED_PARAMETER(PreviousMode); 00402 } 00403 00404 00405 BOOLEAN 00406 KdIsThisAKdTrap ( 00407 IN PEXCEPTION_RECORD ExceptionRecord, 00408 IN PCONTEXT ContextRecord, 00409 IN KPROCESSOR_MODE PreviousMode 00410 ) 00411 00412 /*++ 00413 00414 Routine Description: 00415 00416 This routine is called whenever a user-mode exception occurs and 00417 it might be a kernel debugger exception (Like DbgPrint/DbgPrompt ). 00418 00419 Arguments: 00420 00421 ExceptionRecord - Supplies a pointer to an exception record that 00422 describes the exception. 00423 00424 ContextRecord - Supplies the context at the time of the exception. 00425 00426 PreviousMode - Supplies the previous processor mode. 00427 00428 Return Value: 00429 00430 A value of TRUE is returned if this is for the kernel debugger. 00431 Otherwise, a value of FALSE is returned. 00432 00433 --*/ 00434 00435 { 00436 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00437 (ExceptionRecord->NumberParameters > 0) && 00438 (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK)) { 00439 00440 return TRUE; 00441 } else { 00442 return FALSE; 00443 } 00444 UNREFERENCED_PARAMETER(ContextRecord); 00445 } 00446 00447 BOOLEAN 00448 KdpCheckTracePoint( 00449 IN PEXCEPTION_RECORD ExceptionRecord, 00450 IN OUT PCONTEXT ContextRecord 00451 ); 00452 00453 VOID 00454 SaveSymLoad( 00455 IN PSTRING PathName, 00456 IN PVOID BaseOfDll, 00457 IN LONG ProcessId, 00458 IN BOOLEAN UnloadSymbols 00459 ); 00460 00461 BOOLEAN 00462 KdpStub ( 00463 IN PKTRAP_FRAME TrapFrame, 00464 IN PKEXCEPTION_FRAME ExceptionFrame, 00465 IN PEXCEPTION_RECORD ExceptionRecord, 00466 IN PCONTEXT ContextRecord, 00467 IN KPROCESSOR_MODE PreviousMode, 00468 IN BOOLEAN SecondChance 00469 ) 00470 00471 /*++ 00472 00473 Routine Description: 00474 00475 This routine provides a kernel debugger stub routine to catch debug 00476 prints in a checked system when the kernel debugger is not active. 00477 00478 Arguments: 00479 00480 TrapFrame - Supplies a pointer to a trap frame that describes the 00481 trap. 00482 00483 ExceptionFrame - Supplies a pointer to a exception frame that describes 00484 the trap. 00485 00486 ExceptionRecord - Supplies a pointer to an exception record that 00487 describes the exception. 00488 00489 ContextRecord - Supplies the context at the time of the exception. 00490 00491 PreviousMode - Supplies the previous processor mode. 00492 00493 SecondChance - Supplies a boolean value that determines whether this is 00494 the second chance (TRUE) that the exception has been raised. 00495 00496 Return Value: 00497 00498 A value of TRUE is returned if the exception is handled. Otherwise a 00499 value of FALSE is returned. 00500 00501 --*/ 00502 00503 { 00504 PULONG SymbolArgs; 00505 // 00506 // If the breakpoint is a debug print, then return TRUE. Otherwise, 00507 // return FALSE. 00508 // 00509 00510 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00511 (ExceptionRecord->NumberParameters > 0) && 00512 ((ExceptionRecord->ExceptionInformation[0] == BREAKPOINT_LOAD_SYMBOLS)|| 00513 (ExceptionRecord->ExceptionInformation[0] == BREAKPOINT_UNLOAD_SYMBOLS)|| 00514 (ExceptionRecord->ExceptionInformation[0] == BREAKPOINT_PRINT))) { 00515 00516 ContextRecord->Eip++; 00517 return(TRUE); 00518 } else if (KdPitchDebugger == TRUE) { 00519 return(FALSE); 00520 } else { 00521 return(KdpCheckTracePoint(ExceptionRecord,ContextRecord)); 00522 } 00523 }

Generated on Sat May 15 19:40:35 2004 for test by doxygen 1.3.7