test: ia64/exdsptch.c File Reference

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

# exdsptch.c File Reference

`#include "ntrtlp.h"`

Go to the source code of this file.

## Defines

#define | IS_HANDLER_DEFINED(f, base)
#define | HANDLER(f, base, target)
#define | RAISE_EXCEPTION(Status, ExceptionRecordt)
#define | IS_SAME_FRAME(Frame1, Frame2)
#define | INITIALIZE_FRAME(Frame) Frame.MemoryStackFp = Frame.BackingStoreFp = 0
#define | CHECK_MSTACK_FRAME(Establisher, Target)
#define | CHECK_BSTORE_FRAME(Establisher, Target)
#define | IS_EM_SETJMP_REGISTRATION(ExRegistration)

## Functions

PRUNTIME_FUNCTION | RtlLookupStaticFunctionEntry (IN ULONG_PTR ControlPc, OUT PBOOLEAN InImage)
PRUNTIME_FUNCTION | RtlLookupDynamicFunctionEntry (IN ULONG_PTR ControlPc, OUT PULONGLONG ImageBase, OUT PULONGLONG TargetGp)
VOID | RtlRestoreContext (IN PCONTEXT ContextRecord, IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL)
ULONGLONG | RtlpVirtualUnwind (IN ULONGLONG ImageBase, IN ULONGLONG ControlPc, IN PRUNTIME_FUNCTION FunctionEntry, IN PCONTEXT ContextRecord, OUT PBOOLEAN InFunction, OUT PFRAME_POINTERS EstablisherFrame, IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL)
PEXCEPTION_REGISTRATION_RECORD | RtlpGetRegistrationHead (IN VOID)
VOID | RtlpUnlinkHandler (PEXCEPTION_REGISTRATION_RECORD UnlinkPointer)
PRUNTIME_FUNCTION | RtlLookupFunctionEntry (IN ULONGLONG ControlPc, OUT PULONGLONG ImageBase, OUT PULONGLONG TargetGp)
VOID | RtlpRaiseException (IN PEXCEPTION_RECORD ExceptionRecord)
VOID | RtlRaiseException (IN PEXCEPTION_RECORD ExceptionRecord)
VOID | RtlpRaiseStatus (IN NTSTATUS Status)
VOID | RtlRaiseStatus (IN NTSTATUS Status)
VOID | RtlUnwind (IN PVOID TargetFrame OPTIONAL, IN PVOID TargetIp OPTIONAL, IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL, IN PVOID ReturnValue)
VOID | RtlUnwind2 (IN FRAME_POINTERS TargetFrame OPTIONAL, IN PVOID TargetIp OPTIONAL, IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL, IN PVOID ReturnValue, IN PCONTEXT ContextRecord)
BOOLEAN | RtlDispatchException (IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord)
PLIST_ENTRY | RtlGetFunctionTableListHead (VOID)
BOOLEAN | RtlAddFunctionTable (IN PRUNTIME_FUNCTION FunctionTable, IN ULONG EntryCount, IN ULONGLONG BaseAddress, IN ULONGLONG TargetGp)
BOOLEAN | RtlDeleteFunctionTable (IN PRUNTIME_FUNCTION FunctionTable)

## Variables

LIST_ENTRY | DynamicFunctionTable

## Define Documentation

#define CHECK_BSTORE_FRAME | ( | Establisher,
|  | Target |  | ) |

Value:

    ((Establisher.BackingStoreFp < LowBStoreLimit) ||                         \
         (Establisher.BackingStoreFp > HighBStoreLimit) ||                        \
         ((Target.BackingStoreFp != 0) &&                                         \
          ((ULONG)Target.BackingStoreFp > (ULONG)Establisher.BackingStoreFp)) ||  \
         ((Establisher.BackingStoreFp & 0x7) != 0))

Definition at line 101 of file ia64/exdsptch.c.

Referenced by RtlDispatchException(), and RtlUnwind2().

#define CHECK_MSTACK_FRAME | ( | Establisher,
|  | Target |  | ) |

Value:

    ((Establisher.MemoryStackFp < LowStackLimit) ||                        \
         (Establisher.MemoryStackFp > HighStackLimit) ||                       \
         ((Target.MemoryStackFp != 0) &&                                       \
          ((ULONG)Target.MemoryStackFp < (ULONG)Establisher.MemoryStackFp)) || \
         ((Establisher.MemoryStackFp & 0x3) != 0))

Definition at line 94 of file ia64/exdsptch.c.

Referenced by RtlDispatchException(), and RtlUnwind2().

#define HANDLER | ( | f,
|  | base,
|  | target |  | ) |

Value:

    (PEXCEPTION_ROUTINE)                                                        \
            (*(PULONGLONG) ((LONGLONG)target +                                      \
            (*(PULONGLONG) (base + f->UnwindInfoAddress + sizeof(UNWIND_INFO)  +    \
            (((PUNWIND_INFO) (base + f->UnwindInfoAddress))->DataLength * sizeof(ULONGLONG))))))

Definition at line 71 of file ia64/exdsptch.c.

Referenced by RtlDispatchException(), and RtlUnwind2().

#define INITIALIZE_FRAME | ( | Frame |  | ) | Frame.MemoryStackFp = Frame.BackingStoreFp = 0

| Definition at line 91 of file ia64/exdsptch.c. Referenced by RtlDispatchException().

#define IS_EM_SETJMP_REGISTRATION | ( | ExRegistration |  | ) |

Value:

    (   (ExRegistration != NULL)                                                            &&  \
            (ExRegistration != EXCEPTION_CHAIN_END)                                             &&  \
            (ExRegistration->Next == (struct _EXCEPTION_REGISTRATION_RECORD *)(LONG_PTR) 1)          \
        )

Definition at line 108 of file ia64/exdsptch.c.

Referenced by RtlUnwind().

#define IS_HANDLER_DEFINED | ( | f,
|  | base |  | ) |

Value:

    (f->UnwindInfoAddress &&                                       \
            (((PUNWIND_INFO)(base+f->UnwindInfoAddress))->Flags & 0x3))

Definition at line 67 of file ia64/exdsptch.c.

#define IS_SAME_FRAME | ( | Frame1,
|  | Frame2 |  | ) |

Value:

    ( (Frame1.MemoryStackFp == Frame2.MemoryStackFp) &&            \
          (Frame1.BackingStoreFp == Frame2.BackingStoreFp) )

Definition at line 87 of file ia64/exdsptch.c.

Referenced by RtlDispatchException(), and RtlUnwind2().

#define RAISE_EXCEPTION | ( | Status,
|  | ExceptionRecordt |  | ) |

Value:

    {                \
        EXCEPTION_RECORD ExceptionRecordn;                             \
                                                                       \
        ExceptionRecordn.ExceptionCode = Status;                       \
        ExceptionRecordn.ExceptionFlags = EXCEPTION_NONCONTINUABLE;    \
        ExceptionRecordn.ExceptionRecord = ExceptionRecordt;           \
        ExceptionRecordn.NumberParameters = 0;                         \
        RtlRaiseException(&ExceptionRecordn);                          \
        }

Definition at line 77 of file ia64/exdsptch.c.

## Function Documentation

BOOLEAN RtlAddFunctionTable | ( | IN PRUNTIME_FUNCTION | FunctionTable,
|  | IN ULONG | EntryCount,
|  | IN ULONGLONG | BaseAddress,
|  | IN ULONGLONG | TargetGp
| ) |

Definition at line 1422 of file ia64/exdsptch.c.

