Esempio n. 1
0
static inline NORETURN void resume(unw_cursor_t* cursor, const uint8_t* landing_pad, int64_t switch_value,
                                   const ExcInfo* exc_data) {
    checkExcInfo(exc_data);
    assert(landing_pad);
    if (VERBOSITY("cxx_unwind") >= 4)
        printf("  * RESUMED: ip %p  switch_value %ld\n", (const void*)landing_pad, (long)switch_value);

    if (0 != switch_value) {
        // The exception handler will call __cxa_begin_catch, which stops this timer and logs it.
        per_thread_resume_catch_timer.restart("resume_catch", 20);
    } else {
        // The cleanup code will call _Unwind_Resume, which will stop this timer and log it.
        // TODO: am I sure cleanup code can't raise exceptions? maybe have an assert!
        per_thread_cleanup_timer.restart("cleanup", 20);
#ifndef NDEBUG
        in_cleanup_code = true;
#endif
    }

    // set rax to pointer to exception object
    // set rdx to the switch_value (0 for cleanup, otherwise an index indicating which exception handler to use)
    //
    // NB. assumes x86-64. maybe I should use __builtin_eh_return_data_regno() here?
    // but then, need to translate into UNW_* values somehow. not clear how.
    check(unw_set_reg(cursor, UNW_X86_64_RAX, (unw_word_t)exc_data));
    check(unw_set_reg(cursor, UNW_X86_64_RDX, switch_value));

    // resume!
    check(unw_set_reg(cursor, UNW_REG_IP, (unw_word_t)landing_pad));
    unw_resume(cursor);
    RELEASE_ASSERT(0, "unw_resume returned!");
}
Esempio n. 2
0
void
jffi_longjmp (jmp_buf env, int val)
{
    extern int _jffi_longjmp_cont;
    unw_context_t uc;
    unw_cursor_t c;
    unw_word_t sp, ip, bp = 0;
    uintptr_t *wp = (uintptr_t *) env;
    int i, setjmp_frame;

    if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0) {
        debug("failed to get context");
        abort ();
    }
#ifdef __x86_86__
# define UNW_REG_BP UNW_X86_64_RBP
#else
# define UNW_REG_BP UNW_X86_EBP
#endif
    setjmp_frame = 0;

    do {
        char name[256];
        unw_proc_info_t pi;
        unw_word_t off;
        if (unw_get_reg (&c, UNW_REG_BP, &bp) < 0) {
            abort();
        }
        if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0) {
            abort();
        }
        if (unw_get_reg (&c, UNW_REG_IP, &ip) < 0) {
            abort();
        }
        unw_get_proc_name(&c, name, sizeof(name), &off);
        unw_get_proc_info(&c, &pi);
//        debug("frame %s ip=%llx sp=%llx bp=%llx wp[RP]=%p wp[SP]=%p, pi.start_ip=%llx, pi.end_ip=%llx",
//            name, (long long) ip, (long long) sp, (long long) bp, (void *) wp[JB_RP], (void *) wp[JB_SP],
//            pi.start_ip, pi.end_ip);

        if (wp[JB_SP] > sp || wp[JB_RP] < pi.start_ip || wp[JB_RP] > pi.end_ip) continue;

        /* found the right frame: */
//        debug("found frame to jump back to");
        assert (UNW_NUM_EH_REGS >= 2);
        if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0
            || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0
            || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) &_jffi_longjmp_cont))
            abort ();

        unw_resume (&c);
        // should not reach here
        abort ();
    } while (unw_step (&c) > 0);
