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 David N. Cutler 27-July-1990 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "kdp.h" 00023 00024 // 00025 // Define breakpoint instruction masks. 00026 // 00027 00028 #define BREAKPOINT_CODE_SHIFT 16 00029 #define BREAKPOINT_CODE_MASK (0xfffff << 6) 00030 00031 // 00032 // globals 00033 // 00034 00035 ULONG KdpPageInAddress; 00036 WORK_QUEUE_ITEM KdpPageInWorkItem; 00037 00038 // 00039 // externs 00040 // 00041 00042 extern BOOLEAN KdpControlCPressed; 00043 00044 #pragma optimize( "", off ) 00045 VOID 00046 KdpPageInData ( 00047 IN PUCHAR volatile DataAddress 00048 ) 00049 00050 /*++ 00051 00052 Routine Description: 00053 00054 This routine is called to page in data at the supplied address. 00055 It is called either directly from KdpTrap() or from a worker 00056 thread that is queued by KdpTrap(). 00057 00058 Arguments: 00059 00060 DataAddress - Supplies a pointer to the data to be paged in. 00061 00062 Return Value: 00063 00064 None. 00065 00066 --*/ 00067 00068 { 00069 if (MmIsSystemAddressAccessable(DataAddress)) { 00070 UCHAR c = *DataAddress; 00071 DataAddress = &c; 00072 } 00073 KdpControlCPending = TRUE; 00074 } 00075 #pragma optimize( "", on ) 00076 00077 00078 BOOLEAN 00079 KdpTrap ( 00080 IN PKTRAP_FRAME TrapFrame, 00081 IN PKEXCEPTION_FRAME ExceptionFrame, 00082 IN PEXCEPTION_RECORD ExceptionRecord, 00083 IN PCONTEXT ContextRecord, 00084 IN KPROCESSOR_MODE PreviousMode, 00085 IN BOOLEAN SecondChance 00086 ) 00087 00088 /*++ 00089 00090 Routine Description: 00091 00092 This routine is called whenever a exception is dispatched and the kernel 00093 debugger is active. 00094 00095 Arguments: 00096 00097 TrapFrame - Supplies a pointer to a trap frame that describes the 00098 trap. 00099 00100 ExceptionFrame - Supplies a pointer to a exception frame that describes 00101 the trap. 00102 00103 ExceptionRecord - Supplies a pointer to an exception record that 00104 describes the exception. 00105 00106 ContextRecord - Supplies the context at the time of the exception. 00107 00108 PreviousMode - Supplies the previous processor mode. 00109 00110 SecondChance - Supplies a boolean value that determines whether this is 00111 the second chance (TRUE) that the exception has been raised. 00112 00113 Return Value: 00114 00115 A value of TRUE is returned if the exception is handled. Otherwise a 00116 value of FALSE is returned. 00117 00118 --*/ 00119 00120 { 00121 00122 BOOLEAN Completion; 00123 BOOLEAN Enable; 00124 BOOLEAN UnloadSymbols = FALSE; 00125 STRING Input; 00126 ULONG OldFir; 00127 STRING Output; 00128 PKPRCB Prcb; 00129 00130 // 00131 // Synchronize processor execution, save processor state, enter debugger, 00132 // and flush the current TB. 00133 // 00134 00135 re_enter_debugger: 00136 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); 00137 Prcb = KeGetCurrentPrcb(); 00138 KiSaveProcessorState(TrapFrame, ExceptionFrame); 00139 KeFlushCurrentTb(); 00140 00141 // 00142 // If this is a breakpoint instruction, then check to determine if is 00143 // an internal command. 00144 // 00145 00146 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00147 (((ExceptionRecord->ExceptionInformation[0] & BREAKPOINT_CODE_MASK) >> 00148 BREAKPOINT_CODE_SHIFT) >= DEBUG_PRINT_BREAKPOINT)) { 00149 00150 // 00151 // Switch on the breakpoint code. 00152 // 00153 00154 switch ((ExceptionRecord->ExceptionInformation[0] & BREAKPOINT_CODE_MASK) >> 00155 BREAKPOINT_CODE_SHIFT) { 00156 00157 // 00158 // Print a debug string. 00159 // 00160 // Arguments: 00161 // 00162 // a0 - Supplies a pointer to an output string buffer. 00163 // a1 - Supplies the length of the output string buffer. 00164 // 00165 00166 case DEBUG_PRINT_BREAKPOINT: 00167 Output.Buffer = (PCHAR)((ULONG)ContextRecord->XIntA0); 00168 Output.Length = (USHORT)ContextRecord->XIntA1; 00169 if (KdDebuggerNotPresent == FALSE) { 00170 if (KdpPrintString(&Output)) { 00171 ContextRecord->XIntV0 = (ULONGLONG)((LONG)STATUS_BREAKPOINT); 00172 00173 } else { 00174 ContextRecord->XIntV0 = (ULONGLONG)((LONG)STATUS_SUCCESS); 00175 } 00176 00177 } else { 00178 ContextRecord->XIntV0 = (ULONGLONG)((LONG)STATUS_DEVICE_NOT_CONNECTED); 00179 } 00180 00181 KiRestoreProcessorState(TrapFrame, ExceptionFrame); 00182 KdExitDebugger(Enable); 00183 ContextRecord->Fir += 4; 00184 return TRUE; 00185 00186 // 00187 // Print a debug prompt string, then input a string. 00188 // 00189 // a0 - Supplies a pointer to an output string buffer. 00190 // a1 - Supplies the length of the output string buffer.. 00191 // a2 - supplies a pointer to an input string buffer. 00192 // a3 - Supplies the length of the input string bufffer. 00193 // 00194 00195 case DEBUG_PROMPT_BREAKPOINT: 00196 Output.Buffer = (PCHAR)((ULONG)ContextRecord->XIntA0); 00197 Output.Length = (USHORT)ContextRecord->XIntA1; 00198 Input.Buffer = (PCHAR)((ULONG)ContextRecord->XIntA2); 00199 Input.MaximumLength = (USHORT)ContextRecord->XIntA3; 00200 KdpPromptString(&Output, &Input); 00201 ContextRecord->XIntV0 = (LONG)Input.Length; 00202 KiRestoreProcessorState(TrapFrame, ExceptionFrame); 00203 KdExitDebugger(Enable); 00204 ContextRecord->Fir += 4; 00205 return TRUE; 00206 00207 // 00208 // Load the symbolic information for an image. 00209 // 00210 // Arguments: 00211 // 00212 // a0 - Supplies a pointer to an output string descriptor. 00213 // a1 - Supplies a the base address of the image. 00214 // 00215 00216 case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT: 00217 UnloadSymbols = TRUE; 00218 00219 // 00220 // Fall through 00221 // 00222 00223 case DEBUG_LOAD_SYMBOLS_BREAKPOINT: 00224 OldFir = ContextRecord->Fir; 00225 if (KdDebuggerNotPresent == FALSE) { 00226 KdpReportLoadSymbolsStateChange((PSTRING)((ULONG)ContextRecord->XIntA0), 00227 (PKD_SYMBOLS_INFO)((ULONG)ContextRecord->XIntA1), 00228 UnloadSymbols, 00229 &Prcb->ProcessorState.ContextFrame); 00230 00231 } 00232 00233 RtlCopyMemory(ContextRecord, 00234 &Prcb->ProcessorState.ContextFrame, 00235 sizeof (CONTEXT) ); 00236 00237 KiRestoreProcessorState(TrapFrame, ExceptionFrame); 00238 KdExitDebugger(Enable); 00239 00240 // 00241 // If the kernel debugger did not update the FIR, then increment 00242 // past the break point instruction. 00243 // 00244 00245 if (ContextRecord->Fir == OldFir) { 00246 ContextRecord->Fir += 4; 00247 } 00248 00249 return TRUE; 00250 00251 // 00252 // Unknown internal command. 00253 // 00254 00255 default: 00256 break; 00257 } 00258 } 00259 00260 // 00261 // Report state change to kernel debugger on host machine. 00262 // 00263 00264 Completion = KdpReportExceptionStateChange(ExceptionRecord, 00265 &Prcb->ProcessorState.ContextFrame, 00266 SecondChance); 00267 00268 RtlCopyMemory(ContextRecord, 00269 &Prcb->ProcessorState.ContextFrame, 00270 sizeof(CONTEXT)); 00271 00272 KiRestoreProcessorState(TrapFrame, ExceptionFrame); 00273 KdExitDebugger(Enable); 00274 00275 // 00276 // Check to determine if the user of the remote debugger requested memory 00277 // to be paged in. 00278 // 00279 00280 if (KdpPageInAddress) { 00281 if (KeGetCurrentIrql() <= APC_LEVEL) { 00282 00283 // 00284 // If the IQRL is below DPC level then cause the page fault to 00285 // occur and then re-enter the debugger. This whole process is 00286 // transparent to the user. 00287 // 00288 00289 KdpPageInData((PUCHAR)KdpPageInAddress); 00290 KdpPageInAddress = 0; 00291 KdpControlCPending = FALSE; 00292 goto re_enter_debugger; 00293 00294 } else { 00295 00296 // 00297 // A page fault cannot be taken at an IRQL above APC level. Thus 00298 // a worker item is queued to take the page fault. After the worker 00299 // item takes the page fault it sets the contol-c flag so that the 00300 // user re-enters the debugger just as if control-c was pressed. 00301 // 00302 00303 if (KdpControlCPressed) { 00304 ExInitializeWorkItem(&KdpPageInWorkItem, 00305 (PWORKER_THREAD_ROUTINE) KdpPageInData, 00306 (PVOID) KdpPageInAddress); 00307 00308 ExQueueWorkItem( &KdpPageInWorkItem, DelayedWorkQueue ); 00309 KdpPageInAddress = 0; 00310 } 00311 } 00312 } 00313 00314 KdpControlCPressed = FALSE; 00315 return Completion; 00316 } 00317 00318 BOOLEAN 00319 KdIsThisAKdTrap ( 00320 IN PEXCEPTION_RECORD ExceptionRecord, 00321 IN PCONTEXT ContextRecord, 00322 IN KPROCESSOR_MODE PreviousMode 00323 ) 00324 00325 /*++ 00326 00327 Routine Description: 00328 00329 This routine is called whenever a user-mode exception occurs and 00330 it might be a kernel debugger exception (Like DbgPrint/DbgPrompt ). 00331 00332 Arguments: 00333 00334 ExceptionRecord - Supplies a pointer to an exception record that 00335 describes the exception. 00336 00337 ContextRecord - Supplies the context at the time of the exception. 00338 00339 PreviousMode - Supplies the previous processor mode. 00340 00341 Return Value: 00342 00343 A value of TRUE is returned if this is for the kernel debugger. 00344 Otherwise, a value of FALSE is returned. 00345 00346 --*/ 00347 00348 { 00349 00350 ULONG BreakpointCode; 00351 00352 // 00353 // Isolate the breakpoint code from the breakpoint instruction which 00354 // is stored by the exception dispatch code in the information field 00355 // of the exception record. 00356 // 00357 00358 BreakpointCode = (ExceptionRecord->ExceptionInformation[0] & 00359 BREAKPOINT_CODE_MASK) >> BREAKPOINT_CODE_SHIFT; 00360 00361 // 00362 // Switch on the breakpoint code. 00363 // 00364 00365 switch (BreakpointCode) { 00366 00367 // 00368 // Kernel breakpoint codes. 00369 // 00370 00371 case BREAKIN_BREAKPOINT: 00372 case KERNEL_BREAKPOINT: 00373 00374 #if DEVL 00375 00376 return TRUE; 00377 00378 #else 00379 00380 if (PreviousMode == KernelMode) { 00381 return TRUE; 00382 00383 } else { 00384 return FALSE; 00385 } 00386 00387 #endif 00388 00389 // 00390 // Debug print code. 00391 // 00392 00393 case DEBUG_PRINT_BREAKPOINT: 00394 return TRUE; 00395 00396 // 00397 // Debug prompt code. 00398 // 00399 00400 case DEBUG_PROMPT_BREAKPOINT: 00401 return TRUE; 00402 00403 // 00404 // Debug stop code. 00405 // 00406 00407 case DEBUG_STOP_BREAKPOINT: 00408 00409 #if DEVL 00410 00411 return TRUE; 00412 00413 #else 00414 00415 if (PreviousMode == KernelMode) { 00416 return TRUE; 00417 00418 } else { 00419 return FALSE; 00420 } 00421 00422 #endif 00423 00424 // 00425 // Debug load symbols code. 00426 // 00427 00428 case DEBUG_LOAD_SYMBOLS_BREAKPOINT: 00429 if (PreviousMode == KernelMode) { 00430 return TRUE; 00431 00432 } else { 00433 return FALSE; 00434 } 00435 00436 // 00437 // Debug unload symbols code. 00438 // 00439 00440 case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT: 00441 if (PreviousMode == KernelMode) { 00442 return TRUE; 00443 00444 } else { 00445 return FALSE; 00446 } 00447 00448 // 00449 // All other codes. 00450 // 00451 00452 default: 00453 return FALSE; 00454 } 00455 } 00456 00457 BOOLEAN 00458 KdpStub ( 00459 IN PKTRAP_FRAME TrapFrame, 00460 IN PKEXCEPTION_FRAME ExceptionFrame, 00461 IN PEXCEPTION_RECORD ExceptionRecord, 00462 IN PCONTEXT ContextRecord, 00463 IN KPROCESSOR_MODE PreviousMode, 00464 IN BOOLEAN SecondChance 00465 ) 00466 00467 /*++ 00468 00469 Routine Description: 00470 00471 This routine provides a kernel debugger stub routine that catchs debug 00472 prints in checked systems when the kernel debugger is not active. 00473 00474 Arguments: 00475 00476 TrapFrame - Supplies a pointer to a trap frame that describes the 00477 trap. 00478 00479 ExceptionFrame - Supplies a pointer to a exception frame that describes 00480 the trap. 00481 00482 ExceptionRecord - Supplies a pointer to an exception record that 00483 describes the exception. 00484 00485 ContextRecord - Supplies the context at the time of the exception. 00486 00487 PreviousMode - Supplies the previous processor mode. 00488 00489 SecondChance - Supplies a boolean value that determines whether this is 00490 the second chance (TRUE) that the exception has been raised. 00491 00492 Return Value: 00493 00494 A value of TRUE is returned if the exception is handled. Otherwise a 00495 value of FALSE is returned. 00496 00497 --*/ 00498 00499 { 00500 00501 ULONG BreakpointCode; 00502 00503 // 00504 // Isolate the breakpoint code from the breakpoint instruction which 00505 // is stored by the exception dispatch code in the information field 00506 // of the exception record. 00507 // 00508 00509 BreakpointCode = (ExceptionRecord->ExceptionInformation[0] & 00510 BREAKPOINT_CODE_MASK) >> BREAKPOINT_CODE_SHIFT; 00511 00512 00513 // 00514 // If the breakpoint is a debug print, debug load symbols, or debug 00515 // unload symbols, then return TRUE. Otherwise, return FALSE; 00516 // 00517 00518 if ((BreakpointCode == DEBUG_PRINT_BREAKPOINT) || 00519 (BreakpointCode == DEBUG_LOAD_SYMBOLS_BREAKPOINT) || 00520 (BreakpointCode == DEBUG_UNLOAD_SYMBOLS_BREAKPOINT)) { 00521 ContextRecord->Fir += 4; 00522 return TRUE; 00523 00524 } else { 00525 return FALSE; 00526 } 00527 }

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