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.


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