References DynamicFunctionTable, FALSE, LoaderLock, NULL, RtlAllocateHeap, and TRUE.

    01431                    :
    01432
    01433     Add a dynamic function table to the dynamic function table list. Dynamic
    01434     function tables describe code generated at run-time. The dynamic function
    01435     tables are searched via a call to RtlLookupDynamicFunctionEntry().
    01436     Normally this is only invoked via calls to RtlLookupFunctionEntry().
    01437
    01438     The FunctionTable entries need not be sorted in any particular order. The
    01439     list is scanned for a Min and Max address range and whether or not it is
    01440     sorted. If the latter RtlLookupDynamicFunctionEntry() uses a binary
    01441     search, otherwise it uses a linear search.
    01442
    01443     The dynamic function entries will be searched only after a search
    01444     through the static function entries associated with all current
    01445     process images has failed.
    01446
    01447 Arguments:
    01448
    01449    FunctionTable       Address of an array of function entries where
    01450                        each element is of type RUNTIME_FUNCTION.
    01451
    01452    EntryCount          The number of function entries in the array
    01453
    01454    BaseAddress         Base address to calculate the real address  of the function table entry
    01455    TargetGp            return back to RtlLookupFunctionEntry for future query.
    01456
    01457 Return value:
    01458
    01459    TRUE                if RtlAddFunctionTable completed successfully
    01460    FALSE               if RtlAddFunctionTable completed unsuccessfully
    01461
    01462 --*/
    01463 {
    01464     PDYNAMIC_FUNCTION_TABLE pNew;
    01465     PRUNTIME_FUNCTION FunctionEntry;
    01466     ULONG i;
    01467
    01468     if (EntryCount == 0)
    01469         return FALSE;
    01470
    01471     //
    01472     // Make sure the link list is initialized;
    01473     //
    01474
    01475     if (DynamicFunctionTable.Flink == NULL) {
    01476        InitializeListHead(&DynamicFunctionTable);
    01477     }
    01478
    01479     //
    01480     //  Allocate memory for this link list entry
    01481     //
    01482
    01483     pNew = RtlAllocateHeap( RtlProcessHeap(), 0, sizeof(DYNAMIC_FUNCTION_TABLE) );
    01484
    01485     if (pNew != NULL) {
    01486         pNew->FunctionTable = FunctionTable;
    01487         pNew->EntryCount = EntryCount;
    01488         NtQuerySystemTime( &pNew->TimeStamp );
    01489
    01490         //
    01491         // Scan the function table for Minimum/Maximum and to determine
    01492         // if it is sorted. If the latter, we can perform a binary search.
    01493         //
    01494
    01495         FunctionEntry = FunctionTable;
    01496         pNew->MinimumAddress = RF_BEGIN_ADDRESS( BaseAddress, FunctionEntry);
    01497         pNew->MaximumAddress = RF_END_ADDRESS(BaseAddress, FunctionEntry);
    01498         pNew->Sorted = TRUE;
    01499         FunctionEntry++;
    01500
    01501         for (i = 1; i < EntryCount; FunctionEntry++, i++) {
    01502             if (pNew->Sorted && FunctionEntry->BeginAddress < FunctionTable[i-1].BeginAddress) {
    01503                 pNew->Sorted = FALSE;
    01504             }
    01505             if (RF_BEGIN_ADDRESS(FunctionTable, FunctionEntry) < pNew->MinimumAddress) {
    01506                 pNew->MinimumAddress = RF_BEGIN_ADDRESS( BaseAddress, FunctionEntry);
    01507             }
    01508             if (RF_END_ADDRESS( FunctionTable, FunctionEntry) > pNew->MaximumAddress) {
    01509                 pNew->MaximumAddress = RF_END_ADDRESS( BaseAddress, FunctionEntry);
    01510             }
    01511         }
    01512
    01513         //
    01514         // Insert the new entry in the dynamic function table list.
    01515         // Protect the insertion with the loader lock.
    01516         //
    01517
    01518         pNew->BaseAddress = BaseAddress;
    01519         pNew->TargetGp    = TargetGp;
    01520
    01521         RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
    01522         InsertTailList((PLIST_ENTRY)&DynamicFunctionTable, (PLIST_ENTRY)pNew);
    01523         RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
    01524
    01525         return TRUE;
    01526     } else {
    01527         return FALSE;
    01528     }
    01529 }

BOOLEAN RtlDeleteFunctionTable | ( | IN PRUNTIME_FUNCTION | FunctionTable | ) |

Definition at line 1532 of file ia64/exdsptch.c.

References DynamicFunctionTable, FALSE, LoaderLock, RtlFreeHeap, Status, and TRUE.

    01535 {
    01536
    01537 /*++
    01538
    01539 Routine Description:
    01540
    01541     Remove a dynamic function table from the dynamic function table list.
    01542
    01543 Arguments:
    01544
    01545    FunctionTable       Address of an array of function entries that
    01546                        was passed in a previous call to RtlAddFunctionTable
    01547
    01548 Return Value
    01549
    01550     TRUE - If function completed successfully
    01551     FALSE - If function completed unsuccessfully
    01552
    01553 --*/
    01554
    01555     PDYNAMIC_FUNCTION_TABLE CurrentEntry;
    01556     PLIST_ENTRY Head;
    01557     PLIST_ENTRY Next;
    01558     BOOLEAN Status = FALSE;
    01559
    01560     RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
    01561
    01562     //
    01563     // Search the dynamic function table list for a match on the the function
    01564     // table address.
    01565     //
    01566
    01567     Head = &DynamicFunctionTable;
    01568     for (Next = Head->Blink; Next != Head; Next = Next->Blink) {
    01569         CurrentEntry = CONTAINING_RECORD(Next,DYNAMIC_FUNCTION_TABLE,Links);
    01570         if (CurrentEntry->FunctionTable == FunctionTable) {
    01571             RemoveEntryList((PLIST_ENTRY)CurrentEntry);
    01572             RtlFreeHeap( RtlProcessHeap(), 0, CurrentEntry );
    01573             Status = TRUE;
    01574             break;
    01575         }
    01576     }
    01577
    01578     RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
    01579     return Status;
    01580 }

BOOLEAN RtlDispatchException | ( | IN PEXCEPTION_RECORD | ExceptionRecord,
|  | IN PCONTEXT | ContextRecord
| ) |

Definition at line 985 of file ia64/exdsptch.c.

