Import LLVM libunwind snapshot revision 272680

Significant upstream revisions:

260595: [AArch64] Fix libunwind build when using GNU assembler
270692: Introduce a native-only unwinder build.
270972: Disable cross-unwinding by default.
271004: [libunwind] Improve unwinder stack usage - II
272680: [libunwind] Improve unwinder stack usage - III

Obtained from:	https://llvm.org/svn/llvm-project/libunwind/trunk/
This commit is contained in:
Ed Maste 2016-07-05 18:00:23 +00:00
parent ca83053650
commit e2fc5d984d
12 changed files with 242 additions and 176 deletions

View file

@ -17,4 +17,43 @@
#define _LIBUNWIND_ARM_EHABI 0
#endif
#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
# if defined(__i386__)
# define _LIBUNWIND_TARGET_I386 1
# define _LIBUNWIND_CONTEXT_SIZE 8
# define _LIBUNWIND_CURSOR_SIZE 19
# elif defined(__x86_64__)
# define _LIBUNWIND_TARGET_X86_64 1
# define _LIBUNWIND_CONTEXT_SIZE 21
# define _LIBUNWIND_CURSOR_SIZE 33
# elif defined(__ppc__)
# define _LIBUNWIND_TARGET_PPC 1
# define _LIBUNWIND_CONTEXT_SIZE 117
# define _LIBUNWIND_CURSOR_SIZE 128
# elif defined(__aarch64__)
# define _LIBUNWIND_TARGET_AARCH64 1
# define _LIBUNWIND_CONTEXT_SIZE 66
# define _LIBUNWIND_CURSOR_SIZE 78
# elif defined(__arm__)
# define _LIBUNWIND_TARGET_ARM 1
# define _LIBUNWIND_CONTEXT_SIZE 60
# define _LIBUNWIND_CURSOR_SIZE 67
# elif defined(__or1k__)
# define _LIBUNWIND_TARGET_OR1K 1
# define _LIBUNWIND_CONTEXT_SIZE 16
# define _LIBUNWIND_CURSOR_SIZE 28
# else
# error "Unsupported architecture."
# endif
#else // !_LIBUNWIND_IS_NATIVE_ONLY
# define _LIBUNWIND_TARGET_I386 1
# define _LIBUNWIND_TARGET_X86_64 1
# define _LIBUNWIND_TARGET_PPC 1
# define _LIBUNWIND_TARGET_AARCH64 1
# define _LIBUNWIND_TARGET_ARM 1
# define _LIBUNWIND_TARGET_OR1K 1
# define _LIBUNWIND_CONTEXT_SIZE 128
# define _LIBUNWIND_CURSOR_SIZE 140
#endif // _LIBUNWIND_IS_NATIVE_ONLY
#endif // ____LIBUNWIND_CONFIG_H__

View file

@ -46,12 +46,12 @@ enum {
};
struct unw_context_t {
uint64_t data[128];
uint64_t data[_LIBUNWIND_CONTEXT_SIZE];
};
typedef struct unw_context_t unw_context_t;
struct unw_cursor_t {
uint64_t data[140];
uint64_t data[_LIBUNWIND_CURSOR_SIZE];
};
typedef struct unw_cursor_t unw_cursor_t;

View file