//    debug("failed to find correct frame to jmp to");
}
Esempio n. 3
0
/// Called by personality handler during phase 2 to alter instruction pointer,
/// such as setting where the landing pad is, so _Unwind_Resume() will
/// start executing in the landing pad.
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
                                     uintptr_t new_value) {
  _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0llX)\n",
                             context, (uint64_t) new_value);
  unw_cursor_t *cursor = (unw_cursor_t *)context;
  unw_set_reg(cursor, UNW_REG_IP, new_value);
}
Esempio n. 4
0
/// Called by personality handler during phase 2 to alter register values.
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
                                     uintptr_t value) {
  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIx64
                       ")\n",
                       (void *)context, index, (uint64_t)value);
  unw_cursor_t *cursor = (unw_cursor_t *)context;
  unw_set_reg(cursor, index, value);
}
Esempio n. 5
0
/// Called by personality handler during phase 2 to alter register values.
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
                                     uintptr_t new_value) {
  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, "
                             "value=0x%0llX)\n", context,
                             index, (uint64_t) new_value);
  unw_cursor_t *cursor = (unw_cursor_t *)context;
  unw_set_reg(cursor, index, new_value);
}
Esempio n. 6
0
void
_longjmp (jmp_buf env, int val)
{
  extern int _UI_longjmp_cont;
  unw_context_t uc;
  unw_cursor_t c;
  unw_word_t sp;
  unw_word_t *wp = (unw_word_t *) env;

  if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0)
    abort ();

  do
    {
      if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0)
	abort ();
#ifdef __FreeBSD__
      if (sp != wp[JB_SP] + sizeof(unw_word_t))
#else
      if (sp != wp[JB_SP])
