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

exceptn.c File Reference

#include "ki.h"
#include "kxmips.h"

Go to the source code of this file.

Defines

#define HEADER_FILE
#define KDDEBUG_BREAKPOINT   ((SPEC_OP << 26) | (BREAKIN_BREAKPOINT << 16) | BREAK_OP)
#define DIVIDE_BREAKPOINT   ((SPEC_OP << 26) | (DIVIDE_BY_ZERO_BREAKPOINT << 16) | BREAK_OP)
#define MULTIPLY_BREAKPOINT   ((SPEC_OP << 26) | (MULTIPLY_OVERFLOW_BREAKPOINT << 16) | BREAK_OP)
#define OVERFLOW_BREAKPOINT   ((SPEC_OP << 26) | (DIVIDE_OVERFLOW_BREAKPOINT << 16) | BREAK_OP)
#define KERNEL_BREAKPOINT_INSTRUCTION   0x16000d

Functions

VOID KeContextFromKframes (IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN OUT PCONTEXT ContextFrame)
VOID KeContextToKframes (IN OUT PKTRAP_FRAME TrapFrame, IN OUT PKEXCEPTION_FRAME ExceptionFrame, IN PCONTEXT ContextFrame, IN ULONG ContextFlags, IN KPROCESSOR_MODE PreviousMode)
VOID KiDispatchException (IN PEXCEPTION_RECORD ExceptionRecord, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN FirstChance)
ULONG KiCopyInformation (IN OUT PEXCEPTION_RECORD ExceptionRecord1, IN PEXCEPTION_RECORD ExceptionRecord2)
NTSTATUS KeRaiseUserException (IN NTSTATUS ExceptionCode)


Define Documentation

#define DIVIDE_BREAKPOINT   ((SPEC_OP << 26) | (DIVIDE_BY_ZERO_BREAKPOINT << 16) | BREAK_OP)
 

Definition at line 36 of file mips/exceptn.c.

Referenced by KiDispatchException().

#define HEADER_FILE
 

Definition at line 28 of file mips/exceptn.c.

#define KDDEBUG_BREAKPOINT   ((SPEC_OP << 26) | (BREAKIN_BREAKPOINT << 16) | BREAK_OP)
 

Definition at line 35 of file mips/exceptn.c.

Referenced by KiDispatchException().

#define KERNEL_BREAKPOINT_INSTRUCTION   0x16000d
 

Definition at line 44 of file mips/exceptn.c.

Referenced by KiDispatchException().

#define MULTIPLY_BREAKPOINT   ((SPEC_OP << 26) | (MULTIPLY_OVERFLOW_BREAKPOINT << 16) | BREAK_OP)
 

Definition at line 37 of file mips/exceptn.c.

Referenced by KiDispatchException().

#define OVERFLOW_BREAKPOINT   ((SPEC_OP << 26) | (DIVIDE_OVERFLOW_BREAKPOINT << 16) | BREAK_OP)
 

Definition at line 38 of file mips/exceptn.c.

Referenced by KiDispatchException().


Function Documentation

VOID KeContextFromKframes IN PKTRAP_FRAME  TrapFrame,
IN PKEXCEPTION_FRAME  ExceptionFrame,
IN OUT PCONTEXT  ContextFrame
 

Definition at line 47 of file mips/exceptn.c.

References CONTEXT_CONTROL, CONTEXT_FLOATING_POINT, and CONTEXT_INTEGER.

