bool lsda_init(lsda_t* lsda, exception_context_t* context) { const uint8_t* data = (const uint8_t*)_Unwind_GetLanguageSpecificData(context); if(data == NULL) return false; lsda->region_start = _Unwind_GetRegionStart(context); //-1 because IP points past the faulting instruction lsda->ip = _Unwind_GetIP(context) - 1; lsda->ip_offset = lsda->ip - lsda->region_start; lsda->landing_pads = read_with_encoding(&data, lsda->region_start); lsda->type_table_encoding = *data++; if(lsda->type_table_encoding != DW_EH_PE_omit) { lsda->type_table = (const uint8_t*)read_uleb128(&data); lsda->type_table += (uintptr_t)data; } else { lsda->type_table = NULL; } lsda->call_site_encoding = *data++; uintptr_t length = read_uleb128(&data); lsda->call_site_table = data; lsda->action_table = data + length; return true; }
static const unsigned char * parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p, lsda_header_info *info) { _Unwind_Word tmp; unsigned char lpstart_encoding; info->Start = (context ? _Unwind_GetRegionStart (context) : 0); /* Find @LPStart, the base to which landing pad offsets are relative. */ lpstart_encoding = *p++; if (lpstart_encoding != DW_EH_PE_omit) p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart); else info->LPStart = info->Start; /* Find @TType, the base of the handler and exception spec type data. */ info->ttype_encoding = *p++; if (info->ttype_encoding != DW_EH_PE_omit) { p = read_uleb128 (p, &tmp); info->TType = p + tmp; } else info->TType = 0; /* The encoding and length of the call-site table; the action table immediately follows. */ info->call_site_encoding = *p++; p = read_uleb128 (p, &tmp); info->action_table = p + tmp; return p; }
COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject, struct _Unwind_Context *context) #endif { /* Since C does not have catch clauses, there is nothing to do during */ /* phase 1 (the search phase). */ if ( actions & _UA_SEARCH_PHASE ) return _URC_CONTINUE_UNWIND; /* There is nothing to do if there is no LSDA for this frame. */ const uint8_t* lsda = (uint8_t*)_Unwind_GetLanguageSpecificData(context); if ( lsda == (uint8_t*) 0 ) return _URC_CONTINUE_UNWIND; uintptr_t pc = _Unwind_GetIP(context)-1; uintptr_t funcStart = _Unwind_GetRegionStart(context); uintptr_t pcOffset = pc - funcStart; /* Parse LSDA header. */ uint8_t lpStartEncoding = *lsda++; if (lpStartEncoding != DW_EH_PE_omit) { readEncodedPointer(&lsda, lpStartEncoding); } uint8_t ttypeEncoding = *lsda++; if (ttypeEncoding != DW_EH_PE_omit) { readULEB128(&lsda); } /* Walk call-site table looking for range that includes current PC. */ uint8_t callSiteEncoding = *lsda++; uint32_t callSiteTableLength = readULEB128(&lsda); const uint8_t* callSiteTableStart = lsda; const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; const uint8_t* p=callSiteTableStart; while (p < callSiteTableEnd) { uintptr_t start = readEncodedPointer(&p, callSiteEncoding); uintptr_t length = readEncodedPointer(&p, callSiteEncoding); uintptr_t landingPad = readEncodedPointer(&p, callSiteEncoding); readULEB128(&p); /* action value not used for C code */ if ( landingPad == 0 ) continue; /* no landing pad for this entry */ if ( (start <= pcOffset) && (pcOffset < (start+length)) ) { /* Found landing pad for the PC. * Set Instruction Pointer to so we re-enter function * at landing pad. The landing pad is created by the compiler * to take two parameters in registers. */ _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)exceptionObject); _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); _Unwind_SetIP(context, (funcStart + landingPad)); return _URC_INSTALL_CONTEXT; } } /* No landing pad found, continue unwinding. */ return _URC_CONTINUE_UNWIND; }
static _Unwind_Reason_Code unwind_cb(struct _Unwind_Context *ctx, void *trace_argument) { int *depth = (int *)trace_argument; printf("%i:\tFunction: %08x, IP: %08x\n", *depth, _Unwind_GetRegionStart(ctx), _Unwind_GetIP(ctx)); (*depth)++; return _URC_NO_REASON; }
_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; } }
static void get_region_description_for (_Unwind_Context *uw_context, region_descriptor *region) { const unsigned char * p; _uleb128_t tmp; unsigned char lpbase_encoding; /* Get the base address of the lsda information. If the provided context is null or if there is no associated language specific data, there's nothing we can/should do. */ region->lsda = (_Unwind_Ptr) (uw_context ? _Unwind_GetLanguageSpecificData (uw_context) : 0); if (! region->lsda) return; /* Parse the lsda and fill the region descriptor. */ p = (const unsigned char *)region->lsda; region->base = _Unwind_GetRegionStart (uw_context); /* Find @LPStart, the base to which landing pad offsets are relative. */ lpbase_encoding = *p++; if (lpbase_encoding != DW_EH_PE_omit) p = read_encoded_value (uw_context, lpbase_encoding, p, ®ion->lp_base); else region->lp_base = region->base; /* Find @TType, the base of the handler and exception spec type data. */ region->ttype_encoding = *p++; if (region->ttype_encoding != DW_EH_PE_omit) { p = read_uleb128 (p, &tmp); region->ttype_table = p + tmp; } else region->ttype_table = 0; region->ttype_base = base_of_encoded_value (region->ttype_encoding, uw_context); /* Get the encoding and length of the call-site table; the action table immediately follows. */ region->call_site_encoding = *p++; region->call_site_table = read_uleb128 (p, &tmp); region->action_table = region->call_site_table + tmp; }
static const unsigned char * parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p, struct lsda_header_info *info) { _uleb128_t tmp; unsigned char lpstart_encoding; info->Start = (context ? _Unwind_GetRegionStart (context) : 0); /* Find @LPStart, the base to which landing pad offsets are relative. */ lpstart_encoding = *p++; if (lpstart_encoding != DW_EH_PE_omit) p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart); else info->LPStart = info->Start; /* Find @TType, the base of the handler and exception spec type data. */ info->ttype_encoding = *p++; if (info->ttype_encoding != DW_EH_PE_omit) { #if _GLIBCXX_OVERRIDE_TTYPE_ENCODING /* Older ARM EABI toolchains set this value incorrectly, so use a hardcoded OS-specific format. */ info->ttype_encoding = _GLIBCXX_OVERRIDE_TTYPE_ENCODING; #endif p = read_uleb128 (p, &tmp); info->TType = p + tmp; } else info->TType = 0; /* The encoding and length of the call-site table; the action table immediately follows. */ info->call_site_encoding = *p++; p = read_uleb128 (p, &tmp); info->action_table = p + tmp; return p; }
static _Unwind_Ptr base_of_encoded_value(unsigned char encoding, struct _Unwind_Context *context) { if (encoding == DW_EH_PE_omit) return 0; switch (encoding & 0x70) { case DW_EH_PE_absptr: case DW_EH_PE_pcrel: case DW_EH_PE_aligned: return 0; // No support for textrel or datarel, apparently? #if 0 case DW_EH_PE_textrel: return _Unwind_GetTextRelBase(context); case DW_EH_PE_datarel: return _Unwind_GetDataRelBase(context); #endif case DW_EH_PE_funcrel: return _Unwind_GetRegionStart(context); } abort(); }
static void scan_eh_tab(scan_results& results, _Unwind_Action actions, bool native_exception, _Unwind_Exception* unwind_exception, _Unwind_Context* context) { // Initialize results to found nothing but an error results.ttypeIndex = 0; results.actionRecord = 0; results.languageSpecificData = 0; results.landingPad = 0; results.adjustedPtr = 0; results.reason = _URC_FATAL_PHASE1_ERROR; // Check for consistent actions if (actions & _UA_SEARCH_PHASE) { // Do Phase 1 if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND)) { // None of these flags should be set during Phase 1 // Client error results.reason = _URC_FATAL_PHASE1_ERROR; return; } } else if (actions & _UA_CLEANUP_PHASE) { if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND)) { // _UA_HANDLER_FRAME should only be set if phase 1 found a handler. // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened. // Client error results.reason = _URC_FATAL_PHASE2_ERROR; return; } } else // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set { // One of these should be set. // Client error results.reason = _URC_FATAL_PHASE1_ERROR; return; } // Start scan by getting exception table address const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context); if (lsda == 0) { // There is no exception table results.reason = _URC_CONTINUE_UNWIND; return; } results.languageSpecificData = lsda; // Get the current instruction pointer and offset it before next // instruction in the current frame which threw the exception. uintptr_t ip = _Unwind_GetIP(context) - 1; // Get beginning current frame's code (as defined by the // emitted dwarf code) uintptr_t funcStart = _Unwind_GetRegionStart(context); #if __arm__ if (ip == uintptr_t(-1)) { // no action results.reason = _URC_CONTINUE_UNWIND; return; } else if (ip == 0) call_terminate(native_exception, unwind_exception); // ip is 1-based index into call site table #else // __arm__ uintptr_t ipOffset = ip - funcStart; #endif // __arm__ const uint8_t* classInfo = NULL; // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding // dwarf emission // Parse LSDA header. uint8_t lpStartEncoding = *lsda++; const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); if (lpStart == 0) lpStart = (const uint8_t*)funcStart; uint8_t ttypeEncoding = *lsda++; if (ttypeEncoding != DW_EH_PE_omit) { // Calculate type info locations in emitted dwarf code which // were flagged by type info arguments to llvm.eh.selector // intrinsic uintptr_t classInfoOffset = readULEB128(&lsda); classInfo = lsda + classInfoOffset; } // Walk call-site table looking for range that // includes current PC. uint8_t callSiteEncoding = *lsda++; #if __arm__ (void)callSiteEncoding; // On arm callSiteEncoding is never used #endif uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda)); const uint8_t* callSiteTableStart = lsda; const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; const uint8_t* actionTableStart = callSiteTableEnd; const uint8_t* callSitePtr = callSiteTableStart; while (callSitePtr < callSiteTableEnd) { // There is one entry per call site. #if !__arm__ // The call sites are non-overlapping in [start, start+length) // The call sites are ordered in increasing value of start uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t actionEntry = readULEB128(&callSitePtr); if ((start <= ipOffset) && (ipOffset < (start + length))) #else // __arm__ // ip is 1-based index into this table uintptr_t landingPad = readULEB128(&callSitePtr); uintptr_t actionEntry = readULEB128(&callSitePtr); if (--ip == 0) #endif // __arm__ { // Found the call site containing ip. #if !__arm__ if (landingPad == 0) { // No handler here results.reason = _URC_CONTINUE_UNWIND; return; } landingPad = (uintptr_t)lpStart + landingPad; #else // __arm__ ++landingPad; #endif // __arm__ if (actionEntry == 0) { // Found a cleanup // If this is a type 1 or type 2 search, there are no handlers // If this is a type 3 search, you want to install the cleanup. if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) { results.ttypeIndex = 0; // Redundant but clarifying results.landingPad = landingPad; results.reason = _URC_HANDLER_FOUND; return; } // No handler here results.reason = _URC_CONTINUE_UNWIND; return; } // Convert 1-based byte offset into const uint8_t* action = actionTableStart + (actionEntry - 1); // Scan action entries until you find a matching handler, cleanup, or the end of action list while (true) { const uint8_t* actionRecord = action; int64_t ttypeIndex = readSLEB128(&action); if (ttypeIndex > 0) { // Found a catch, does it actually catch? // First check for catch (...) const __shim_type_info* catchType = get_shim_type_info(static_cast<uint64_t>(ttypeIndex), classInfo, ttypeEncoding, native_exception, unwind_exception); if (catchType == 0) { // Found catch (...) catches everything, including foreign exceptions // If this is a type 1 search save state and return _URC_HANDLER_FOUND // If this is a type 2 search save state and return _URC_HANDLER_FOUND // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = get_thrown_object_ptr(unwind_exception); results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } // Else this is a catch (T) clause and will never // catch a foreign exception else if (native_exception) { __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; void* adjustedPtr = get_thrown_object_ptr(unwind_exception); const __shim_type_info* excpType = static_cast<const __shim_type_info*>(exception_header->exceptionType); if (adjustedPtr == 0 || excpType == 0) { // Something very bad happened call_terminate(native_exception, unwind_exception); } if (catchType->can_catch(excpType, adjustedPtr)) { // Found a matching handler // If this is a type 1 search save state and return _URC_HANDLER_FOUND // If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan if (actions & _UA_SEARCH_PHASE) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = adjustedPtr; results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } } // Scan next action ... } else if (ttypeIndex < 0) { // Found an exception spec. If this is a foreign exception, // it is always caught. if (native_exception) { // Does the exception spec catch this native exception? __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; void* adjustedPtr = get_thrown_object_ptr(unwind_exception); const __shim_type_info* excpType = static_cast<const __shim_type_info*>(exception_header->exceptionType); if (adjustedPtr == 0 || excpType == 0) { // Something very bad happened call_terminate(native_exception, unwind_exception); } if (exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, excpType, adjustedPtr, unwind_exception)) { // native exception caught by exception spec // If this is a type 1 search, save state and return _URC_HANDLER_FOUND // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan if (actions & _UA_SEARCH_PHASE) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = adjustedPtr; results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } } else { // foreign exception caught by exception spec // If this is a type 1 search, save state and return _URC_HANDLER_FOUND // If this is a type 2 search, save state and return _URC_HANDLER_FOUND // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = get_thrown_object_ptr(unwind_exception); results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } // Scan next action ... } else // ttypeIndex == 0 { // Found a cleanup // If this is a type 1 search, ignore it and continue scan // If this is a type 2 search, ignore it and continue scan // If this is a type 3 search, save state and return _URC_HANDLER_FOUND if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = get_thrown_object_ptr(unwind_exception); results.reason = _URC_HANDLER_FOUND; return; } } const uint8_t* temp = action; int64_t actionOffset = readSLEB128(&temp); if (actionOffset == 0) { // End of action list, no matching handler or cleanup found results.reason = _URC_CONTINUE_UNWIND; return; } // Go to next action action += actionOffset; } // there is no break out of this loop, only return } #if !__arm__ else if (ipOffset < start) { // There is no call site for this ip // Something bad has happened. We should never get here. // Possible stack corruption. call_terminate(native_exception, unwind_exception); } #endif // !__arm__ } // there might be some tricky cases which break out of this loop // It is possible that no eh table entry specify how to handle // this exception. By spec, terminate it immediately. call_terminate(native_exception, unwind_exception); }
_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"); // Calculate what the instruction pointer was just before the // exception was thrown for this stack frame uintptr_t throw_ip = _Unwind_GetIP(context) - 1; // 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 there's no LP we can't handle this exception; move on if (not cs.lp) continue; uintptr_t func_start = _Unwind_GetRegionStart(context); // Calculate the range of the instruction pointer valid for this // landing pad; if this LP can handle the current exception then // the IP for this stack frame must be in this range uintptr_t try_start = func_start + cs.start; uintptr_t try_end = func_start + cs.start + cs.len; // Check if this is the correct LP for the current try block if (throw_ip < try_start) continue; if (throw_ip > try_end) continue; // We found a landing pad for this exception; resume execution 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)); _Unwind_SetIP(context, func_start + cs.lp); break; } return _URC_INSTALL_CONTEXT; } else { printf("Personality function, error\n"); return _URC_FATAL_PHASE1_ERROR; } }
_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"); // Calculate what the instruction pointer was just before the // exception was thrown for this stack frame uintptr_t throw_ip = _Unwind_GetIP(context) - 1; // Get a pointer to the raw memory address of the LSDA LSDA_ptr raw_lsda = (LSDA_ptr) _Unwind_GetLanguageSpecificData(context); // Create an object to hide some part of the LSDA processing LSDA lsda(raw_lsda); // Go through each call site in this stack frame to check whether // the current exception can be handled here for(const LSDA_CS *cs = lsda.next_call_site_entry(true); cs != NULL; cs = lsda.next_call_site_entry()) { // If there's no landing pad we can't handle this exception if (not cs->lp) continue; uintptr_t func_start = _Unwind_GetRegionStart(context); // Calculate the range of the instruction pointer valid for this // landing pad; if this LP can handle the current exception then // the IP for this stack frame must be in this range uintptr_t try_start = func_start + cs->start; uintptr_t try_end = func_start + cs->start + cs->len; // Check if this is the correct LP for the current try block if (throw_ip < try_start) continue; if (throw_ip > try_end) continue; // Get the offset into the action table for this LP if (cs->action > 0) { // cs->action is the offset + 1; that way cs->action == 0 // means there is no associated entry in the action table const size_t action_offset = cs->action - 1; const LSDA_ptr action = lsda.action_tbl_start + action_offset; // For a landing pad with a catch the action table will // hold an index to a list of types int type_index = action[0]; const void* catch_type_info = lsda.types_table_start[ -1 * type_index ]; const std::type_info *catch_ti = (const std::type_info *) catch_type_info; printf("%s\n", catch_ti->name()); } // We found a landing pad for this exception; resume execution 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)); _Unwind_SetIP(context, func_start + cs->lp); break; } return _URC_INSTALL_CONTEXT; } else { printf("Personality function, error\n"); return _URC_FATAL_PHASE1_ERROR; } }