References CHECK_BSTORE_FRAME, CHECK_MSTACK_FRAME, EXCEPTION_COLLIDED_UNWIND, EXCEPTION_NESTED_CALL, EXCEPTION_NONCONTINUABLE, EXCEPTION_STACK_INVALID, ExceptionCollidedUnwind, ExceptionContinueExecution, ExceptionContinueSearch, ExceptionNestedException, FALSE, HANDLER, Index, INITIALIZE_FRAME, IS_HANDLER_DEFINED, IS_SAME_FRAME, NtGlobalFlag, NULL, RAISE_EXCEPTION, RtlImageDirectoryEntryToData(), RtlLookupFunctionEntry(), Rtlp64GetBStoreLimits(), Rtlp64GetStackLimits(), RtlpExecuteEmHandlerForException(), RtlpLogExceptionHandler(), RtlpLogLastExceptionDisposition(), RtlVirtualUnwind(), SHORT, Size, and TRUE.

    00992                    :
    00993
    00994     This function attempts to dispatch an exception to a frame based
    00995     handler by searching backwards through the call frames by unwinding
    00996     the RSE backing store as well as the memory stack.  The search begins
    00997     with the frame specified in the context record and continues backward
    00998     until either a handler is found that handles the exception, the stack
    00999     and/or the backing store is found to be invalid (i.e., out of limits
    01000     or unaligned), or the end of the call hierarchy is reached.
    01001
    01002     As each frame is encountered, the PC where control left the corresponding
    01003     function is determined and used to lookup exception handler information
    01004     in the runtime function table built by the linker. If the respective
    01005     routine has an exception handler, then the handler is called. If the
    01006     handler does not handle the exception, then the prologue of the routine
    01007     is undone to "unwind" the effect of the prologue and then the next
    01008     frame is examined.
    01009
    01010 Arguments:
    01011
    01012     ExceptionRecord - Supplies a pointer to an exception record.
    01013
    01014     ContextRecord - Supplies a pointer to a context record.
    01015
    01016 Return Value:
    01017
    01018     If the exception is handled by one of the frame based handlers, then
    01019     a value of TRUE is returned. Otherwise a value of FALSE is returned.
    01020
    01021 --*/
    01022
    01023 {
    01024     ULONGLONG TargetGp;
    01025     ULONGLONG ImageBase;
    01026     CONTEXT ContextRecordEm;
    01027     ULONGLONG ControlPc;
    01028     ULONGLONG NextPc;
    01029     DISPATCHER_CONTEXT DispatcherContext;
    01030     EXCEPTION_DISPOSITION Disposition;
    01031     ULONG ExceptionFlags;
    01032     PRUNTIME_FUNCTION FunctionEntry;
    01033     FRAME_POINTERS EstablisherFrame;
    01034     FRAME_POINTERS TargetFrame;       // to be removed in the future
    01035     ULONGLONG HighStackLimit;
    01036     ULONGLONG LowStackLimit;
    01037     ULONGLONG HighBStoreLimit;
    01038     ULONGLONG LowBStoreLimit;
    01039     FRAME_POINTERS NestedFrame;
    01040     FRAME_POINTERS NullFrame;
    01041     ULONG Index;
    01042     ULONG Size;
    01043     BOOLEAN InFunction;
    01044
    01045     //
    01046     // Get the current stack limits, make a copy of the context record,
    01047     // get the initial PC value, capture the exception flags, and set
    01048     // the nested exception frame pointer.
    01049     //
    01050
    01051     Rtlp64GetStackLimits(&LowStackLimit, &HighStackLimit);
    01052     Rtlp64GetBStoreLimits(&LowBStoreLimit, &HighBStoreLimit);
    01053
    01054     RtlMoveMemory(&ContextRecordEm, ContextRecord, sizeof(CONTEXT));
    01055
    01056     if ( (ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) &&
    01057          (ExceptionRecord->NumberParameters == 5) &&
    01058          (ExceptionRecord->ExceptionInformation[4] & (1 << ISR_X)) )
    01059     {
    01060         ControlPc = ExceptionRecord->ExceptionInformation[3];
    01061         ControlPc = RtlIa64InsertIPSlotNumber(ControlPc,
    01062                                ((ContextRecordEm.StIPSR >> PSR_RI) & 0x3));
    01063     } else {
    01064         ControlPc = RtlIa64InsertIPSlotNumber(ContextRecordEm.StIIP,
    01065                                ((ContextRecordEm.StIPSR >> PSR_RI) & 0x3));
    01066     }
    01067
    01068     ExceptionFlags = ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE;
    01069
    01070     INITIALIZE_FRAME(NestedFrame);
    01071     INITIALIZE_FRAME(NullFrame);
    01072
    01073     //
    01074     // Start with the frame specified by the context record and search
    01075     // backwards through the chain of call frames attempting to find an
    01076     // exception handler that will handle the exception.
    01077     //
    01078
    01079     do {
    01080
    01081         //
    01082         // Lookup the function table entry using the point at which control
    01083         // left the procedure.
    01084         //
    01085
    01086
    01087         FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, &TargetGp);
    01088
    01089         //
    01090         // If there is a function table entry for the routine, then
    01091         // virtually unwind to the caller of the current routine to
    01092         // obtain the virtual frame pointer of the establisher and check
    01093         // if there is an exception handler for the frame.
    01094         //
    01095
    01096         if (FunctionEntry != NULL) {
    01097             NextPc = RtlVirtualUnwind(ImageBase,
    01098                                       ControlPc,
    01099                                       FunctionEntry,
    01100                                       &ContextRecordEm,
    01101                                       &InFunction,
    01102                                       &EstablisherFrame,
    01103                                       NULL);
    01104
    01105             //
    01106             // If either one or both of the two virtual frame pointers are
    01107             // not within the specified stack limits or unaligned,
    01108             // then set the stack invalid flag in the exception record and
    01109             // return exception not handled.  Otherwise, check if the
    01110             // current routine has an exception handler.
    01111             //
    01112
    01113             if (CHECK_MSTACK_FRAME(EstablisherFrame, NullFrame)) {
    01114
    01115                 ExceptionFlags |= EXCEPTION_STACK_INVALID;
    01116                 break;
    01117
    01118             } else if (CHECK_BSTORE_FRAME(EstablisherFrame, NullFrame)) {
    01119
    01120                 ExceptionFlags |= EXCEPTION_STACK_INVALID;
    01121                 break;
    01122
    01123             } else if ((IS_HANDLER_DEFINED(FunctionEntry, ImageBase) && InFunction)) {
    01124
    01125                 //
    01126                 // The handler (i.e. personality routine) has to be called
    01127                 // to search for an exception handler in this frame.  The
    01128                 // handler must be executed by calling a stub routine that
    01129                 // is written in assembler.  This is required because up
    01130                 // level addressing of this routine information is required
    01131                 // when a nested exception is encountered.
    01132                 //
    01133
    01134                 DispatcherContext.ControlPc = ControlPc;
    01135                 DispatcherContext.FunctionEntry = FunctionEntry;
    01136                 DispatcherContext.ImageBase = ImageBase;
    01137
    01138                 do {
    01139
    01140                     ExceptionRecord->ExceptionFlags = ExceptionFlags;
    01141
    01142                     if (NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING) {
    01143                         Index = RtlpLogExceptionHandler(
    01144                                         ExceptionRecord,
    01145                                         ContextRecord,
    01146                                         (ULONG)ControlPc,
    01147                                         FunctionEntry,
    01148                                         sizeof(RUNTIME_FUNCTION));
    01149                     }
    01150
    01151                     DispatcherContext.EstablisherFrame = EstablisherFrame;
    01152                     DispatcherContext.ContextRecord = ContextRecord;
    01153                     Disposition = RtlpExecuteEmHandlerForException(
    01154                                       ExceptionRecord,
    01155                                       EstablisherFrame.MemoryStackFp,
    01156                                       EstablisherFrame.BackingStoreFp,
    01157                                       ContextRecord,
    01158                                       &DispatcherContext,
    01159                                       TargetGp,
    01160                                       HANDLER(FunctionEntry, ImageBase, TargetGp));
    01161
    01162                     if (NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING) {
    01163                         RtlpLogLastExceptionDisposition(Index, Disposition);
    01164                     }
    01165
    01166                     ExceptionFlags |=
    01167                         (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE);
    01168
    01169                     ExceptionFlags &= ~EXCEPTION_COLLIDED_UNWIND;
    01170
    01171                     //
    01172                     // If the current scan is within a nested context and the
    01173                     // frame just examined is the end of the nested region,
    01174                     // then clear the nested context frame and the nested
    01175                     // exception flag in the exception flags.
    01176                     //
    01177
    01178                     if (IS_SAME_FRAME(NestedFrame, EstablisherFrame)) {
    01179                         ExceptionFlags &= (~EXCEPTION_NESTED_CALL);
    01180                         INITIALIZE_FRAME(NestedFrame);
    01181                     }
    01182
    01183                     //
    01184                     // Case on the handler disposition.
    01185                     //
    01186
    01187                     switch (Disposition) {
    01188
    01189                     //
    01190                     // The disposition is to continue execution.
    01191                     //
    01192                     // If the exception is not continuable, then raise the
    01193                     // exception STATUS_NONCONTINUABLE_EXCEPTION.  Otherwise,
    01194                     // return exception handled.
    01195                     //
    01196
    01197                     case ExceptionContinueExecution:
    01198                         if ((ExceptionFlags & EXCEPTION_NONCONTINUABLE) != 0) {
    01199                             RAISE_EXCEPTION(STATUS_NONCONTINUABLE_EXCEPTION,
    01200                                             ExceptionRecord);
    01201                         } else {
    01202                             return TRUE;
    01203                         }
    01204
    01205                     //
    01206                     // The disposition is to continue the search.
    01207                     //
    01208                     // Get the next frame address and continue the search.
    01209                     //
    01210
    01211                     case ExceptionContinueSearch:
    01212                         break;
    01213
    01214                     //
    01215                     // The disposition is nested exception.
    01216                     //
    01217                     // Set the nested context frame to the establisher frame
    01218                     // address and set the nested exception flag in the
    01219                     // exception flags.
    01220                     //
    01221
    01222                     case ExceptionNestedException:
    01223                         ExceptionFlags |= EXCEPTION_NESTED_CALL;
    01224                         if (DispatcherContext.EstablisherFrame.MemoryStackFp > NestedFrame.MemoryStackFp) {
    01225                             NestedFrame = DispatcherContext.EstablisherFrame;
    01226                         }
    01227                         break;
    01228
    01229                     //
    01230                     // The disposition is hitting a frame processed by a
    01231                     // previous unwind.
    01232                     //
    01233                     // Set the target of the current dispatch to the context
    01234                     // record of the previous unwind
    01235                     //
    01236
    01237                     case ExceptionCollidedUnwind:
    01238                         ControlPc = DispatcherContext.ControlPc;
    01239                         NextPc = ControlPc;
    01240                         EstablisherFrame = DispatcherContext.EstablisherFrame;
    01241                         FunctionEntry = DispatcherContext.FunctionEntry;
    01242                         ImageBase = DispatcherContext.ImageBase;
    01243                         RtlMoveMemory(&ContextRecordEm,
    01244                                       DispatcherContext.ContextRecord,
    01245                                       sizeof(CONTEXT));
    01246                         ExceptionFlags |= EXCEPTION_COLLIDED_UNWIND;
    01247                         TargetGp = (ULONG_PTR)(RtlImageDirectoryEntryToData(
    01248                                                    (PVOID)ImageBase,
    01249                                                    TRUE,
    01250                                                    IMAGE_DIRECTORY_ENTRY_GLOBALPTR,
    01251                                                    &Size
    01252                                                    ));
    01253                         break;
    01254
    01255                     //
    01256                     // All other disposition values are invalid.
    01257                     //
    01258                     // Raise invalid disposition exception.
    01259                     //
    01260
    01261                     default:
    01262                         RAISE_EXCEPTION(STATUS_INVALID_DISPOSITION, ExceptionRecord);
    01263                         break;
    01264                     }
    01265
    01266                 } while ((ExceptionFlags & EXCEPTION_COLLIDED_UNWIND) != 0);
    01267
    01268             }
    01269
    01270         } else {
    01271
    01272             //
    01273             // No function table entry is found.
    01274             //
    01275
    01276             SHORT BsFrameSize, TempFrameSize;
    01277
    01278             NextPc = RtlIa64InsertIPSlotNumber((ContextRecordEm.BrRp-16), 2);
    01279             ContextRecordEm.StIFS = ContextRecordEm.RsPFS;
    01280             BsFrameSize = (SHORT)(ContextRecordEm.StIFS >> PFS_SIZE_SHIFT) & PFS_SIZE_MASK;
    01281             TempFrameSize = BsFrameSize - (SHORT)((ContextRecordEm.RsBSP >> 3) & NAT_BITS_PER_RNAT_REG);
    01282             while (TempFrameSize > 0) {
    01283                 BsFrameSize++;
    01284                 TempFrameSize -= NAT_BITS_PER_RNAT_REG;
    01285             }
    01286             ContextRecordEm.RsBSP -= BsFrameSize * sizeof(ULONGLONG);
    01287             ContextRecordEm.RsBSPSTORE = ContextRecordEm.RsBSP;
    01288
    01289             if (NextPc == ControlPc) {
    01290                 break;
    01291             }
    01292         }
    01293
    01294         //
    01295         // Set the point at which control left the previous routine.
    01296         //
    01297
    01298         ControlPc = NextPc;
    01299
    01300     } while ( (ContextRecordEm.IntSp < HighStackLimit) ||
    01301               (ContextRecordEm.RsBSP > LowBStoreLimit) );
    01302
    01303     //
    01304     // Could not handle the exception.
    01305     //
    01306     // Set final exception flags and return exception not handled.
    01307     //
    01308
    01309     ExceptionRecord->ExceptionFlags = ExceptionFlags;
    01310     return FALSE;
    01311 }

