Example #1
0
void sync_regstate(_Unwind_Context* context) {
  assertx(tl_regState == VMRegState::DIRTY);

  uintptr_t frameRbp = _Unwind_GetGR(context, Debug::RBP);
  uintptr_t frameRip = _Unwind_GetIP(context);
  FTRACE(2, "syncing regstate for rbp: {:#x} rip: {:#x}\n", frameRbp, frameRip);

  /*
   * fixupWork expects to be looking at the first frame that is out of
   * the TC.  We have RBP/RIP for the TC frame that called out here,
   * so we make a fake ActRec here to give it what it expects.
   *
   * Note: this doesn't work for IndirectFixup situations.  However,
   * currently IndirectFixup is only used for destructors, which
   * aren't allowed to throw, so this is ok.
   */
  ActRec fakeAr;
  fakeAr.m_sfp = reinterpret_cast<ActRec*>(frameRbp);
  fakeAr.m_savedRip = frameRip;

  Stats::inc(Stats::TC_SyncUnwind);
  mcg->fixupMap().fixupWork(g_context.getNoCheck(), &fakeAr);
  tl_regState = VMRegState::CLEAN;
  FTRACE(2, "synced vmfp: {} vmsp: {} vmpc: {}\n", vmfp(), vmsp(), vmpc());
}
/* ARM unwinder personality handler referenced from interpreter .ARM.extab. */
LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb,
			       _Unwind_Context *ctx)
{
  void *cf = (void *)_Unwind_GetGR(ctx, 13);
  lua_State *L = cframe_L(cf);
  int errcode;

  switch ((state & _US_ACTION_MASK)) {
  case _US_VIRTUAL_UNWIND_FRAME:
    if ((state & _US_FORCE_UNWIND)) break;
    return _URC_HANDLER_FOUND;
  case _US_UNWIND_FRAME_STARTING:
    if (LJ_UEXCLASS_CHECK(ucb->exclass)) {
      errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass);
    } else {
      errcode = LUA_ERRRUN;
      setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
    }
    cf = err_unwind(L, cf, errcode);
    if ((state & _US_FORCE_UNWIND) || cf == NULL) break;
    _Unwind_SetGR(ctx, 15, (uint32_t)lj_vm_unwind_ext);
    _Unwind_SetGR(ctx, 0, (uint32_t)ucb);
    _Unwind_SetGR(ctx, 1, (uint32_t)errcode);
    _Unwind_SetGR(ctx, 2, cframe_unwind_ff(cf) ?
			    (uint32_t)lj_vm_unwind_ff_eh :
			    (uint32_t)lj_vm_unwind_c_eh);
    return _URC_INSTALL_CONTEXT;
  default:
    return _URC_FAILURE;
  }
  if (__gnu_unwind_frame(ucb, ctx) != _URC_OK)
    return _URC_FAILURE;
  return _URC_CONTINUE_UNWIND;
}
Example #3
0
_Unwind_Reason_Code
__runcont_personality(int version, _Unwind_Action actions,
                    _Unwind_Exception_Class exception_class,
                    struct _Unwind_Exception *ue_header,
                    struct _Unwind_Context *context)
{
    if (actions & _UA_SEARCH_PHASE)
        return _URC_CONTINUE_UNWIND;
    if (actions & _UA_CLEANUP_PHASE) {
        void** base = (void**)_Unwind_GetGR(context,5);
        struct cont* c = (struct cont*)*(base+2);
        *((int32_t (**)(struct cont*, int32_t)) c) = runcont_dirty;
        return _URC_CONTINUE_UNWIND;
    }
    abort();
}
Example #4
0
static _Unwind_Reason_Code
gum_gcc_backtracer_append_address (struct _Unwind_Context * context,
                                   void * user_data)
{
  GumGccBacktraceCtx * btctx = (GumGccBacktraceCtx *) user_data;
  GumReturnAddressArray * arr = btctx->return_addresses;

  if (GSIZE_TO_POINTER (_Unwind_GetGR (context, 7)) < btctx->start_address)
    return _URC_NO_REASON;

  if (arr->len == G_N_ELEMENTS (arr->items))
    return _URC_NORMAL_STOP;

  arr->items[arr->len++] = GSIZE_TO_POINTER (_Unwind_GetIP (context));
  return _URC_NO_REASON;
}
Example #5
0
/* ARM unwinder personality handler referenced from interpreter .ARM.extab. */
LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx)
{
  void *cf = (void *)_Unwind_GetGR(ctx, 13);
  lua_State *L = cframe_L(cf);
  if ((state & _US_ACTION_MASK) == _US_VIRTUAL_UNWIND_FRAME) {
    setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
    return _URC_HANDLER_FOUND;
  }
  if ((state&(_US_ACTION_MASK|_US_FORCE_UNWIND)) == _US_UNWIND_FRAME_STARTING) {
    _Unwind_DeleteException(ucb);
    _Unwind_SetGR(ctx, 15, (uint32_t)(void *)lj_err_throw);
    _Unwind_SetGR(ctx, 0, (uint32_t)L);
    _Unwind_SetGR(ctx, 1, (uint32_t)LUA_ERRRUN);
    return _URC_INSTALL_CONTEXT;
  }
  if (__gnu_unwind_frame(ucb, ctx) != _URC_OK)
    return _URC_FAILURE;
  return _URC_CONTINUE_UNWIND;
}
static _Unwind_Reason_Code
UtilBacktraceFromPointerCallback(struct _Unwind_Context *ctx, // IN: Unwind context
                                 void *cbData)                // IN/OUT: Our status
{
   struct UtilBacktraceFromPointerData *data = cbData;
   uintptr_t cfa = _Unwind_GetCFA(ctx);

   /*
    * Stack grows down.  So if we are below basePtr, do nothing...
    */

   if (cfa >= data->basePtr && data->frameNr < 500) {
#ifndef VM_X86_64
#   error You should not build this on 32bit - there is no eh_frame there.
#endif
      /* bump basePtr for glibc unwind bug, see [302237] */
      data->basePtr = cfa + 8;
      /* Do output without leading '0x' to save some horizontal space... */
      data->outFunc(data->outFuncData,
                    "Backtrace[%u] %016lx rip=%016lx rbx=%016lx rbp=%016lx "
                    "r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
                    data->frameNr, cfa, _Unwind_GetIP(ctx),
                    _Unwind_GetGR(ctx, 3), _Unwind_GetGR(ctx, 6),
                    _Unwind_GetGR(ctx, 12), _Unwind_GetGR(ctx, 13),
                    _Unwind_GetGR(ctx, 14), _Unwind_GetGR(ctx, 15));
      data->frameNr++;
      return _URC_NO_REASON;
   } else if (data->skippedFrames < MAX_SKIPPED_FRAMES && !data->frameNr) {
      /*
       * Skip over the frames before the specified starting point of the
       * backtrace.
       */

      data->skippedFrames++;
      return _URC_NO_REASON;
   }
   return _URC_END_OF_STACK;
}
Example #7
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;
}
Example #8
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;
}