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

chandler.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1995 Intel Corporation 00004 Copyright (c) 1990 Microsoft Corporation 00005 00006 Module Name: 00007 00008 chandler.c 00009 00010 Abstract: 00011 00012 This module implements the C specific exception handler that provides 00013 structured condition handling for the C language. 00014 00015 Author: 00016 00017 William K. Cheung (wcheung) 29-Dec-1995 00018 00019 Based on the version by David N. Cutler (davec) 11-Sep-1990 00020 00021 Environment: 00022 00023 Any mode. 00024 00025 Revision History: 00026 00027 --*/ 00028 00029 #include "nt.h" 00030 00031 // 00032 // Define procedure prototypes for exception filter and termination handler 00033 // execution routines defined in jmpunwnd.s. 00034 // 00035 00036 LONG 00037 __C_ExecuteExceptionFilter ( 00038 ULONGLONG MemoryStack, 00039 ULONGLONG BackingStore, 00040 NTSTATUS ExceptionCode, 00041 PEXCEPTION_POINTERS ExceptionPointers, 00042 ULONGLONG ExceptionFilter, 00043 ULONGLONG GlobalPointer 00044 ); 00045 00046 VOID 00047 __C_ExecuteTerminationHandler ( 00048 ULONGLONG MemoryStack, 00049 ULONGLONG BackingStore, 00050 BOOLEAN AbnormalTermination, 00051 ULONGLONG TerminationHandler, 00052 ULONGLONG GlobalPointer 00053 ); 00054 00055 00056 EXCEPTION_DISPOSITION 00057 __C_specific_handler ( 00058 IN PEXCEPTION_RECORD ExceptionRecord, 00059 IN unsigned __int64 MemoryStackFp, 00060 IN unsigned __int64 BackingStoreFp, 00061 IN OUT PCONTEXT ContextRecord, 00062 IN OUT PDISPATCHER_CONTEXT DispatcherContext, 00063 IN unsigned __int64 GlobalPointer 00064 ) 00065 00066 /*++ 00067 00068 Routine Description: 00069 00070 This function scans the scope tables associated with the specified 00071 procedure and calls exception and termination handlers as necessary. 00072 00073 Arguments: 00074 00075 ExceptionRecord - Supplies a pointer to an exception record. 00076 00077 MemoryStackFp - Supplies a pointer to memory stack frame of the 00078 establisher function. 00079 00080 BackingStoreFp - Supplies a pointer to RSE stack frame of the 00081 establisher function. 00082 00083 ContextRecord - Supplies a pointer to a context record. 00084 00085 DispatcherContext - Supplies a pointer to the exception dispatcher or 00086 unwind dispatcher context. 00087 00088 Return Value: 00089 00090 If the exception is handled by one of the exception filter routines, then 00091 there is no return from this routine and RtlUnwind is called. Otherwise, 00092 an exception disposition value of continue execution or continue search is 00093 returned. 00094 00095 --*/ 00096 00097 { 00098 ULONGLONG ImageBase; 00099 ULONGLONG ControlPc; 00100 ULONGLONG TargetPc; 00101 ULONGLONG Handler; 00102 EXCEPTION_POINTERS ExceptionPointers; 00103 PRUNTIME_FUNCTION FunctionEntry; 00104 ULONG Index; 00105 ULONG Size; 00106 PSCOPE_TABLE ScopeTable; 00107 LONG Value; 00108 00109 // 00110 // Get address of where control left the establisher, the address of the 00111 // function table entry that describes the function, and the address of 00112 // the scope table. 00113 // 00114 00115 FunctionEntry = DispatcherContext->FunctionEntry; 00116 ImageBase = DispatcherContext->ImageBase; 00117 ScopeTable = (PSCOPE_TABLE) (ImageBase + *(PULONG) 00118 GetLanguageSpecificData(FunctionEntry, ImageBase)); 00119 00120 ControlPc = DispatcherContext->ControlPc - ImageBase; 00121 00122 // 00123 // If an unwind is not in progress, then scan the scope table and call 00124 // the appropriate exception filter routines. Otherwise, scan the scope 00125 // table and call the appropriate termination handlers using the target 00126 // PC obtained from the context record. 00127 // are called. 00128 // 00129 00130 if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) { 00131 00132 // 00133 // Scan the scope table and call the appropriate exception filter 00134 // routines. 00135 // 00136 00137 ExceptionPointers.ExceptionRecord = ExceptionRecord; 00138 ExceptionPointers.ContextRecord = ContextRecord; 00139 for (Index = 0; Index < ScopeTable->Count; Index += 1) { 00140 if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) && 00141 (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress) && 00142 (ScopeTable->ScopeRecord[Index].JumpTarget != 0)) { 00143 00144 // 00145 // Call the exception filter routine. 00146 // 00147 00148 ULONG Offset = ScopeTable->ScopeRecord[Index].HandlerAddress; 00149 00150 switch (Offset & 0x7) { 00151 00152 case 7: 00153 Value = EXCEPTION_EXECUTE_HANDLER; 00154 break; 00155 00156 case 5: 00157 Value = EXCEPTION_CONTINUE_SEARCH; 00158 break; 00159 00160 case 3: 00161 Value = EXCEPTION_CONTINUE_EXECUTION; 00162 break; 00163 00164 default: 00165 Value = __C_ExecuteExceptionFilter( 00166 MemoryStackFp, 00167 BackingStoreFp, 00168 ExceptionRecord->ExceptionCode, 00169 &ExceptionPointers, 00170 (ImageBase + Offset), 00171 GlobalPointer); 00172 break; 00173 } 00174 00175 // 00176 // If the return value is less than zero, then dismiss the 00177 // exception. Otherwise, if the value is greater than zero, 00178 // then unwind to the target exception handler. Otherwise, 00179 // continue the search for an exception filter. 00180 // 00181 00182 if (Value < 0) { 00183 return ExceptionContinueExecution; 00184 00185 } else if (Value > 0) { 00186 00187 FRAME_POINTERS EstablisherFrame = {MemoryStackFp, 00188 BackingStoreFp}; 00189 00190 RtlUnwind2(EstablisherFrame, 00191 (PVOID)(ImageBase + ScopeTable->ScopeRecord[Index].JumpTarget), 00192 ExceptionRecord, 00193 (PVOID)(ULONGLONG)ExceptionRecord->ExceptionCode, 00194 ContextRecord); 00195 } 00196 } 00197 } 00198 00199 } else { 00200 00201 // 00202 // Scan the scope table and call the appropriate termination handler 00203 // routines. 00204 // 00205 00206 TargetPc = ContextRecord->StIIP - ImageBase; 00207 for (Index = 0; Index < ScopeTable->Count; Index += 1) { 00208 if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) && 00209 (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress)) { 00210 00211 // 00212 // If the target PC is within the same scope the control PC 00213 // is within, then this is an uplevel goto out of an inner try 00214 // scope or a long jump back into a try scope. Terminate the 00215 // scan termination handlers. 00216 // 00217 // N.B. The target PC can be just beyond the end of the scope, 00218 // in which case it is a leave from the scope. 00219 // 00220 00221 00222 if ((TargetPc >= ScopeTable->ScopeRecord[Index].BeginAddress) && 00223 (TargetPc < ScopeTable->ScopeRecord[Index].EndAddress)) { 00224 break; 00225 00226 } else { 00227 00228 // 00229 // If the scope table entry describes an exception filter 00230 // and the associated exception handler is the target of 00231 // the unwind, then terminate the scan for termination 00232 // handlers. Otherwise, if the scope table entry describes 00233 // a termination handler, then record the address of the 00234 // end of the scope as the new control PC address and call 00235 // the termination handler. 00236 // 00237 00238 if (ScopeTable->ScopeRecord[Index].JumpTarget != 0) { 00239 if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget) { 00240 break; 00241 } 00242 00243 } else { 00244 00245 DispatcherContext->ControlPc = ImageBase + 00246 ScopeTable->ScopeRecord[Index].EndAddress; 00247 00248 Handler = ImageBase + ScopeTable->ScopeRecord[Index].HandlerAddress; 00249 __C_ExecuteTerminationHandler( 00250 MemoryStackFp, 00251 BackingStoreFp, 00252 TRUE, 00253 Handler, 00254 GlobalPointer); 00255 } 00256 } 00257 } 00258 } 00259 } 00260 00261 // 00262 // Continue search for exception or termination handlers. 00263 // 00264 00265 return ExceptionContinueSearch; 00266 }

Generated on Sat May 15 19:39:23 2004 for test by doxygen 1.3.7