PLIST_ENTRY RtlGetFunctionTableListHead | ( | VOID |  | ) |

Definition at line 1402 of file ia64/exdsptch.c.

References DynamicFunctionTable.

    01408                    :
    01409
    01410     Return the address of the dynamic function table list head.
    01411
    01412 Return value:
    01413
    01414     Address of dynamic function table list head.
    01415
    01416 --*/
    01417 {
    01418     return &DynamicFunctionTable;
    01419 }

PRUNTIME_FUNCTION RtlLookupDynamicFunctionEntry | ( | IN ULONG_PTR | ControlPc,
|  | OUT PULONGLONG | ImageBase,
|  | OUT PULONGLONG | TargetGp
| ) |

Definition at line 1583 of file ia64/exdsptch.c.

References DynamicFunctionTable, LoaderLock, and NULL.

Referenced by RtlLookupDirectFunctionEntry(), and RtlLookupFunctionEntry().

    01591                    :
    01592
    01593   This function searches through the dynamic function entry
    01594   tables and returns the function entry address that corresponds
    01595   to the specified ControlPc. This routine does NOT perform the
    01596   secondary function entry indirection. That is performed
    01597   by RtlLookupFunctionEntry().
    01598
    01599   Argument:
    01600
    01601      ControlPc           Supplies a ControlPc.
    01602      ImageBase           OUT Base address for dynamic code
    01603
    01604   Return Value
    01605
    01606      NULL - No function entry found that contains the ControlPc.
    01607
    01608      NON-NULL - Address of the function entry that describes the
    01609                 code containing ControlPC.
    01610
    01611 --*/
    01612
    01613 {
    01614     PDYNAMIC_FUNCTION_TABLE CurrentEntry;
    01615     PLIST_ENTRY Next,Head;
    01616     PRUNTIME_FUNCTION FunctionTable;
    01617     PRUNTIME_FUNCTION FunctionEntry;
    01618     LONG High;
    01619     LONG Low;
    01620     LONG Middle;
    01621     SIZE_T BaseAddress;
    01622
    01623
    01624     if (DynamicFunctionTable.Flink == NULL || ImageBase == NULL)
    01625         return NULL;
    01626
    01627
    01628         //
    01629         //  Search the tree starting from the head, continue until the entry
    01630         //  is found or we reach the end of the list.
    01631         //
    01632     if (RtlTryEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock) ) {
    01633
    01634         Head = &DynamicFunctionTable;
    01635         for (Next = Head->Blink; Next != Head; Next = Next->Blink) {
    01636             CurrentEntry = CONTAINING_RECORD(Next,DYNAMIC_FUNCTION_TABLE,Links);
    01637             FunctionTable = CurrentEntry->FunctionTable;
    01638
    01639             //
    01640             // Check if the ControlPC is within the range of this function table
    01641             //
    01642
    01643             if ((ControlPc >= CurrentEntry->MinimumAddress) &&
    01644                 (ControlPc <  CurrentEntry->MaximumAddress) ) {
    01645
    01646
    01647                 // If this function table is sorted do a binary search.
    01648
    01649                 BaseAddress = CurrentEntry->BaseAddress;
    01650                 if (CurrentEntry->Sorted) {
    01651
    01652                     //
    01653                     // Perform binary search on the function table for a function table
    01654                     // entry that subsumes the specified PC.
    01655                     //
    01656
    01657                     Low = 0;
    01658                     High = CurrentEntry->EntryCount -1 ;
    01659
    01660                     while (High >= Low) {
    01661
    01662                         //
    01663                         // Compute next probe index and test entry. If the specified PC
    01664                         // is greater than of equal to the beginning address and less
    01665                         // than the ending address of the function table entry, then
    01666                         // return the address of the function table entry. Otherwise,
    01667                         // continue the search.
    01668                         //
    01669
    01670
    01671                         Middle = (Low + High) >> 1;
    01672                         FunctionEntry = &FunctionTable[Middle];
    01673
    01674                         if (ControlPc < RF_BEGIN_ADDRESS( BaseAddress, FunctionEntry)) {
    01675                             High = Middle - 1;
    01676
    01677                         } else if (ControlPc >= RF_END_ADDRESS( BaseAddress, FunctionEntry)) {
    01678                             Low = Middle + 1;
    01679
    01680                         } else {
    01681
    01682                             *ImageBase = CurrentEntry->BaseAddress;
    01683
    01684                             if ( TargetGp != NULL )
    01685                                 *TargetGp  = CurrentEntry->TargetGp;
    01686
    01687                             RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
    01688                             return FunctionEntry;
    01689                         }
    01690                     }
    01691
    01692                 } else {    // Not sorted. Do linear search.
    01693
    01694                     PRUNTIME_FUNCTION LastFunctionEntry = &FunctionTable[CurrentEntry->EntryCount];
    01695
    01696
    01697                     for (FunctionEntry = FunctionTable; FunctionEntry < LastFunctionEntry; FunctionEntry++) {
    01698
    01699                         if ((ControlPc >= RF_BEGIN_ADDRESS( BaseAddress, FunctionEntry)) &&
    01700                             (ControlPc <  RF_END_ADDRESS( BaseAddress, FunctionEntry))) {
    01701
    01702
    01703                             *ImageBase = CurrentEntry->BaseAddress;
    01704
    01705                             if ( TargetGp != NULL )
    01706                                 *TargetGp  = CurrentEntry->TargetGp;
    01707
    01708                             RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
    01709                             return FunctionEntry;
    01710                         }
    01711                     }
    01712                 } // binary/linear search
    01713             } // if in range
    01714         } // for (... Next != Head ...)
    01715         RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
    01716     } // LoaderLock
    01717
    01718     return NULL;
    01719 }

PRUNTIME_FUNCTION RtlLookupFunctionEntry | ( | IN ULONGLONG | ControlPc,
|  | OUT PULONGLONG | ImageBase,
|  | OUT PULONGLONG | TargetGp
| ) |

Definition at line 184 of file ia64/exdsptch.c.