@ -35,7 +35,7 @@ namespace libunwind {
#include "Registers.hpp"
#if _LIBUNWIND_ARM_EHABI
#if defined(__FreeBSD__)
#if defined(__FreeBSD__) || defined(__NetBSD__)
typedef void *_Unwind_Ptr;
@ -61,7 +61,8 @@ extern EHTEntry __exidx_end;
#endif // !defined(_LIBUNWIND_IS_BAREMETAL)
#endif // _LIBUNWIND_ARM_EHABI
#if defined(__CloudABI__) || defined(__FreeBSD__) || defined(__linux__)
#if defined(__CloudABI__) || defined(__FreeBSD__) || defined(__linux__) || \
defined(__NetBSD__)
#if _LIBUNWIND_SUPPORT_DWARF_UNWIND && _LIBUNWIND_SUPPORT_DWARF_INDEX
#include <link.h>
// Macro for machine-independent access to the ELF program headers. This

View file

@ -27,6 +27,7 @@
namespace libunwind {
#if defined(_LIBUNWIND_TARGET_I386)
/// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka
/// unwind) by modifying a Registers_x86 register set
template <typename A>
@ -255,8 +256,10 @@ void CompactUnwinder_x86<A>::framelessUnwind(
// old esp is before return address
registers.setSP((uint32_t)returnAddressLocation + 4);
}
#endif // _LIBUNWIND_TARGET_I386
#if defined(_LIBUNWIND_TARGET_X86_64)
/// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka
/// unwind) by modifying a Registers_x86_64 register set
template <typename A>
@ -484,9 +487,11 @@ void CompactUnwinder_x86_64<A>::framelessUnwind(A &addressSpace,
// old esp is before return address
registers.setSP(returnAddressLocation + 8);
}
#endif // _LIBUNWIND_TARGET_X86_64
#if defined(_LIBUNWIND_TARGET_AARCH64)
/// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka
/// unwind) by modifying a Registers_arm64 register set
template <typename A>
@ -686,6 +691,7 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(
return UNW_STEP_SUCCESS;
}
#endif // _LIBUNWIND_TARGET_AARCH64
} // namespace libunwind

View file

@ -25,6 +25,7 @@ namespace libunwind {
struct v128 { uint32_t vec[4]; };
#if defined(_LIBUNWIND_TARGET_I386)
/// Registers_x86 holds the register state of a thread in a 32-bit intel
/// process.
class _LIBUNWIND_HIDDEN Registers_x86 {
@ -86,8 +87,8 @@ private:
};
inline Registers_x86::Registers_x86(const void *registers) {
static_assert(sizeof(Registers_x86) < sizeof(unw_context_t),
"x86 registers do not fit into unw_context_t");
static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),
"x86 registers do not fit into unw_context_t");
memcpy(&_registers, registers, sizeof(_registers));
}
@ -211,8 +212,10 @@ inline v128 Registers_x86::getVectorRegister(int) const {
inline void Registers_x86::setVectorRegister(int, v128) {
_LIBUNWIND_ABORT("no x86 vector registers");
}
#endif // _LIBUNWIND_TARGET_I386
#if defined(_LIBUNWIND_TARGET_X86_64)
/// Registers_x86_64 holds the register state of a thread in a 64-bit intel
/// process.
class _LIBUNWIND_HIDDEN Registers_x86_64 {
@ -278,8 +281,8 @@ private:
};
inline Registers_x86_64::Registers_x86_64(const void *registers) {
static_assert(sizeof(Registers_x86_64) < sizeof(unw_context_t),
"x86_64 registers do not fit into unw_context_t");
static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),
"x86_64 registers do not fit into unw_context_t");
memcpy(&_registers, registers, sizeof(_registers));
}
@ -459,8 +462,10 @@ inline v128 Registers_x86_64::getVectorRegister(int) const {
inline void Registers_x86_64::setVectorRegister(int, v128) {
_LIBUNWIND_ABORT("no x86_64 vector registers");
}
#endif // _LIBUNWIND_TARGET_X86_64
#if defined(_LIBUNWIND_TARGET_PPC)
/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
/// process.
class _LIBUNWIND_HIDDEN Registers_ppc {
@ -543,8 +548,8 @@ private:
};
inline Registers_ppc::Registers_ppc(const void *registers) {
static_assert(sizeof(Registers_ppc) < sizeof(unw_context_t),
"ppc registers do not fit into unw_context_t");
static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),
"ppc registers do not fit into unw_context_t");
memcpy(&_registers, static_cast<const uint8_t *>(registers),
sizeof(_registers));
static_assert(sizeof(ppc_thread_state_t) == 160,
@ -1023,8 +1028,10 @@ inline const char *Registers_ppc::getRegisterName(int regNum) {
}
}
#endif // _LIBUNWIND_TARGET_PPC
#if defined(_LIBUNWIND_TARGET_AARCH64)
/// Registers_arm64 holds the register state of a thread in a 64-bit arm
/// process.
class _LIBUNWIND_HIDDEN Registers_arm64 {
@ -1071,8 +1078,8 @@ private:
};
inline Registers_arm64::Registers_arm64(const void *registers) {
static_assert(sizeof(Registers_arm64) < sizeof(unw_context_t),
"arm64 registers do not fit into unw_context_t");
static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
"arm64 registers do not fit into unw_context_t");
memcpy(&_registers, registers, sizeof(_registers));
static_assert(sizeof(GPRs) == 0x110,
"expected VFP registers to be at offset 272");
@ -1289,7 +1296,9 @@ inline v128 Registers_arm64::getVectorRegister(int) const {
inline void Registers_arm64::setVectorRegister(int, v128) {
_LIBUNWIND_ABORT("no arm64 vector register support yet");
}
#endif // _LIBUNWIND_TARGET_AARCH64
#if defined(_LIBUNWIND_TARGET_ARM)
/// Registers_arm holds the register state of a thread in a 32-bit arm
/// process.
///
@ -1395,8 +1404,8 @@ inline Registers_arm::Registers_arm(const void *registers)
_saved_vfp_d16_d31(false),
_saved_iwmmx(false),
_saved_iwmmx_control(false) {
static_assert(sizeof(Registers_arm) < sizeof(unw_context_t),
"arm registers do not fit into unw_context_t");
static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
"arm registers do not fit into unw_context_t");
// See unw_getcontext() note about data.
memcpy(&_registers, registers, sizeof(_registers));
memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
@ -1711,6 +1720,10 @@ inline v128 Registers_arm::getVectorRegister(int) const {
inline void Registers_arm::setVectorRegister(int, v128) {
_LIBUNWIND_ABORT("ARM vector support not implemented");
}
#endif // _LIBUNWIND_TARGET_ARM
#if defined(_LIBUNWIND_TARGET_OR1K)
/// Registers_or1k holds the register state of a thread in an OpenRISC1000
/// process.
class _LIBUNWIND_HIDDEN Registers_or1k {
@ -1745,8 +1758,8 @@ private:
};
inline Registers_or1k::Registers_or1k(const void *registers) {
static_assert(sizeof(Registers_or1k) < sizeof(unw_context_t),
"or1k registers do not fit into unw_context_t");
static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
"or1k registers do not fit into unw_context_t");
memcpy(&_registers, static_cast<const uint8_t *>(registers),
sizeof(_registers));
}
@ -1893,6 +1906,7 @@ inline const char *Registers_or1k::getRegisterName(int regNum) {
}
}
#endif // _LIBUNWIND_TARGET_OR1K
} // namespace libunwind
#endif // __REGISTERS_HPP__