#endif
	continue;

      if (!bsp_match (&c, wp))
	continue;

      /* found the right frame: */

      assert (UNW_NUM_EH_REGS >= 2);

      if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0
	  || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0
	  || unw_set_reg (&c, UNW_REG_IP,
			  (unw_word_t) (uintptr_t) &_UI_longjmp_cont))
	abort ();

      unw_resume (&c);

      abort ();
    }
  while (unw_step (&c) > 0);

  abort ();
}
Esempio n. 7
0
_Unwind_VRS_Result _Unwind_VRS_Set(
    _Unwind_Context *context,
    _Unwind_VRS_RegClass regclass,
    uint32_t regno,
    _Unwind_VRS_DataRepresentation representation,
    void *valuep) {
  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, regclass=%d reg=%d, rep=%d, "
                             "value=0x%0llX)\n", context, regclass,
                             regno, representation, 0LL /* FIXME */);
  unw_cursor_t *cursor = (unw_cursor_t *)context;
  switch (regclass) {
    case _UVRSC_CORE: {
      if (representation != _UVRSD_UINT32)
        _LIBUNWIND_ABORT("Core register representation must be _UVRSD_UINT32.");
      return unw_set_reg(cursor, regno, *((unw_word_t*)valuep)) == UNW_ESUCCESS ?
          _UVRSR_OK : _UVRSR_FAILED;
    }
    // FIXME: Are these right? See 4.7 on lazy-saving
    case _UVRSC_WMMXD:
    case _UVRSC_WMMXC:
    case _UVRSC_VFP: {
      unw_fpreg_t value;
      switch (representation) {
        case _UVRSD_VFPX:
          // TODO(ajwong): What does this mean?
          break;
        case _UVRSD_UINT64: {
          uint64_t tmp = *(uint64_t*)valuep;
          memcpy(&value, &tmp, sizeof(tmp));
          break;
        }
        case _UVRSD_FLOAT: {
          float tmp = *(float*)valuep;
          memcpy(&value, &tmp, sizeof(tmp));
          break;
        }
        case _UVRSD_DOUBLE: {
          double tmp = *(double*)valuep;
          memcpy(&value, &tmp, sizeof(tmp));
          break;
        }
        case _UVRSD_UINT32: {
          uint32_t tmp = *(uint32_t*)valuep;
          memcpy(&value, &tmp, sizeof(tmp));
          break;
        }
        default:
          _LIBUNWIND_ABORT("Invalid VFP data representation.");
      }
      return unw_set_fpreg(cursor, regno, value) == UNW_ESUCCESS ?
          _UVRSR_OK : _UVRSR_FAILED;
    }
  }
  return _UVRSR_NOT_IMPLEMENTED;
}
Esempio n. 8
0
static void WinContextToUnwindCursor(CONTEXT *winContext, unw_cursor_t *cursor)
{
#if defined(_AMD64_)
    unw_set_reg(cursor, UNW_REG_IP, winContext->Rip);
    unw_set_reg(cursor, UNW_REG_SP, winContext->Rsp);
    unw_set_reg(cursor, UNW_X86_64_RBP, winContext->Rbp);
    unw_set_reg(cursor, UNW_X86_64_RBX, winContext->Rbx);
    unw_set_reg(cursor, UNW_X86_64_R12, winContext->R12);
    unw_set_reg(cursor, UNW_X86_64_R13, winContext->R13);
    unw_set_reg(cursor, UNW_X86_64_R14, winContext->R14);
    unw_set_reg(cursor, UNW_X86_64_R15, winContext->R15);
#endif
}
Esempio n. 9
0
static int
unwind_and_resume (long iteration, int (*next_func[])())
{
  unw_context_t uc;
  unw_cursor_t c;
  unw_word_t ip;
  int i, ret;

  if (verbose)
    printf (" %s(iteration=%ld, next_func=%p)\n",
	    __FUNCTION__, iteration, next_func);

  unw_getcontext (&uc);
  if ((ret = unw_init_local (&c, &uc)) < 0)
    panic ("unw_init_local (ret=%d)", ret);

  for (i = 0; i < unwind_count; ++i)
    if ((ret = unw_step (&c)) < 0)
      panic ("unw_step (ret=%d)", ret);

  if (unw_get_reg (&c, UNW_REG_IP, &ip) < 0
      || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) &resumption_point_label) < 0
      || unw_set_reg (&c, UNW_REG_EH + 0, 0)	/* ret val */
      || unw_set_reg (&c, UNW_REG_EH + 1, ip))
    panic ("failed to redirect to resumption_point\n");

  if (verbose)
    {
      unw_word_t bsp;
      if (unw_get_reg (&c, UNW_IA64_BSP, &bsp) < 0)
	panic ("unw_get_reg() failed\n");
      printf ("  bsp=%lx, old ip=%lx, new ip=%p\n", bsp,
	      ip, &resumption_point_label);
    }

  ret = unw_resume (&c);
  panic ("unw_resume() returned (ret=%d)!!\n", ret);
  return 0;
}
Esempio n. 10
0
/// Scans unwind information to find the function that contains the
/// specified code address "pc".
_LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) {
  _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)\n", pc);
  // This is slow, but works.
  // We create an unwind cursor then alter the IP to be pc
  unw_cursor_t cursor;
  unw_context_t uc;
  unw_proc_info_t info;
  unw_getcontext(&uc);
  unw_init_local(&cursor, &uc);
  unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long) pc);
  if (unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS)
    return (void *)(long) info.start_ip;
  else
    return NULL;
}
Esempio n. 11
0
static void
restore_context (MonoContext *ctx)
{
	int res;
	unw_word_t ip;

	res = unw_get_reg (&ctx->cursor, UNW_IA64_IP, &ip);
	g_assert (res == 0);

	/* Set this to 0 to tell OP_START_HANDLER that it doesn't have to set the frame pointer */
	res = unw_set_reg (&ctx->cursor, UNW_IA64_GR + 15, 0);
	g_assert (res == 0);

	unw_resume (&ctx->cursor);
}
Esempio n. 12
0
void unwindExc(Box* exc_obj) {
    unw_cursor_t cursor;
    unw_context_t uc;
    unw_word_t ip, sp;

    unw_getcontext(&uc);
    unw_init_local(&cursor, &uc);

    int code;
    unw_proc_info_t pip;

    while (unw_step(&cursor) > 0) {
        unw_get_reg(&cursor, UNW_REG_IP, &ip);
        unw_get_reg(&cursor, UNW_REG_SP, &sp);
        printf("ip = %lx, sp = %lx\n", (long)ip, (long)sp);

        code = unw_get_proc_info(&cursor, &pip);
        RELEASE_ASSERT(code == 0, "");

        // printf("%lx %lx %lx %lx %lx %lx %d %d %p\n", pip.start_ip, pip.end_ip, pip.lsda, pip.handler, pip.gp,
        // pip.flags, pip.format, pip.unwind_info_size, pip.unwind_info);

        assert((pip.lsda == 0) == (pip.handler == 0));
        assert(pip.flags == 0);

        if (pip.handler == 0) {
            if (VERBOSITY())
                printf("Skipping frame without handler\n");

            continue;
        }

        printf("%lx %lx %lx\n", pip.lsda, pip.handler, pip.flags);
        // assert(pip.handler == (uintptr_t)__gxx_personality_v0 || pip.handler == (uintptr_t)__py_personality_v0);

        // auto handler_fn = (int (*)(int, int, uint64_t, void*, void*))pip.handler;
        ////handler_fn(1, 1 /* _UA_SEARCH_PHASE */, 0 /* exc_class */, NULL, NULL);
        // handler_fn(2, 2 /* _UA_SEARCH_PHASE */, 0 /* exc_class */, NULL, NULL);
        unw_set_reg(&cursor, UNW_REG_IP, 1);

        // TODO testing:
        // unw_resume(&cursor);
    }

    abort();
}
Esempio n. 13
0
/// Find dwarf unwind info for an address 'pc' in some function.
_LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *pc,
                                               struct dwarf_eh_bases *bases) {
  // This is slow, but works.
  // We create an unwind cursor then alter the IP to be pc
  unw_cursor_t cursor;
  unw_context_t uc;
  unw_proc_info_t info;
  unw_getcontext(&uc);
  unw_init_local(&cursor, &uc);
  unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long) pc);
  unw_get_proc_info(&cursor, &info);
  bases->tbase = (uintptr_t)info.extra;
  bases->dbase = 0; // dbase not used on Mac OS X
  bases->func = (uintptr_t)info.start_ip;
  _LIBUNWIND_TRACE_API("_Unwind_Find_FDE(pc=%p) => %p\n", pc,
                  (void *)(long) info.unwind_info);
  return (void *)(long) info.unwind_info;
}
Esempio n. 14
0
static void
sighandler (int signal)
{
  unw_cursor_t cursor, cursor2;
  unw_word_t ip;
  unw_context_t uc;

  if (verbose)
    printf ("caught signal %d\n", signal);

  unw_getcontext (&uc);
  if (unw_init_local (&cursor, &uc) < 0)
    panic ("unw_init() failed!\n");

  /* get cursor for caller of sighandler: */
  if (unw_step (&cursor) < 0)
    panic ("unw_step() failed!\n");

  cursor2 = cursor;
  while (!unw_is_signal_frame (&cursor2))
    if (unw_step (&cursor2) < 0)
      panic ("failed to find signal frame!\n");

  if (unw_step (&cursor2) < 0)
    panic ("unw_step() failed!\n");

  if (unw_get_reg (&cursor2, UNW_REG_IP, &ip) < 0)
    panic ("failed to get IP!\n");

  /* skip faulting instruction (doesn't handle MLX template) */
  ++ip;
  if ((ip & 0x3) == 0x3)
    ip += 13;

  if (unw_set_reg (&cursor2, UNW_REG_IP, ip) < 0)
    panic ("failed to set IP!\n");

  unw_resume (&cursor);	/* update context & return to caller of sighandler() */

  panic ("unexpected return from unw_resume()!\n");
}
Esempio n. 15
0
static _Unwind_Reason_Code
unwind_phase2(unw_context_t *uc, struct _Unwind_Exception *exception_object, bool resume) {
  // See comment at the start of unwind_phase1 regarding VRS integrity.
  unw_cursor_t cursor2;
  unw_init_local(&cursor2, uc);

  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object);
  int frame_count = 0;

  // Walk each frame until we reach where search phase said to stop.
  while (true) {
    // Ask libuwind to get next frame (skip over first which is
    // _Unwind_RaiseException or _Unwind_Resume).
    //
    // Resume only ever makes sense for 1 frame.
    _Unwind_State state =
        resume ? _US_UNWIND_FRAME_RESUME : _US_UNWIND_FRAME_STARTING;
    if (resume && frame_count == 1) {
      // On a resume, first unwind the _Unwind_Resume() frame. The next frame
      // is now the landing pad for the cleanup from a previous execution of
      // phase2. To continue unwindingly correctly, replace VRS[15] with the
      // IP of the frame that the previous run of phase2 installed the context
      // for. After this, continue unwinding as if normal.
      //
      // See #7.4.6 for details.
      unw_set_reg(&cursor2, UNW_REG_IP, exception_object->unwinder_cache.reserved2);
      resume = false;
    }
    int stepResult = unw_step(&cursor2);
    if (stepResult == 0) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
                            "bottom => _URC_END_OF_STACK\n",
                            exception_object);
      return _URC_END_OF_STACK;
    } else if (stepResult < 0) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => "
                            "_URC_FATAL_PHASE1_ERROR\n",
                            exception_object);
      return _URC_FATAL_PHASE2_ERROR;
    }

    // Get info about this frame.
    unw_word_t sp;
    unw_proc_info_t frameInfo;
    unw_get_reg(&cursor2, UNW_REG_SP, &sp);
    if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
                            "failed => _URC_FATAL_PHASE1_ERROR\n",
                            exception_object);
      return _URC_FATAL_PHASE2_ERROR;
    }

    // When tracing, print state information.
    if (_LIBUNWIND_TRACING_UNWINDING) {
      char functionName[512];
      unw_word_t offset;
      if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) !=
           UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip))
        strcpy(functionName, ".anonymous.");
      _LIBUNWIND_TRACE_UNWINDING(
          "unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, "
          "lsda=0x%llX, personality=0x%llX\n",
          exception_object, frameInfo.start_ip, functionName, sp,
          frameInfo.lsda, frameInfo.handler);
    }

    // If there is a personality routine, tell it we are unwinding.
    if (frameInfo.handler != 0) {
      __personality_routine p =
          (__personality_routine)(long)(frameInfo.handler);
      struct _Unwind_Context *context = (struct _Unwind_Context *)(&cursor2);
#ifdef __arm__
      exception_object->pr_cache.fnstart = frameInfo.start_ip;
      exception_object->pr_cache.ehtp = (_Unwind_EHT_Header *)frameInfo.unwind_info;
      exception_object->pr_cache.additional = frameInfo.flags;
      _Unwind_Reason_Code personalityResult =
          (*p)(state, exception_object, context);
#else
      _Unwind_Action action = _UA_CLEANUP_PHASE;
      if (sp == exception_object->private_2) {
        // Tell personality this was the frame it marked in phase 1.
        action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
      }
       _Unwind_Reason_Code personalityResult =
          (*p)(1, action, exception_object->exception_class, exception_object,
               context);
#endif
      switch (personalityResult) {
      case _URC_CONTINUE_UNWIND:
        // Continue unwinding
        _LIBUNWIND_TRACE_UNWINDING(
            "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
            exception_object);
#ifdef __arm__
        if (sp == exception_object->barrier_cache.sp) {
#else
        if (sp == exception_object->private_2) {
#endif
          // Phase 1 said we would stop at this frame, but we did not...
          _LIBUNWIND_ABORT("during phase1 personality function said it would "
                           "stop here, but now in phase2 it did not stop here");
        }
        break;
      case _URC_INSTALL_CONTEXT:
        _LIBUNWIND_TRACE_UNWINDING(
            "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n",
            exception_object);
        // Personality routine says to transfer control to landing pad.
        // We may get control back if landing pad calls _Unwind_Resume().
        if (_LIBUNWIND_TRACING_UNWINDING) {
          unw_word_t pc;
          unw_get_reg(&cursor2, UNW_REG_IP, &pc);
          unw_get_reg(&cursor2, UNW_REG_SP, &sp);
          _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering  "
                                     "user code with ip=0x%llX, sp=0x%llX\n",
                                    exception_object, pc, sp);
        }

#ifdef __arm__
        // #7.4.1 says we need to preserve pc for when _Unwind_Resume is called
        // back, to find this same frame.
        unw_word_t pc;
        unw_get_reg(&cursor2, UNW_REG_IP, &pc);
        exception_object->unwinder_cache.reserved2 = (uint32_t)pc;
#endif
        unw_resume(&cursor2);
        // unw_resume() only returns if there was an error.
        return _URC_FATAL_PHASE2_ERROR;
#ifdef __arm__
      // # 7.4.3
      case _URC_FAILURE:
        abort();
#endif
      default:
        // Personality routine returned an unknown result code.
        _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
                      personalityResult);
        return _URC_FATAL_PHASE2_ERROR;
      }
    }
    frame_count++;
  }

  // Clean up phase did not resume at the frame that the search phase
  // said it would...
  return _URC_FATAL_PHASE2_ERROR;
}

