1 /** 2 * ARM-specific unwind definitions. These are taken from the ARM EHABI 3 * specification. 4 */ 5 typedef enum 6 { 7 _URC_OK = 0, /* operation completed successfully */ 8 _URC_FOREIGN_EXCEPTION_CAUGHT = 1, 9 _URC_END_OF_STACK = 5, 10 _URC_HANDLER_FOUND = 6, 11 _URC_INSTALL_CONTEXT = 7, 12 _URC_CONTINUE_UNWIND = 8, 13 _URC_FAILURE = 9, /* unspecified failure of some kind */ 14 _URC_FATAL_PHASE1_ERROR = _URC_FAILURE 15 } _Unwind_Reason_Code; 16 17 typedef uint32_t _Unwind_State; 18 #ifdef __clang__ 19 static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0; 20 static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1; 21 static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2; 22 #else // GCC fails at knowing what a constant expression is 23 # define _US_VIRTUAL_UNWIND_FRAME 0 24 # define _US_UNWIND_FRAME_STARTING 1 25 # define _US_UNWIND_FRAME_RESUME 2 26 #endif 27 28 typedef struct _Unwind_Context _Unwind_Context; 29 30 typedef uint32_t _Unwind_EHT_Header; 31 32 struct _Unwind_Exception 33 { 34 uint64_t exception_class; 35 void (*exception_cleanup)(_Unwind_Reason_Code, struct _Unwind_Exception *); 36 /* Unwinder cache, private fields for the unwinder's use */ 37 struct 38 { 39 uint32_t reserved1; 40 uint32_t reserved2; 41 uint32_t reserved3; 42 uint32_t reserved4; 43 uint32_t reserved5; 44 /* init reserved1 to 0, then don't touch */ 45 } unwinder_cache; 46 /* Propagation barrier cache (valid after phase 1): */ 47 struct 48 { 49 uint32_t sp; 50 uint32_t bitpattern[5]; 51 } barrier_cache; 52 /* Cleanup cache (preserved over cleanup): */ 53 struct 54 { 55 uint32_t bitpattern[4]; 56 } cleanup_cache; 57 /* Pr cache (for pr's benefit): */ 58 struct 59 { 60 /** function start address */ 61 uint32_t fnstart; 62 /** pointer to EHT entry header word */ 63 _Unwind_EHT_Header *ehtp; 64 /** additional data */ 65 uint32_t additional; 66 uint32_t reserved1; 67 } pr_cache; 68 /** Force alignment of next item to 8-byte boundary */ 69 long long int :0; 70 }; 71 72 /* Unwinding functions */ 73 _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *ucbp); 74 void _Unwind_Resume(struct _Unwind_Exception *ucbp); 75 void _Unwind_Complete(struct _Unwind_Exception *ucbp); 76 void _Unwind_DeleteException(struct _Unwind_Exception *ucbp); 77 void *_Unwind_GetLanguageSpecificData(struct _Unwind_Context*); 78 79 typedef enum 80 { 81 _UVRSR_OK = 0, 82 _UVRSR_NOT_IMPLEMENTED = 1, 83 _UVRSR_FAILED = 2 84 } _Unwind_VRS_Result; 85 typedef enum 86 { 87 _UVRSC_CORE = 0, 88 _UVRSC_VFP = 1, 89 _UVRSC_WMMXD = 3, 90 _UVRSC_WMMXC = 4 91 } _Unwind_VRS_RegClass; 92 typedef enum 93 { 94 _UVRSD_UINT32 = 0, 95 _UVRSD_VFPX = 1, 96 _UVRSD_UINT64 = 3, 97 _UVRSD_FLOAT = 4, 98 _UVRSD_DOUBLE = 5 99 } _Unwind_VRS_DataRepresentation; 100 101 _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *context, 102 _Unwind_VRS_RegClass regclass, 103 uint32_t regno, 104 _Unwind_VRS_DataRepresentation representation, 105 void *valuep); 106 _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, 107 _Unwind_VRS_RegClass regclass, 108 uint32_t regno, 109 _Unwind_VRS_DataRepresentation representation, 110 void *valuep); 111 112 /* Return the base-address for data references. */ 113 extern unsigned long _Unwind_GetDataRelBase(struct _Unwind_Context *); 114 115 /* Return the base-address for text references. */ 116 extern unsigned long _Unwind_GetTextRelBase(struct _Unwind_Context *); 117 extern unsigned long _Unwind_GetRegionStart(struct _Unwind_Context *); 118 119 typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *, 120 void *); 121 extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); 122 extern _Unwind_Reason_Code 123 _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *); 124 125 /** 126 * The next set of functions are compatibility extensions, implementing Itanium 127 * ABI functions on top of ARM ones. 128 */ 129 130 #define _UA_SEARCH_PHASE 1 131 #define _UA_CLEANUP_PHASE 2 132 #define _UA_HANDLER_FRAME 4 133 #define _UA_FORCE_UNWIND 8 134 135 static inline unsigned long _Unwind_GetGR(struct _Unwind_Context *context, int reg) 136 { 137 unsigned long val; 138 _Unwind_VRS_Get(context, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); 139 return val; 140 } 141 static inline void _Unwind_SetGR(struct _Unwind_Context *context, int reg, unsigned long val) 142 { 143 _Unwind_VRS_Set(context, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); 144 } 145 static inline unsigned long _Unwind_GetIP(_Unwind_Context *context) 146 { 147 // Low bit store the thumb state - discard it 148 return _Unwind_GetGR(context, 15) & ~1; 149 } 150 static inline void _Unwind_SetIP(_Unwind_Context *context, unsigned long val) 151 { 152 // The lowest bit of the instruction pointer indicates whether we're in 153 // thumb or ARM mode. This is assumed to be fixed throughout a function, 154 // so must be propagated when setting the program counter. 155 unsigned long thumbState = _Unwind_GetGR(context, 15) & 1; 156 _Unwind_SetGR(context, 15, (val | thumbState)); 157 } 158 159 /** GNU API function that unwinds the frame */ 160 _Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception*, struct _Unwind_Context*); 161 162 163 #define DECLARE_PERSONALITY_FUNCTION(name) \ 164 _Unwind_Reason_Code name(_Unwind_State state,\ 165 struct _Unwind_Exception *exceptionObject,\ 166 struct _Unwind_Context *context); 167 168 #define BEGIN_PERSONALITY_FUNCTION(name) \ 169 _Unwind_Reason_Code name(_Unwind_State state,\ 170 struct _Unwind_Exception *exceptionObject,\ 171 struct _Unwind_Context *context)\ 172 {\ 173 int version = 1;\ 174 uint64_t exceptionClass = exceptionObject->exception_class;\ 175 int actions;\ 176 switch (state)\ 177 {\ 178 default: return _URC_FAILURE;\ 179 case _US_VIRTUAL_UNWIND_FRAME:\ 180 {\ 181 actions = _UA_SEARCH_PHASE;\ 182 break;\ 183 }\ 184 case _US_UNWIND_FRAME_STARTING:\ 185 {\ 186 actions = _UA_CLEANUP_PHASE;\ 187 if (exceptionObject->barrier_cache.sp == _Unwind_GetGR(context, 13))\ 188 {\ 189 actions |= _UA_HANDLER_FRAME;\ 190 }\ 191 break;\ 192 }\ 193 case _US_UNWIND_FRAME_RESUME:\ 194 {\ 195 return continueUnwinding(exceptionObject, context);\ 196 break;\ 197 }\ 198 }\ 199 _Unwind_SetGR (context, 12, (unsigned long)exceptionObject);\ 200 201 #define CALL_PERSONALITY_FUNCTION(name) name(state,exceptionObject,context) 202