View file

@ -438,39 +438,21 @@ extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr2(
}
static _Unwind_Reason_Code
unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
// EHABI #7.3 discusses preserving the VRS in a "temporary VRS" during
// phase 1 and then restoring it to the "primary VRS" for phase 2. The
// effect is phase 2 doesn't see any of the VRS manipulations from phase 1.
// In this implementation, the phases don't share the VRS backing store.
// Instead, they are passed the original |uc| and they create a new VRS
// from scratch thus achieving the same effect.
unw_cursor_t cursor1;
unw_init_local(&cursor1, uc);
unw_init_local(cursor, uc);
// Walk each frame looking for a place to stop.
for (bool handlerNotFound = true; handlerNotFound;) {
#if !_LIBUNWIND_ARM_EHABI
// Ask libuwind to get next frame (skip over first which is
// _Unwind_RaiseException).
int stepResult = unw_step(&cursor1);
if (stepResult == 0) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
"bottom => _URC_END_OF_STACK\n",
static_cast<void *>(exception_object));
return _URC_END_OF_STACK;
} else if (stepResult < 0) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => "
"_URC_FATAL_PHASE1_ERROR\n",
static_cast<void *>(exception_object));
return _URC_FATAL_PHASE1_ERROR;
}
#endif
// See if frame has code to run (has personality routine).
unw_proc_info_t frameInfo;
if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) {
if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
"failed => _URC_FATAL_PHASE1_ERROR\n",
static_cast<void *>(exception_object));
@ -482,12 +464,12 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((unw_get_proc_name(&cursor1, functionBuf, sizeof(functionBuf),
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
unw_word_t pc;
unw_get_reg(&cursor1, UNW_REG_IP, &pc);
unw_get_reg(cursor, UNW_REG_IP, &pc);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, "
"lsda=0x%llX, personality=0x%llX\n",
@ -505,7 +487,7 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
"unwind_phase1(ex_ojb=%p): calling personality function %p\n",
static_cast<void *>(exception_object),
reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p)));
struct _Unwind_Context *context = (struct _Unwind_Context *)(&cursor1);
struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);
exception_object->pr_cache.fnstart = frameInfo.start_ip;
exception_object->pr_cache.ehtp =
(_Unwind_EHT_Header *)frameInfo.unwind_info;
@ -553,12 +535,11 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
return _URC_NO_REASON;
}
static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
_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);
unw_init_local(cursor, uc);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n",
static_cast<void *>(exception_object));
@ -580,31 +561,16 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
// for. After this, continue unwinding as if normal.
//
// See #7.4.6 for details.
unw_set_reg(&cursor2, UNW_REG_IP,
unw_set_reg(cursor, UNW_REG_IP,
exception_object->unwinder_cache.reserved2);
resume = false;
}
#if !_LIBUNWIND_ARM_EHABI
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",
static_cast<void *>(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",
static_cast<void *>(exception_object));
return _URC_FATAL_PHASE2_ERROR;
}
#endif
// 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) {
unw_get_reg(cursor, UNW_REG_SP, &sp);
if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
"failed => _URC_FATAL_PHASE1_ERROR\n",
static_cast<void *>(exception_object));
@ -616,7 +582,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
@ -632,7 +598,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
if (frameInfo.handler != 0) {
__personality_routine p =
(__personality_routine)(long)(frameInfo.handler);
struct _Unwind_Context *context = (struct _Unwind_Context *)(&cursor2);
struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);
// EHABI #7.2
exception_object->pr_cache.fnstart = frameInfo.start_ip;
exception_object->pr_cache.ehtp =
@ -661,8 +627,8 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
// 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);
unw_get_reg(cursor, UNW_REG_IP, &pc);
unw_get_reg(cursor, UNW_REG_SP, &sp);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
"user code with ip=0x%llX, sp=0x%llX\n",
static_cast<void *>(exception_object),
@ -673,10 +639,10 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
// EHABI #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);
unw_get_reg(cursor, UNW_REG_IP, &pc);
exception_object->unwinder_cache.reserved2 = (uint32_t)pc;
}
unw_resume(&cursor2);
unw_resume(cursor);
// unw_resume() only returns if there was an error.
return _URC_FATAL_PHASE2_ERROR;
@ -705,6 +671,7 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n",
static_cast<void *>(exception_object));
unw_context_t uc;
unw_cursor_t cursor;
unw_getcontext(&uc);
// This field for is for compatibility with GCC to say this isn't a forced
@ -712,12 +679,12 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
exception_object->unwinder_cache.reserved1 = 0;
// phase 1: the search phase
_Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object);
_Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);
if (phase1 != _URC_NO_REASON)
return phase1;
// phase 2: the clean up phase
return unwind_phase2(&uc, exception_object, false);
return unwind_phase2(&uc, &cursor, exception_object, false);
}
_LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) {
@ -742,12 +709,13 @@ _Unwind_Resume(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n",
static_cast<void *>(exception_object));
unw_context_t uc;
unw_cursor_t cursor;
unw_getcontext(&uc);
// _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
// which is in the same position as private_1 below.
// TODO(ajwong): Who wronte the above? Why is it true?
unwind_phase2(&uc, exception_object, true);
unwind_phase2(&uc, &cursor, exception_object, true);
// Clients assume _Unwind_Resume() does not return, so all we can do is abort.
_LIBUNWIND_ABORT("_Unwind_Resume() can't return");

View file

@ -481,30 +481,39 @@ private:
return stepWithCompactEncoding(dummy);
}
#if defined(_LIBUNWIND_TARGET_X86_64)
int stepWithCompactEncoding(Registers_x86_64 &) {
return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
_info.format, _info.start_ip, _addressSpace, _registers);
}
#endif
#if defined(_LIBUNWIND_TARGET_I386)
int stepWithCompactEncoding(Registers_x86 &) {
return CompactUnwinder_x86<A>::stepWithCompactEncoding(
_info.format, (uint32_t)_info.start_ip, _addressSpace, _registers);
}
#endif
#if defined(_LIBUNWIND_TARGET_PPC)
int stepWithCompactEncoding(Registers_ppc &) {
return UNW_EINVAL;
}
#endif
#if defined(_LIBUNWIND_TARGET_AARCH64)
int stepWithCompactEncoding(Registers_arm64 &) {
return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
_info.format, _info.start_ip, _addressSpace, _registers);
}
#endif
bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
R dummy;
return compactSaysUseDwarf(dummy, offset);
}
#if defined(_LIBUNWIND_TARGET_X86_64)
bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const {
if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) {
if (offset)
@ -513,7 +522,9 @@ private:
}
return false;
}
#endif
#if defined(_LIBUNWIND_TARGET_I386)
bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const {
if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) {
if (offset)
@ -522,11 +533,15 @@ private:
}
return false;
}
#endif
#if defined(_LIBUNWIND_TARGET_PPC)
bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const {
return true;
}
#endif
#if defined(_LIBUNWIND_TARGET_AARCH64)
bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const {
if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) {
if (offset)
@ -535,6 +550,7 @@ private:
}
return false;
}
#endif
#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
@ -543,25 +559,35 @@ private:
return dwarfEncoding(dummy);
}
#if defined(_LIBUNWIND_TARGET_X86_64)
compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const {
return UNWIND_X86_64_MODE_DWARF;
}
#endif
#if defined(_LIBUNWIND_TARGET_I386)
compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const {
return UNWIND_X86_MODE_DWARF;
}
#endif
#if defined(_LIBUNWIND_TARGET_PPC)
compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const {
return 0;
}
#endif
#if defined(_LIBUNWIND_TARGET_AARCH64)
compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
return UNWIND_ARM64_MODE_DWARF;
}
#endif
#if defined (_LIBUNWIND_TARGET_OR1K)
compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const {
return 0;
}
#endif
#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
@ -577,7 +603,7 @@ template <typename A, typename R>
UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
: _addressSpace(as), _registers(context), _unwindInfoMissing(false),
_isSignalFrame(false) {
static_assert(sizeof(UnwindCursor<A, R>) < sizeof(unw_cursor_t),
static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
"UnwindCursor<> does not fit in unw_cursor_t");
memset(&_info, 0, sizeof(_info));
}