References NULL, RtlImageDirectoryEntryToData(), RtlLookupDynamicFunctionEntry(), RtlPcToFileHeader(), Size, TRUE, and USHORT.

    00192                    :
    00193
    00194     This function searches the currently active function tables for an
    00195     entry that corresponds to the specified PC value.
    00196
    00197 Arguments:
    00198
    00199     ControlPc - Supplies the virtual address of an instruction bundle
    00200         within the specified function.
    00201
    00202     ImageBase - Returns the base address of the module to which the
    00203                 function belongs.
    00204
    00205     TargetGp - Returns the global pointer value of the module.
    00206
    00207 Return Value:
    00208
    00209     If there is no entry in the function table for the specified PC, then
    00210     NULL is returned.  Otherwise, the address of the function table entry
    00211     that corresponds to the specified PC is returned.
    00212
    00213 --*/
    00214
    00215 {
    00216     PRUNTIME_FUNCTION FunctionEntry;
    00217     PRUNTIME_FUNCTION FunctionTable;
    00218     ULONG SizeOfExceptionTable;
    00219     ULONG Size;
    00220     LONG High;
    00221     LONG Middle;
    00222     LONG Low;
    00223     USHORT i;
    00224
    00225     //
    00226     // Search for the image that includes the specified swizzled PC value.
    00227     //
    00228
    00229     *ImageBase = (ULONG_PTR)RtlPcToFileHeader((PVOID)ControlPc,
    00230                                               (PVOID *)ImageBase);
    00231
    00232
    00233     //
    00234     // If an image is found that includes the specified PC, then locate the
    00235     // function table for the image.
    00236     //
    00237
    00238     if ((PVOID)*ImageBase != NULL) {
    00239
    00240         *TargetGp = (ULONG_PTR)(RtlImageDirectoryEntryToData(
    00241                                (PVOID)*ImageBase,
    00242                                TRUE,
    00243                                IMAGE_DIRECTORY_ENTRY_GLOBALPTR,
    00244                                &Size
    00245                                ));
    00246
    00247         FunctionTable = (PRUNTIME_FUNCTION)RtlImageDirectoryEntryToData(
    00248                          (PVOID)*ImageBase,
    00249                          TRUE,
    00250                          IMAGE_DIRECTORY_ENTRY_EXCEPTION,
    00251                          &SizeOfExceptionTable);
    00252
    00253         //
    00254         // If a function table is located, then search the table for a
    00255         // function table entry for the specified PC.
    00256         //
    00257
    00258         if (FunctionTable != NULL) {
    00259
    00260             //
    00261             // Initialize search indices.
    00262             //
    00263
    00264             Low = 0;
    00265             High = (SizeOfExceptionTable / sizeof(RUNTIME_FUNCTION)) - 1;
    00266             ControlPc = ControlPc - *ImageBase;
    00267
    00268             //
    00269             // Perform binary search on the function table for a function table
    00270             // entry that subsumes the specified PC.
    00271             //
    00272
    00273             while (High >= Low) {
    00274
    00275                 //
    00276                 // Compute next probe index and test entry. If the specified PC
    00277                 // is greater than of equal to the beginning address and less
    00278                 // than the ending address of the function table entry, then
    00279                 // return the address of the function table entry. Otherwise,
    00280                 // continue the search.
    00281                 //
    00282
    00283                 Middle = (Low + High) >> 1;
    00284                 FunctionEntry = &FunctionTable[Middle];
    00285
    00286                 if (ControlPc < FunctionEntry->BeginAddress) {
    00287                     High = Middle - 1;
    00288
    00289                 } else if (ControlPc >= FunctionEntry->EndAddress) {
    00290                     Low = Middle + 1;
    00291
    00292                 } else {
    00293                     return FunctionEntry;
    00294
    00295                 }
    00296             }
    00297         }
    00298     }
    00299 #if !defined(NTOS_KERNEL_RUNTIME)
    00300
    00301     else     // ImageBase == NULL
    00302         return   RtlLookupDynamicFunctionEntry ( ControlPc, ImageBase, TargetGp );
    00303
    00304 #endif  // NTOS_KERNEL_RUNTIME
    00305
    00306     return NULL;
    00307 }

PRUNTIME_FUNCTION RtlLookupStaticFunctionEntry | ( | IN ULONG_PTR | ControlPc,
|  | OUT PBOOLEAN | InImage
| ) |

| Referenced by RtlLookupDirectFunctionEntry().

PEXCEPTION_REGISTRATION_RECORD RtlpGetRegistrationHead | ( | IN | VOID | ) |

Definition at line 128 of file ia64/exdsptch.c.

    00134                    :
    00135
    00136     This function returns the address of the first exception registration
    00137     record for the current context.
    00138
    00139 Arguments:
    00140
    00141     None.
    00142
    00143 Return Value:
    00144
    00145     The address of the first registration record.
    00146
    00147 --*/
    00148
    00149 {
    00150     PTEB CurrentTeb = NtCurrentTeb();
    00151
    00152     return (CurrentTeb ? CurrentTeb->NtTib.ExceptionList : EXCEPTION_CHAIN_END);
    00153 }

VOID RtlpRaiseException | ( | IN PEXCEPTION_RECORD | ExceptionRecord | ) |

Definition at line 311 of file ia64/exdsptch.c.

References NTSTATUS(), NULL, RtlLookupFunctionEntry(), RtlRaiseStatus(), RtlVirtualUnwind(), Status, and TRUE.

Referenced by RtlRaiseException().

    00317                    :
    00318
    00319     This function raises a software exception by building a context record
    00320     and calling the raise exception system service.
    00321
    00322 Arguments:
    00323
    00324     ExceptionRecord - Supplies a pointer to an exception record.
    00325
    00326 Return Value:
    00327
    00328     None.
    00329
    00330 --*/
    00331
    00332 {
    00333     ULONGLONG ImageBase;
    00334     ULONGLONG TargetGp;
    00335     ULONGLONG ControlPc;
    00336     CONTEXT ContextRecord;
    00337     FRAME_POINTERS EstablisherFrame;
    00338     PRUNTIME_FUNCTION FunctionEntry;
    00339     BOOLEAN InFunction;
    00340     ULONGLONG NextPc;
    00341     NTSTATUS Status;
    00342
    00343     //
    00344     // Capture the current context, virtually unwind to the caller of this
    00345     // routine, set the fault instruction address to that of the caller, and
    00346     // call the raise exception system service.
    00347     //
    00348
    00349     RtlCaptureContext(&ContextRecord);
    00350     ControlPc = RtlIa64InsertIPSlotNumber((ContextRecord.BrRp-16), 2);
    00351     FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, &TargetGp);
    00352     NextPc = RtlVirtualUnwind(ImageBase,
    00353                               ControlPc,
    00354                               FunctionEntry,
    00355                               &ContextRecord,
    00356                               &InFunction,
    00357                               &EstablisherFrame,
    00358                               NULL);
    00359
    00360     ContextRecord.StIIP = NextPc + 8;
    00361     ContextRecord.StIPSR &= ~((ULONGLONG) 3 << PSR_RI);
    00362     ExceptionRecord->ExceptionAddress = (PVOID)ContextRecord.StIIP;
    00363     Status = ZwRaiseException(ExceptionRecord, &ContextRecord, TRUE);
    00364
    00365     //
    00366     // There should never be a return from this system service unless
    00367     // there is a problem with the argument list itself. Raise another
    00368     // exception specifying the status value returned.
    00369     //
    00370
    00371     RtlRaiseStatus(Status);
    00372     return;
    00373 }

VOID RtlpRaiseStatus | ( | IN NTSTATUS | Status | ) |

Definition at line 409 of file ia64/exdsptch.c.

References EXCEPTION_NONCONTINUABLE, NULL, RtlLookupFunctionEntry(), RtlRaiseStatus(), RtlVirtualUnwind(), Status, and TRUE.

Referenced by RtlRaiseStatus().

    00415                    :
    00416
    00417     This function raises an exception with the specified status value. The
    00418     exception is marked as noncontinuable with no parameters.
    00419
    00420 Arguments:
    00421
    00422     Status - Supplies the status value to be used as the exception code
    00423         for the exception that is to be raised.
    00424
    00425 Return Value:
    00426
    00427     None.
    00428
    00429 --*/
    00430
    00431 {
    00432     ULONGLONG ImageBase;
    00433     ULONGLONG TargetGp;
    00434     ULONGLONG ControlPc;
    00435     ULONGLONG NextPc;
    00436     CONTEXT ContextRecord;
    00437     FRAME_POINTERS EstablisherFrame;
    00438     EXCEPTION_RECORD ExceptionRecord;
    00439     PRUNTIME_FUNCTION FunctionEntry;
    00440     BOOLEAN InFunction;
    00441
    00442     //
    00443     // Construct an exception record.
    00444     //
    00445
    00446     ExceptionRecord.ExceptionCode = Status;
    00447     ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD)NULL;
    00448     ExceptionRecord.NumberParameters = 0;
    00449     ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
    00450
    00451     //
    00452     // Capture the current context, virtually unwind to the caller of this
    00453     // routine, set the fault instruction address to that of the caller, and
    00454     // call the raise exception system service.
    00455     //
    00456
    00457     RtlCaptureContext(&ContextRecord);
    00458     ControlPc = RtlIa64InsertIPSlotNumber((ContextRecord.BrRp-16), 2);
    00459     FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, &TargetGp);
    00460     NextPc = RtlVirtualUnwind(ImageBase,
    00461                               ControlPc,
    00462                               FunctionEntry,
    00463                               &ContextRecord,
    00464                               &InFunction,
    00465                               &EstablisherFrame,
    00466                               NULL);
    00467     ContextRecord.StIIP = NextPc + 8;
    00468     ContextRecord.StIPSR &= ~((ULONGLONG) 3 << PSR_RI);
    00469     ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.StIIP;
    00470     Status = ZwRaiseException(&ExceptionRecord, &ContextRecord, TRUE);
    00471
    00472     //
    00473     // There should never be a return from this system service unless
    00474     // there is a problem with the argument list itself. Raise another
    00475     // exception specifying the status value returned.
    00476     //
    00477
    00478     RtlRaiseStatus(Status);
    00479     return;
    00480 }

