Beispiel #1
0
///  Called by __cxa_rethrow().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
#if LIBCXXABI_ARM_EHABI
  _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), "
                       "private_1=%ld\n",
                       exception_object,
                       (long)exception_object->unwinder_cache.reserved1);
#else
  _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), "
                       "private_1=%ld\n",
                       exception_object,
                       (long)exception_object->private_1);
#endif

#if LIBCXXABI_ARM_EHABI
  // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
  // which is in the same position as private_1 below.
  return _Unwind_RaiseException(exception_object);
#else
  // If this is non-forced and a stopping place was found, then this is a
  // re-throw.
  // Call _Unwind_RaiseException() as if this was a new exception
  if (exception_object->private_1 == 0) {
    return _Unwind_RaiseException(exception_object);
    // Will return if there is no catch clause, so that __cxa_rethrow can call
    // std::terminate().
  }

  // Call through to _Unwind_Resume() which distiguishes between forced and
  // regular exceptions.
  _Unwind_Resume(exception_object);
  _LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()"
                   " which unexpectedly returned");
#endif
}
Beispiel #2
0
_Unwind_VRS_Result _Unwind_VRS_Get(
    _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, *((uint32_t*)valuep));
  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_get_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;
      if (unw_get_fpreg(cursor, regno, &value) != UNW_ESUCCESS)
        return _UVRSR_FAILED;
      switch (representation) {
        case _UVRSD_VFPX:
          // TODO(ajwong): What does this mean?
          break;
        case _UVRSD_UINT64: {
          uint64_t tmp;
          memcpy(&tmp, &value, sizeof(tmp));
          *(uint64_t*)valuep = tmp;
          break;
        }
        case _UVRSD_FLOAT: {
          float tmp;
          memcpy(&tmp, &value, sizeof(tmp));
          *(float*)valuep = tmp;
          break;
        }
        case _UVRSD_DOUBLE: {
          double tmp;
          memcpy(&tmp, &value, sizeof(tmp));
          *(double*)valuep = tmp;
          break;
        }
        case _UVRSD_UINT32: {
          uint32_t tmp;
          memcpy(&tmp, &value, sizeof(tmp));
          *(uint32_t*)valuep = tmp;
          break;
        }
        default:
          _LIBUNWIND_ABORT("Invalid VFP data representation.");
      }
      return _UVRSR_OK;
    }
  }
  return _UVRSR_NOT_IMPLEMENTED;
}
Beispiel #3
0
/// Called by personality handler during phase 2 to get register values.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
                                          int index) {
  _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)\n",
                             context, index);
  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
  return ufc->resumeParameters[index];
}
Beispiel #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 new_value) {
  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)\n"
                            , context, index, new_value);
  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
  ufc->resumeParameters[index] = new_value;
}
Beispiel #5
0
/// Called by personality handler during phase 2 to alter instruction pointer.
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
                                     uintptr_t new_value) {
  _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0lX)\n",
                             context, new_value);
  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
  ufc->resumeLocation = new_value - 1;
}
Beispiel #6
0
/// Called by personality handler during phase 2 to find the start of the
/// function.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
  // Not supported or needed for sjlj based unwinding
  (void)context;
  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)\n", context);
  return 0;
}
Beispiel #7
0
/// Called by personality handler during phase 2 to get base address for text
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
  // Not supported or needed for sjlj based unwinding
  (void)context;
  _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)\n", context);
  _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
}
Beispiel #8
0
/// Called by personality handler during phase 2 to get LSDA for current frame.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
  _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) "
                             "=> 0x%0lX\n",  context, ufc->lsda);
  return ufc->lsda;
}
Beispiel #9
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);
}
Beispiel #10
0
/// Called by personality handler during phase 2 to get instruction pointer.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
  unw_cursor_t *cursor = (unw_cursor_t *)context;
  unw_word_t result;
  unw_get_reg(cursor, UNW_REG_IP, &result);
  _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%llX\n", context,
                             (uint64_t) result);
  return (uintptr_t)result;
}
Beispiel #11
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);
}
Beispiel #12
0
/// Called by personality handler during phase 2 to get instruction pointer.
/// ipBefore is a boolean that says if IP is already adjusted to be the call
/// site address.  Normally IP is the return address.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
                                              int *ipBefore) {
  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
  *ipBefore = 0;
  _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX\n",
                             context, ipBefore, ufc->resumeLocation + 1);
  return ufc->resumeLocation + 1;
}
Beispiel #13
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);
}
Beispiel #14
0
/// Called by personality handler during phase 2 if a foreign exception
/// is caught.
_LIBUNWIND_EXPORT void
_Unwind_DeleteException(struct _Unwind_Exception *exception_object) {
  _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n",
                              exception_object);
  if (exception_object->exception_cleanup != NULL)
    (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
                                           exception_object);
}
Beispiel #15
0
/// Called by personality handler during phase 2 to get register values.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetGR(struct _Unwind_Context *context, int index) {
  unw_cursor_t *cursor = (unw_cursor_t *)context;
  unw_word_t result;
  unw_get_reg(cursor, index, &result);
  _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64 "\n",
                       (void *)context, index, (uint64_t)result);
  return (uintptr_t)result;
}
Beispiel #16
0
_LIBUNWIND_EXPORT void __register_frame_info_bases(const void *fde, void *ob,
                                                   void *tb, void *db) {
  (void)fde;
  (void)ob;
  (void)tb;
  (void)db;
 _LIBUNWIND_TRACE_API("__register_frame_info_bases(%p,%p, %p, %p)\n",
                            fde, ob, tb, db);
  // do nothing, this function never worked in Mac OS X
}
Beispiel #17
0
/// Called by personality handler to get "Call Frame Area" for current frame.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
  _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)\n", context);
  if (context != NULL) {
    _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
    // Setjmp/longjmp based exceptions don't have a true CFA.
    // Instead, the SP in the jmpbuf is the closest approximation.
    return (uintptr_t) ufc->jbuf[2];
  }
  return 0;
}
Beispiel #18
0
/// Called by personality handler during phase 2 to find the start of the
/// function.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
  unw_cursor_t *cursor = (unw_cursor_t *)context;
  unw_proc_info_t frameInfo;
  uintptr_t result = 0;
  if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
    result = (uintptr_t)frameInfo.start_ip;
  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIXPTR "\n",
                             context, result);
  return result;
}
Beispiel #19
0
/// When _Unwind_RaiseException() is in phase2, it hands control
/// to the personality function at each frame.  The personality
/// may force a jump to a landing pad in that function, the landing
/// pad code may then call _Unwind_Resume() to continue with the
/// unwinding.  Note: the call to _Unwind_Resume() is from compiler
/// geneated user code.  All other _Unwind_* routines are called
/// by the C++ runtime __cxa_* routines.
///
/// Re-throwing an exception is implemented by having the code call
/// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
_LIBUNWIND_EXPORT void
_Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) {
  _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)\n", exception_object);

  if (exception_object->private_1 != 0)
    unwind_phase2_forced(exception_object,
                         (_Unwind_Stop_Fn) exception_object->private_1,
                         (void *)exception_object->private_2);
  else
    unwind_phase2(exception_object);

  // clients assume _Unwind_Resume() does not return, so all we can do is abort.
  _LIBUNWIND_ABORT("_Unwind_SjLj_Resume() can't return");
}
Beispiel #20
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;
}
Beispiel #21
0
/// Called by personality handler during phase 2 to get LSDA for current frame.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
  unw_cursor_t *cursor = (unw_cursor_t *)context;
  unw_proc_info_t frameInfo;
  uintptr_t result = 0;
  if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
    result = (uintptr_t)frameInfo.lsda;
  _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p)"
                             "=> 0x%" PRIXPTR "\n", context, result);
  if (result != 0) {
    if (*((uint8_t *)result) != 0xFF)
      _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIXPTR " does not start with 0xFF\n", result);
  }
  return result;
}
Beispiel #22
0
/// When _Unwind_RaiseException() is in phase2, it hands control
/// to the personality function at each frame.  The personality
/// may force a jump to a landing pad in that function, the landing
/// pad code may then call _Unwind_Resume() to continue with the
/// unwinding.  Note: the call to _Unwind_Resume() is from compiler
/// geneated user code.  All other _Unwind_* routines are called
/// by the C++ runtime __cxa_* routines.
///
/// Note: re-throwing an exception (as opposed to continuing the unwind)
/// is implemented by having the code call __cxa_rethrow() which
/// in turn calls _Unwind_Resume_or_Rethrow().
_LIBUNWIND_EXPORT void
_Unwind_Resume(_Unwind_Exception *exception_object) {
  _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", (void *)exception_object);
  unw_context_t uc;
  unw_getcontext(&uc);

  if (exception_object->private_1 != 0)
    unwind_phase2_forced(&uc, exception_object,
                         (_Unwind_Stop_Fn) exception_object->private_1,
                         (void *)exception_object->private_2);
  else
    unwind_phase2(&uc, exception_object);

  // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
  _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
}
Beispiel #23
0
/// Not used by C++.
/// Unwinds stack, calling "stop" function at each frame.
/// Could be used to implement longjmp().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_ForcedUnwind(struct _Unwind_Exception *exception_object,
                     _Unwind_Stop_Fn stop, void *stop_parameter) {
  _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n",
                  exception_object, stop);
  unw_context_t uc;
  unw_getcontext(&uc);

  // Mark that this is a forced unwind, so _Unwind_Resume() can do
  // the right thing.
  exception_object->private_1 = (uintptr_t) stop;
  exception_object->private_2 = (uintptr_t) stop_parameter;

  // do it
  return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);
}
Beispiel #24
0
/// Called by __cxa_throw.  Only returns if there is a fatal error
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) {
  _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)\n", exception_object);

  // mark that this is a non-forced unwind, so _Unwind_Resume() can do the right
  // thing
  exception_object->private_1 = 0;
  exception_object->private_2 = 0;

  // phase 1: the search phase
  _Unwind_Reason_Code phase1 = unwind_phase1(exception_object);
  if (phase1 != _URC_NO_REASON)
    return phase1;

  // phase 2: the clean up phase
  return unwind_phase2(exception_object);
}
Beispiel #25
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;
}
Beispiel #26
0
/// Called by __cxa_throw.  Only returns if there is a fatal error.
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_RaiseException(_Unwind_Exception *exception_object) {
    _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n",
                         exception_object);
    unw_context_t uc;
    unw_getcontext(&uc);

    // Mark that this is a non-forced unwind, so _Unwind_Resume()
    // can do the right thing.
    exception_object->private_1 = 0;
    exception_object->private_2 = 0;

    // phase 1: the search phase
    _Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object);
    if (phase1 != _URC_NO_REASON)
        return phase1;

    // phase 2: the clean up phase
    return unwind_phase2(&uc, exception_object);
}
Beispiel #27
0
/// When _Unwind_RaiseException() is in phase2, it hands control
/// to the personality function at each frame.  The personality
/// may force a jump to a landing pad in that function, the landing
/// pad code may then call _Unwind_Resume() to continue with the
/// unwinding.  Note: the call to _Unwind_Resume() is from compiler
/// geneated user code.  All other _Unwind_* routines are called
/// by the C++ runtime __cxa_* routines.
///
/// Note: re-throwing an exception (as opposed to continuing the unwind)
/// is implemented by having the code call __cxa_rethrow() which
/// in turn calls _Unwind_Resume_or_Rethrow().
_LIBUNWIND_EXPORT void
_Unwind_Resume(struct _Unwind_Exception *exception_object) {
  _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", exception_object);
  unw_context_t uc;
  unw_getcontext(&uc);

#ifdef __arm__
  // TODO(piman): Do we need a "force unwind" mechanism?
#else
  if (exception_object->private_1 != 0)
    unwind_phase2_forced(&uc, exception_object,
                         (_Unwind_Stop_Fn) exception_object->private_1,
                         (void *)exception_object->private_2);
  else
#endif
    unwind_phase2(&uc, exception_object, true);

  // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
  _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
}
Beispiel #28
0
///  Called by __cxa_rethrow().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) {
  _LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), "
                             "private_1=%ld\n",
                              exception_object, exception_object->private_1);
  // If this is non-forced and a stopping place was found, then this is a
  // re-throw.
  // Call _Unwind_RaiseException() as if this was a new exception.
  if (exception_object->private_1 == 0) {
    return _Unwind_SjLj_RaiseException(exception_object);
    // should return if there is no catch clause, so that __cxa_rethrow can call
    // std::terminate()
  }

  // Call through to _Unwind_Resume() which distiguishes between forced and
  // regular exceptions.
  _Unwind_SjLj_Resume(exception_object);
  _LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called "
                    "_Unwind_SjLj_Resume() which unexpectedly returned");
}
Beispiel #29
0
/// Called by personality handler during phase 2 to get base address for text
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
  (void)context;
  _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)\n", context);
  _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
}
Beispiel #30
0
/// Called by personality handler during phase 2 to get instruction pointer.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
  _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%lX\n", context,
                  ufc->resumeLocation + 1);
  return ufc->resumeLocation + 1;
}