00055 : 00056 00057 This routine moves the selected contents of the specified trap and exception frames 00058 frames into the specified context frame according to the specified context 00059 flags. 00060 00061 Arguments: 00062 00063 TrapFrame - Supplies a pointer to a trap frame from which volatile context 00064 should be copied into the context record. 00065 00066 ExceptionFrame - Supplies a pointer to an exception frame from which context 00067 should be copied into the context record. 00068 00069 ContextFrame - Supplies a pointer to the context frame that receives the 00070 context copied from the trap and exception frames. 00071 00072 Return Value: 00073 00074 None. 00075 00076 --*/ 00077 00078 { 00079 00080 ULONG ContextFlags; 00081 00082 // 00083 // Set control information if specified. 00084 // 00085 00086 ContextFlags = ContextFrame->ContextFlags; 00087 if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) { 00088 00089 // 00090 // Set integer register gp, ra, sp, FIR, and PSR. 00091 // 00092 00093 ContextFrame->XIntGp = TrapFrame->XIntGp; 00094 ContextFrame->XIntSp = TrapFrame->XIntSp; 00095 ContextFrame->Fir = TrapFrame->Fir; 00096 ContextFrame->Psr = TrapFrame->Psr; 00097 ContextFrame->XIntRa = TrapFrame->XIntRa; 00098 } 00099 00100 // 00101 // Set integer register contents if specified. 00102 // 00103 00104 if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) { 00105 00106 // 00107 // Set integer registers zero, and, at - t9, k0, k1, lo, and hi. 00108 // 00109 00110 ContextFrame->XIntZero = 0; 00111 ContextFrame->XIntAt = TrapFrame->XIntAt; 00112 ContextFrame->XIntV0 = TrapFrame->XIntV0; 00113 ContextFrame->XIntV1 = TrapFrame->XIntV1; 00114 ContextFrame->XIntA0 = TrapFrame->XIntA0; 00115 ContextFrame->XIntA1 = TrapFrame->XIntA1; 00116 ContextFrame->XIntA2 = TrapFrame->XIntA2; 00117 ContextFrame->XIntA3 = TrapFrame->XIntA3; 00118 ContextFrame->XIntT0 = TrapFrame->XIntT0; 00119 ContextFrame->XIntT1 = TrapFrame->XIntT1; 00120 ContextFrame->XIntT2 = TrapFrame->XIntT2; 00121 ContextFrame->XIntT3 = TrapFrame->XIntT3; 00122 ContextFrame->XIntT4 = TrapFrame->XIntT4; 00123 ContextFrame->XIntT5 = TrapFrame->XIntT5; 00124 ContextFrame->XIntT6 = TrapFrame->XIntT6; 00125 ContextFrame->XIntT7 = TrapFrame->XIntT7; 00126 ContextFrame->XIntT8 = TrapFrame->XIntT8; 00127 ContextFrame->XIntT9 = TrapFrame->XIntT9; 00128 ContextFrame->XIntK0 = 0; 00129 ContextFrame->XIntK1 = 0; 00130 ContextFrame->XIntLo = TrapFrame->XIntLo; 00131 ContextFrame->XIntHi = TrapFrame->XIntHi; 00132 00133 // 00134 // Set integer registers s0 - s7, and s8. 00135 // 00136 00137 ContextFrame->XIntS0 = TrapFrame->XIntS0; 00138 ContextFrame->XIntS1 = TrapFrame->XIntS1; 00139 ContextFrame->XIntS2 = TrapFrame->XIntS2; 00140 ContextFrame->XIntS3 = TrapFrame->XIntS3; 00141 ContextFrame->XIntS4 = TrapFrame->XIntS4; 00142 ContextFrame->XIntS5 = TrapFrame->XIntS5; 00143 ContextFrame->XIntS6 = TrapFrame->XIntS6; 00144 ContextFrame->XIntS7 = TrapFrame->XIntS7; 00145 ContextFrame->XIntS8 = TrapFrame->XIntS8; 00146 } 00147 00148 // 00149 // Set floating register contents if specified. 00150 // 00151 00152 if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) { 00153 00154 // 00155 // Set floating registers f0 - f19. 00156 // 00157 00158 RtlMoveMemory(&ContextFrame->FltF0, &TrapFrame->FltF0, 00159 sizeof(ULONG) * (20)); 00160 00161 // 00162 // Set floating registers f20 - f31. 00163 // 00164 00165 RtlMoveMemory(&ContextFrame->FltF20, &ExceptionFrame->FltF20, 00166 sizeof(ULONG) * (12)); 00167 00168 // 00169 // Set floating status register. 00170 // 00171 00172 ContextFrame->Fsr = TrapFrame->Fsr; 00173 } 00174 00175 return; 00176 }

VOID KeContextToKframes IN OUT PKTRAP_FRAME  TrapFrame,
IN OUT PKEXCEPTION_FRAME  ExceptionFrame,
IN PCONTEXT  ContextFrame,
IN ULONG  ContextFlags,
IN KPROCESSOR_MODE  PreviousMode
 

Definition at line 179 of file mips/exceptn.c.

References CONTEXT_CONTROL, CONTEXT_FLOATING_POINT, and CONTEXT_INTEGER.

00189 : 00190 00191 This routine moves the selected contents of the specified context frame into 00192 the specified trap and exception frames according to the specified context 00193 flags. 00194 00195 Arguments: 00196 00197 TrapFrame - Supplies a pointer to a trap frame that receives the volatile 00198 context from the context record. 00199 00200 ExceptionFrame - Supplies a pointer to an exception frame that receives 00201 the nonvolatile context from the context record. 00202 00203 ContextFrame - Supplies a pointer to a context frame that contains the 00204 context that is to be copied into the trap and exception frames. 00205 00206 ContextFlags - Supplies the set of flags that specify which parts of the 00207 context frame are to be copied into the trap and exception frames. 00208 00209 PreviousMode - Supplies the processor mode for which the trap and exception 00210 frames are being built. 00211 00212 Return Value: 00213 00214 None. 00215 00216 --*/ 00217 00218 { 00219 00220 // 00221 // Set control information if specified. 00222 // 00223 00224 if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) { 00225 00226 // 00227 // Set integer register gp, sp, ra, FIR, and PSR. 00228 // 00229 00230 TrapFrame->XIntGp = ContextFrame->XIntGp; 00231 TrapFrame->XIntSp = ContextFrame->XIntSp; 00232 TrapFrame->Fir = ContextFrame->Fir; 00233 TrapFrame->Psr = SANITIZE_PSR(ContextFrame->Psr, PreviousMode); 00234 TrapFrame->XIntRa = ContextFrame->XIntRa; 00235 } 00236 00237 // 00238 // Set integer registers contents if specified. 00239 // 00240 00241 if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) { 00242 00243 // 00244 // Set integer registers at - t9, lo, and hi. 00245 // 00246 00247 TrapFrame->XIntAt = ContextFrame->XIntAt; 00248 TrapFrame->XIntV0 = ContextFrame->XIntV0; 00249 TrapFrame->XIntV1 = ContextFrame->XIntV1; 00250 TrapFrame->XIntA0 = ContextFrame->XIntA0; 00251 TrapFrame->XIntA1 = ContextFrame->XIntA1; 00252 TrapFrame->XIntA2 = ContextFrame->XIntA2; 00253 TrapFrame->XIntA3 = ContextFrame->XIntA3; 00254 TrapFrame->XIntT0 = ContextFrame->XIntT0; 00255 TrapFrame->XIntT1 = ContextFrame->XIntT1; 00256 TrapFrame->XIntT2 = ContextFrame->XIntT2; 00257 TrapFrame->XIntT3 = ContextFrame->XIntT3; 00258 TrapFrame->XIntT4 = ContextFrame->XIntT4; 00259 TrapFrame->XIntT5 = ContextFrame->XIntT5; 00260 TrapFrame->XIntT6 = ContextFrame->XIntT6; 00261 TrapFrame->XIntT7 = ContextFrame->XIntT7; 00262 TrapFrame->XIntT8 = ContextFrame->XIntT8; 00263 TrapFrame->XIntT9 = ContextFrame->XIntT9; 00264 TrapFrame->XIntLo = ContextFrame->XIntLo; 00265 TrapFrame->XIntHi = ContextFrame->XIntHi; 00266 00267 // 00268 // Set integer registers s0 - s7, and s8. 00269 // 00270 00271 TrapFrame->XIntS0 = ContextFrame->XIntS0; 00272 TrapFrame->XIntS1 = ContextFrame->XIntS1; 00273 TrapFrame->XIntS2 = ContextFrame->XIntS2; 00274 TrapFrame->XIntS3 = ContextFrame->XIntS3; 00275 TrapFrame->XIntS4 = ContextFrame->XIntS4; 00276 TrapFrame->XIntS5 = ContextFrame->XIntS5; 00277 TrapFrame->XIntS6 = ContextFrame->XIntS6; 00278 TrapFrame->XIntS7 = ContextFrame->XIntS7; 00279 TrapFrame->XIntS8 = ContextFrame->XIntS8; 00280 } 00281 00282 // 00283 // Set floating register contents if specified. 00284 // 00285 00286 if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) { 00287 00288 // 00289 // Set floating registers f0 - f19. 00290 // 00291 00292 RtlMoveMemory(&TrapFrame->FltF0, &ContextFrame->FltF0, 00293 sizeof(ULONG) * (20)); 00294 00295 // 00296 // Set floating registers f20 - f31. 00297 // 00298 00299 RtlMoveMemory(&ExceptionFrame->FltF20, &ContextFrame->FltF20, 00300 sizeof(ULONG) * (12)); 00301 00302 // 00303 // Set floating status register. 00304 // 00305 00306 TrapFrame->Fsr = SANITIZE_FSR(ContextFrame->Fsr, PreviousMode); 00307 } 00308 00309 return; 00310 }

NTSTATUS KeRaiseUserException IN NTSTATUS  ExceptionCode  ) 
 

Definition at line 863 of file mips/exceptn.c.

References ASSERT, KeGetCurrentThread, KeRaiseUserExceptionDispatcher, and UserMode.

00869 : 00870 00871 This function causes an exception to be raised in the calling thread's 00872 usermode context. This is accomplished by editing the trap frame the 00873 kernel was entered with to point to trampoline code that raises the 00874 requested exception. 00875 00876 Arguments: 00877 00878 ExceptionCode - Supplies the status value to be used as the exception 00879 code for the exception that is to be raised. 00880 00881 Return Value: 00882 00883 The status value that should be returned by the caller. 00884 00885 --*/ 00886 00887 { 00888 00889 PKTRAP_FRAME TrapFrame; 00890 00891 ASSERT(KeGetPreviousMode() == UserMode); 00892 00893 TrapFrame = KeGetCurrentThread()->TrapFrame; 00894 TrapFrame->Fir = KeRaiseUserExceptionDispatcher; 00895 return ExceptionCode; 00896 } }

ULONG KiCopyInformation IN OUT PEXCEPTION_RECORD  ExceptionRecord1,
IN PEXCEPTION_RECORD  ExceptionRecord2
 

Definition at line 823 of file mips/exceptn.c.

References EXCEPTION_EXECUTE_HANDLER.

00830 : 00831 00832 This function is called from an exception filter to copy the exception 00833 information from one exception record to another when an exception occurs. 00834 00835 Arguments: 00836 00837 ExceptionRecord1 - Supplies a pointer to the destination exception record. 00838 00839 ExceptionRecord2 - Supplies a pointer to the source exception record. 00840 00841 Return Value: 00842 00843 A value of EXCEPTION_EXECUTE_HANDLER is returned as the function value. 00844 00845 --*/ 00846 00847 { 00848 00849 // 00850 // Copy one exception record to another and return value that causes 00851 // an exception handler to be executed. 00852 // 00853 00854 RtlMoveMemory((PVOID)ExceptionRecord1, 00855 (PVOID)ExceptionRecord2, 00856 sizeof(EXCEPTION_RECORD)); 00857 00858 return EXCEPTION_EXECUTE_HANDLER; 00859 }

VOID KiDispatchException IN PEXCEPTION_RECORD  ExceptionRecord,
IN PKEXCEPTION_FRAME  ExceptionFrame,
IN PKTRAP_FRAME  TrapFrame,
IN KPROCESSOR_MODE  PreviousMode,
IN BOOLEAN  FirstChance
 

Definition at line 313 of file mips/exceptn.c.

References CONTEXT_FULL, DATA_BUS_ERROR, DbgkForwardException(), DIVIDE_BREAKPOINT, FALSE, Index, INSTRUCTION_BUS_ERROR, KDDEBUG_BREAKPOINT, KdIsThisAKdTrap(), KeBugCheckEx(), KeContextFromKframes(), KeContextToKframes(), KeGetCurrentPrcb, KeGetCurrentThread, KERNEL_BREAKPOINT_INSTRUCTION, KernelMode, KeUserExceptionDispatcher, KiCopyInformation(), KiDataBusError(), KiDebugRoutine, KiEmulateFloating(), KiEmulateReference(), KiInstructionBusError(), KMODE_EXCEPTION_NOT_HANDLED, MULTIPLY_BREAKPOINT, NULL, OVERFLOW_BREAKPOINT, ProbeForWrite(), PsGetCurrentProcess, RtlDispatchException(), TRUE, and UserMode.

00323 : 00324 00325 This function is called to dispatch an exception to the proper mode and 00326 to cause the exception dispatcher to be called. 00327 00328 If the exception is a data misalignment, the previous mode is user, this 00329 is the first chance for handling the exception, and the current thread 00330 has enabled automatic alignment fixup, then an attempt is made to emulate 00331 the unaligned reference. Data misalignment exceptions are never emulated 00332 for kernel mode. 00333 00334 If the exception is a floating exception (N.B. the pseudo status 00335 STATUS_FLOAT_STACK_CHECK is used to signify this and is converted to the 00336 proper code by the floating emulation routine), then an attempt is made 00337 to emulate the floating operation if it is not implemented. 00338 00339 If the exception is neither a data misalignment nor a floating point 00340 exception and the the previous mode is kernel, then the exception 00341 dispatcher is called directly to process the exception. Otherwise the 00342 exception record, exception frame, and trap frame contents are copied 00343 to the user mode stack. The contents of the exception frame and trap 00344 are then modified such that when control is returned, execution will 00345 commense in user mode in a routine which will call the exception 00346 dispatcher. 00347 00348 Arguments: 00349 00350 ExceptionRecord - Supplies a pointer to an exception record. 00351 00352 ExceptionFrame - Supplies a pointer to an exception frame. 00353 00354 TrapFrame - Supplies a pointer to a trap frame. 00355 00356 PreviousMode - Supplies the previous processor mode. 00357 00358 FirstChance - Supplies a boolean variable that specifies whether this 00359 is the first (TRUE) or second (FALSE) time that this exception has 00360 been processed. 00361 00362 Return Value: 00363 00364 None. 00365 00366 --*/ 00367 00368 { 00369 00370 CONTEXT ContextFrame; 00371 PULONG Destination; 00372 EXCEPTION_RECORD ExceptionRecord1; 00373 ULONG Index; 00374 LONG Length; 00375 PULONGLONG Source; 00376 BOOLEAN UserApcPending; 00377 ULONG UserStack1; 00378 ULONG UserStack2; 00379 00380 // 00381 // If the exception is an access violation, and the previous mode is 00382 // user mode, then attempt to emulate a load or store operation if 00383 // the exception address is at the end of a page. 00384 // 00385 // N.B. The following is a workaround for a r4000 chip bug where an 00386 // address privilege violation is reported as a access violation 00387 // on a load or store instruction that is the last instruction 00388 // in a page. 00389 // 00390 00391 if ((ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) && 00392 (((ULONG)ExceptionRecord->ExceptionAddress & 0xffc) == 0xffc) && 00393 (PreviousMode != KernelMode) && 00394 (KiEmulateReference(ExceptionRecord, ExceptionFrame, TrapFrame) != FALSE)) { 00395 KeGetCurrentPrcb()->KeAlignmentFixupCount += 1; 00396 goto Handled2; 00397 } 00398 00399 // 00400 // If the exception is a data bus error, then process the error. 00401 // 00402 // N.B. A special exception code is used to signal a data bus error. 00403 // This code is equivalent to the bug check code merged with a 00404 // reserved facility code and the reserved bit set. 00405 // 00406 // N.B. If control returns, then it is assumed that the error has been 00407 // corrected. 00408 // 00409 00410 if (ExceptionRecord->ExceptionCode == (DATA_BUS_ERROR | 0xdfff0000)) { 00411 00412 // 00413 // N.B. The following is a workaround for a r4000 chip bug where an 00414 // address privilege violation is reported as a data bus error 00415 // on a load or store instruction that is the last instruction 00416 // in a page. 00417 // 00418 00419 if ((ExceptionRecord->ExceptionInformation[1] < 0x80000000) && 00420 (((ULONG)ExceptionRecord->ExceptionAddress & 0xffc) == 0xffc) && 00421 (PreviousMode != KernelMode)) { 00422 if (KiEmulateReference(ExceptionRecord, ExceptionFrame, TrapFrame) != FALSE) { 00423 KeGetCurrentPrcb()->KeAlignmentFixupCount += 1; 00424 goto Handled2; 00425 } 00426 } 00427 00428 KiDataBusError(ExceptionRecord, ExceptionFrame, TrapFrame); 00429 goto Handled2; 00430 } 00431 00432 // 00433 // If the exception is an instruction bus error, then process the error. 00434 // 00435 // N.B. A special exception code is used to signal an instruction bus 00436 // error. This code is equivalent to the bug check code merged 00437 // with a reserved facility code and the reserved bit set. 00438 // 00439 // N.B. If control returns, then it is assumed that the error hand been 00440 // corrected. 00441 // 00442 00443 if (ExceptionRecord->ExceptionCode == (INSTRUCTION_BUS_ERROR | 0xdfff0000)) { 00444 KiInstructionBusError(ExceptionRecord, ExceptionFrame, TrapFrame); 00445 goto Handled2; 00446 } 00447 00448 // 00449 // If the exception is a data misalignment, this is the first change for 00450 // handling the exception, and the current thread has enabled automatic 00451 // alignment fixup, then attempt to emulate the unaligned reference. 00452 // 00453 00454 if ((ExceptionRecord->ExceptionCode == STATUS_DATATYPE_MISALIGNMENT) && 00455 (FirstChance != FALSE) && 00456 ((KeGetCurrentThread()->AutoAlignment != FALSE) || 00457 (KeGetCurrentThread()->ApcState.Process->AutoAlignment != FALSE) || 00458 (((ExceptionRecord->ExceptionInformation[1] & 0x7fff0000) == 0x7fff0000) && 00459 (PreviousMode != KernelMode))) && 00460 (KiEmulateReference(ExceptionRecord, ExceptionFrame, TrapFrame) != FALSE)) { 00461 KeGetCurrentPrcb()->KeAlignmentFixupCount += 1; 00462 goto Handled2; 00463 } 00464 00465 // 00466 // If the exception is a floating exception, then attempt to emulate the 00467 // operation. 00468 // 00469 // N.B. The pseudo status STATUS_FLOAT_STACK_CHECK is used to signify 00470 // that the exception is a floating exception and that this it the 00471 // first chance for handling the exception. The floating emulation 00472 // routine converts the status code to the proper floating status 00473 // value. 00474 // 00475 00476 if ((ExceptionRecord->ExceptionCode == STATUS_FLOAT_STACK_CHECK) && 00477 (KiEmulateFloating(ExceptionRecord, ExceptionFrame, TrapFrame) != FALSE)) { 00478 TrapFrame->Fsr = SANITIZE_FSR(TrapFrame->Fsr, PreviousMode); 00479 goto Handled2; 00480 } 00481 00482 // 00483 // If the exception is a breakpoint, then translate it to an appropriate 00484 // exception code if it is a division by zero or an integer overflow 00485 // caused by multiplication. 00486 // 00487 00488 if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) { 00489 if (ExceptionRecord->ExceptionInformation[0] == DIVIDE_BREAKPOINT) { 00490 ExceptionRecord->ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO; 00491 00492 } else if ((ExceptionRecord->ExceptionInformation[0] == MULTIPLY_BREAKPOINT) || 00493 (ExceptionRecord->ExceptionInformation[0] == OVERFLOW_BREAKPOINT)) { 00494 ExceptionRecord->ExceptionCode = STATUS_INTEGER_OVERFLOW; 00495 00496 } else if (ExceptionRecord->ExceptionInformation[0] == KDDEBUG_BREAKPOINT) { 00497 TrapFrame->Fir += 4; 00498 } 00499 } 00500 00501 // 00502 // Move machine state from trap and exception frames to a context frame, 00503 // and increment the number of exceptions dispatched. 00504 // 00505 00506 ContextFrame.ContextFlags = CONTEXT_FULL; 00507 KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextFrame); 00508 KeGetCurrentPrcb()->KeExceptionDispatchCount += 1; 00509 00510 // 00511 // Select the method of handling the exception based on the previous mode. 00512 // 00513 00514 if (PreviousMode == KernelMode) { 00515 00516 // 00517 // Previous mode was kernel. 00518 // 00519 // If this is the first chance, the kernel debugger is active, and 00520 // the exception is a kernel breakpoint, then give the kernel debugger 00521 // a chance to handle the exception. 00522 // 00523 // If this is the first chance and the kernel debugger is not active 00524 // or does not handle the exception, then attempt to find a frame 00525 // handler to handle the exception. 00526 // 00527 // If this is the second chance or the exception is not handled, then 00528 // if the kernel debugger is active, then give the kernel debugger a 00529 // second chance to handle the exception. If the kernel debugger does 00530 // not handle the exception, then bug check. 00531 // 00532 00533 if (FirstChance != FALSE) { 00534 00535 // 00536 // If the kernel debugger is active, the exception is a breakpoint, 00537 // and the breakpoint is handled by the kernel debugger, then give 00538 // the kernel debugger a chance to handle the exception. 00539 // 00540 00541 if ((KiDebugRoutine != NULL) && 00542 (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00543 (KdIsThisAKdTrap(ExceptionRecord, 00544 &ContextFrame, 00545 KernelMode) != FALSE)) { 00546 00547 if (((KiDebugRoutine) (TrapFrame, 00548 ExceptionFrame, 00549 ExceptionRecord, 00550 &ContextFrame, 00551 KernelMode, 00552 FALSE)) != FALSE) { 00553 00554 goto Handled1; 00555 } 00556 } 00557 00558 // 00559 // This is the first chance to handle the exception. 00560 // 00561 00562 if (RtlDispatchException(ExceptionRecord, &ContextFrame) != FALSE) { 00563 goto Handled1; 00564 } 00565 } 00566 00567 // 00568 // This is the second chance to handle the exception. 00569 // 00570 00571 if (KiDebugRoutine != NULL) { 00572 if (((KiDebugRoutine) (TrapFrame, 00573 ExceptionFrame, 00574 ExceptionRecord, 00575 &ContextFrame, 00576 PreviousMode, 00577 TRUE)) != FALSE) { 00578 goto Handled1; 00579 } 00580 } 00581 00582 KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, 00583 ExceptionRecord->ExceptionCode, 00584 (ULONG)ExceptionRecord->ExceptionAddress, 00585 ExceptionRecord->ExceptionInformation[0], 00586 ExceptionRecord->ExceptionInformation[1]); 00587 00588 } else { 00589 00590 // 00591 // Previous mode was user. 00592 // 00593 // If this is the first chance, the kernel debugger is active, the 00594 // exception is a kernel breakpoint, and the current process is not 00595 // being debugged, or the current process is being debugged, but the 00596 // the breakpoint is not a kernel breakpoint instruction, then give 00597 // the kernel debugger a chance to handle the exception. 00598 // 00599 // If this is the first chance and the current process has a debugger 00600 // port, then send a message to the debugger port and wait for a reply. 00601 // If the debugger handles the exception, then continue execution. Else 00602 // transfer the exception information to the user stack, transition to 00603 // user mode, and attempt to dispatch the exception to a frame based 00604 // handler. If a frame based handler handles the exception, then continue 00605 // execution. Otherwise, execute the raise exception system service 00606 // which will call this routine a second time to process the exception. 00607 // 00608 // If this is the second chance and the current process has a debugger 00609 // port, then send a message to the debugger port and wait for a reply. 00610 // If the debugger handles the exception, then continue execution. Else 00611 // if the current process has a subsystem port, then send a message to 00612 // the subsystem port and wait for a reply. If the subsystem handles the 00613 // exception, then continue execution. Else terminate the thread. 00614 // 00615 00616 if (FirstChance != FALSE) { 00617 00618 // 00619 // If the kernel debugger is active, the exception is a kernel 00620 // breakpoint, and the current process is not being debugged, 00621 // or the current process is being debugged, but the breakpoint 00622 // is not a kernel breakpoint instruction, then give the kernel 00623 // debugger a chance to handle the exception. 00624 // 00625 00626 if ((KiDebugRoutine != NULL) && 00627 (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00628 (KdIsThisAKdTrap(ExceptionRecord, 00629 &ContextFrame, 00630 UserMode) != FALSE) && 00631 ((PsGetCurrentProcess()->DebugPort == NULL) || 00632 ((PsGetCurrentProcess()->DebugPort != NULL) && 00633 (ExceptionRecord->ExceptionInformation[0] != 00634 KERNEL_BREAKPOINT_INSTRUCTION)))) { 00635 00636 if (((KiDebugRoutine) (TrapFrame, 00637 ExceptionFrame, 00638 ExceptionRecord, 00639 &ContextFrame, 00640 UserMode, 00641 FALSE)) != FALSE) { 00642 00643 goto Handled1; 00644 } 00645 } 00646 00647 // 00648 // This is the first chance to handle the exception. 00649 // 00650 00651 if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) { 00652 TrapFrame->Fsr = SANITIZE_FSR(TrapFrame->Fsr, UserMode); 00653 goto Handled2; 00654 } 00655 00656 // 00657 // Transfer exception information to the user stack, transition 00658 // to user mode, and attempt to dispatch the exception to a frame 00659 // based handler. 00660 // 00661 00662 repeat: 00663 try { 00664 00665 // 00666 // Coerce the 64-bit integer register context to 32-bits 00667 // and store in the 32-bit context area of the context 00668 // record. 00669 // 00670 // N.B. This only works becasue the 32- and 64-bit integer 00671 // register context does not overlap in the context 00672 // record. 00673 // 00674 00675 Destination = &ContextFrame.IntZero; 00676 Source = &ContextFrame.XIntZero; 00677 for (Index = 0; Index < 32; Index += 1) { 00678 *Destination++ = (ULONG)*Source++; 00679 } 00680 00681 // 00682 // Compute length of exception record and new aligned stack 00683 // address. 00684 // 00685 00686 Length = (sizeof(EXCEPTION_RECORD) + 7) & (~7); 00687 UserStack1 = (ULONG)(ContextFrame.XIntSp & (~7)) - Length; 00688 00689 // 00690 // Probe user stack area for writeability and then transfer the 00691 // exception record to the user stack area. 00692 // 00693 00694 ProbeForWrite((PCHAR)UserStack1, Length, sizeof(QUAD)); 00695 RtlMoveMemory((PVOID)UserStack1, ExceptionRecord, Length); 00696 00697 // 00698 // Compute length of context record and new aligned user stack 00699 // pointer. 00700 // 00701 00702 Length = sizeof(CONTEXT); 00703 UserStack2 = UserStack1 - Length; 00704 00705 // 00706 // Probe user stack area for writeability and then transfer the 00707 // context record to the user stack. 00708 // 00709 00710 ProbeForWrite((PCHAR)UserStack2, Length, sizeof(QUAD)); 00711 RtlMoveMemory((PVOID)UserStack2, &ContextFrame, sizeof(CONTEXT)); 00712 00713 // 00714 // Set address of exception record, context record, and the 00715 // and the new stack pointer in the current trap frame. 00716 // 00717 00718 TrapFrame->XIntSp = (LONG)UserStack2; 00719 TrapFrame->XIntS8 = (LONG)UserStack2; 00720 TrapFrame->XIntS0 = (LONG)UserStack1; 00721 TrapFrame->XIntS1 = (LONG)UserStack2; 00722 00723 // 00724 // Sanitize the floating status register so a recursive 00725 // exception will not occur. 00726 // 00727 00728 TrapFrame->Fsr = SANITIZE_FSR(ContextFrame.Fsr, UserMode); 00729 00730 // 00731 // Set the address of the exception routine that will call the 00732 // exception dispatcher and then return to the trap handler. 00733 // The trap handler will restore the exception and trap frame 00734 // context and continue execution in the routine that will 00735 // call the exception dispatcher. 00736 // 00737 00738 TrapFrame->Fir = KeUserExceptionDispatcher; 00739 return; 00740 00741 // 00742 // If an exception occurs, then copy the new exception information 00743 // to an exception record and handle the exception. 00744 // 00745 00746 } except (KiCopyInformation(&ExceptionRecord1, 00747 (GetExceptionInformation())->ExceptionRecord)) { 00748 00749 // 00750 // If the exception is a stack overflow, then attempt 00751 // to raise the stack overflow exception. Otherwise, 00752 // the user's stack is not accessible, or is misaligned, 00753 // and second chance processing is performed. 00754 // 00755 00756 if (ExceptionRecord1.ExceptionCode == STATUS_STACK_OVERFLOW) { 00757 ExceptionRecord1.ExceptionAddress = ExceptionRecord->ExceptionAddress; 00758 RtlMoveMemory((PVOID)ExceptionRecord, 00759 &ExceptionRecord1, sizeof(EXCEPTION_RECORD)); 00760 goto repeat; 00761 } 00762 } 00763 } 00764 00765 // 00766 // This is the second chance to handle the exception. 00767 // 00768 00769 UserApcPending = KeGetCurrentThread()->ApcState.UserApcPending; 00770 if (DbgkForwardException(ExceptionRecord, TRUE, TRUE)) { 00771 TrapFrame->Fsr = SANITIZE_FSR(TrapFrame->Fsr, UserMode); 00772 goto Handled2; 00773 00774 } else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE)) { 00775 00776 // 00777 // If a user APC was not previously pending and one is now 00778 // pending, then the thread has been terminated and the PC 00779 // must be forced to a legal address so an infinite loop does 00780 // not occur for the case where a jump to an unmapped address 00781 // occured. 00782 // 00783 00784 if ((UserApcPending == FALSE) && 00785 (KeGetCurrentThread()->ApcState.UserApcPending != FALSE)) { 00786 TrapFrame->Fir = (ULONG)USPCR; 00787 } 00788 00789 TrapFrame->Fsr = SANITIZE_FSR(TrapFrame->Fsr, UserMode); 00790 goto Handled2; 00791 00792 } else { 00793 ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode); 00794 KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, 00795 ExceptionRecord->ExceptionCode, 00796 (ULONG)ExceptionRecord->ExceptionAddress, 00797 ExceptionRecord->ExceptionInformation[0], 00798 ExceptionRecord->ExceptionInformation[1]); 00799 } 00800 } 00801 00802 // 00803 // Move machine state from context frame to trap and exception frames and 00804 // then return to continue execution with the restored state. 00805 // 00806 00807 Handled1: 00808 KeContextToKframes(TrapFrame, ExceptionFrame, &ContextFrame, 00809 ContextFrame.ContextFlags, PreviousMode); 00810 00811 // 00812 // Exception was handled by the debugger or the associated subsystem 00813 // and state was modified, if necessary, using the get state and set 00814 // state capabilities. Therefore the context frame does not need to 00815 // be transfered to the trap and exception frames. 00816 // 00817 00818 Handled2: 00819 return; 00820 }


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