View file

@ -33,16 +33,15 @@
#if !_LIBUNWIND_ARM_EHABI
static _Unwind_Reason_Code
unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
unw_cursor_t cursor1;
unw_init_local(&cursor1, uc);
unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
unw_init_local(cursor, uc);
// Walk each frame looking for a place to stop.
bool handlerNotFound = true;
while (handlerNotFound) {
// Ask libuwind to get next frame (skip over first which is
// _Unwind_RaiseException).
int stepResult = unw_step(&cursor1);
int stepResult = unw_step(cursor);
if (stepResult == 0) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
"bottom => _URC_END_OF_STACK\n",
@ -58,7 +57,7 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
// See if frame has code to run (has personality routine).
unw_proc_info_t frameInfo;
unw_word_t sp;
if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) {
if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
"failed => _URC_FATAL_PHASE1_ERROR\n",
(void *)exception_object);
@ -70,12 +69,12 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((unw_get_proc_name(&cursor1, functionBuf, sizeof(functionBuf),
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
unw_word_t pc;
unw_get_reg(&cursor1, UNW_REG_IP, &pc);
unw_get_reg(cursor, UNW_REG_IP, &pc);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): pc=0x%" PRIx64 ", start_ip=0x%" PRIx64
", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n",
@ -93,13 +92,13 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
(void *)exception_object, (void *)(uintptr_t)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
exception_object, (struct _Unwind_Context *)(&cursor1));
exception_object, (struct _Unwind_Context *)(cursor));
switch (personalityResult) {
case _URC_HANDLER_FOUND:
// found a catch clause or locals that need destructing in this frame
// stop search and remember stack pointer at the frame
handlerNotFound = false;
unw_get_reg(&cursor1, UNW_REG_SP, &sp);
unw_get_reg(cursor, UNW_REG_SP, &sp);
exception_object->private_2 = (uintptr_t)sp;
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n",
@ -127,9 +126,8 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
static _Unwind_Reason_Code
unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
unw_cursor_t cursor2;
unw_init_local(&cursor2, uc);
unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
unw_init_local(cursor, uc);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n",
(void *)exception_object);
@ -139,7 +137,7 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
// Ask libuwind to get next frame (skip over first which is
// _Unwind_RaiseException).
int stepResult = unw_step(&cursor2);
int stepResult = unw_step(cursor);
if (stepResult == 0) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
"bottom => _URC_END_OF_STACK\n",
@ -155,8 +153,8 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
// 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) {
unw_get_reg(cursor, UNW_REG_SP, &sp);
if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
"failed => _URC_FATAL_PHASE1_ERROR\n",
(void *)exception_object);
@ -168,7 +166,7 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
@ -191,7 +189,7 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
}
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(&cursor2));
(struct _Unwind_Context *)(cursor));
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
// Continue unwinding
@ -212,14 +210,14 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
// 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);
unw_get_reg(cursor, UNW_REG_IP, &pc);
unw_get_reg(cursor, UNW_REG_SP, &sp);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
"user code with ip=0x%" PRIx64
", sp=0x%" PRIx64 "\n",
(void *)exception_object, pc, sp);
}
unw_resume(&cursor2);
unw_resume(cursor);
// unw_resume() only returns if there was an error.
return _URC_FATAL_PHASE2_ERROR;
default:
@ -237,18 +235,17 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
}
static _Unwind_Reason_Code
unwind_phase2_forced(unw_context_t *uc,
unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
_Unwind_Exception *exception_object,
_Unwind_Stop_Fn stop, void *stop_parameter) {
unw_cursor_t cursor2;
unw_init_local(&cursor2, uc);
unw_init_local(cursor, uc);
// Walk each frame until we reach where search phase said to stop
while (unw_step(&cursor2) > 0) {
while (unw_step(cursor) > 0) {
// Update info about this frame.
unw_proc_info_t frameInfo;
if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
"failed => _URC_END_OF_STACK\n",
(void *)exception_object);
@ -260,7 +257,7 @@ unwind_phase2_forced(unw_context_t *uc,
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
@ -276,7 +273,7 @@ unwind_phase2_forced(unw_context_t *uc,
(_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);
(struct _Unwind_Context *)(cursor), stop_parameter);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n",
(void *)exception_object, stopResult);
@ -296,7 +293,7 @@ unwind_phase2_forced(unw_context_t *uc,
(void *)exception_object, (void *)(uintptr_t)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(&cursor2));
(struct _Unwind_Context *)(cursor));
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
@ -311,7 +308,7 @@ unwind_phase2_forced(unw_context_t *uc,
"_URC_INSTALL_CONTEXT\n",
(void *)exception_object);
// We may get control back if landing pad calls _Unwind_Resume().
unw_resume(&cursor2);
unw_resume(cursor);
break;
default:
// Personality routine returned an unknown result code.
@ -332,7 +329,7 @@ unwind_phase2_forced(unw_context_t *uc,
_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);
(struct _Unwind_Context *)(cursor), stop_parameter);
// Clean up phase did not resume at the frame that the search phase said it
// would.
@ -346,6 +343,7 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n",
(void *)exception_object);
unw_context_t uc;
unw_cursor_t cursor;
unw_getcontext(&uc);
// Mark that this is a non-forced unwind, so _Unwind_Resume()
@ -354,12 +352,12 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
exception_object->private_2 = 0;
// phase 1: the search phase
_Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object);
_Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);
if (phase1 != _URC_NO_REASON)
return phase1;
// phase 2: the clean up phase
return unwind_phase2(&uc, exception_object);
return unwind_phase2(&uc, &cursor, exception_object);
}
@ -379,14 +377,15 @@ _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_cursor_t cursor;
unw_getcontext(&uc);
if (exception_object->private_1 != 0)
unwind_phase2_forced(&uc, exception_object,
unwind_phase2_forced(&uc, &cursor, exception_object,
(_Unwind_Stop_Fn) exception_object->private_1,
(void *)exception_object->private_2);
else
unwind_phase2(&uc, exception_object);
unwind_phase2(&uc, &cursor, exception_object);
// Clients assume _Unwind_Resume() does not return, so all we can do is abort.
_LIBUNWIND_ABORT("_Unwind_Resume() can't return");
@ -403,6 +402,7 @@ _Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
_LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n",
(void *)exception_object, (void *)(uintptr_t)stop);
unw_context_t uc;
unw_cursor_t cursor;
unw_getcontext(&uc);
// Mark that this is a forced unwind, so _Unwind_Resume() can do
@ -411,7 +411,7 @@ _Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
exception_object->private_2 = (uintptr_t) stop_parameter;
// do it
return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);
return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter);
}