#ifndef __arm__
static _Unwind_Reason_Code
unwind_phase2_forced(unw_context_t *uc,
                     struct _Unwind_Exception *exception_object,
                     _Unwind_Stop_Fn stop, void *stop_parameter) {
  unw_cursor_t cursor2;
  unw_init_local(&cursor2, uc);

  // Walk each frame until we reach where search phase said to stop
  while (unw_step(&cursor2) > 0) {

    // Update info about this frame.
    unw_proc_info_t frameInfo;
    if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
                                 "failed => _URC_END_OF_STACK\n",
                                 exception_object);
      return _URC_FATAL_PHASE2_ERROR;
    }

    // When tracing, print state information.
    if (_LIBUNWIND_TRACING_UNWINDING) {
      char functionName[512];
      unw_word_t offset;
      if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) !=
           UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip))
        strcpy(functionName, ".anonymous.");
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p):  "
                                 "start_ip=0x%llX, func=%s, lsda=0x%llX, "
                                 " personality=0x%llX\n",
                                 exception_object, frameInfo.start_ip,
                                 functionName, frameInfo.lsda,
                                 frameInfo.handler);
    }

    // Call stop function at each frame.
    _Unwind_Action action =
        (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
    _Unwind_Reason_Code stopResult =
        (*stop)(1, action, exception_object->exception_class, exception_object,
                (struct _Unwind_Context *)(&cursor2), stop_parameter);
    _LIBUNWIND_TRACE_UNWINDING(
        "unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n",
        exception_object, stopResult);
    if (stopResult != _URC_NO_REASON) {
      _LIBUNWIND_TRACE_UNWINDING(
          "unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n",
          exception_object);
      return _URC_FATAL_PHASE2_ERROR;
    }

    // If there is a personality routine, tell it we are unwinding.
    if (frameInfo.handler != 0) {
      __personality_routine p =
          (__personality_routine)(long)(frameInfo.handler);
      _LIBUNWIND_TRACE_UNWINDING(
          "unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n",
          exception_object, p);
      _Unwind_Reason_Code personalityResult =
          (*p)(1, action, exception_object->exception_class, exception_object,
               (struct _Unwind_Context *)(&cursor2));
      switch (personalityResult) {
      case _URC_CONTINUE_UNWIND:
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
                                "personality  returned _URC_CONTINUE_UNWIND\n",
                                 exception_object);
        // Destructors called, continue unwinding
        break;
      case _URC_INSTALL_CONTEXT:
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
                                  "personality returned _URC_INSTALL_CONTEXT\n",
                                   exception_object);
        // We may get control back if landing pad calls _Unwind_Resume().
        unw_resume(&cursor2);
        break;
      default:
        // Personality routine returned an unknown result code.
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
                                   "personality returned %d, "
                                   "_URC_FATAL_PHASE2_ERROR\n",
                                   exception_object, personalityResult);
        return _URC_FATAL_PHASE2_ERROR;
      }
    }
  }

  // Call stop function one last time and tell it we've reached the end
  // of the stack.
  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
                        "function with _UA_END_OF_STACK\n",
                        exception_object);
  _Unwind_Action lastAction =
      (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
  (*stop)(1, lastAction, exception_object->exception_class, exception_object,
          (struct _Unwind_Context *)(&cursor2), stop_parameter);

  // Clean up phase did not resume at the frame that the search phase said it
  // would.
  return _URC_FATAL_PHASE2_ERROR;
}
Esempio n. 16
0
static void WinContextToUnwindCursor(CONTEXT *winContext, unw_cursor_t *cursor)
{
#if defined(_AMD64_)
    unw_set_reg(cursor, UNW_REG_IP, winContext->Rip);
    unw_set_reg(cursor, UNW_REG_SP, winContext->Rsp);
    unw_set_reg(cursor, UNW_X86_64_RBP, winContext->Rbp);
    unw_set_reg(cursor, UNW_X86_64_RBX, winContext->Rbx);
    unw_set_reg(cursor, UNW_X86_64_R12, winContext->R12);
    unw_set_reg(cursor, UNW_X86_64_R13, winContext->R13);
    unw_set_reg(cursor, UNW_X86_64_R14, winContext->R14);
    unw_set_reg(cursor, UNW_X86_64_R15, winContext->R15);
#elif defined(_ARM_)
    unw_set_reg(cursor, UNW_ARM_R13, winContext->Sp);
    unw_set_reg(cursor, UNW_ARM_R14, winContext->Lr);
    unw_set_reg(cursor, UNW_ARM_R15, winContext->Pc);
    unw_set_reg(cursor, UNW_ARM_R4, winContext->R4);
    unw_set_reg(cursor, UNW_ARM_R5, winContext->R5);
    unw_set_reg(cursor, UNW_ARM_R6, winContext->R6);
    unw_set_reg(cursor, UNW_ARM_R7, winContext->R7);
    unw_set_reg(cursor, UNW_ARM_R8, winContext->R8);
    unw_set_reg(cursor, UNW_ARM_R9, winContext->R9);
    unw_set_reg(cursor, UNW_ARM_R10, winContext->R10);
    unw_set_reg(cursor, UNW_ARM_R11, winContext->R11);
#endif
}
Esempio n. 17
0
PROTECTED void
_Unwind_SetIP (struct _Unwind_Context *context, unsigned long new_value)
{
  unw_set_reg (&context->cursor, UNW_REG_IP, new_value);
}
Esempio n. 18
0
int
backtrace(void **trace, int size)
{
    unw_cursor_t cursor; unw_context_t uc;
    unw_word_t ip;
    int n = 0;

    unw_getcontext(&uc);
    unw_init_local(&cursor, &uc);
    while (unw_step(&cursor) > 0) {
	unw_get_reg(&cursor, UNW_REG_IP, &ip);
	trace[n++] = (void *)ip;
	{
	    char buf[256];
	    unw_get_proc_name(&cursor, buf, 256, &ip);
	    if (strncmp("_sigtramp", buf, sizeof("_sigtramp")) == 0) {
		goto darwin_sigtramp;
	    }
	}
    }
    return n;
darwin_sigtramp:
    /* darwin's bundled libunwind doesn't support signal trampoline */
    {
	ucontext_t *uctx;
	/* get _sigtramp's ucontext_t and set values to cursor
	 * http://www.opensource.apple.com/source/Libc/Libc-825.25/i386/sys/_sigtramp.s
	 * http://www.opensource.apple.com/source/libunwind/libunwind-35.1/src/unw_getcontext.s
	 */
	unw_get_reg(&cursor, UNW_X86_64_RBX, &ip);
	uctx = (ucontext_t *)ip;
	unw_set_reg(&cursor, UNW_X86_64_RAX, uctx->uc_mcontext->__ss.__rax);
	unw_set_reg(&cursor, UNW_X86_64_RBX, uctx->uc_mcontext->__ss.__rbx);
	unw_set_reg(&cursor, UNW_X86_64_RCX, uctx->uc_mcontext->__ss.__rcx);
	unw_set_reg(&cursor, UNW_X86_64_RDX, uctx->uc_mcontext->__ss.__rdx);
	unw_set_reg(&cursor, UNW_X86_64_RDI, uctx->uc_mcontext->__ss.__rdi);
	unw_set_reg(&cursor, UNW_X86_64_RSI, uctx->uc_mcontext->__ss.__rsi);
	unw_set_reg(&cursor, UNW_X86_64_RBP, uctx->uc_mcontext->__ss.__rbp);
	unw_set_reg(&cursor, UNW_X86_64_RSP, 8+(uctx->uc_mcontext->__ss.__rsp));
	unw_set_reg(&cursor, UNW_X86_64_R8,  uctx->uc_mcontext->__ss.__r8);
	unw_set_reg(&cursor, UNW_X86_64_R9,  uctx->uc_mcontext->__ss.__r9);
	unw_set_reg(&cursor, UNW_X86_64_R10, uctx->uc_mcontext->__ss.__r10);
	unw_set_reg(&cursor, UNW_X86_64_R11, uctx->uc_mcontext->__ss.__r11);
	unw_set_reg(&cursor, UNW_X86_64_R12, uctx->uc_mcontext->__ss.__r12);
	unw_set_reg(&cursor, UNW_X86_64_R13, uctx->uc_mcontext->__ss.__r13);
	unw_set_reg(&cursor, UNW_X86_64_R14, uctx->uc_mcontext->__ss.__r14);
	unw_set_reg(&cursor, UNW_X86_64_R15, uctx->uc_mcontext->__ss.__r15);
	ip = uctx->uc_mcontext->__ss.__rip;
	if (((char*)ip)[-2] == 0x0f && ((char*)ip)[-1] == 5) {
	    /* signal received in syscall */
	    trace[n++] = (void *)ip;
	    ip = *(unw_word_t*)uctx->uc_mcontext->__ss.__rsp;
	}
	trace[n++] = (void *)ip;
	unw_set_reg(&cursor, UNW_REG_IP, ip);
    }
    while (unw_step(&cursor) > 0) {
	unw_get_reg(&cursor, UNW_REG_IP, &ip);
	trace[n++] = (void *)ip;
    }
    return n;
}
Esempio n. 19
0
void
siglongjmp (sigjmp_buf env, int val)
{
  unw_word_t *wp = (unw_word_t *) env;
  extern int _UI_siglongjmp_cont;
  extern int _UI_longjmp_cont;
  unw_context_t uc;
  unw_cursor_t c;
  unw_word_t sp;
  int *cont;

  if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0)
    abort ();

  do
    {
      if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0)
	abort ();
