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

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