Recon 2012 Skochinsky Compiler Internals
Recon 2012 Skochinsky Compiler Internals
Visual C++
Structured Exception Handling (SEH)
C++ Exception Handling (EH)
GCC
RTTI
SjLj exceptions
Zero-cost (table based)
SEH vs C++ EH
SEH (Structured Exceptions Handling) is the low-level,
system layer
Allows to handle exceptions sent by the kernel or raised
by user code
C++ exceptions in MSVC are implemented on top of SEH
// -8 DWORD _esp;
// -4 PEXCEPTION_POINTERS xpointers;
struct _EH3_EXCEPTION_REGISTRATION
{
struct _EH3_EXCEPTION_REGISTRATION *Next;
PVOID ExceptionHandler;
PSCOPETABLE_ENTRY ScopeTable;
DWORD TryLevel;
};
C++ implementation
struct EHRegistrationNode {
// -4 void *_esp;
EHRegistrationNode *pNext;
void * frameHandler;
int state;
};
Field Meaning
magicNumber 0x19930520: original (pre-VC2005?)
0x19930521: pESTypeList is valid
0x19930522: EHFlags is valid
maxState/pUnwindMap Number of entries and pointer to unwind map
nTryBlocks/pTryBlockM Number of entries and pointer to try{} block map
ap
nIPMapEntries IP-to-state map (unused on x86)
pIPtoStateMap
pESTypeList List of exceptions in the throw specification
(undocumented feature)
EHFlags FI_EHS_FLAG=1: function was compiled /EHs
Handler Data
__C_specific_handler Scope table
__GSHandlerCheck GS data
__GSHandlerCheck_SEH Scope table + GS data
__CxxFrameHandler3 RVA to FuncInfo
__GSHandlerCheck_EH RVA to FuncInfo + GS data
SEH
http://uninformed.org/index.cgi?v=4&a=1
http://www.nynaeve.net/?p=99
C++ EH/RTTI
http://www.codeproject.com/Articles/2126/How-a-C-compiler-
implements-exception-handling
http://www.openrce.org/articles/full_view/21
Wine sources
Visual Studio 2012 RC includes sources of the EH
implementation
see VC\src\crt\ehdata.h and VC\src\crt\eh\
includes parts of "ARMNT" and WinRT
C++ in GCC
`vtable for'SubClass
dd 0 ; offset to base
dd offset `typeinfo for'SubClass ; type info pointer
dd offset SubClass::vfunc1(void) ; first virtual function
dd offset BaseClass::vfunc2(void) ; second virtual function
[1] http://sourcery.mentor.com/public/cxx-abi/abi.html
`typeinfo for'SubClass
dd offset `vtable for'__cxxabiv1::__si_class_type_info+8
dd offset `typeinfo name for'SubClass ; "8SubClass"
dd offset `typeinfo for'BaseClass
__lp__GpsRun _GpsRun_lp_02
LDR R2, [SP,#0xD4+_sjlj_ctx.data] LDR R2, [SP,#0xD4+handler_switch_val]
LDR R3, [SP,#0xD4+_sjlj_ctx.call_site] CMP R2, #2
STR R2, [SP,#0xD4+exc_obj] BNE _catch_ellipsis
LDR R2, [SP,#0xD4+_sjlj_ctx.data+4] LDR R0, [SP,#0xD4+exc_obj]
CMP R3, #1 BLX ___cxa_begin_catch
STR R2, [SP,#0xD4+handler_switch_val] [...]
BEQ _GpsRun_lp_01 MOVS R3, #0
CMP R3, #2 STR R3, [SP,#0xD4+_sjlj_ctx.call_site]
BEQ _GpsRun_lp_02 BLX ___cxa_end_catch
Field Meaning
Length (uint32) total length of following data; 0 means
end of all records
Extended Length (uint64) present if Length==0xFFFFFFFF
CIE_id (uint32) Must be 0 for a CIE
Version (uint8) 1 or 3
Augmentation (asciiz string) Indicates presence of additional fields
Code alignment factor (uleb128) Usually 1
Data alignment factor (sleb128) Usually -4 (encoded as 0x7C)
return_address_register (uint8 (version Dwarf number of the return register
1) or uleb128)
Augmentation data length (uleb128) Present if Augmentation[0]=='z'
Augmentation data Present if Augmentation[0]=='z'
Initial instructions Dwarf Call Frame Instructions
Field Meaning
Length (uint32) total length of following data; 0 means
end of all records
Extended Length (uint64) present if Length==0xFFFFFFFF
CIE pointer (uint32) Distance to parent CIE from this field
Initial location (fde_encoding) Address of the first instruction in the
range
Range length (fde_encoding.size) Length of the address range
Augmentation data length (uleb128) Present if CIE.Augmentation[0]=='z'
Augmentation data Present if CIE.Augmentation[0]=='z'
Instructions Dwarf Call Frame Instructions
LSDA
Header
Call site table
Action table
Types table (optional)
LSDA Header
Field Meaning
lpstart_encoding (uint8) Encoding of the following field (landing pad start
offset)
LPStart (encoded) Present if lpstart_encoding != DW_EH_PE_omit
(otherwise default: start of the range in FDE)
ttype_encoding (uint8) Encoding of the pointers in type table
TType (uleb128) Offset to type table from the end of the header
Present if ttype_encoding != DW_EH_PE_omit
struct unwind_info_section_header
{
uint32_t version; // UNWIND_SECTION_VERSION
uint32_t commonEncodingsArraySectionOffset;
uint32_t commonEncodingsArrayCount;
uint32_t personalityArraySectionOffset;
uint32_t personalityArrayCount;
uint32_t indexSectionOffset;
uint32_t indexCount;
// compact_unwind_encoding_t[]
// uintptr_t personalities[]
// unwind_info_section_header_index_entry[]
// unwind_info_section_header_lsda_index_entry[]
};
.ARM.exidx contains a map from program addresses to unwind info instead of .eh_frame
Short unwind encodings are inlined, longer ones are stored in .ARM.extab
EABI provides standard personality routines, or custom ones can be used
GCC still uses __gxx_personality_v0, and the same LSDA encoding
This kind of exception handling is also used in Symbian EPOC files
Word 0 Word 1
+-+----------------------+ EXIDX_CANTUNWIND +----------------------+-+
|0| prel31_offset_to_fnc | | |1|
+-+----------------------+ +----------------------+-+
31 30 0 31 1 0
The ex table entry itself +-+----------------------+
encoded in 31bit |1| ex_tbl_entry |
+-+----------------------+
31 30 0
prel31 offset of the start +-+----------------------+
of the table entry for |0| tbl_entry_offset |
this function +-+----------------------+
31 30 0
Credit: https://wiki.linaro.org/KenWerner/Sandbox/libunwind
http://www.airs.com/blog/archives/460 (.eh_frame)
http://stackoverflow.com/questions/87220/
apple/gcc: gcc/gcc-5493/libstdc++-v3/libsupc++/
http://sourcery.mentor.com/public/cxx-abi/abi-eh.html
http://sourcery.mentor.com/public/cxx-abi/exceptions.pdf
http://www.x86-64.org/documentation/abi.pdf
Exploiting the Hard-Working DWARF (James Oakley &
Sergey Bratus)
Questions?