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 Copyright (c) 1998 Intel Corporation 00005 00006 Module Name: 00007 00008 kdtrap.c 00009 00010 Abstract: 00011 00012 This module contains code to implement the target side of the portable 00013 kernel debugger. 00014 00015 Author: 00016 00017 David N. Cutler 27-July-1990 00018 00019 Revision History: 00020 00021 --*/ 00022 00023 #include "kdp.h" 00024 #ifdef _GAMBIT_ 00025 #include "ssc.h" 00026 #endif // _GAMBIT_ 00027 00028 00029 BOOLEAN 00030 KdpTrap ( 00031 IN PKTRAP_FRAME TrapFrame, 00032 IN PKEXCEPTION_FRAME ExceptionFrame, 00033 IN PEXCEPTION_RECORD ExceptionRecord, 00034 IN PCONTEXT ContextRecord, 00035 IN KPROCESSOR_MODE PreviousMode, 00036 IN BOOLEAN SecondChance 00037 ) 00038 00039 /*++ 00040 00041 Routine Description: 00042 00043 This routine is called whenever a exception is dispatched and the kernel 00044 debugger is active. 00045 00046 Arguments: 00047 00048 TrapFrame - Supplies a pointer to a trap frame that describes the 00049 trap. 00050 00051 ExceptionFrame - Supplies a pointer to a exception frame that describes 00052 the trap. 00053 00054 ExceptionRecord - Supplies a pointer to an exception record that 00055 describes the exception. 00056 00057 ContextRecord - Supplies the context at the time of the exception. 00058 00059 PreviousMode - Supplies the previous processor mode. 00060 00061 SecondChance - Supplies a boolean value that determines whether this is 00062 the second chance (TRUE) that the exception has been raised. 00063 00064 Return Value: 00065 00066 A value of TRUE is returned if the exception is handled. Otherwise a 00067 value of FALSE is returned. 00068 00069 --*/ 00070 00071 { 00072 00073 BOOLEAN Completion = FALSE; 00074 BOOLEAN Enable; 00075 BOOLEAN UnloadSymbols = FALSE; 00076 ULONGLONG OldStIIP, OldStIPSR; 00077 STRING Input; 00078 STRING Output; 00079 PKPRCB Prcb; 00080 00081 // 00082 // Synchronize processor execution, save processor state, enter debugger, 00083 // and flush the current TB. 00084 // 00085 00086 KeFlushCurrentTb(); 00087 00088 // 00089 // If this is a breakpoint instruction, then check to determine if is 00090 // an internal command. 00091 // 00092 00093 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00094 (ExceptionRecord->ExceptionInformation[0] >= DEBUG_PRINT_BREAKPOINT)) { 00095 00096 // 00097 // Switch on the breakpoint code. 00098 // 00099 00100 switch (ExceptionRecord->ExceptionInformation[0]) { 00101 00102 // 00103 // Print a debug string. 00104 // 00105 // Arguments: IA64 passes arguments via RSE not GR's. Since arguments are not 00106 // part of CONTEXT struct, they need to be copies Temp registers. 00107 // (see NTOS/RTL/IA64/DEBUGSTB.S) 00108 // 00109 // T0 - Supplies a pointer to an output string buffer. 00110 // T1 - Supplies the length of the output string buffer. 00111 // 00112 00113 case DEBUG_PRINT_BREAKPOINT: 00114 00115 // 00116 // Advance to next instruction slot so that the BREAK instruction 00117 // does not get re-executed 00118 // 00119 00120 RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2, 00121 ContextRecord->StIPSR, 00122 ContextRecord->StIIP); 00123 00124 Output.Buffer = (PCHAR)ContextRecord->IntT0; 00125 Output.Length = (USHORT)ContextRecord->IntT1; 00126 00127 KdLogDbgPrint(&Output); 00128 00129 if (KdDebuggerNotPresent == FALSE) { 00130 00131 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); 00132 if (KdpPrintString(&Output)) { 00133 ContextRecord->IntV0 = (ULONG)STATUS_BREAKPOINT; 00134 00135 } else { 00136 ContextRecord->IntV0 = (ULONG)STATUS_SUCCESS; 00137 } 00138 KdExitDebugger(Enable); 00139 00140 } else { 00141 ContextRecord->IntV0 = (ULONG)STATUS_DEVICE_NOT_CONNECTED; 00142 } 00143 00144 return TRUE; 00145 00146 // 00147 // Print a debug prompt string, then input a string. 00148 // 00149 // T0 - Supplies a pointer to an output string buffer. 00150 // T1 - Supplies the length of the output string buffer.. 00151 // T2 - supplies a pointer to an input string buffer. 00152 // T3 - Supplies the length of the input string bufffer. 00153 // 00154 00155 case DEBUG_PROMPT_BREAKPOINT: 00156 00157 // 00158 // Advance to next instruction slot so that the BREAK instruction 00159 // does not get re-executed 00160 // 00161 00162 RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2, 00163 ContextRecord->StIPSR, 00164 ContextRecord->StIIP); 00165 00166 Output.Buffer = (PCHAR)ContextRecord->IntT0; 00167 Output.Length = (USHORT)ContextRecord->IntT1; 00168 Input.Buffer = (PCHAR)ContextRecord->IntT2; 00169 Input.MaximumLength = (USHORT)ContextRecord->IntT3; 00170 00171 KdLogDbgPrint(&Output); 00172 00173 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); 00174 00175 KdpPromptString(&Output, &Input); 00176 00177 ContextRecord->IntV0 = Input.Length; 00178 00179 KdExitDebugger(Enable); 00180 return TRUE; 00181 00182 // 00183 // Load the symbolic information for an image. 00184 // 00185 // Arguments: 00186 // 00187 // T0 - Supplies a pointer to an output string descriptor. 00188 // T1 - Supplies a the base address of the image. 00189 // 00190 00191 case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT: 00192 UnloadSymbols = TRUE; 00193 00194 // 00195 // Fall through 00196 // 00197 00198 case DEBUG_LOAD_SYMBOLS_BREAKPOINT: 00199 00200 // 00201 // Advance to next instruction slot so that the BREAK instruction 00202 // does not get re-executed 00203 // 00204 00205 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); 00206 Prcb = KeGetCurrentPrcb(); 00207 KiSaveProcessorControlState(&Prcb->ProcessorState); 00208 OldStIPSR = ContextRecord->StIPSR; 00209 OldStIIP = ContextRecord->StIIP; 00210 RtlCopyMemory(&Prcb->ProcessorState.ContextFrame, 00211 ContextRecord, 00212 sizeof(CONTEXT)); 00213 00214 if (KdDebuggerNotPresent == FALSE) { 00215 KdpReportLoadSymbolsStateChange((PSTRING)ContextRecord->IntT0, 00216 (PKD_SYMBOLS_INFO) ContextRecord->IntT1, 00217 UnloadSymbols, 00218 &Prcb->ProcessorState.ContextFrame); 00219 00220 } 00221 00222 RtlCopyMemory(ContextRecord, 00223 &Prcb->ProcessorState.ContextFrame, 00224 sizeof(CONTEXT)); 00225 00226 KiRestoreProcessorControlState(&Prcb->ProcessorState); 00227 KdExitDebugger(Enable); 00228 00229 // 00230 // If the kernel debugger did not update the IP, then increment 00231 // past the breakpoint instruction. 00232 // 00233 00234 if ((ContextRecord->StIIP == OldStIIP) && 00235 ((ContextRecord->StIPSR & IPSR_RI_MASK) == (OldStIPSR & IPSR_RI_MASK))) { 00236 RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2, 00237 ContextRecord->StIPSR, 00238 ContextRecord->StIIP); 00239 } 00240 00241 return TRUE; 00242 00243 // 00244 // Kernel breakin break 00245 // 00246 00247 case BREAKIN_BREAKPOINT: 00248 00249 // 00250 // Advance to next instruction slot so that the BREAK instruction 00251 // does not get re-executed 00252 // 00253 00254 RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2, 00255 ContextRecord->StIPSR, 00256 ContextRecord->StIIP); 00257 break; 00258 00259 // 00260 // Unknown internal command. 00261 // 00262 00263 default: 00264 break; 00265 } 00266 00267 } 00268 00269 // 00270 // Get here if single step or BREAKIN breakpoint 00271 // 00272 00273 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) || 00274 (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) || 00275 (NtGlobalFlag & FLG_STOP_ON_EXCEPTION) || 00276 SecondChance) { 00277 00278 // 00279 // Report state change to kernel debugger on host 00280 // 00281 00282 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); 00283 Prcb = KeGetCurrentPrcb(); 00284 KiSaveProcessorControlState(&Prcb->ProcessorState); 00285 00286 RtlCopyMemory(&Prcb->ProcessorState.ContextFrame, 00287 ContextRecord, 00288 sizeof (CONTEXT)); 00289 00290 Completion = KdpReportExceptionStateChange( 00291 ExceptionRecord, 00292 &Prcb->ProcessorState.ContextFrame, 00293 SecondChance); 00294 00295 RtlCopyMemory(ContextRecord, 00296 &Prcb->ProcessorState.ContextFrame, 00297 sizeof (CONTEXT)); 00298 00299 KiRestoreProcessorControlState(&Prcb->ProcessorState); 00300 KdExitDebugger(Enable); 00301 00302 00303 KdpControlCPressed = FALSE; 00304 00305 } else { 00306 00307 // 00308 // This is real exception that user doesn't want to see, 00309 // so do NOT report it to debugger. 00310 // 00311 00312 // return FALSE; 00313 } 00314 00315 // 00316 // Always return TRUE if this is the first chance to handle the 00317 // exception. Otherwise, return the completion status of the 00318 // state change reporting. 00319 // 00320 00321 if( SecondChance ){ 00322 return Completion; 00323 } else { 00324 return TRUE; 00325 } 00326 } 00327 00328 BOOLEAN 00329 KdIsThisAKdTrap ( 00330 IN PEXCEPTION_RECORD ExceptionRecord, 00331 IN PCONTEXT ContextRecord, 00332 IN KPROCESSOR_MODE PreviousMode 00333 ) 00334 00335 /*++ 00336 00337 Routine Description: 00338 00339 This routine is called whenever a user-mode exception occurs and 00340 it might be a kernel debugger exception (Like DbgPrint/DbgPrompt ). 00341 00342 Arguments: 00343 00344 ExceptionRecord - Supplies a pointer to an exception record that 00345 describes the exception. 00346 00347 ContextRecord - Supplies the context at the time of the exception. 00348 00349 PreviousMode - Supplies the previous processor mode. 00350 00351 Return Value: 00352 00353 A value of TRUE is returned if this is for the kernel debugger. 00354 Otherwise, a value of FALSE is returned. 00355 00356 --*/ 00357 00358 { 00359 00360 ULONG_PTR BreakpointCode; 00361 00362 // 00363 // Isolate the breakpoint code from the breakpoint instruction which 00364 // is stored by the exception dispatch code in the information field 00365 // of the exception record. 00366 // 00367 00368 BreakpointCode = (ULONG) ExceptionRecord->ExceptionInformation[0]; 00369 00370 // 00371 // Switch on the breakpoint code. 00372 // 00373 00374 switch (BreakpointCode) { 00375 00376 // 00377 // Kernel breakpoint codes. 00378 // 00379 00380 case BREAKIN_BREAKPOINT: 00381 case KERNEL_BREAKPOINT: 00382 00383 #if DEVL 00384 00385 return TRUE; 00386 00387 #else 00388 00389 if (PreviousMode == KernelMode) { 00390 return TRUE; 00391 00392 } else { 00393 return FALSE; 00394 } 00395 00396 #endif 00397 00398 // 00399 // Debug print code. 00400 // 00401 00402 case DEBUG_PRINT_BREAKPOINT: 00403 return TRUE; 00404 00405 // 00406 // Debug prompt code. 00407 // 00408 00409 case DEBUG_PROMPT_BREAKPOINT: 00410 return TRUE; 00411 00412 // 00413 // Debug stop code. 00414 // 00415 00416 case DEBUG_STOP_BREAKPOINT: 00417 00418 #if DEVL 00419 00420 return TRUE; 00421 00422 #else 00423 00424 if (PreviousMode == KernelMode) { 00425 return TRUE; 00426 00427 } else { 00428 return FALSE; 00429 } 00430 00431 #endif 00432 00433 // 00434 // Debug load symbols code. 00435 // 00436 00437 case DEBUG_LOAD_SYMBOLS_BREAKPOINT: 00438 if (PreviousMode == KernelMode) { 00439 return TRUE; 00440 00441 } else { 00442 return FALSE; 00443 } 00444 00445 // 00446 // Debug unload symbols code. 00447 // 00448 00449 case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT: 00450 if (PreviousMode == KernelMode) { 00451 return TRUE; 00452 00453 } else { 00454 return FALSE; 00455 } 00456 00457 // 00458 // All other codes. 00459 // 00460 00461 default: 00462 return FALSE; 00463 } 00464 } 00465 00466 BOOLEAN 00467 KdpStub ( 00468 IN PKTRAP_FRAME TrapFrame, 00469 IN PKEXCEPTION_FRAME ExceptionFrame, 00470 IN PEXCEPTION_RECORD ExceptionRecord, 00471 IN PCONTEXT ContextRecord, 00472 IN KPROCESSOR_MODE PreviousMode, 00473 IN BOOLEAN SecondChance 00474 ) 00475 00476 /*++ 00477 00478 Routine Description: 00479 00480 This routine provides a kernel debugger stub routine that catchs debug 00481 prints in checked systems when the kernel debugger is not active. 00482 00483 Arguments: 00484 00485 TrapFrame - Supplies a pointer to a trap frame that describes the 00486 trap. 00487 00488 ExceptionFrame - Supplies a pointer to a exception frame that describes 00489 the trap. 00490 00491 ExceptionRecord - Supplies a pointer to an exception record that 00492 describes the exception. 00493 00494 ContextRecord - Supplies the context at the time of the exception. 00495 00496 PreviousMode - Supplies the previous processor mode. 00497 00498 SecondChance - Supplies a boolean value that determines whether this is 00499 the second chance (TRUE) that the exception has been raised. 00500 00501 Return Value: 00502 00503 A value of TRUE is returned if the exception is handled. Otherwise a 00504 value of FALSE is returned. 00505 00506 --*/ 00507 00508 { 00509 00510 ULONG_PTR BreakpointCode; 00511 #ifdef _GAMBIT_ 00512 PHYSICAL_ADDRESS PAddress; 00513 #endif // _GAMBIT_ 00514 00515 // 00516 // Isolate the breakpoint code from the breakpoint instruction which 00517 // is stored by the exception dispatch code in the information field 00518 // of the exception record. 00519 // 00520 00521 BreakpointCode = (ULONG) ExceptionRecord->ExceptionInformation[0]; 00522 00523 00524 // 00525 // If the breakpoint is a debug print, debug load symbols, or debug 00526 // unload symbols, then return TRUE. Otherwise, return FALSE; 00527 // 00528 00529 if ((BreakpointCode == DEBUG_PRINT_BREAKPOINT) || 00530 (BreakpointCode == DEBUG_LOAD_SYMBOLS_BREAKPOINT) || 00531 (BreakpointCode == DEBUG_UNLOAD_SYMBOLS_BREAKPOINT)) { 00532 00533 // 00534 // Advance to next instruction slot so that the BREAK instruction 00535 // does not get re-executed 00536 // 00537 00538 RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2, 00539 ContextRecord->StIPSR, 00540 ContextRecord->StIIP); 00541 00542 00543 #ifdef _GAMBIT_ 00544 if (BreakpointCode == DEBUG_PRINT_BREAKPOINT) { 00545 if ((PUCHAR)ContextRecord->IntT0) { 00546 PAddress = MmGetPhysicalAddress ((PUCHAR)ContextRecord->IntT0); 00547 if (PAddress.QuadPart != 0ULL) { 00548 SscDbgPrintf((PVOID)PAddress.QuadPart); 00549 } 00550 } 00551 } 00552 #endif // _GAMBIT_ 00553 00554 return TRUE; 00555 00556 } else { 00557 return FALSE; 00558 } 00559 }

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