1*0b57cec5SDimitry Andric //===------------------------------- unwind.h -----------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric // 8*0b57cec5SDimitry Andric // C++ ABI Level 1 ABI documented at: 9*0b57cec5SDimitry Andric // https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #ifndef __UNWIND_H__ 14*0b57cec5SDimitry Andric #define __UNWIND_H__ 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #include <__libunwind_config.h> 17*0b57cec5SDimitry Andric 18*0b57cec5SDimitry Andric #include <stdint.h> 19*0b57cec5SDimitry Andric #include <stddef.h> 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) && defined(_WIN32) 22*0b57cec5SDimitry Andric #include <windows.h> 23*0b57cec5SDimitry Andric #include <ntverp.h> 24*0b57cec5SDimitry Andric #endif 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andric #if defined(__APPLE__) 27*0b57cec5SDimitry Andric #define LIBUNWIND_UNAVAIL __attribute__ (( unavailable )) 28*0b57cec5SDimitry Andric #else 29*0b57cec5SDimitry Andric #define LIBUNWIND_UNAVAIL 30*0b57cec5SDimitry Andric #endif 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric typedef enum { 33*0b57cec5SDimitry Andric _URC_NO_REASON = 0, 34*0b57cec5SDimitry Andric _URC_OK = 0, 35*0b57cec5SDimitry Andric _URC_FOREIGN_EXCEPTION_CAUGHT = 1, 36*0b57cec5SDimitry Andric _URC_FATAL_PHASE2_ERROR = 2, 37*0b57cec5SDimitry Andric _URC_FATAL_PHASE1_ERROR = 3, 38*0b57cec5SDimitry Andric _URC_NORMAL_STOP = 4, 39*0b57cec5SDimitry Andric _URC_END_OF_STACK = 5, 40*0b57cec5SDimitry Andric _URC_HANDLER_FOUND = 6, 41*0b57cec5SDimitry Andric _URC_INSTALL_CONTEXT = 7, 42*0b57cec5SDimitry Andric _URC_CONTINUE_UNWIND = 8, 43*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_ARM_EHABI) 44*0b57cec5SDimitry Andric _URC_FAILURE = 9 45*0b57cec5SDimitry Andric #endif 46*0b57cec5SDimitry Andric } _Unwind_Reason_Code; 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric typedef enum { 49*0b57cec5SDimitry Andric _UA_SEARCH_PHASE = 1, 50*0b57cec5SDimitry Andric _UA_CLEANUP_PHASE = 2, 51*0b57cec5SDimitry Andric _UA_HANDLER_FRAME = 4, 52*0b57cec5SDimitry Andric _UA_FORCE_UNWIND = 8, 53*0b57cec5SDimitry Andric _UA_END_OF_STACK = 16 // gcc extension to C++ ABI 54*0b57cec5SDimitry Andric } _Unwind_Action; 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric typedef struct _Unwind_Context _Unwind_Context; // opaque 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_ARM_EHABI) 59*0b57cec5SDimitry Andric typedef uint32_t _Unwind_State; 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0; 62*0b57cec5SDimitry Andric static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1; 63*0b57cec5SDimitry Andric static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2; 64*0b57cec5SDimitry Andric static const _Unwind_State _US_ACTION_MASK = 3; 65*0b57cec5SDimitry Andric /* Undocumented flag for force unwinding. */ 66*0b57cec5SDimitry Andric static const _Unwind_State _US_FORCE_UNWIND = 8; 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric typedef uint32_t _Unwind_EHT_Header; 69*0b57cec5SDimitry Andric /* 70*0b57cec5SDimitry Andric * gcc_personality_v0 references 'struct _Unwind_Exception' all over the place. 71*0b57cec5SDimitry Andric * Nothing in libunwind cares about 'struct _Unwind_Control_Block,' so make it 72*0b57cec5SDimitry Andric * the alias of struct _Unwind_Exception, instead of the other way around. 73*0b57cec5SDimitry Andric */ 74*0b57cec5SDimitry Andric struct _Unwind_Exception; 75*0b57cec5SDimitry Andric typedef struct _Unwind_Exception _Unwind_Exception; 76*0b57cec5SDimitry Andric typedef struct _Unwind_Exception _Unwind_Control_Block; /* Alias */ 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric struct _Unwind_Exception { 79*0b57cec5SDimitry Andric uint64_t exception_class; 80*0b57cec5SDimitry Andric void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*); 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric /* Unwinder cache, private fields for the unwinder's use */ 83*0b57cec5SDimitry Andric struct { 84*0b57cec5SDimitry Andric uint32_t reserved1; /* init reserved1 to 0, then don't touch */ 85*0b57cec5SDimitry Andric uint32_t reserved2; 86*0b57cec5SDimitry Andric uint32_t reserved3; 87*0b57cec5SDimitry Andric uint32_t reserved4; 88*0b57cec5SDimitry Andric uint32_t reserved5; 89*0b57cec5SDimitry Andric } unwinder_cache; 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric /* Propagation barrier cache (valid after phase 1): */ 92*0b57cec5SDimitry Andric struct { 93*0b57cec5SDimitry Andric uint32_t sp; 94*0b57cec5SDimitry Andric uint32_t bitpattern[5]; 95*0b57cec5SDimitry Andric } barrier_cache; 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric /* Cleanup cache (preserved over cleanup): */ 98*0b57cec5SDimitry Andric struct { 99*0b57cec5SDimitry Andric uint32_t bitpattern[4]; 100*0b57cec5SDimitry Andric } cleanup_cache; 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric /* Pr cache (for pr's benefit): */ 103*0b57cec5SDimitry Andric struct { 104*0b57cec5SDimitry Andric uint32_t fnstart; /* function start address */ 105*0b57cec5SDimitry Andric _Unwind_EHT_Header* ehtp; /* pointer to EHT entry header word */ 106*0b57cec5SDimitry Andric uint32_t additional; 107*0b57cec5SDimitry Andric uint32_t reserved1; 108*0b57cec5SDimitry Andric } pr_cache; 109*0b57cec5SDimitry Andric 110*0b57cec5SDimitry Andric long long int :0; /* Enforce the 8-byte alignment */ 111*0b57cec5SDimitry Andric } __attribute__((__aligned__(8))); 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) 114*0b57cec5SDimitry Andric (_Unwind_State state, 115*0b57cec5SDimitry Andric _Unwind_Exception* exceptionObject, 116*0b57cec5SDimitry Andric struct _Unwind_Context* context); 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric typedef _Unwind_Reason_Code (*__personality_routine) 119*0b57cec5SDimitry Andric (_Unwind_State state, 120*0b57cec5SDimitry Andric _Unwind_Exception* exceptionObject, 121*0b57cec5SDimitry Andric struct _Unwind_Context* context); 122*0b57cec5SDimitry Andric #else 123*0b57cec5SDimitry Andric struct _Unwind_Context; // opaque 124*0b57cec5SDimitry Andric struct _Unwind_Exception; // forward declaration 125*0b57cec5SDimitry Andric typedef struct _Unwind_Exception _Unwind_Exception; 126*0b57cec5SDimitry Andric 127*0b57cec5SDimitry Andric struct _Unwind_Exception { 128*0b57cec5SDimitry Andric uint64_t exception_class; 129*0b57cec5SDimitry Andric void (*exception_cleanup)(_Unwind_Reason_Code reason, 130*0b57cec5SDimitry Andric _Unwind_Exception *exc); 131*0b57cec5SDimitry Andric #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) 132*0b57cec5SDimitry Andric uintptr_t private_[6]; 133*0b57cec5SDimitry Andric #else 134*0b57cec5SDimitry Andric uintptr_t private_1; // non-zero means forced unwind 135*0b57cec5SDimitry Andric uintptr_t private_2; // holds sp that phase1 found for phase2 to use 136*0b57cec5SDimitry Andric #endif 137*0b57cec5SDimitry Andric #if __SIZEOF_POINTER__ == 4 138*0b57cec5SDimitry Andric // The implementation of _Unwind_Exception uses an attribute mode on the 139*0b57cec5SDimitry Andric // above fields which has the side effect of causing this whole struct to 140*0b57cec5SDimitry Andric // round up to 32 bytes in size (48 with SEH). To be more explicit, we add 141*0b57cec5SDimitry Andric // pad fields added for binary compatibility. 142*0b57cec5SDimitry Andric uint32_t reserved[3]; 143*0b57cec5SDimitry Andric #endif 144*0b57cec5SDimitry Andric // The Itanium ABI requires that _Unwind_Exception objects are "double-word 145*0b57cec5SDimitry Andric // aligned". GCC has interpreted this to mean "use the maximum useful 146*0b57cec5SDimitry Andric // alignment for the target"; so do we. 147*0b57cec5SDimitry Andric } __attribute__((__aligned__)); 148*0b57cec5SDimitry Andric 149*0b57cec5SDimitry Andric typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) 150*0b57cec5SDimitry Andric (int version, 151*0b57cec5SDimitry Andric _Unwind_Action actions, 152*0b57cec5SDimitry Andric uint64_t exceptionClass, 153*0b57cec5SDimitry Andric _Unwind_Exception* exceptionObject, 154*0b57cec5SDimitry Andric struct _Unwind_Context* context, 155*0b57cec5SDimitry Andric void* stop_parameter ); 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric typedef _Unwind_Reason_Code (*__personality_routine) 158*0b57cec5SDimitry Andric (int version, 159*0b57cec5SDimitry Andric _Unwind_Action actions, 160*0b57cec5SDimitry Andric uint64_t exceptionClass, 161*0b57cec5SDimitry Andric _Unwind_Exception* exceptionObject, 162*0b57cec5SDimitry Andric struct _Unwind_Context* context); 163*0b57cec5SDimitry Andric #endif 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric #ifdef __cplusplus 166*0b57cec5SDimitry Andric extern "C" { 167*0b57cec5SDimitry Andric #endif 168*0b57cec5SDimitry Andric 169*0b57cec5SDimitry Andric // 170*0b57cec5SDimitry Andric // The following are the base functions documented by the C++ ABI 171*0b57cec5SDimitry Andric // 172*0b57cec5SDimitry Andric #ifdef __USING_SJLJ_EXCEPTIONS__ 173*0b57cec5SDimitry Andric extern _Unwind_Reason_Code 174*0b57cec5SDimitry Andric _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object); 175*0b57cec5SDimitry Andric extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object); 176*0b57cec5SDimitry Andric #else 177*0b57cec5SDimitry Andric extern _Unwind_Reason_Code 178*0b57cec5SDimitry Andric _Unwind_RaiseException(_Unwind_Exception *exception_object); 179*0b57cec5SDimitry Andric extern void _Unwind_Resume(_Unwind_Exception *exception_object); 180*0b57cec5SDimitry Andric #endif 181*0b57cec5SDimitry Andric extern void _Unwind_DeleteException(_Unwind_Exception *exception_object); 182*0b57cec5SDimitry Andric 183*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_ARM_EHABI) 184*0b57cec5SDimitry Andric typedef enum { 185*0b57cec5SDimitry Andric _UVRSC_CORE = 0, /* integer register */ 186*0b57cec5SDimitry Andric _UVRSC_VFP = 1, /* vfp */ 187*0b57cec5SDimitry Andric _UVRSC_WMMXD = 3, /* Intel WMMX data register */ 188*0b57cec5SDimitry Andric _UVRSC_WMMXC = 4 /* Intel WMMX control register */ 189*0b57cec5SDimitry Andric } _Unwind_VRS_RegClass; 190*0b57cec5SDimitry Andric 191*0b57cec5SDimitry Andric typedef enum { 192*0b57cec5SDimitry Andric _UVRSD_UINT32 = 0, 193*0b57cec5SDimitry Andric _UVRSD_VFPX = 1, 194*0b57cec5SDimitry Andric _UVRSD_UINT64 = 3, 195*0b57cec5SDimitry Andric _UVRSD_FLOAT = 4, 196*0b57cec5SDimitry Andric _UVRSD_DOUBLE = 5 197*0b57cec5SDimitry Andric } _Unwind_VRS_DataRepresentation; 198*0b57cec5SDimitry Andric 199*0b57cec5SDimitry Andric typedef enum { 200*0b57cec5SDimitry Andric _UVRSR_OK = 0, 201*0b57cec5SDimitry Andric _UVRSR_NOT_IMPLEMENTED = 1, 202*0b57cec5SDimitry Andric _UVRSR_FAILED = 2 203*0b57cec5SDimitry Andric } _Unwind_VRS_Result; 204*0b57cec5SDimitry Andric 205*0b57cec5SDimitry Andric extern void _Unwind_Complete(_Unwind_Exception* exception_object); 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric extern _Unwind_VRS_Result 208*0b57cec5SDimitry Andric _Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, 209*0b57cec5SDimitry Andric uint32_t regno, _Unwind_VRS_DataRepresentation representation, 210*0b57cec5SDimitry Andric void *valuep); 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric extern _Unwind_VRS_Result 213*0b57cec5SDimitry Andric _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, 214*0b57cec5SDimitry Andric uint32_t regno, _Unwind_VRS_DataRepresentation representation, 215*0b57cec5SDimitry Andric void *valuep); 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric extern _Unwind_VRS_Result 218*0b57cec5SDimitry Andric _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, 219*0b57cec5SDimitry Andric uint32_t discriminator, 220*0b57cec5SDimitry Andric _Unwind_VRS_DataRepresentation representation); 221*0b57cec5SDimitry Andric #endif 222*0b57cec5SDimitry Andric 223*0b57cec5SDimitry Andric #if !defined(_LIBUNWIND_ARM_EHABI) 224*0b57cec5SDimitry Andric 225*0b57cec5SDimitry Andric extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index); 226*0b57cec5SDimitry Andric extern void _Unwind_SetGR(struct _Unwind_Context *context, int index, 227*0b57cec5SDimitry Andric uintptr_t new_value); 228*0b57cec5SDimitry Andric extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context); 229*0b57cec5SDimitry Andric extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value); 230*0b57cec5SDimitry Andric 231*0b57cec5SDimitry Andric #else // defined(_LIBUNWIND_ARM_EHABI) 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE) 234*0b57cec5SDimitry Andric #define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern 235*0b57cec5SDimitry Andric #else 236*0b57cec5SDimitry Andric #define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__ 237*0b57cec5SDimitry Andric #endif 238*0b57cec5SDimitry Andric 239*0b57cec5SDimitry Andric // These are de facto helper functions for ARM, which delegate the function 240*0b57cec5SDimitry Andric // calls to _Unwind_VRS_Get/Set(). These are not a part of ARM EHABI 241*0b57cec5SDimitry Andric // specification, thus these function MUST be inlined. Please don't replace 242*0b57cec5SDimitry Andric // these with the "extern" function declaration; otherwise, the program 243*0b57cec5SDimitry Andric // including this <unwind.h> header won't be ABI compatible and will result in 244*0b57cec5SDimitry Andric // link error when we are linking the program with libgcc. 245*0b57cec5SDimitry Andric 246*0b57cec5SDimitry Andric _LIBUNWIND_EXPORT_UNWIND_LEVEL1 247*0b57cec5SDimitry Andric uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { 248*0b57cec5SDimitry Andric uintptr_t value = 0; 249*0b57cec5SDimitry Andric _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); 250*0b57cec5SDimitry Andric return value; 251*0b57cec5SDimitry Andric } 252*0b57cec5SDimitry Andric 253*0b57cec5SDimitry Andric _LIBUNWIND_EXPORT_UNWIND_LEVEL1 254*0b57cec5SDimitry Andric void _Unwind_SetGR(struct _Unwind_Context *context, int index, 255*0b57cec5SDimitry Andric uintptr_t value) { 256*0b57cec5SDimitry Andric _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); 257*0b57cec5SDimitry Andric } 258*0b57cec5SDimitry Andric 259*0b57cec5SDimitry Andric _LIBUNWIND_EXPORT_UNWIND_LEVEL1 260*0b57cec5SDimitry Andric uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { 261*0b57cec5SDimitry Andric // remove the thumb-bit before returning 262*0b57cec5SDimitry Andric return _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1); 263*0b57cec5SDimitry Andric } 264*0b57cec5SDimitry Andric 265*0b57cec5SDimitry Andric _LIBUNWIND_EXPORT_UNWIND_LEVEL1 266*0b57cec5SDimitry Andric void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) { 267*0b57cec5SDimitry Andric uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1); 268*0b57cec5SDimitry Andric _Unwind_SetGR(context, 15, value | thumb_bit); 269*0b57cec5SDimitry Andric } 270*0b57cec5SDimitry Andric #endif // defined(_LIBUNWIND_ARM_EHABI) 271*0b57cec5SDimitry Andric 272*0b57cec5SDimitry Andric extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context); 273*0b57cec5SDimitry Andric extern uintptr_t 274*0b57cec5SDimitry Andric _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context); 275*0b57cec5SDimitry Andric #ifdef __USING_SJLJ_EXCEPTIONS__ 276*0b57cec5SDimitry Andric extern _Unwind_Reason_Code 277*0b57cec5SDimitry Andric _Unwind_SjLj_ForcedUnwind(_Unwind_Exception *exception_object, 278*0b57cec5SDimitry Andric _Unwind_Stop_Fn stop, void *stop_parameter); 279*0b57cec5SDimitry Andric #else 280*0b57cec5SDimitry Andric extern _Unwind_Reason_Code 281*0b57cec5SDimitry Andric _Unwind_ForcedUnwind(_Unwind_Exception *exception_object, 282*0b57cec5SDimitry Andric _Unwind_Stop_Fn stop, void *stop_parameter); 283*0b57cec5SDimitry Andric #endif 284*0b57cec5SDimitry Andric 285*0b57cec5SDimitry Andric #ifdef __USING_SJLJ_EXCEPTIONS__ 286*0b57cec5SDimitry Andric typedef struct _Unwind_FunctionContext *_Unwind_FunctionContext_t; 287*0b57cec5SDimitry Andric extern void _Unwind_SjLj_Register(_Unwind_FunctionContext_t fc); 288*0b57cec5SDimitry Andric extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc); 289*0b57cec5SDimitry Andric #endif 290*0b57cec5SDimitry Andric 291*0b57cec5SDimitry Andric // 292*0b57cec5SDimitry Andric // The following are semi-suppoted extensions to the C++ ABI 293*0b57cec5SDimitry Andric // 294*0b57cec5SDimitry Andric 295*0b57cec5SDimitry Andric // 296*0b57cec5SDimitry Andric // called by __cxa_rethrow(). 297*0b57cec5SDimitry Andric // 298*0b57cec5SDimitry Andric #ifdef __USING_SJLJ_EXCEPTIONS__ 299*0b57cec5SDimitry Andric extern _Unwind_Reason_Code 300*0b57cec5SDimitry Andric _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception *exception_object); 301*0b57cec5SDimitry Andric #else 302*0b57cec5SDimitry Andric extern _Unwind_Reason_Code 303*0b57cec5SDimitry Andric _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object); 304*0b57cec5SDimitry Andric #endif 305*0b57cec5SDimitry Andric 306*0b57cec5SDimitry Andric // _Unwind_Backtrace() is a gcc extension that walks the stack and calls the 307*0b57cec5SDimitry Andric // _Unwind_Trace_Fn once per frame until it reaches the bottom of the stack 308*0b57cec5SDimitry Andric // or the _Unwind_Trace_Fn function returns something other than _URC_NO_REASON. 309*0b57cec5SDimitry Andric typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *, 310*0b57cec5SDimitry Andric void *); 311*0b57cec5SDimitry Andric extern _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void *); 312*0b57cec5SDimitry Andric 313*0b57cec5SDimitry Andric // _Unwind_GetCFA is a gcc extension that can be called from within a 314*0b57cec5SDimitry Andric // personality handler to get the CFA (stack pointer before call) of 315*0b57cec5SDimitry Andric // current frame. 316*0b57cec5SDimitry Andric extern uintptr_t _Unwind_GetCFA(struct _Unwind_Context *); 317*0b57cec5SDimitry Andric 318*0b57cec5SDimitry Andric 319*0b57cec5SDimitry Andric // _Unwind_GetIPInfo is a gcc extension that can be called from within a 320*0b57cec5SDimitry Andric // personality handler. Similar to _Unwind_GetIP() but also returns in 321*0b57cec5SDimitry Andric // *ipBefore a non-zero value if the instruction pointer is at or before the 322*0b57cec5SDimitry Andric // instruction causing the unwind. Normally, in a function call, the IP returned 323*0b57cec5SDimitry Andric // is the return address which is after the call instruction and may be past the 324*0b57cec5SDimitry Andric // end of the function containing the call instruction. 325*0b57cec5SDimitry Andric extern uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, 326*0b57cec5SDimitry Andric int *ipBefore); 327*0b57cec5SDimitry Andric 328*0b57cec5SDimitry Andric 329*0b57cec5SDimitry Andric // __register_frame() is used with dynamically generated code to register the 330*0b57cec5SDimitry Andric // FDE for a generated (JIT) code. The FDE must use pc-rel addressing to point 331*0b57cec5SDimitry Andric // to its function and optional LSDA. 332*0b57cec5SDimitry Andric // __register_frame() has existed in all versions of Mac OS X, but in 10.4 and 333*0b57cec5SDimitry Andric // 10.5 it was buggy and did not actually register the FDE with the unwinder. 334*0b57cec5SDimitry Andric // In 10.6 and later it does register properly. 335*0b57cec5SDimitry Andric extern void __register_frame(const void *fde); 336*0b57cec5SDimitry Andric extern void __deregister_frame(const void *fde); 337*0b57cec5SDimitry Andric 338*0b57cec5SDimitry Andric // _Unwind_Find_FDE() will locate the FDE if the pc is in some function that has 339*0b57cec5SDimitry Andric // an associated FDE. Note, Mac OS X 10.6 and later, introduces "compact unwind 340*0b57cec5SDimitry Andric // info" which the runtime uses in preference to DWARF unwind info. This 341*0b57cec5SDimitry Andric // function will only work if the target function has an FDE but no compact 342*0b57cec5SDimitry Andric // unwind info. 343*0b57cec5SDimitry Andric struct dwarf_eh_bases { 344*0b57cec5SDimitry Andric uintptr_t tbase; 345*0b57cec5SDimitry Andric uintptr_t dbase; 346*0b57cec5SDimitry Andric uintptr_t func; 347*0b57cec5SDimitry Andric }; 348*0b57cec5SDimitry Andric extern const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *); 349*0b57cec5SDimitry Andric 350*0b57cec5SDimitry Andric 351*0b57cec5SDimitry Andric // This function attempts to find the start (address of first instruction) of 352*0b57cec5SDimitry Andric // a function given an address inside the function. It only works if the 353*0b57cec5SDimitry Andric // function has an FDE (DWARF unwind info). 354*0b57cec5SDimitry Andric // This function is unimplemented on Mac OS X 10.6 and later. Instead, use 355*0b57cec5SDimitry Andric // _Unwind_Find_FDE() and look at the dwarf_eh_bases.func result. 356*0b57cec5SDimitry Andric extern void *_Unwind_FindEnclosingFunction(void *pc); 357*0b57cec5SDimitry Andric 358*0b57cec5SDimitry Andric // Mac OS X does not support text-rel and data-rel addressing so these functions 359*0b57cec5SDimitry Andric // are unimplemented 360*0b57cec5SDimitry Andric extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) 361*0b57cec5SDimitry Andric LIBUNWIND_UNAVAIL; 362*0b57cec5SDimitry Andric extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) 363*0b57cec5SDimitry Andric LIBUNWIND_UNAVAIL; 364*0b57cec5SDimitry Andric 365*0b57cec5SDimitry Andric // Mac OS X 10.4 and 10.5 had implementations of these functions in 366*0b57cec5SDimitry Andric // libgcc_s.dylib, but they never worked. 367*0b57cec5SDimitry Andric /// These functions are no longer available on Mac OS X. 368*0b57cec5SDimitry Andric extern void __register_frame_info_bases(const void *fde, void *ob, void *tb, 369*0b57cec5SDimitry Andric void *db) LIBUNWIND_UNAVAIL; 370*0b57cec5SDimitry Andric extern void __register_frame_info(const void *fde, void *ob) 371*0b57cec5SDimitry Andric LIBUNWIND_UNAVAIL; 372*0b57cec5SDimitry Andric extern void __register_frame_info_table_bases(const void *fde, void *ob, 373*0b57cec5SDimitry Andric void *tb, void *db) 374*0b57cec5SDimitry Andric LIBUNWIND_UNAVAIL; 375*0b57cec5SDimitry Andric extern void __register_frame_info_table(const void *fde, void *ob) 376*0b57cec5SDimitry Andric LIBUNWIND_UNAVAIL; 377*0b57cec5SDimitry Andric extern void __register_frame_table(const void *fde) 378*0b57cec5SDimitry Andric LIBUNWIND_UNAVAIL; 379*0b57cec5SDimitry Andric extern void *__deregister_frame_info(const void *fde) 380*0b57cec5SDimitry Andric LIBUNWIND_UNAVAIL; 381*0b57cec5SDimitry Andric extern void *__deregister_frame_info_bases(const void *fde) 382*0b57cec5SDimitry Andric LIBUNWIND_UNAVAIL; 383*0b57cec5SDimitry Andric 384*0b57cec5SDimitry Andric #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) 385*0b57cec5SDimitry Andric #ifndef _WIN32 386*0b57cec5SDimitry Andric typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD; 387*0b57cec5SDimitry Andric typedef struct _CONTEXT CONTEXT; 388*0b57cec5SDimitry Andric typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT; 389*0b57cec5SDimitry Andric #elif !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000 390*0b57cec5SDimitry Andric typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT; 391*0b57cec5SDimitry Andric #endif 392*0b57cec5SDimitry Andric // This is the common wrapper for GCC-style personality functions with SEH. 393*0b57cec5SDimitry Andric extern EXCEPTION_DISPOSITION _GCC_specific_handler(EXCEPTION_RECORD *exc, 394*0b57cec5SDimitry Andric void *frame, 395*0b57cec5SDimitry Andric CONTEXT *ctx, 396*0b57cec5SDimitry Andric DISPATCHER_CONTEXT *disp, 397*0b57cec5SDimitry Andric __personality_routine pers); 398*0b57cec5SDimitry Andric #endif 399*0b57cec5SDimitry Andric 400*0b57cec5SDimitry Andric #ifdef __cplusplus 401*0b57cec5SDimitry Andric } 402*0b57cec5SDimitry Andric #endif 403*0b57cec5SDimitry Andric 404*0b57cec5SDimitry Andric #endif // __UNWIND_H__ 405