VOID RtlpUnlinkHandler | ( | PEXCEPTION_REGISTRATION_RECORD | UnlinkPointer | ) |

Definition at line 157 of file ia64/exdsptch.c.

Referenced by RtlUnwind().

    00163                    :
    00164
    00165     This function removes the specified exception registration record
    00166     (and thus the relevant handler) from the exception traversal chain.
    00167
    00168 Arguments:
    00169
    00170     UnlinkPointer - Address of registration record to unlink.
    00171
    00172 Return Value:
    00173
    00174     None.
    00175
    00176 --*/
    00177
    00178 {
    00179     NtCurrentTeb()->NtTib.ExceptionList = UnlinkPointer->Next;
    00180 }

ULONGLONG RtlpVirtualUnwind | ( | IN ULONGLONG | ImageBase,
|  | IN ULONGLONG | ControlPc,
|  | IN PRUNTIME_FUNCTION | FunctionEntry,
|  | IN PCONTEXT | ContextRecord,
|  | OUT PBOOLEAN | InFunction,
|  | OUT PFRAME_POINTERS | EstablisherFrame,
|  | IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers | OPTIONAL
| ) |

Definition at line 1315 of file ia64/exdsptch.c.

References RtlVirtualUnwind().

    01327                    :
    01328
    01329     This function virtually unwinds the specfified function by executing its
    01330     prologue code backwards.
    01331
    01332     If the function is a leaf function, then the address where control left
    01333     the previous frame is obtained from the context record. If the function
    01334     is a nested function, but not an exception or interrupt frame, then the
    01335     prologue code is executed backwards and the address where control left
    01336     the previous frame is obtained from the updated context record.
    01337
    01338     Otherwise, an exception or interrupt entry to the system is being unwound
    01339     and a specially coded prologue restores the return address twice. Once
    01340     from the fault instruction address and once from the saved return address
    01341     register. The first restore is returned as the function value and the
    01342     second restore is place in the updated context record.
    01343
    01344     If a context pointers record is specified, then the address where each
    01345     nonvolatile registers is restored from is recorded in the appropriate
    01346     element of the context pointers record.
    01347
    01348     N.B. This function copies the specified context record and only computes
    01349          the establisher frame and whether control is actually in a function.
    01350
    01351 Arguments:
    01352
    01353     ImageBase - Base address of the module to which the function belongs.
    01354
    01355     ControlPc - Supplies the address where control left the specified
    01356         function.
    01357
    01358     FunctionEntry - Supplies the address of the function table entry for the
    01359         specified function.
    01360
    01361     ContextRecord - Supplies the address of a context record.
    01362
    01363     InFunction - Supplies a pointer to a variable that receives whether the
    01364         control PC is within the current function.
    01365
    01366     EstablisherFrame - Supplies a pointer to a variable that receives the
    01367         the establisher frame pointer value.
    01368
    01369     ContextPointers - Supplies an optional pointer to a context pointers
    01370         record.
    01371
    01372 Return Value:
    01373
    01374     The address where control left the previous frame is returned as the
    01375     function value.
    01376
    01377 --*/
    01378
    01379 {
    01380
    01381     CONTEXT LocalContext;
    01382
    01383     //
    01384     // Copy the context record so updates will not be reflected in the
    01385     // original copy and then virtually unwind to the caller of the
    01386     // specified control point.
    01387     //
    01388
    01389     RtlCopyMemory((PVOID)&LocalContext, ContextRecord, sizeof(CONTEXT));
    01390     return RtlVirtualUnwind(ImageBase,
    01391                             ControlPc,
    01392                             FunctionEntry,
    01393                             &LocalContext,
    01394                             InFunction,
    01395                             EstablisherFrame,
    01396                             ContextPointers);
    01397 }

VOID RtlRaiseException | ( | IN PEXCEPTION_RECORD | ExceptionRecord | ) |

Definition at line 377 of file ia64/exdsptch.c.

References RtlpRaiseException().

    00383                    :
    00384
    00385     This function raises a software exception by building a context record
    00386     and calling the raise exception system service.
    00387
    00388     N.B. This routine is a shell routine that simply calls another routine
    00389          to do the real work. The reason this is done is to avoid a problem
    00390          in try/finally scopes where the last statement in the scope is a
    00391          call to raise an exception.
    00392
    00393 Arguments:
    00394
    00395     ExceptionRecord - Supplies a pointer to an exception record.
    00396
    00397 Return Value:
    00398
    00399     None.
    00400
    00401 --*/
    00402
    00403 {
    00404     RtlpRaiseException(ExceptionRecord);
    00405     return;
    00406 }

VOID RtlRaiseStatus | ( | IN NTSTATUS | Status | ) |

Definition at line 484 of file ia64/exdsptch.c.

References RtlpRaiseStatus(), and Status.

    00490                    :
    00491
    00492     This function raises an exception with the specified status value. The
    00493     exception is marked as noncontinuable with no parameters.
    00494
    00495     N.B. This routine is a shell routine that simply calls another routine
    00496          to do the real work. The reason this is done is to avoid a problem
    00497          in try/finally scopes where the last statement in the scope is a
    00498          call to raise an exception.
    00499
    00500 Arguments:
    00501
    00502     Status - Supplies the status value to be used as the exception code
    00503         for the exception that is to be raised.
    00504
    00505 Return Value:
    00506
    00507     None.
    00508
    00509 --*/
    00510
    00511 {
    00512     RtlpRaiseStatus(Status);
    00513     return;
    00514 }

VOID RtlRestoreContext | ( | IN PCONTEXT | ContextRecord,
|  | IN PEXCEPTION_RECORD ExceptionRecord | OPTIONAL
| ) |

| Referenced by RtlUnwind2().

VOID RtlUnwind | ( | IN PVOID TargetFrame | OPTIONAL,
|  | IN PVOID TargetIp | OPTIONAL,
|  | IN PEXCEPTION_RECORD ExceptionRecord | OPTIONAL,
|  | IN PVOID | ReturnValue
| ) |

Definition at line 518 of file ia64/exdsptch.c.

References IS_EM_SETJMP_REGISTRATION, NULL, and RtlUnwind2().

    00527                    :
    00528
    00529     This function initiates an unwind of procedure call frames. The machine
    00530     state at the time of the call to unwind is captured in a context record
    00531     and the unwinding flag is set in the exception flags of the exception
    00532     record. If the TargetFrame parameter is not specified, then the exit unwind
    00533     flag is also set in the exception flags of the exception record. A backward
    00534     scan through the procedure call frames is then performed to find the target
    00535     of the unwind operation.
    00536
    00537     As each frame is encounter, the PC where control left the corresponding
    00538     function is determined and used to lookup exception handler information
    00539     in the runtime function table built by the linker. If the respective
    00540     routine has an exception handler, then the handler is called.
    00541
    00542     N.B. This routine is provided for backward compatibility with release 1.
    00543
    00544 Arguments:
    00545
    00546     TargetFrame - Supplies an optional pointer to the call frame that is the
    00547         target of the unwind. If this parameter is not specified, then an exit
    00548         unwind is performed.
    00549
    00550     TargetIp - Supplies an optional instruction address that specifies the
    00551         continuation address of the unwind. This address is ignored if the
    00552         target frame parameter is not specified.
    00553
    00554     ExceptionRecord - Supplies an optional pointer to an exception record.
    00555
    00556     ReturnValue - Supplies a value that is to be placed in the integer
    00557         function return register just before continuing execution.
    00558
    00559 Return Value:
    00560
    00561     None.
    00562
    00563 --*/
    00564
    00565 {
    00566     CONTEXT ContextRecord;
    00567     FRAME_POINTERS Frame;
    00568     PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;
    00569
    00570     Frame.MemoryStackFp = (ULONG_PTR)TargetFrame;
    00571     Frame.BackingStoreFp = 0;
    00572     ContextRecord.StIPSR = 0;
    00573
    00574     RegistrationPointer = (PEXCEPTION_REGISTRATION_RECORD)TargetFrame;
    00575     if ((RegistrationPointer != NULL) &&
    00576         IS_EM_SETJMP_REGISTRATION(RegistrationPointer)) {
    00577
    00578         //
    00579         // iA longjmp to an EM setjmp site, materialize the TargetFrame.
    00580         // resume execution in EM mode.
    00581         //
    00582
    00583         PULONGLONG Record = (PULONGLONG)(RegistrationPointer);
    00584
    00585         Frame.MemoryStackFp = Record[1];
    00586         Frame.BackingStoreFp = Record[2];
    00587     }
    00588
    00589     //
    00590     // Call real unwind routine specifying a context record as an
    00591     // extra argument.
    00592     //
    00593
    00594     RtlUnwind2(Frame,
    00595                TargetIp,
    00596                ExceptionRecord,
    00597                ReturnValue,
    00598                &ContextRecord);
    00599
    00600     return;
    00601 }

