static _Unwind_Reason_Code backtrace (struct _Unwind_Context *context, void *varg) { struct callers_data *arg = (struct callers_data *) varg; uintptr pc; int ip_before_insn = 0; #ifdef HAVE_GETIPINFO pc = _Unwind_GetIPInfo (context, &ip_before_insn); #else pc = _Unwind_GetIP (context); #endif /* FIXME: If PC is in the __morestack routine, we should ignore it. */ if (arg->skip > 0) --arg->skip; else if (arg->index >= arg->max) return _URC_END_OF_STACK; else { /* Here PC will be the return address. We actually want the address of the call instruction, so back up one byte and count on the lookup routines handling that correctly. */ if (!ip_before_insn) --pc; arg->pcbuf[arg->index] = pc; ++arg->index; } return _URC_NO_REASON; }
static _Unwind_Reason_Code unwind (struct _Unwind_Context *context, void *vdata) { struct backtrace_data *bdata = (struct backtrace_data *) vdata; uintptr_t pc; int ip_before_insn = 0; #ifdef HAVE_GETIPINFO pc = _Unwind_GetIPInfo (context, &ip_before_insn); #else pc = _Unwind_GetIP (context); #endif if (bdata->skip > 0) { --bdata->skip; return _URC_NO_REASON; } if (!ip_before_insn) --pc; if (!bdata->can_alloc) bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL); else bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback, bdata->error_callback, bdata->data); if (bdata->ret != 0) return _URC_END_OF_STACK; return _URC_NO_REASON; }
static _Unwind_Reason_Code simple_unwind (struct _Unwind_Context *context, void *vdata) { struct backtrace_simple_data *bdata = (struct backtrace_simple_data *) vdata; uintptr_t pc; int ip_before_insn = 0; #ifdef HAVE_GETIPINFO pc = _Unwind_GetIPInfo (context, &ip_before_insn); #else pc = _Unwind_GetIP (context); #endif if (bdata->skip > 0) { --bdata->skip; return _URC_NO_REASON; } if (!ip_before_insn) --pc; bdata->ret = bdata->callback (bdata->data, pc); if (bdata->ret != 0) return _URC_END_OF_STACK; return _URC_NO_REASON; }
static _Unwind_Ptr get_ip_from_context (_Unwind_Context *uw_context) { int ip_before_insn = 0; #ifdef HAVE_GETIPINFO _Unwind_Ptr ip = _Unwind_GetIPInfo (uw_context, &ip_before_insn); #else _Unwind_Ptr ip = _Unwind_GetIP (uw_context); #endif /* Subtract 1 if necessary because GetIPInfo yields a call return address in this case, while we are interested in information for the call point. This does not always yield the exact call instruction address but always brings the IP back within the corresponding region. */ if (!ip_before_insn) ip--; return ip; }
static void db_action_for (action_descriptor *action, _Unwind_Context *uw_context) { int ip_before_insn = 0; #ifdef HAVE_GETIPINFO _Unwind_Ptr ip = _Unwind_GetIPInfo (uw_context, &ip_before_insn); #else _Unwind_Ptr ip = _Unwind_GetIP (uw_context); #endif if (!ip_before_insn) ip--; db (DB_ACTIONS, "For ip @ 0x%08x => ", ip); switch (action->kind) { case unknown: db (DB_ACTIONS, "lpad @ 0x%x, record @ 0x%x\n", action->landing_pad, action->table_entry); break; case nothing: db (DB_ACTIONS, "Nothing\n"); break; case cleanup: db (DB_ACTIONS, "Cleanup\n"); break; case handler: db (DB_ACTIONS, "Handler, filter = %d\n", action->ttype_filter); break; default: db (DB_ACTIONS, "Err? Unexpected action kind !\n"); break; } return; }
static void db_region_for (region_descriptor *region, _Unwind_Context *uw_context) { int ip_before_insn = 0; #ifdef HAVE_GETIPINFO _Unwind_Ptr ip = _Unwind_GetIPInfo (uw_context, &ip_before_insn); #else _Unwind_Ptr ip = _Unwind_GetIP (uw_context); #endif if (!ip_before_insn) ip--; if (! (db_accepted_codes () & DB_REGIONS)) return; db (DB_REGIONS, "For ip @ 0x%08x => ", ip); if (region->lsda) db (DB_REGIONS, "lsda @ 0x%x", region->lsda); else db (DB_REGIONS, "no lsda"); db (DB_REGIONS, "\n"); }
PERSONALITY_FUNCTION (int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class, struct _Unwind_Exception *ue_header, struct _Unwind_Context *context) #endif { struct ObjcException *xh = (struct ObjcException *) ue_header; struct lsda_header_info info; const unsigned char *language_specific_data; const unsigned char *action_record; const unsigned char *p; _Unwind_Ptr landing_pad, ip; int handler_switch_value; int saw_cleanup = 0, saw_handler; void *return_object; int foreign_exception; int ip_before_insn = 0; #ifdef __ARM_EABI_UNWINDER__ _Unwind_Action actions; switch (state & _US_ACTION_MASK) { case _US_VIRTUAL_UNWIND_FRAME: actions = _UA_SEARCH_PHASE; break; case _US_UNWIND_FRAME_STARTING: actions = _UA_CLEANUP_PHASE; if (!(state & _US_FORCE_UNWIND) && ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13)) actions |= _UA_HANDLER_FRAME; break; case _US_UNWIND_FRAME_RESUME: CONTINUE_UNWINDING; break; default: abort(); } actions |= state & _US_FORCE_UNWIND; foreign_exception = 0; ip = (_Unwind_Ptr) ue_header; _Unwind_SetGR(context, 12, ip); #else /* Interface version check. */ if (version != 1) return _URC_FATAL_PHASE1_ERROR; foreign_exception = !(exception_class == __objc_exception_class); #endif /* Shortcut for phase 2 found handler for domestic exception. */ if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME) && !foreign_exception) { #ifdef __ARM_EABI_UNWINDER__ handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1]; landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3]; #else handler_switch_value = xh->handlerSwitchValue; landing_pad = xh->landingPad; #endif goto install_context; } language_specific_data = (const unsigned char *) _Unwind_GetLanguageSpecificData (context); /* If no LSDA, then there are no handlers or cleanups. */ if (! language_specific_data) CONTINUE_UNWINDING; /* Parse the LSDA header. */ p = parse_lsda_header (context, language_specific_data, &info); info.ttype_base = base_of_encoded_value (info.ttype_encoding, context); #ifdef HAVE_GETIPINFO ip = _Unwind_GetIPInfo (context, &ip_before_insn); #else ip = _Unwind_GetIP (context); #endif if (! ip_before_insn) --ip; landing_pad = 0; action_record = 0; handler_switch_value = 0; #ifdef SJLJ_EXCEPTIONS /* The given "IP" is an index into the call-site table, with two exceptions -- -1 means no-action, and 0 means terminate. But since we're using uleb128 values, we've not got random access to the array. */ if ((int) ip < 0) return _URC_CONTINUE_UNWIND; else { _Unwind_Word cs_lp, cs_action; do { p = read_uleb128 (p, &cs_lp); p = read_uleb128 (p, &cs_action); } while (--ip); /* Can never have null landing pad for sjlj -- that would have been indicated by a -1 call site index. */ landing_pad = cs_lp + 1; if (cs_action) action_record = info.action_table + cs_action - 1; goto found_something; } #else /* Search the call-site table for the action associated with this IP. */ while (p < info.action_table) { _Unwind_Ptr cs_start, cs_len, cs_lp; _Unwind_Word cs_action; /* Note that all call-site encodings are "absolute" displacements. */ p = read_encoded_value (0, info.call_site_encoding, p, &cs_start); p = read_encoded_value (0, info.call_site_encoding, p, &cs_len); p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp); p = read_uleb128 (p, &cs_action); /* The table is sorted, so if we've passed the ip, stop. */ if (ip < info.Start + cs_start) p = info.action_table; else if (ip < info.Start + cs_start + cs_len) { if (cs_lp) landing_pad = info.LPStart + cs_lp; if (cs_action) action_record = info.action_table + cs_action - 1; goto found_something; } } #endif /* SJLJ_EXCEPTIONS */ /* If ip is not present in the table, C++ would call terminate. */ /* ??? As with Java, it's perhaps better to tweek the LSDA to that no-action is mapped to no-entry. */ return _URC_CONTINUE_UNWIND; found_something: saw_cleanup = 0; saw_handler = 0; if (landing_pad == 0) { /* If ip is present, and has a null landing pad, there are no cleanups or handlers to be run. */ } else if (action_record == 0) { /* If ip is present, has a non-null landing pad, and a null action table offset, then there are only cleanups present. Cleanups use a zero switch value, as set above. */ saw_cleanup = 1; } else { /* Otherwise we have a catch handler. */ _Unwind_Sword ar_filter, ar_disp; while (1) { p = action_record; p = read_sleb128 (p, &ar_filter); read_sleb128 (p, &ar_disp); if (ar_filter == 0) { /* Zero filter values are cleanups. */ saw_cleanup = 1; } /* During forced unwinding, we only run cleanups. With a foreign exception class, we have no class info to match. */ else if ((actions & _UA_FORCE_UNWIND) || foreign_exception) ; else if (ar_filter > 0) { /* Positive filter values are handlers. */ Class catch_type = get_ttype_entry (&info, ar_filter); if (isKindOf (xh->value, catch_type)) { handler_switch_value = ar_filter; saw_handler = 1; break; } } else { /* Negative filter values are exception specifications, which Objective-C does not use. */ abort (); } if (ar_disp == 0) break; action_record = p + ar_disp; } } if (! saw_handler && ! saw_cleanup) CONTINUE_UNWINDING; if (actions & _UA_SEARCH_PHASE) { if (!saw_handler) CONTINUE_UNWINDING; /* For domestic exceptions, we cache data from phase 1 for phase 2. */ if (!foreign_exception) { #ifdef __ARM_EABI_UNWIDER__ ue_header->barrier_cache.sp = _Unwind_GetGR(context, 13); ue_header->barrier_cache.bitpattern[1] = (_uw) handler_switch_value; ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad; #else xh->handlerSwitchValue = handler_switch_value; xh->landingPad = landing_pad; #endif } return _URC_HANDLER_FOUND; } install_context: if (saw_cleanup == 0) { return_object = xh->value; if (!(actions & _UA_SEARCH_PHASE)) _Unwind_DeleteException(&xh->base); } _Unwind_SetGR (context, __builtin_eh_return_data_regno (0), __builtin_extend_pointer (saw_cleanup ? xh : return_object)); _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), handler_switch_value); _Unwind_SetIP (context, landing_pad); return _URC_INSTALL_CONTEXT; }
_Unwind_Reason_Code PERSONALITY_FUNCTION (int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class, struct _Unwind_Exception *ue_header, struct _Unwind_Context *context) #endif { lsda_header_info info; const unsigned char *language_specific_data, *p, *action_record; _Unwind_Ptr landing_pad, ip; int ip_before_insn = 0; _Bool is_foreign; G *g; #ifdef __ARM_EABI_UNWINDER__ _Unwind_Action actions; switch (state & _US_ACTION_MASK) { case _US_VIRTUAL_UNWIND_FRAME: actions = _UA_SEARCH_PHASE; break; case _US_UNWIND_FRAME_STARTING: actions = _UA_CLEANUP_PHASE; if (!(state & _US_FORCE_UNWIND) && ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13)) actions |= _UA_HANDLER_FRAME; break; case _US_UNWIND_FRAME_RESUME: CONTINUE_UNWINDING; break; default: abort(); } actions |= state & _US_FORCE_UNWIND; is_foreign = 0; /* The dwarf unwinder assumes the context structure holds things like the function and LSDA pointers. The ARM implementation caches these in the exception header (UCB). To avoid rewriting everything we make the virtual IP register point at the UCB. */ ip = (_Unwind_Ptr) ue_header; _Unwind_SetGR (context, 12, ip); #else if (version != 1) return _URC_FATAL_PHASE1_ERROR; is_foreign = exception_class != __go_exception_class; #endif language_specific_data = (const unsigned char *) _Unwind_GetLanguageSpecificData (context); /* If no LSDA, then there are no handlers or cleanups. */ if (! language_specific_data) CONTINUE_UNWINDING; /* Parse the LSDA header. */ p = parse_lsda_header (context, language_specific_data, &info); #ifdef HAVE_GETIPINFO ip = _Unwind_GetIPInfo (context, &ip_before_insn); #else ip = _Unwind_GetIP (context); #endif if (! ip_before_insn) --ip; landing_pad = 0; action_record = NULL; #ifdef __USING_SJLJ_EXCEPTIONS__ /* The given "IP" is an index into the call-site table, with two exceptions -- -1 means no-action, and 0 means terminate. But since we're using uleb128 values, we've not got random access to the array. */ if ((int) ip <= 0) return _URC_CONTINUE_UNWIND; else { _uleb128_t cs_lp, cs_action; do { p = read_uleb128 (p, &cs_lp); p = read_uleb128 (p, &cs_action); } while (--ip); /* Can never have null landing pad for sjlj -- that would have been indicated by a -1 call site index. */ landing_pad = (_Unwind_Ptr)cs_lp + 1; if (cs_action) action_record = info.action_table + cs_action - 1; goto found_something; } #else /* Search the call-site table for the action associated with this IP. */ while (p < info.action_table) { _Unwind_Ptr cs_start, cs_len, cs_lp; _uleb128_t cs_action; /* Note that all call-site encodings are "absolute" displacements. */ p = read_encoded_value (0, info.call_site_encoding, p, &cs_start); p = read_encoded_value (0, info.call_site_encoding, p, &cs_len); p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp); p = read_uleb128 (p, &cs_action); /* The table is sorted, so if we've passed the ip, stop. */ if (ip < info.Start + cs_start) p = info.action_table; else if (ip < info.Start + cs_start + cs_len) { if (cs_lp) landing_pad = info.LPStart + cs_lp; if (cs_action) action_record = info.action_table + cs_action - 1; goto found_something; } } #endif /* IP is not in table. No associated cleanups. */ CONTINUE_UNWINDING; found_something: if (landing_pad == 0) { /* IP is present, but has a null landing pad. No handler to be run. */ CONTINUE_UNWINDING; } if (actions & _UA_SEARCH_PHASE) { if (action_record == 0) { /* This indicates a cleanup rather than an exception handler. */ CONTINUE_UNWINDING; } return _URC_HANDLER_FOUND; } /* It's possible for g to be NULL here for an exception thrown by a language other than Go. */ g = runtime_g (); if (g == NULL) { if (!is_foreign) abort (); } else { g->exception = ue_header; g->isforeign = is_foreign; } _Unwind_SetGR (context, __builtin_eh_return_data_regno (0), (_Unwind_Ptr) ue_header); _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0); _Unwind_SetIP (context, landing_pad); return _URC_INSTALL_CONTEXT; }
_Unwind_Reason_Code PERSONALITY_FUNCTION (int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED, struct _Unwind_Exception *ue_header, struct _Unwind_Context *context) #endif { lsda_header_info info; const unsigned char *language_specific_data, *p, *action_record; _Unwind_Ptr landing_pad, ip; int ip_before_insn = 0; #ifdef __ARM_EABI_UNWINDER__ if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING) CONTINUE_UNWINDING; /* The dwarf unwinder assumes the context structure holds things like the function and LSDA pointers. The ARM implementation caches these in the exception header (UCB). To avoid rewriting everything we make the virtual IP register point at the UCB. */ ip = (_Unwind_Ptr) ue_header; _Unwind_SetGR (context, 12, ip); #else if (version != 1) return _URC_FATAL_PHASE1_ERROR; /* Currently we only support cleanups for C. */ if ((actions & _UA_CLEANUP_PHASE) == 0) CONTINUE_UNWINDING; #endif language_specific_data = (const unsigned char *) _Unwind_GetLanguageSpecificData (context); /* If no LSDA, then there are no handlers or cleanups. */ if (! language_specific_data) CONTINUE_UNWINDING; /* Parse the LSDA header. */ p = parse_lsda_header (context, language_specific_data, &info); #ifdef HAVE_GETIPINFO ip = _Unwind_GetIPInfo (context, &ip_before_insn); #else ip = _Unwind_GetIP (context); #endif if (! ip_before_insn) --ip; landing_pad = 0; #ifdef __USING_SJLJ_EXCEPTIONS__ /* The given "IP" is an index into the call-site table, with two exceptions -- -1 means no-action, and 0 means terminate. But since we're using uleb128 values, we've not got random access to the array. */ if ((int) ip <= 0) return _URC_CONTINUE_UNWIND; else { _uleb128_t cs_lp, cs_action; do { p = read_uleb128 (p, &cs_lp); p = read_uleb128 (p, &cs_action); } while (--ip); /* Can never have null landing pad for sjlj -- that would have been indicated by a -1 call site index. */ landing_pad = (_Unwind_Ptr)cs_lp + 1; if (cs_action) action_record = info.action_table + cs_action - 1; goto found_something; } #else /* Search the call-site table for the action associated with this IP. */ while (p < info.action_table) { _Unwind_Ptr cs_start, cs_len, cs_lp; _uleb128_t cs_action; /* Note that all call-site encodings are "absolute" displacements. */ p = read_encoded_value (0, info.call_site_encoding, p, &cs_start); p = read_encoded_value (0, info.call_site_encoding, p, &cs_len); p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp); p = read_uleb128 (p, &cs_action); /* The table is sorted, so if we've passed the ip, stop. */ if (ip < info.Start + cs_start) p = info.action_table; else if (ip < info.Start + cs_start + cs_len) { if (cs_lp) landing_pad = info.LPStart + cs_lp; if (cs_action) action_record = info.action_table + cs_action - 1; goto found_something; } } #endif /* IP is not in table. No associated cleanups. */ /* ??? This is where C++ calls std::terminate to catch throw from a destructor. */ CONTINUE_UNWINDING; found_something: if (landing_pad == 0) { /* IP is present, but has a null landing pad. No handler to be run. */ CONTINUE_UNWINDING; } _Unwind_SetGR (context, __builtin_eh_return_data_regno (0), (_Unwind_Ptr) ue_header); _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0); _Unwind_SetIP (context, landing_pad); return _URC_INSTALL_CONTEXT; }
_Unwind_Reason_Code __runa_personality(int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class, struct _Unwind_Exception *ue_header, struct _Unwind_Context *context) { enum found_handler_type { found_nothing, found_terminate, found_cleanup, found_handler } found_type; struct lsda_header_info info; const unsigned char *language_specific_data; const unsigned char *action_record; const unsigned char *p; _Unwind_Ptr landing_pad, ip; int handler_switch_value; void* thrown_ptr = 0; bool foreign_exception; int ip_before_insn = 0; //__cxa_exception* xh = __get_exception_header_from_ue(ue_header); // Interface version check. if (version != 1) return _URC_FATAL_PHASE1_ERROR; foreign_exception = exception_class != RUNA_CLASS; // Shortcut for phase 2 found handler for domestic exception. if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME) && !foreign_exception) { restore_caught_exception(ue_header, &handler_switch_value, &language_specific_data, &landing_pad); found_type = (landing_pad == 0 ? found_terminate : found_handler); goto install_context; } language_specific_data = (const unsigned char *) _Unwind_GetLanguageSpecificData(context); // If no LSDA, then there are no handlers or cleanups. if (!language_specific_data) return _URC_CONTINUE_UNWIND; // Parse the LSDA header. p = parse_lsda_header(context, language_specific_data, &info); info.ttype_base = base_of_encoded_value(info.ttype_encoding, context); ip = _Unwind_GetIPInfo(context, &ip_before_insn); //ip = _Unwind_GetIP(context); if (!ip_before_insn) --ip; landing_pad = 0; action_record = 0; handler_switch_value = 0; // Search the call-site table for the action associated with this IP. while (p < info.action_table) { _Unwind_Ptr cs_start, cs_len, cs_lp; _uleb128_t cs_action; // Note that all call-site encodings are "absolute" displacements. p = read_encoded_value(0, info.call_site_encoding, p, &cs_start); p = read_encoded_value(0, info.call_site_encoding, p, &cs_len); p = read_encoded_value(0, info.call_site_encoding, p, &cs_lp); p = read_uleb128(p, &cs_action); // The table is sorted, so if we've passed the ip, stop. if (ip < info.Start + cs_start) { p = info.action_table; } else if (ip < info.Start + cs_start + cs_len) { if (cs_lp) landing_pad = info.LPStart + cs_lp; if (cs_action) action_record = info.action_table + cs_action - 1; goto found_something; } } // If ip is not present in the table, call terminate. This is for // a destructor inside a cleanup, or a library routine the compiler // was not expecting to throw. found_type = found_terminate; goto do_something; found_something: if (landing_pad == 0) { // If ip is present, and has a null landing pad, there are // no cleanups or handlers to be run. found_type = found_nothing; } else if (action_record == 0) { // If ip is present, has a non-null landing pad, and a null // action table offset, then there are only cleanups present. // Cleanups use a zero switch value, as set above. found_type = found_cleanup; } else { // Otherwise we have a catch handler or exception specification. _sleb128_t ar_filter, ar_disp; //const std::type_info* catch_type; //_throw_typet* throw_type; bool saw_cleanup = false; bool saw_handler = false; { //thrown_ptr = __get_object_from_ue(ue_header); //throw_type = __get_exception_header_from_obj(thrown_ptr)->exceptionType; } while (1) { p = action_record; p = read_sleb128(p, &ar_filter); read_sleb128(p, &ar_disp); if (ar_filter == 0) { // Zero filter values are cleanups. saw_cleanup = true; } else if (ar_filter > 0) { // Positive filter values are handlers. //catch_type = get_ttype_entry(&info, ar_filter); //printf("positive filter value -- handler found\n"); saw_handler = true; break; // Null catch type is a catch-all handler; we can catch foreign // exceptions with this. Otherwise we must match types. //if (!catch_type || (throw_type && // get_adjusted_ptr(catch_type, throw_type, &thrown_ptr))) { // saw_handler = true; // break; //} } else { printf("negative filter value -- exception spec\n"); // Negative filter values are exception specifications. // ??? How do foreign exceptions fit in? As far as I can // see we can't match because there's no __cxa_exception // object to stuff bits in for __cxa_call_unexpected to use. // Allow them iff the exception spec is non-empty. I.e. // a throw() specification results in __unexpected. //if ((throw_type && !(actions & _UA_FORCE_UNWIND) && !foreign_exception) ? // !check_exception_spec(&info, throw_type, thrown_ptr, ar_filter) : // empty_exception_spec(&info, ar_filter)) { // saw_handler = true; // break; //} } if (ar_disp == 0) break; action_record = p + ar_disp; } if (saw_handler) { handler_switch_value = ar_filter; found_type = found_handler; } else { found_type = (saw_cleanup ? found_cleanup : found_nothing); } } do_something: if (found_type == found_nothing) return _URC_CONTINUE_UNWIND; if (actions & _UA_SEARCH_PHASE) { if (found_type == found_cleanup) return _URC_CONTINUE_UNWIND; // For domestic exceptions, we cache data from phase 1 for phase 2. if (!foreign_exception) { save_caught_exception(ue_header, handler_switch_value, language_specific_data, landing_pad); } return _URC_HANDLER_FOUND; } install_context: // We can't use any of the cxa routines with foreign exceptions, // because they all expect ue_header to be a struct __cxa_exception. // So in that case, call terminate or unexpected directly. if ((actions & _UA_FORCE_UNWIND) || foreign_exception) { if (found_type == found_terminate) abort(); // std::terminate(); else if (handler_switch_value < 0) { printf("WTF\n"); //__try // { std::unexpected (); } //__catch(...) // { std::terminate (); } } } else { if (found_type == found_terminate) abort(); //__cxa_call_terminate(ue_header); // Cache the TType base value for __cxa_call_unexpected, as we won't // have an _Unwind_Context then. if (handler_switch_value < 0) { parse_lsda_header(context, language_specific_data, &info); info.ttype_base = base_of_encoded_value(info.ttype_encoding, context); //xh->catchTemp = base_of_encoded_value (info.ttype_encoding, context); } } /* For targets with pointers smaller than the word size, we must extend the pointer, and this extension is target dependent. */ _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), __builtin_extend_pointer(ue_header)); _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), handler_switch_value); _Unwind_SetIP(context, landing_pad); return _URC_INSTALL_CONTEXT; }
static void get_call_site_action_for (_Unwind_Context *uw_context, region_descriptor *region, action_descriptor *action) { const unsigned char *p = region->call_site_table; int ip_before_insn = 0; #ifdef HAVE_GETIPINFO _Unwind_Ptr ip = _Unwind_GetIPInfo (uw_context, &ip_before_insn); #else _Unwind_Ptr ip = _Unwind_GetIP (uw_context); #endif /* Subtract 1 if necessary because GetIPInfo yields a call return address in this case, while we are interested in information for the call point. This does not always yield the exact call instruction address but always brings the IP back within the corresponding region. */ if (!ip_before_insn) ip--; /* Unless we are able to determine otherwise... */ action->kind = nothing; db (DB_CSITE, "\n"); while (p < region->action_table) { _Unwind_Ptr cs_start, cs_len, cs_lp; _uleb128_t cs_action; /* Note that all call-site encodings are "absolute" displacements. */ p = read_encoded_value (0, region->call_site_encoding, p, &cs_start); p = read_encoded_value (0, region->call_site_encoding, p, &cs_len); p = read_encoded_value (0, region->call_site_encoding, p, &cs_lp); p = read_uleb128 (p, &cs_action); db (DB_CSITE, "c_site @ 0x%08x (+0x%03x), len = %3d, lpad @ 0x%08x (+0x%03x)\n", region->base+cs_start, cs_start, cs_len, region->lp_base+cs_lp, cs_lp); /* The table is sorted, so if we've passed the IP, stop. */ if (ip < region->base + cs_start) break; /* If we have a match, fill the ACTION fields accordingly. */ else if (ip < region->base + cs_start + cs_len) { /* Let the caller know there may be an action to take, but let it determine the kind. */ action->kind = unknown; if (cs_lp) action->landing_pad = region->lp_base + cs_lp; else action->landing_pad = 0; if (cs_action) action->table_entry = region->action_table + cs_action - 1; else action->table_entry = 0; db (DB_CSITE, "+++\n"); return; } } db (DB_CSITE, "---\n"); }
static void get_call_site_action_for (_Unwind_Context *uw_context, region_descriptor *region, action_descriptor *action) { int ip_before_insn = 0; #ifdef HAVE_GETIPINFO _Unwind_Ptr call_site = _Unwind_GetIPInfo (uw_context, &ip_before_insn); #else _Unwind_Ptr call_site = _Unwind_GetIP (uw_context); #endif /* Subtract 1 if necessary because GetIPInfo returns the actual call site value + 1 in this case. */ if (!ip_before_insn) call_site--; /* call_site is a direct index into the call-site table, with two special values : -1 for no-action and 0 for "terminate". The latter should never show up for Ada. To test for the former, beware that _Unwind_Ptr might be unsigned. */ if ((int)call_site < 0) { action->kind = nothing; return; } else if (call_site == 0) { db (DB_ERR, "========> Err, null call_site for Ada/sjlj\n"); action->kind = nothing; return; } else { _uleb128_t cs_lp, cs_action; /* Let the caller know there may be an action to take, but let it determine the kind. */ action->kind = unknown; /* We have a direct index into the call-site table, but this table is made of leb128 values, the encoding length of which is variable. We can't merely compute an offset from the index, then, but have to read all the entries before the one of interest. */ const unsigned char *p = region->call_site_table; do { p = read_uleb128 (p, &cs_lp); p = read_uleb128 (p, &cs_action); } while (--call_site); action->landing_pad = cs_lp + 1; if (cs_action) action->table_entry = region->action_table + cs_action - 1; else action->table_entry = 0; return; } }