View file

@ -282,8 +282,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
ldp x22,x23, [x0, #0x0B0]
ldp x24,x25, [x0, #0x0C0]
ldp x26,x27, [x0, #0x0D0]
ldp x28,fp, [x0, #0x0E0]
ldr lr, [x0, #0x100] // restore pc into lr
ldp x28,x29, [x0, #0x0E0]
ldr x30, [x0, #0x100] // restore pc into lr
ldr x1, [x0, #0x0F8]
mov sp,x1 // restore sp
@ -306,7 +306,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
ldr d31, [x0, #0x208]
ldp x0, x1, [x0, #0x000] // restore x0,x1
ret lr // jump to pc
ret x30 // jump to pc
#elif defined(__arm__) && !defined(__APPLE__)

View file

@ -263,11 +263,11 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
stp x22,x23, [x0, #0x0B0]
stp x24,x25, [x0, #0x0C0]
stp x26,x27, [x0, #0x0D0]
stp x28,fp, [x0, #0x0E0]
str lr, [x0, #0x0F0]
stp x28,x29, [x0, #0x0E0]
str x30, [x0, #0x0F0]
mov x1,sp
str x1, [x0, #0x0F8]
str lr, [x0, #0x100] // store return address as pc
str x30, [x0, #0x100] // store return address as pc
// skip cpsr
stp d0, d1, [x0, #0x110]
stp d2, d3, [x0, #0x120]

View file

@ -16,6 +16,7 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
// Define static_assert() unless already defined by compiler.
#ifndef __has_feature
@ -29,28 +30,6 @@
// Platform specific configuration defines.
#ifdef __APPLE__
#include <Availability.h>
#ifdef __cplusplus
extern "C" {
#endif
void __assert_rtn(const char *, const char *, int, const char *)
__attribute__((noreturn));
#ifdef __cplusplus
}
#endif
#define _LIBUNWIND_BUILD_ZERO_COST_APIS (defined(__i386__) || \
defined(__x86_64__) || \
defined(__arm64__) || \
defined(__mips__))
#define _LIBUNWIND_BUILD_SJLJ_APIS defined(__arm__)
#define _LIBUNWIND_SUPPORT_FRAME_APIS (defined(__i386__) || \
defined(__x86_64__))
#define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
#define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
#define _LIBUNWIND_LOG(msg, ...) fprintf(stderr, "libuwind: " msg, __VA_ARGS__)
#define _LIBUNWIND_ABORT(msg) __assert_rtn(__func__, __FILE__, __LINE__, msg)
#if defined(FOR_DYLD)
#define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 0
@ -60,35 +39,51 @@
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
#define _LIBUNWIND_SUPPORT_DWARF_INDEX 0
#endif
#else
#include <stdlib.h>
static inline void assert_rtn(const char* func, const char* file, int line, const char* msg) __attribute__ ((noreturn));
static inline void assert_rtn(const char* func, const char* file, int line, const char* msg) {
fprintf(stderr, "libunwind: %s %s:%d - %s\n", func, file, line, msg);
assert(false);
abort();
}
#define _LIBUNWIND_BUILD_ZERO_COST_APIS (defined(__i386__) || \
defined(__x86_64__) || \
defined(__arm__) || \
defined(__aarch64__))
#define _LIBUNWIND_BUILD_SJLJ_APIS 0
#define _LIBUNWIND_SUPPORT_FRAME_APIS (defined(__i386__) || \
defined(__x86_64__))
#define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
#define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
#define _LIBUNWIND_LOG(msg, ...) fprintf(stderr, "libuwind: " msg, __VA_ARGS__)
#define _LIBUNWIND_ABORT(msg) assert_rtn(__func__, __FILE__, __LINE__, msg)
#define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND !defined(__arm__) || \
defined(__ARM_DWARF_EH__)
#define _LIBUNWIND_SUPPORT_DWARF_INDEX _LIBUNWIND_SUPPORT_DWARF_UNWIND
#if defined(__ARM_DWARF_EH__) || !defined(__arm__)
#define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
#define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
#else
#define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 0
#define _LIBUNWIND_SUPPORT_DWARF_INDEX 0
#endif
#endif
// FIXME: these macros are not correct for COFF targets
#define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
#define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
#if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__)
#define _LIBUNWIND_BUILD_SJLJ_APIS 1
#else
#define _LIBUNWIND_BUILD_SJLJ_APIS 0
#endif
#if defined(__i386__) || defined(__x86_64__)
#define _LIBUNWIND_SUPPORT_FRAME_APIS 1
#else
#define _LIBUNWIND_SUPPORT_FRAME_APIS 0
#endif
#if defined(__i386__) || defined(__x86_64__) || \
(!defined(__APPLE__) && defined(__arm__)) || \
(defined(__arm64__) || defined(__aarch64__)) || \
(defined(__APPLE__) && defined(__mips__))
#define _LIBUNWIND_BUILD_ZERO_COST_APIS 1
#else
#define _LIBUNWIND_BUILD_ZERO_COST_APIS 0
#endif
#define _LIBUNWIND_ABORT(msg) \
do { \
fprintf(stderr, "libunwind: %s %s:%d - %s\n", __func__, __FILE__, \
__LINE__, msg); \
fflush(stderr); \
abort(); \
} while (0)
#define _LIBUNWIND_LOG(msg, ...) fprintf(stderr, "libuwind: " msg, __VA_ARGS__)
// Macros that define away in non-Debug builds
#ifdef NDEBUG
@ -124,5 +119,25 @@
#define _LIBUNWIND_TRACING_UNWINDING logUnwinding()
#endif
#ifdef __cplusplus
// Used to fit UnwindCursor and Registers_xxx types against unw_context_t /
// unw_cursor_t sized memory blocks.
#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
# define COMP_OP ==
#else
# define COMP_OP <
#endif
template <typename _Type, typename _Mem>
struct check_fit {
template <typename T>
struct blk_count {
static const size_t count =
(sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
};
static const bool does_fit =
(blk_count<_Type>::count COMP_OP blk_count<_Mem>::count);
};
#undef COMP_OP
#endif // __cplusplus
#endif // LIBUNWIND_CONFIG_H

View file

@ -45,30 +45,27 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
_LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)\n",
static_cast<void *>(cursor),
static_cast<void *>(context));
// Use "placement new" to allocate UnwindCursor in the cursor buffer.
#if defined(__i386__)
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86>(
context, LocalAddressSpace::sThisAddressSpace);
# define REGISTER_KIND Registers_x86
#elif defined(__x86_64__)
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86_64>(
context, LocalAddressSpace::sThisAddressSpace);
# define REGISTER_KIND Registers_x86_64
#elif defined(__ppc__)
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_ppc>(
context, LocalAddressSpace::sThisAddressSpace);
#elif defined(__arm64__) || defined(__aarch64__)
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm64>(
context, LocalAddressSpace::sThisAddressSpace);
# define REGISTER_KIND Registers_ppc
#elif defined(__aarch64__)
# define REGISTER_KIND Registers_arm64
#elif _LIBUNWIND_ARM_EHABI
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm>(
context, LocalAddressSpace::sThisAddressSpace);
# define REGISTER_KIND Registers_arm
#elif defined(__or1k__)
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_or1k>(
context, LocalAddressSpace::sThisAddressSpace);
# define REGISTER_KIND Registers_or1k
#elif defined(__mips__)
#warning The MIPS architecture is not supported.
# warning The MIPS architecture is not supported.
#else
#error Architecture not supported
# error Architecture not supported
#endif
// Use "placement new" to allocate UnwindCursor in the cursor buffer.
new ((void *)cursor) UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
context, LocalAddressSpace::sThisAddressSpace);
#undef REGISTER_KIND
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
co->setInfoBasedOnIPRegister();