#ifdef __FreeBSD__
      if (sp != wp[JB_SP] + sizeof(unw_word_t))
#else
      if (sp != wp[JB_SP])
#endif
	continue;

      if (!bsp_match (&c, wp))
	continue;

      /* found the right frame: */

      /* default to resuming without restoring signal-mask */
      cont = &_UI_longjmp_cont;

      /* Order of evaluation is important here: if unw_resume()
	 restores signal mask, we must set it up appropriately, even
	 if wp[JB_MASK_SAVED] is FALSE.  */
      if (!resume_restores_sigmask (&c, wp) && wp[JB_MASK_SAVED])
	{
	  /* sigmask was saved */
	  if (UNW_NUM_EH_REGS < 4 || _NSIG >= 16 * sizeof (unw_word_t))
	    /* signal mask doesn't fit into EH arguments and we can't
	       put it on the stack without overwriting something
	       else... */
	    abort ();
	  else
	    if (unw_set_reg (&c, UNW_REG_EH + 2, wp[JB_MASK]) < 0
		|| (_NSIG > 8 * sizeof (unw_word_t)
		    && unw_set_reg (&c, UNW_REG_EH + 3, wp[JB_MASK + 1]) < 0))
	      abort ();
	  cont = &_UI_siglongjmp_cont;
	}

      if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0
	  || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0
	  || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) cont))
	abort ();

      unw_resume (&c);

      abort ();
    }
  while (unw_step (&c) > 0);

  abort ();
}
Esempio n. 20
0
bool SetFrameRegisterCallback::execute_real()
{
  ret = unw_set_reg(cp_, reg_, val_);
  return true;
}
Esempio n. 21
0
//
// Called by personality handler during phase 2 to alter register values
//
EXPORT void _Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t new_value)
{
	DEBUG_PRINT_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0llX)\n", context, index, (uint64_t)new_value);
	unw_cursor_t* cursor = (unw_cursor_t*)context;
	unw_set_reg(cursor, index, new_value);
}