Пример #1
0
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;
}
Пример #2
0
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;
}
_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;
    }
}
Пример #4
0
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, &region->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;
}
Пример #5
0
_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)
/* APPLE LOCAL begin LLVM */
#endif
/* APPLE LOCAL end LLVM */
{
  lsda_header_info info;
  const unsigned char *language_specific_data, *p, *action_record;
  _Unwind_Ptr landing_pad, ip;

/* APPLE LOCAL begin LLVM */
#ifdef __ARM_EABI_UNWINDER__
  if (state != _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
/* APPLE LOCAL end LLVM */
  if (version != 1)
    return _URC_FATAL_PHASE1_ERROR;

  /* Currently we only support cleanups for C.  */
  if ((actions & _UA_CLEANUP_PHASE) == 0)
/* APPLE LOCAL begin LLVM */
    CONTINUE_UNWINDING;
#endif
/* APPLE LOCAL end LLVM */

  language_specific_data = (const unsigned char *)
    _Unwind_GetLanguageSpecificData (context);

  /* If no LSDA, then there are no handlers or cleanups.  */
  if (! language_specific_data)
/* APPLE LOCAL begin LLVM */
    CONTINUE_UNWINDING;
/* APPLE LOCAL end LLVM */

  /* Parse the LSDA header.  */
  p = parse_lsda_header (context, language_specific_data, &info);
  ip = _Unwind_GetIP (context) - 1;
  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
    {
      _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

  /* IP is not in table.  No associated cleanups.  */
  /* ??? This is where C++ calls std::terminate to catch throw
     from a destructor.  */
/* APPLE LOCAL begin LLVM */
  CONTINUE_UNWINDING;
/* APPLE LOCAL end LLVM */

 found_something:
  if (landing_pad == 0)
    {
      /* IP is present, but has a null landing pad.
	 No handler to be run.  */
/* APPLE LOCAL begin LLVM */
      CONTINUE_UNWINDING;
/* APPLE LOCAL end LLVM */
    }

  _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;
}
Пример #6
0
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;
}
Пример #7
0
_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;
}
Пример #8
0
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);
}
Пример #9
0
_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;

}
_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;
    }
}