alloc ex 1 __cxa_throw called no one handled __cxa_throw, terminate!
mycppabi
and add something like this: void __gxx_personality_v0() { printf("Personality function FTW\n"); }
_Unwind_Reason_Code __gxx_personality_v0 ( int version, _Unwind_Action actions, uint64_t exceptionClass, _Unwind_Exception* unwind_exception, _Unwind_Context* context);
mycppabi.cpp
, we get: #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> namespace __cxxabiv1 { struct __class_type_info { virtual void foo() {} } ti; } #define EXCEPTION_BUFF_SIZE 255 char exception_buff[EXCEPTION_BUFF_SIZE]; extern "C" { void* __cxa_allocate_exception(size_t thrown_size) { printf(&"alloc ex %i\n", thrown_size); if (thrown_size > EXCEPTION_BUFF_SIZE) printf("Exception too big"); return &exception_buff; } void __cxa_free_exception(void *thrown_exception); #include <unwind.h> typedef void (*unexpected_handler)(void); typedef void (*terminate_handler)(void); struct __cxa_exception { std::type_info * exceptionType; void (*exceptionDestructor) (void *); unexpected_handler unexpectedHandler; terminate_handler terminateHandler; __cxa_exception * nextException; int handlerCount; int handlerSwitchValue; const char * actionRecord; const char * languageSpecificData; void * catchTemp; void * adjustedPtr; _Unwind_Exception unwindHeader; }; void __cxa_throw(void* thrown_exception, struct type_info *tinfo, void (*dest)(void*)) { printf("__cxa_throw called\n"); __cxa_exception *header = ((__cxa_exception *) thrown_exception - 1); _Unwind_RaiseException(&header->unwindHeader); // __cxa_throw printf("no one handled __cxa_throw, terminate!\n"); exit(0); } void __cxa_begin_catch() { printf("begin FTW\n"); } void __cxa_end_catch() { printf("end FTW\n"); } _Unwind_Reason_Code __gxx_personality_v0 ( int version, _Unwind_Action actions, uint64_t exceptionClass, _Unwind_Exception* unwind_exception, _Unwind_Context* context) { printf("Personality function FTW!\n"); } }
Breakpoint 1, __gxx_personality_v0 (version=1, actions=1, exceptionClass=134514792, unwind_exception=0x804a060, context=0xbffff0f0)
_Unwind_
function know that we want to handle an exception? alloc ex 1 __cxa_throw called Personality function FTW Personality function FTW no one handled __cxa_throw, terminate!
_Unwind_Reason_Code __gxx_personality_v0 ( int version, _Unwind_Action actions, uint64_t exceptionClass, _Unwind_Exception* unwind_exception, _Unwind_Context* context) { if (actions &_UA_SEARCH_PHASE) { printf("Personality function, lookup phase\n"); return _URC_HANDLER_FOUND; } else if (actions & _UA_CLEANUP_PHASE) { printf("Personality function, cleanup\n"); return _URC_INSTALL_CONTEXT; } else { printf("Personality function, error\n"); return _URC_FATAL_PHASE1_ERROR; } }
alloc ex 1 __cxa_throw called Personality function, lookup phase Personality function, cleanup try_but_dont_catch handled the exception catchit handled the exception
Breakpoint 1, __gxx_personality_v0 (version=1, actions=6, exceptionClass=134515400, unwind_exception=0x804a060, context=0xbffff0f0) at mycppabi.cpp:77 84 const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context); 85 uintptr_t ip = _Unwind_GetIP(context) - 1; 86 uintptr_t funcStart = _Unwind_GetRegionStart(context); 87 uintptr_t ipOffset = ip - funcStart;
_Unwind_GetIP = (void *) 0x804861d _Unwind_GetRegionStart = (void *) 0x8048612 _Unwind_GetLanguageSpecificData = (void *) 0x8048e3c function pointer to try_but_dont_catch = 0x8048612 &<try_but_dont_catch()> (gdb) disassemble /m try_but_dont_catch Dump of assembler code for function try_but_dont_catch(): 10 void try_but_dont_catch() { [...] 11 try { 12 raise(); 0x08048619 <+7>: call 0x80485e8 <raise()> 13 } catch(Fake_Exception&) { 0x08048651 <+63>: call 0x804874a <__cxa_begin_catch()> 0x08048665 <+83>: call 0x804875e <__cxa_end_catch()> 0x0804866a <+88>: jmp 0x804861e <try_but_dont_catch()+12> 14 printf("Caught a Fake_Exception!\n"); 0x08048659 <+71>: movl $0x8048971,(%esp) 0x08048660 <+78>: call 0x80484c0 <puts@plt> 15 } 16 17 printf("try_but_dont_catch handled the exception\n"); 0x0804861e <+12>;: movl $0x8048948,(%esp) 0x08048625 <+19>: call 0x80484c0 <puts@plt> 18 } 0x0804862a <+24>: add $0x24,%esp
.local_frame_entry: .globl __gxx_personality_v0 .section .gcc_except_table,"a",@progbits .align 4
.local_lsda_1: # . .byte 0xff # landing pads; 0, func's ptr # (_Unwind_GetRegionStart) .byte 0 # LSDA: LLSDATT1 LLSDATTD1 # LSDA, .uleb128 .local_lsda_end - .local_lsda_call_site_table_header
.local_lsda_call_site_table_header: # Encoding of items in the landing pad table. Again, we don't care. .byte 0x1. # The length of the call site table (ie the landing pads) .uleb128 .local_lsda_call_site_table_end - .local_lsda_call_site_table
.local_lsda_call_site_table: .uleb128 .LEHB0-.LFB1 .uleb128 .LEHE0-.LEHB0 .uleb128 .L8-.LFB1 .uleb128 0x1 .uleb128 .LEHB1-.LFB1 .uleb128 .LEHE1-.LEHB1 .uleb128 0 .uleb128 0 .uleb128 .LEHB2-.LFB1 .uleb128 .LEHE2-.LEHB2 .uleb128 .L9-.LFB1 .uleb128 0 .local_lsda_call_site_table_end:
struct lsda_call_site_entry { // IP size_t cs_start; // IP size_t cs_len; // Landing pad size_t cs_lp; // size_t cs_action; };
struct LSDA_Header { uint8_t lsda_start_encoding; uint8_t lsda_type_encoding; uint8_t lsda_call_site_table_length; }; struct LSDA_Call_Site_Header { uint8_t encoding; uint8_t length; }; struct LSDA_Call_Site { LSDA_Call_Site(const uint8_t *ptr) { cs_start = ptr[0]; cs_len = ptr[1]; cs_lp = ptr[2]; cs_action = ptr[3]; } uint8_t cs_start; uint8_t cs_len; uint8_t cs_lp; uint8_t cs_action; }; _Unwind_Reason_Code __gxx_personality_v0 ( int version, _Unwind_Action actions, uint64_t exceptionClass, _Unwind_Exception* unwind_exception, _Unwind_Context* context) { if (actions & _UA_SEARCH_PHASE) { printf("Personality function, lookup phase\n"); return _URC_HANDLER_FOUND; } else if (actions & _UA_CLEANUP_PHASE) { printf("Personality function, cleanup\n"); const uint8_t* lsda = (const uint8_t*) _Unwind_GetLanguageSpecificData(context); LSDA_Header *header = (LSDA_Header*)(lsda); LSDA_Call_Site_Header *cs_header = (LSDA_Call_Site_Header*) (lsda + sizeof(LSDA_Header)); size_t cs_in_table = cs_header->length / sizeof(LSDA_Call_Site); // cs_table_base uint8, // const uint8_t *cs_table_base = lsda + sizeof(LSDA_Header) + sizeof(LSDA_Call_Site_Header); // call site for (size_t i=0; i < cs_in_table; ++i) { const uint8_t *offset = &cs_table_base[i * sizeof(LSDA_Call_Site)]; LSDA_Call_Site cs(offset); printf("Found a CS:\n"); printf("\tcs_start: %i\n", cs.cs_start); printf("\tcs_len: %i\n", cs.cs_len); printf("\tcs_lp: %i\n", cs.cs_lp); printf("\tcs_action: %i\n", cs.cs_action); } uintptr_t ip = _Unwind_GetIP(context); uintptr_t funcStart = _Unwind_GetRegionStart(context); uintptr_t ipOffset = ip - funcStart; return _URC_INSTALL_CONTEXT; } else { printf("Personality function, error\n"); return _URC_FATAL_PHASE1_ERROR; } } }
const uint8_t *cs_table_base = lsda + sizeof(LSDA_Header) + sizeof(LSDA_Call_Site_Header); for (size_t i=0; i < cs_in_table; ++i) { const uint8_t *offset = &cs_table_base[i * sizeof(LSDA_Call_Site)]; LSDA_Call_Site cs(offset); if (cs.cs_lp) { uintptr_t func_start = _Unwind_GetRegionStart(context); _Unwind_SetIP(context, func_start + cs.cs_lp); break; } } return _URC_INSTALL_CONTEXT;
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> namespace __cxxabiv1 { struct __class_type_info { virtual void foo() {} } ti; } #define EXCEPTION_BUFF_SIZE 255 char exception_buff[EXCEPTION_BUFF_SIZE]; extern "C" { void* __cxa_allocate_exception(size_t thrown_size) { printf("alloc ex %i\n", thrown_size); if (thrown_size > EXCEPTION_BUFF_SIZE) printf("Exception too big"); return &exception_buff; } void __cxa_free_exception(void *thrown_exception); #include <unwind.h> typedef void (*unexpected_handler)(void); typedef void (*terminate_handler)(void); struct __cxa_exception { std::type_info * exceptionType; void (*exceptionDestructor) (void *); unexpected_handler unexpectedHandler; terminate_handler terminateHandler; __cxa_exception * nextException; int handlerCount; int handlerSwitchValue; const char * actionRecord; const char * languageSpecificData; void * catchTemp; void * adjustedPtr; _Unwind_Exception unwindHeader; }; void __cxa_throw(void* thrown_exception, struct type_info *tinfo, void (*dest)(void*)) { printf("__cxa_throw called\n"); __cxa_exception *header = ((__cxa_exception *) thrown_exception - 1); _Unwind_RaiseException(&header->unwindHeader); // __cxa_throw never returns printf("no one handled __cxa_throw, terminate!\n"); exit(0); } void __cxa_begin_catch() { printf("begin FTW\n"); } void __cxa_end_catch() { printf("end FTW\n"); } /**********************************************/ /** * The LSDA is a read only place in memory; we'll create a typedef for * this to avoid a const mess later on; LSDA_ptr refers to readonly and * &LSDA_ptr will be a non-const pointer to a const place in memory */ typedef const uint8_t* LSDA_ptr; struct LSDA_Header { /** * Read the LSDA table into a struct; advances the lsda pointer * as many bytes as read */ LSDA_Header(LSDA_ptr *lsda) { LSDA_ptr read_ptr = *lsda; // Copy the LSDA fields start_encoding = read_ptr[0]; type_encoding = read_ptr[1]; ttype = read_ptr[2]; // Advance the lsda pointer *lsda = read_ptr + sizeof(LSDA_Header); } uint8_t start_encoding; uint8_t type_encoding; uint8_t ttype; }; struct LSDA_CS_Header { // Same as other LSDA constructors LSDA_CS_Header(LSDA_ptr *lsda) { LSDA_ptr read_ptr = *lsda; encoding = read_ptr[0]; length = read_ptr[1]; *lsda = read_ptr + sizeof(LSDA_CS_Header); } uint8_t encoding; uint8_t length; }; struct LSDA_CS { // Same as other LSDA constructors LSDA_CS(LSDA_ptr *lsda) { LSDA_ptr read_ptr = *lsda; start = read_ptr[0]; len = read_ptr[1]; lp = read_ptr[2]; action = read_ptr[3]; *lsda = read_ptr + sizeof(LSDA_CS); } // Note start, len and lp would be void*'s, but they are actually relative // addresses: start and lp are relative to the start of the function, len // is relative to start // Offset into function from which we could handle a throw uint8_t start; // Length of the block that might throw uint8_t len; // Landing pad uint8_t lp; // Offset into action table + 1 (0 means no action) // Used to run destructors uint8_t action; }; /**********************************************/ _Unwind_Reason_Code __gxx_personality_v0 ( int version, _Unwind_Action actions, uint64_t exceptionClass, _Unwind_Exception* unwind_exception, _Unwind_Context* context) { if (actions & _UA_SEARCH_PHASE) { printf("Personality function, lookup phase\n"); return _URC_HANDLER_FOUND; } else if (actions & _UA_CLEANUP_PHASE) { printf("Personality function, cleanup\n"); // Pointer to the beginning of the raw LSDA LSDA_ptr lsda = (uint8_t*)_Unwind_GetLanguageSpecificData(context); // Read LSDA headerfor the LSDA LSDA_Header header(&lsda); // Read the LSDA CS header LSDA_CS_Header cs_header(&lsda); // Calculate where the end of the LSDA CS table is const LSDA_ptr lsda_cs_table_end = lsda + cs_header.length; // Loop through each entry in the CS table while (lsda < lsda_cs_table_end) { LSDA_CS cs(&lsda); if (cs.lp) { int r0 = __builtin_eh_return_data_regno(0); int r1 = __builtin_eh_return_data_regno(1); _Unwind_SetGR(context, r0, (uintptr_t)(unwind_exception)); // Note the following code hardcodes the exception type; // we'll fix that later on _Unwind_SetGR(context, r1, (uintptr_t)(1)); uintptr_t func_start = _Unwind_GetRegionStart(context); _Unwind_SetIP(context, func_start + cs.lp); break; } } return _URC_INSTALL_CONTEXT; } else { printf("Personality function, error\n"); return _URC_FATAL_PHASE1_ERROR; } } }
./app alloc ex 1 __cxa_throw called Personality function, lookup phase Personality function, cleanup begin FTW Caught a Fake_Exception! end FTW try_but_dont_catch handled the exception catchit handled the exception
.local_lsda_call_site_table: .uleb128 .LEHB0-.LFB1 .uleb128 .LEHE0-.LEHB0 .uleb128 .L8-.LFB1 .uleb128 0x1 .uleb128 .LEHB1-.LFB1 .uleb128 .LEHE1-.LEHB1 .uleb128 0 .uleb128 0 .uleb128 .LEHB2-.LFB1 .uleb128 .LEHE2-.LEHB2 .uleb128 .L9-.LFB1 .uleb128 0 .local_lsda_call_site_table_end:
struct LSDA_CS { // len lp void*'s, // : start and lp , len // // , uint8_t start; // uint8_t len; // Landing pad uint8_t lp; // action table + 1 (0 " ") // uint8_t action; };
void foo() { L0: try { do_something(); L1: } catch (const Exception1& ex) { ... } catch (const Exception2& ex) { ... } catch (const ExceptionN& ex) { ... } catch (...) { } L2: }
Source: https://habr.com/ru/post/279151/
All Articles