VOID RtlUnwind2 | ( | IN FRAME_POINTERS TargetFrame | OPTIONAL,
|  | IN PVOID TargetIp | OPTIONAL,
|  | IN PEXCEPTION_RECORD ExceptionRecord | OPTIONAL,
|  | IN PVOID | ReturnValue,
|  | IN PCONTEXT | ContextRecord
| ) |

Definition at line 605 of file ia64/exdsptch.c.

References CHECK_BSTORE_FRAME, CHECK_MSTACK_FRAME, EXCEPTION_COLLIDED_UNWIND, EXCEPTION_EXIT_UNWIND, EXCEPTION_TARGET_UNWIND, EXCEPTION_UNWINDING, ExceptionCollidedUnwind, ExceptionContinueSearch, FALSE, HANDLER, IS_HANDLER_DEFINED, IS_SAME_FRAME, KernelMode, NULL, RAISE_EXCEPTION, RtlImageDirectoryEntryToData(), RtlLookupFunctionEntry(), Rtlp64GetBStoreLimits(), Rtlp64GetStackLimits(), RtlpExecuteEmHandlerForUnwind(), RtlpVirtualUnwind(), RtlRestoreContext(), RtlVirtualUnwind(), SHORT, Size, TRUE, and UserMode.

    00615                    :
    00616
    00617     This function initiates an unwind of procedure call frames. The machine
    00618     state at the time of the call to unwind is captured in a context record
    00619     and the unwinding flag is set in the exception flags of the exception
    00620     record. If the TargetFrame parameter is not specified, then the exit unwind
    00621     flag is also set in the exception flags of the exception record. A backward
    00622     scan through the procedure call frames is then performed to find the target
    00623     of the unwind operation.
    00624
    00625     As each frame is encounter, the PC where control left the corresponding
    00626     function is determined and used to lookup exception handler information
    00627     in the runtime function table built by the linker. If the respective
    00628     routine has an exception handler, then the handler is called.
    00629
    00630 Arguments:
    00631
    00632     TargetFrame - Supplies an optional pointer to the call frame that is the
    00633         target of the unwind. If this parameter is not specified, then an exit
    00634         unwind is performed.
    00635
    00636     TargetIp - Supplies an optional instruction address that specifies the
    00637         continuation address of the unwind. This address is ignored if the
    00638         target frame parameter is not specified.
    00639
    00640     ExceptionRecord - Supplies an optional pointer to an exception record.
    00641
    00642     ReturnValue - Supplies a value that is to be placed in the integer
    00643         function return register just before continuing execution.
    00644
    00645     ContextRecord - Supplies a pointer to a context record that can be used
    00646         to store context druing the unwind operation.
    00647
    00648 Return Value:
    00649
    00650     None.
    00651
    00652 --*/
    00653
    00654 {
    00655     ULONGLONG TargetGp;
    00656     ULONGLONG ImageBase;
    00657     ULONGLONG ControlPc;
    00658     ULONGLONG NextPc;
    00659     ULONG ExceptionFlags;
    00660     DISPATCHER_CONTEXT DispatcherContext;
    00661     EXCEPTION_DISPOSITION Disposition;
    00662     FRAME_POINTERS EstablisherFrame;
    00663     EXCEPTION_RECORD ExceptionRecord1;
    00664     PRUNTIME_FUNCTION FunctionEntry;
    00665     ULONGLONG HighStackLimit;
    00666     ULONGLONG LowStackLimit;
    00667     ULONGLONG HighBStoreLimit;
    00668     ULONGLONG LowBStoreLimit;
    00669     ULONG Size;
    00670     BOOLEAN InFunction;
    00671
    00672     //
    00673     // Get current memory stack and backing store limits, capture the
    00674     // current context, virtually unwind to the caller of this routine,
    00675     // get the initial PC value, and set the unwind target address.
    00676     //
    00677     // N.B. The target gp value is found in the input context record.
    00678     //      The unwinder guarantees that it will not be destroyed
    00679     //      as it is just a scratch register.
    00680     //
    00681
    00682     RtlCaptureContext(ContextRecord);
    00683
    00684     //
    00685     // Before getting the limits from the TEB, must flush the RSE to have
    00686     // the OS to grow the backing store and update the BStoreLimit.
    00687     //
    00688
    00689     Rtlp64GetStackLimits(&LowStackLimit, &HighStackLimit);
    00690     Rtlp64GetBStoreLimits(&LowBStoreLimit, &HighBStoreLimit);
    00691
    00692     ControlPc = RtlIa64InsertIPSlotNumber((ContextRecord->BrRp-16), 2);
    00693     FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, &TargetGp);
    00694     NextPc = RtlVirtualUnwind(ImageBase,
    00695                               ControlPc,
    00696                               FunctionEntry,
    00697                               ContextRecord,
    00698                               &InFunction,
    00699                               &EstablisherFrame,
    00700                               NULL);
    00701
    00702     ControlPc = NextPc;
    00703     ContextRecord->StIIP = (ULONGLONG)TargetIp;
    00704
    00705 #if defined(NTOS_KERNEL_RUNTIME)
    00706     ContextRecord->StIPSR = SANITIZE_PSR(ContextRecord->StIPSR, KernelMode);
    00707 #else
    00708     ContextRecord->StIPSR = SANITIZE_PSR(ContextRecord->StIPSR, UserMode);
    00709 #endif // defined(NTOS_KERNEL_RUNTIME)
    00710
    00711     //
    00712     // If an exception record is not specified, then build a local exception
    00713     // record for use in calling exception handlers during the unwind operation.
    00714     //
    00715
    00716     if (ARGUMENT_PRESENT(ExceptionRecord) == FALSE) {
    00717         ExceptionRecord = &ExceptionRecord1;
    00718         ExceptionRecord1.ExceptionCode = STATUS_UNWIND;
    00719         ExceptionRecord1.ExceptionRecord = NULL;
    00720         ExceptionRecord1.ExceptionAddress = (PVOID)ControlPc;
    00721         ExceptionRecord1.NumberParameters = 0;
    00722     }
    00723
    00724     //
    00725     // If the target frame of the unwind is specified, then a normal unwind
    00726     // is being performed. Otherwise, an exit unwind is being performed.
    00727     //
    00728
    00729     ExceptionFlags = EXCEPTION_UNWINDING;
    00730     if (TargetFrame.BackingStoreFp == 0 && TargetFrame.MemoryStackFp == 0) {
    00731         ExceptionRecord->ExceptionFlags |= EXCEPTION_EXIT_UNWIND;
    00732     }
    00733
    00734     //
    00735     // Scan backward through the call frame hierarchy and call exception
    00736     // handlers until the target frame of the unwind is reached.
    00737     //
    00738
    00739     do {
    00740
    00741         //
    00742         // Lookup the function table entry using the point at which control
    00743         // left the procedure.
    00744         //
    00745
    00746
    00747         FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, &TargetGp);
    00748
    00749         //
    00750         // If there is a function table entry for the routine, then
    00751         // virtually unwind to the caller of the routine to obtain the
    00752         // virtual frame pointer of the establisher, but don't update
    00753         // the context record.
    00754         //
    00755
    00756         if (FunctionEntry != NULL) {
    00757             NextPc = RtlpVirtualUnwind(ImageBase,
    00758                                        ControlPc,
    00759                                        FunctionEntry,
    00760                                        ContextRecord,
    00761                                        &InFunction,
    00762                                        &EstablisherFrame,
    00763                                        NULL);
    00764
    00765         //
    00766         // If virtual frame is not within the specified limits, unaligned,
    00767         // or the target frame is below the virtual frame and an exit
    00768         // unwind is not being performed, then raise the exception
    00769         // STATUS_BAD_STACK or STATUS_BAD_BSTORE. Otherwise,
    00770         // check to determine if the current routine has an exception
    00771         // handler.
    00772         //
    00773
    00774             if (CHECK_MSTACK_FRAME(EstablisherFrame, TargetFrame)) {
    00775
    00776                 RAISE_EXCEPTION(STATUS_BAD_STACK, ExceptionRecord);
    00777
    00778             } else if (CHECK_BSTORE_FRAME(EstablisherFrame, TargetFrame)) {
    00779
    00780                 RAISE_EXCEPTION(STATUS_BAD_STACK, ExceptionRecord);
    00781
    00782             } else if (InFunction && IS_HANDLER_DEFINED(FunctionEntry, ImageBase)) {
    00783
    00784                 //
    00785                 // The frame has an exception handler.
    00786                 //
    00787                 // The handler (i.e. personality routine) has to be called to
    00788                 // execute any termination routines in this frame.
    00789                 //
    00790                 // The control PC, establisher frame pointer, the address
    00791                 // of the function table entry, and the address of the
    00792                 // context record are all stored in the dispatcher context.
    00793                 // This information is used by the unwind linkage routine
    00794                 // and can be used by the exception handler itself.
    00795                 //
    00796
    00797                 DispatcherContext.ControlPc = ControlPc;
    00798                 DispatcherContext.FunctionEntry = FunctionEntry;
    00799                 DispatcherContext.ImageBase = ImageBase;
    00800                 DispatcherContext.ContextRecord = ContextRecord;
    00801
    00802                 //
    00803                 // Call the exception handler.
    00804                 //
    00805
    00806                 do {
    00807
    00808                     //
    00809                     // If the establisher frame is the target of the unwind
    00810                     // operation, then set the target unwind flag.
    00811                     //
    00812
    00813                     if (IS_SAME_FRAME(TargetFrame, EstablisherFrame)) {
    00814                         ExceptionFlags |= EXCEPTION_TARGET_UNWIND;
    00815                     }
    00816
    00817                     ExceptionRecord->ExceptionFlags = ExceptionFlags;
    00818
    00819                     //
    00820                     // Set the specified return value in case the exception
    00821                     // handler directly continues execution.
    00822                     //
    00823
    00824                     ContextRecord->IntV0 = (ULONGLONG)ReturnValue;
    00825
    00826                     //
    00827                     // A linkage routine written in assembler is used to
    00828                     // actually call the actual exception handler. This is
    00829                     // required by the exception handler that is associated
    00830                     // with the linkage routine so it can have access to two
    00831                     // sets of dispatcher context when it is called.
    00832                     //
    00833
    00834                     DispatcherContext.EstablisherFrame = EstablisherFrame;
    00835                     Disposition = RtlpExecuteEmHandlerForUnwind(
    00836                                       ExceptionRecord,
    00837                                       EstablisherFrame.MemoryStackFp,
    00838                                       EstablisherFrame.BackingStoreFp,
    00839                                       ContextRecord,
    00840                                       &DispatcherContext,
    00841                                       TargetGp,
    00842                                       HANDLER(FunctionEntry, ImageBase, TargetGp));
    00843
    00844                     //
    00845                     // Clear target unwind and collided unwind flags.
    00846                     //
    00847
    00848                     ExceptionFlags &= ~(EXCEPTION_COLLIDED_UNWIND |
    00849                                                 EXCEPTION_TARGET_UNWIND);
    00850
    00851                     //
    00852                     // Case on the handler disposition.
    00853                     //
    00854
    00855                     switch (Disposition) {
    00856
    00857                     //
    00858                     // The disposition is to continue the search.
    00859                     //
    00860                     // If the target frame has not been reached, then
    00861                     // virtually unwind to the caller of the current
    00862                     // routine, update the context record, and continue
    00863                     // the search for a handler.
    00864                     //
    00865
    00866                     case ExceptionContinueSearch :
    00867
    00868                         if (!IS_SAME_FRAME(EstablisherFrame, TargetFrame)) {
    00869                             NextPc = RtlVirtualUnwind(ImageBase,
    00870                                                       ControlPc,
    00871                                                       FunctionEntry,
    00872                                                       ContextRecord,
    00873                                                       &InFunction,
    00874                                                       &EstablisherFrame,
    00875                                                       NULL);
    00876                         }
    00877                         break;
    00878
    00879                     //
    00880                     // The disposition is collided unwind.
    00881                     //
    00882                     // Set the target of the current unwind to the context
    00883                     // record of the previous unwind, and reexecute the
    00884                     // exception handler from the collided frame with the
    00885                     // collided unwind flag set in the exception record.
    00886                     //
    00887
    00888                     case ExceptionCollidedUnwind :
    00889
    00890                         ControlPc = DispatcherContext.ControlPc;
    00891                         FunctionEntry = DispatcherContext.FunctionEntry;
    00892                         ImageBase = DispatcherContext.ImageBase;
    00893                         ContextRecord = DispatcherContext.ContextRecord;
    00894                         ContextRecord->StIIP = (ULONGLONG)TargetIp;
    00895                         ExceptionFlags |= EXCEPTION_COLLIDED_UNWIND;
    00896                         EstablisherFrame = DispatcherContext.EstablisherFrame;
    00897                         TargetGp = (ULONG_PTR)(RtlImageDirectoryEntryToData(
    00898                                                    (PVOID)ImageBase,
    00899                                                    TRUE,
    00900                                                    IMAGE_DIRECTORY_ENTRY_GLOBALPTR,
    00901                                                    &Size
    00902                                                    ));
    00903                         break;
    00904
    00905                     //
    00906                     // All other disposition values are invalid.
    00907                     //
    00908                     // Raise invalid disposition exception.
    00909                     //
    00910
    00911                     default :
    00912                         RAISE_EXCEPTION(STATUS_INVALID_DISPOSITION, ExceptionRecord);
    00913                     }
    00914
    00915                 } while ((ExceptionFlags & EXCEPTION_COLLIDED_UNWIND) != 0);
    00916
    00917             } else {
    00918
    00919                 //
    00920                 // If the target frame has not been reached, then virtually
    00921                 // unwind to the caller of the current routine and update
    00922                 // the context record.
    00923                 //
    00924
    00925                 if (!IS_SAME_FRAME(EstablisherFrame, TargetFrame)) {
    00926                     NextPc = RtlVirtualUnwind(ImageBase,
    00927                                               ControlPc,
    00928                                               FunctionEntry,
    00929                                               ContextRecord,
    00930                                               &InFunction,
    00931                                               &EstablisherFrame,
    00932                                               NULL);
    00933                 }
    00934             }
    00935
    00936         } else {
    00937
    00938             //
    00939             // No function table entry was found.
    00940             //
    00941
    00942             SHORT BsFrameSize, TempFrameSize;
    00943
    00944             NextPc = RtlIa64InsertIPSlotNumber((ContextRecord->BrRp-16), 2);
    00945             ContextRecord->StIFS = ContextRecord->RsPFS;
    00946             BsFrameSize = (SHORT)(ContextRecord->StIFS >> PFS_SIZE_SHIFT) & PFS_SIZE_MASK;
    00947             TempFrameSize = BsFrameSize - (SHORT)((ContextRecord->RsBSP >> 3) & NAT_BITS_PER_RNAT_REG);
    00948             while (TempFrameSize > 0) {
    00949                 BsFrameSize++;
    00950                 TempFrameSize -= NAT_BITS_PER_RNAT_REG;
    00951             }
    00952             ContextRecord->RsBSP -= BsFrameSize * sizeof(ULONGLONG);
    00953             ContextRecord->RsBSPSTORE = ContextRecord->RsBSP;
    00954         }
    00955
    00956         //
    00957         // Set point at which control left the previous routine.
    00958         //
    00959
    00960         ControlPc = NextPc;
    00961
    00962     } while (((EstablisherFrame.MemoryStackFp < HighStackLimit) ||
    00963              (EstablisherFrame.BackingStoreFp > LowBStoreLimit)) &&
    00964              !(IS_SAME_FRAME(EstablisherFrame, TargetFrame)));
    00965
    00966     //
    00967     // If the establisher stack pointer is equal to the target frame
    00968     // pointer, then continue execution. Otherwise, an exit unwind was
    00969     // performed or the target of the unwind did not exist and the
    00970     // debugger and subsystem are given a second chance to handle the
    00971     // unwind.
    00972     //
    00973
    00974     if (IS_SAME_FRAME(EstablisherFrame, TargetFrame)) {
    00975         ContextRecord->IntGp = TargetGp;
    00976         ContextRecord->StIPSR &= ~(0x3i64 << PSR_RI);
    00977         ContextRecord->IntV0 = (ULONGLONG)ReturnValue;
    00978         RtlRestoreContext(ContextRecord, ExceptionRecord);
    00979     } else {
    00980         ZwRaiseException(ExceptionRecord, ContextRecord, FALSE);
    00981     }
    00982 }

## Variable Documentation

LIST_ENTRY DynamicFunctionTable

| Definition at line 52 of file ia64/exdsptch.c.