Difference between revisions of "Techwiki:SEH64"
ThePhysicist (talk | contribs) (→_CxxFrameHandler3) |
ThePhysicist (talk | contribs) (→_CxxFrameHandler3) |
||
Line 139: | Line 139: | ||
TryBlockMapEntry* pTryBlockMap; // mapping of catch blocks to try blocks | TryBlockMapEntry* pTryBlockMap; // mapping of catch blocks to try blocks | ||
DWORD nIPMapEntries; // not used on x86 | DWORD nIPMapEntries; // not used on x86 | ||
− | + | DATA3* pIPtoStateMap; // not used on x86 | |
ESTypeList* pESTypeList; // VC7+ only, expected exceptions list (function "throw" specifier) | ESTypeList* pESTypeList; // VC7+ only, expected exceptions list (function "throw" specifier) | ||
int EHFlags; // VC8+ only, bit 0 set if function was compiled with /EHs | int EHFlags; // VC8+ only, bit 0 set if function was compiled with /EHs | ||
Line 147: | Line 147: | ||
#define MAGIC_VC7 0x19930521 // VC7.x(2002-2003) | #define MAGIC_VC7 0x19930521 // VC7.x(2002-2003) | ||
#define MAGIC_VC8 0x19930522 // VC8 (2005) | #define MAGIC_VC8 0x19930522 // VC8 (2005) | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
struct UnwindMapEntry | struct UnwindMapEntry |
Revision as of 19:38, 28 April 2009
Contents
Function Table
The function table can be found in the .pdata section of the executable. It's an array of RUNTIME_FUNCTION structures. NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION] is the corresponding data directory entry. It's VirtualAddress member points to the beginning of this section, it's Size member divided by sizeof(RUNTIME_FUNCTION) gives the numer of entries.
typedef struct _RUNTIME_FUNCTION { ULONG BeginAddress; ULONG EndAddress; ULONG UnwindData; } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
BeginAddress is the RVA of the beginning of the corresponding function. EndAddress is the RVA of the end of the corresponding function. UnwindData is the RVA of the UNWIND_INFO structure belonging to this function.
All RUNTIME_FUNCTION entries are sorted, beginning with the smallest address and never overlapping. There may be gaps though. If an address is not found inside the table, it is supposed to be a leaf function and RSP points to the functions return address.
The table that corresponds to a certain address can be found using
PRUNTIME_FUNCTION NTAPI RtlLookupFunctionTable( IN DWORD64 ControlPc, OUT PDWORD64 ImageBase, OUT PULONG Length);
The function entry can be found by using
PRUNTIME_FUNCTION NTAPI RtlLookupFunctionEntry( IN DWORD64 ControlPc, OUT PDWORD64 ImageBase, OUT PUNWIND_HISTORY_TABLE HistoryTable);
Unwind Data
The UnwindData member of the RUNTIME_FUNCTION entry is the RVA of an UNWIND_INFO structure.
typedef struct _UNWIND_INFO { UBYTE Version:3; UBYTE Flags:5; UBYTE SizeOfProlog; UBYTE CountOfCodes; UBYTE FrameRegister:4; UBYTE FrameOffset:4; UNWIND_CODE UnwindCode[1]; /* union { OPTIONAL ULONG ExceptionHandler; OPTIONAL ULONG FunctionEntry; }; OPTIONAL ULONG ExceptionData[]; */ } UNWIND_INFO, *PUNWIND_INFO;
Version
- Should be 1
Flags
- Can be can be one of the following values
#define UNW_FLAG_NHANDLER 0 #define UNW_FLAG_EHANDLER 1 #define UNW_FLAG_UHANDLER 2 #define UNW_FLAG_FHANDLER 3 // inofficial #define UNW_FLAG_CHAININFO 4
SizeOfProlog
- Size of the functions prolog in bytes.
CountOfCodes
- Number of UNWIND_CODE entries in this structure.
FrameRegister
FrameOffset
ExceptionHandler
- RVA of the language specific handler. See below.
ExceptionData
- This data is specific to the language specific handler and a pointer to this data is passed to the handler in the DISPATCHER_CONTEXT structure.
The exception handler for RtlpExecuteHandlerForUnwind (RtlpUnwindHandler) has a Flags value of 3. The handler is responsible for collided unwinds, see http://www.nynaeve.net/?p=107
The Language specific handler
This function must correspond to the following prototype:
typedef EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)( IN PEXCEPTION_RECORD ExceptionRecord, IN ULONG64 EstablisherFrame, IN OUT PCONTEXT ContextRecord, IN OUT PDISPATCHER_CONTEXT DispatcherContext);
_C_specific_handler
In this case ExceptionData is a SCOPE_TABLE structure.
typedef struct _SCOPE_TABLE { ULONG Count; struct { ULONG BeginAddress; ULONG EndAddress; ULONG HandlerAddress; ULONG JumpTarget; } ScopeRecord[1]; } SCOPE_TABLE, *PSCOPE_TABLE;
_CxxFrameHandler3
This function is exported by msvcr90.dll. Used with C++ exceptions (try/catch). In this case the Flags field in the UNWIND_INFO structure is 3. http://multitouchvista.codeplex.com/Thread/View.aspx?ThreadId=51520
int __CxxFrameHandler3( EHExceptionRecord * pExcept, EHRegistrationNode * pRN, void * pContext, void * pDC); struct EHExceptionRecord { EXCEPTION_RECORD ExceptionRecord; ??? }; struct EHRegistrationNode (FIXME: this is x86) { EHRegistrationNode *prev; DWORD ehhandler_code; DWORD id; DWORD saved_ebp; };
The ExceptionData is an RVA to a FuncInfo structure in the rdata segment. Pointers are in fact RVAs.
struct FuncInfo { DWORD magicNumber; // compiler version int maxState; // number of entries in unwind table UnwindMapEntry* pUnwindMap; // table of unwind destructors DWORD nTryBlocks; // number of try blocks in the function TryBlockMapEntry* pTryBlockMap; // mapping of catch blocks to try blocks DWORD nIPMapEntries; // not used on x86 DATA3* pIPtoStateMap; // not used on x86 ESTypeList* pESTypeList; // VC7+ only, expected exceptions list (function "throw" specifier) int EHFlags; // VC8+ only, bit 0 set if function was compiled with /EHs };
#define MAGIC_VC 0x19930520 // up to VC6 #define MAGIC_VC7 0x19930521 // VC7.x(2002-2003) #define MAGIC_VC8 0x19930522 // VC8 (2005)
struct UnwindMapEntry { int toState; // target state void (*action)(); // action to perform (unwind funclet address) };
struct TryBlockMapEntry { int tryLow; int tryHigh; // this try {} covers states ranging from tryLow to tryHigh int catchHigh; // highest state inside catch handlers of this try int nCatches; // number of catch handlers HandlerType* pHandlerArray; //catch handlers table };
struct HandlerType { DWORD adjectives;// 0x01: const, 0x02: volatile, 0x08: reference TypeDescriptor* pType;// RTTI descriptor of the exception type. 0=any (ellipsis) int dispCatchObj;// ebp-based offset of the exception object in the function stack. 0 = no object (catch by type) void* addressOfHandler;// address of the catch handler code. returns address where to continues execution (i.e. code after the try block) ??? DWORD dw4;// 0x38 };
typedef struct { RVA ThrowingFunction; DWORD dw04; // 0xffffffff RVA ScopeBegin; DWORD dw0c; // 0x0 RVA EndScope; DWORD dw14; // 0xffffffff RVA Sub1; DWORD dw1c; // 0 RVA Sub2; DWORD dw1c; // 1 RVA Sub3; DWORD dw1c; // 0 ... more RVA/DWORD combinations for more catch blocks } DATA3;
References
- MSDN: Unwind Data Definitions in C
- MSDN: RUNTIME_FUNCTION Structure
- MSDN: RtlLookupFunctionEntry Function
- MSDN: UNWIND_INFO Structure
- MSDN: The Language Specific Handler
- MSDN: Unwind Helpers for MASM
- Collided Unwinds
- MSDN: EXCEPTION_RECORD Structure
- SEH exceptions on Windows CE (ARM) *2
- Lifetime of an exception
- Reversing Microsoft Visual C++ Part I: Exception Handling