test: chandler.c Source File

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 }