#define LIBUNWIND_UNAVAIL
#endif
+// FIXME: This is also in cxxabi.h and libunwind.h, can we consolidate?
+#if !defined(__USING_SJLJ_EXCEPTIONS__) && defined(__arm__) && \
+ !defined(__ARM_DWARF_EH__) && !defined(__APPLE__)
+#define LIBCXXABI_ARM_EHABI 1
+#else
+#define LIBCXXABI_ARM_EHABI 0
+#endif
+
typedef enum {
_URC_NO_REASON = 0,
+ _URC_OK = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
_URC_FATAL_PHASE2_ERROR = 2,
_URC_FATAL_PHASE1_ERROR = 3,
_URC_END_OF_STACK = 5,
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
- _URC_CONTINUE_UNWIND = 8
+ _URC_CONTINUE_UNWIND = 8,
+#if LIBCXXABI_ARM_EHABI
+ _URC_FAILURE = 9
+#endif
} _Unwind_Reason_Code;
typedef enum {
_UA_END_OF_STACK = 16 // gcc extension to C++ ABI
} _Unwind_Action;
+typedef struct _Unwind_Context _Unwind_Context; // opaque
+
+#if LIBCXXABI_ARM_EHABI
+typedef uint32_t _Unwind_State;
+
+static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0;
+static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1;
+static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2;
+
+typedef uint32_t _Unwind_EHT_Header;
+
+struct _Unwind_Control_Block;
+typedef struct _Unwind_Control_Block _Unwind_Control_Block;
+typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */
+
+struct _Unwind_Control_Block {
+ uint64_t exception_class;
+ void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*);
+
+ /* Unwinder cache, private fields for the unwinder's use */
+ struct {
+ uint32_t reserved1; /* init reserved1 to 0, then don't touch */
+ uint32_t reserved2;
+ uint32_t reserved3;
+ uint32_t reserved4;
+ uint32_t reserved5;
+ } unwinder_cache;
+
+ /* Propagation barrier cache (valid after phase 1): */
+ struct {
+ uint32_t sp;
+ uint32_t bitpattern[5];
+ } barrier_cache;
+
+ /* Cleanup cache (preserved over cleanup): */
+ struct {
+ uint32_t bitpattern[4];
+ } cleanup_cache;
+
+ /* Pr cache (for pr's benefit): */
+ struct {
+ uint32_t fnstart; /* function start address */
+ _Unwind_EHT_Header* ehtp; /* pointer to EHT entry header word */
+ uint32_t additional;
+ uint32_t reserved1;
+ } pr_cache;
+
+ long long int :0; /* Enforce the 8-byte alignment */
+};
+
+typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
+ (_Unwind_State state,
+ _Unwind_Exception* exceptionObject,
+ struct _Unwind_Context* context);
+
+typedef _Unwind_Reason_Code (*__personality_routine)
+ (_Unwind_State state,
+ _Unwind_Exception* exceptionObject,
+ struct _Unwind_Context* context);
+#else
struct _Unwind_Context; // opaque
struct _Unwind_Exception; // forward declaration
+typedef struct _Unwind_Exception _Unwind_Exception;
struct _Unwind_Exception {
uint64_t exception_class;
void (*exception_cleanup)(_Unwind_Reason_Code reason,
- struct _Unwind_Exception *exc);
+ _Unwind_Exception *exc);
uintptr_t private_1; // non-zero means forced unwind
uintptr_t private_2; // holds sp that phase1 found for phase2 to use
#if !__LP64__
(int version,
_Unwind_Action actions,
uint64_t exceptionClass,
- struct _Unwind_Exception* exceptionObject,
+ _Unwind_Exception* exceptionObject,
struct _Unwind_Context* context,
void* stop_parameter );
(int version,
_Unwind_Action actions,
uint64_t exceptionClass,
- struct _Unwind_Exception* exceptionObject,
+ _Unwind_Exception* exceptionObject,
struct _Unwind_Context* context);
+#endif
#ifdef __cplusplus
extern "C" {
//
// The following are the base functions documented by the C++ ABI
//
-#if __arm__
+#if __USING_SJLJ_EXCEPTIONS__
extern _Unwind_Reason_Code
- _Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object);
-extern void _Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object);
+ _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object);
+extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object);
#else
extern _Unwind_Reason_Code
- _Unwind_RaiseException(struct _Unwind_Exception *exception_object);
-extern void _Unwind_Resume(struct _Unwind_Exception *exception_object);
+ _Unwind_RaiseException(_Unwind_Exception *exception_object);
+extern void _Unwind_Resume(_Unwind_Exception *exception_object);
#endif
-extern void _Unwind_DeleteException(struct _Unwind_Exception *exception_object);
+extern void _Unwind_DeleteException(_Unwind_Exception *exception_object);
+
+#if LIBCXXABI_ARM_EHABI
+typedef enum {
+ _UVRSC_CORE = 0, /* integer register */
+ _UVRSC_VFP = 1, /* vfp */
+ _UVRSC_WMMXD = 3, /* Intel WMMX data register */
+ _UVRSC_WMMXC = 4 /* Intel WMMX control register */
+} _Unwind_VRS_RegClass;
+
+typedef enum {
+ _UVRSD_UINT32 = 0,
+ _UVRSD_VFPX = 1,
+ _UVRSD_UINT64 = 3,
+ _UVRSD_FLOAT = 4,
+ _UVRSD_DOUBLE = 5
+} _Unwind_VRS_DataRepresentation;
+
+typedef enum {
+ _UVRSR_OK = 0,
+ _UVRSR_NOT_IMPLEMENTED = 1,
+ _UVRSR_FAILED = 2
+} _Unwind_VRS_Result;
+
+extern void _Unwind_Complete(_Unwind_Exception* exception_object);
+
+extern _Unwind_VRS_Result
+_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
+ uint32_t regno, _Unwind_VRS_DataRepresentation representation,
+ void *valuep);
+
+extern _Unwind_VRS_Result
+_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
+ uint32_t regno, _Unwind_VRS_DataRepresentation representation,
+ void *valuep);
+
+extern _Unwind_VRS_Result
+_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
+ uint32_t discriminator,
+ _Unwind_VRS_DataRepresentation representation);
+
+extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context,
+ uint32_t *data, size_t offset,
+ size_t len);
+
+static inline uintptr_t _Unwind_GetGR(struct _Unwind_Context* context,
+ int index) {
+ uintptr_t value = 0;
+ _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
+ return value;
+}
+
+static inline void _Unwind_SetGR(struct _Unwind_Context* context, int index,
+ uintptr_t new_value) {
+ _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index,
+ _UVRSD_UINT32, &new_value);
+}
+
+static inline uintptr_t _Unwind_GetIP(struct _Unwind_Context* context) {
+ // remove the thumb-bit before returning
+ return (_Unwind_GetGR(context, 15) & (~(uintptr_t)0x1));
+}
+
+static inline void _Unwind_SetIP(struct _Unwind_Context* context,
+ uintptr_t new_value) {
+ uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
+ _Unwind_SetGR(context, 15, new_value | thumb_bit);
+}
+#else
extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index);
extern void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t new_value);
extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context);
extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value);
+#endif
+
extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context);
extern uintptr_t
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context);
-#if __arm__
+#if __USING_SJLJ_EXCEPTIONS__
extern _Unwind_Reason_Code
- _Unwind_SjLj_ForcedUnwind(struct _Unwind_Exception *exception_object,
+ _Unwind_SjLj_ForcedUnwind(_Unwind_Exception *exception_object,
_Unwind_Stop_Fn stop, void *stop_parameter);
#else
extern _Unwind_Reason_Code
- _Unwind_ForcedUnwind(struct _Unwind_Exception *exception_object,
+ _Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
_Unwind_Stop_Fn stop, void *stop_parameter);
#endif
-#if __arm__
+#if __USING_SJLJ_EXCEPTIONS__
typedef struct _Unwind_FunctionContext *_Unwind_FunctionContext_t;
extern void _Unwind_SjLj_Register(_Unwind_FunctionContext_t fc);
extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc);
//
// called by __cxa_rethrow().
//
-#if __arm__
+#if __USING_SJLJ_EXCEPTIONS__
extern _Unwind_Reason_Code
- _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object);
+ _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception *exception_object);
#else
extern _Unwind_Reason_Code
- _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *exception_object);
+ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object);
#endif
// _Unwind_Backtrace() is a gcc extension that walks the stack and calls the
// _Unwind_GetIPInfo is a gcc extension that can be called from within a
-// personality handler. Similar to _Unwind_GetIP() but also returns in
-// *ipBefore a non-zero value if the instruction pointer is at or before the
-// instruction causing the unwind. Normally, in a function call, the IP returned
+// personality handler. Similar to _Unwind_GetIP() but also returns in
+// *ipBefore a non-zero value if the instruction pointer is at or before the
+// instruction causing the unwind. Normally, in a function call, the IP returned
// is the return address which is after the call instruction and may be past the
// end of the function containing the call instruction.
extern uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,