1232950Stheraven/* 2232950Stheraven * Copyright 2012 David Chisnall. All rights reserved. 3232950Stheraven * 4232950Stheraven * Permission is hereby granted, free of charge, to any person obtaining a copy 5232950Stheraven * of this software and associated documentation files (the "Software"), to 6232950Stheraven * deal in the Software without restriction, including without limitation the 7232950Stheraven * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8232950Stheraven * sell copies of the Software, and to permit persons to whom the Software is 9232950Stheraven * furnished to do so, subject to the following conditions: 10232950Stheraven * 11232950Stheraven * The above copyright notice and this permission notice shall be 12232950Stheraven * included in all copies or substantial portions of the Software. 13232950Stheraven * 14232950Stheraven * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15232950Stheraven * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16232950Stheraven * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17232950Stheraven * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18232950Stheraven * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19232950Stheraven * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20232950Stheraven * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21232950Stheraven */ 22232950Stheraven 23227972Stheraven/** 24227972Stheraven * ARM-specific unwind definitions. These are taken from the ARM EHABI 25227972Stheraven * specification. 26227972Stheraven */ 27227972Stheraven typedef enum 28227972Stheraven{ 29227972Stheraven _URC_OK = 0, /* operation completed successfully */ 30227972Stheraven _URC_FOREIGN_EXCEPTION_CAUGHT = 1, 31227972Stheraven _URC_END_OF_STACK = 5, 32227972Stheraven _URC_HANDLER_FOUND = 6, 33227972Stheraven _URC_INSTALL_CONTEXT = 7, 34227972Stheraven _URC_CONTINUE_UNWIND = 8, 35227972Stheraven _URC_FAILURE = 9, /* unspecified failure of some kind */ 36227972Stheraven _URC_FATAL_PHASE1_ERROR = _URC_FAILURE 37227972Stheraven} _Unwind_Reason_Code; 38227972Stheraven 39227972Stheraventypedef uint32_t _Unwind_State; 40227972Stheraven#ifdef __clang__ 41227972Stheravenstatic const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0; 42227972Stheravenstatic const _Unwind_State _US_UNWIND_FRAME_STARTING = 1; 43227972Stheravenstatic const _Unwind_State _US_UNWIND_FRAME_RESUME = 2; 44227972Stheraven#else // GCC fails at knowing what a constant expression is 45227972Stheraven# define _US_VIRTUAL_UNWIND_FRAME 0 46227972Stheraven# define _US_UNWIND_FRAME_STARTING 1 47227972Stheraven# define _US_UNWIND_FRAME_RESUME 2 48227972Stheraven#endif 49227972Stheraven 50227972Stheraventypedef struct _Unwind_Context _Unwind_Context; 51227972Stheraven 52227972Stheraventypedef uint32_t _Unwind_EHT_Header; 53227972Stheraven 54227972Stheravenstruct _Unwind_Exception 55227972Stheraven{ 56227972Stheraven uint64_t exception_class; 57227972Stheraven void (*exception_cleanup)(_Unwind_Reason_Code, struct _Unwind_Exception *); 58227972Stheraven /* Unwinder cache, private fields for the unwinder's use */ 59227972Stheraven struct 60227972Stheraven { 61227972Stheraven uint32_t reserved1; 62227972Stheraven uint32_t reserved2; 63227972Stheraven uint32_t reserved3; 64227972Stheraven uint32_t reserved4; 65227972Stheraven uint32_t reserved5; 66227972Stheraven /* init reserved1 to 0, then don't touch */ 67227972Stheraven } unwinder_cache; 68227972Stheraven /* Propagation barrier cache (valid after phase 1): */ 69227972Stheraven struct 70227972Stheraven { 71227972Stheraven uint32_t sp; 72227972Stheraven uint32_t bitpattern[5]; 73227972Stheraven } barrier_cache; 74227972Stheraven /* Cleanup cache (preserved over cleanup): */ 75227972Stheraven struct 76227972Stheraven { 77227972Stheraven uint32_t bitpattern[4]; 78227972Stheraven } cleanup_cache; 79227972Stheraven /* Pr cache (for pr's benefit): */ 80227972Stheraven struct 81227972Stheraven { 82227972Stheraven /** function start address */ 83227972Stheraven uint32_t fnstart; 84227972Stheraven /** pointer to EHT entry header word */ 85227972Stheraven _Unwind_EHT_Header *ehtp; 86227972Stheraven /** additional data */ 87227972Stheraven uint32_t additional; 88227972Stheraven uint32_t reserved1; 89227972Stheraven } pr_cache; 90227972Stheraven /** Force alignment of next item to 8-byte boundary */ 91227972Stheraven long long int :0; 92227972Stheraven}; 93227972Stheraven 94227972Stheraven/* Unwinding functions */ 95227972Stheraven_Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *ucbp); 96227972Stheravenvoid _Unwind_Resume(struct _Unwind_Exception *ucbp); 97227972Stheravenvoid _Unwind_Complete(struct _Unwind_Exception *ucbp); 98227972Stheravenvoid _Unwind_DeleteException(struct _Unwind_Exception *ucbp); 99227972Stheravenvoid *_Unwind_GetLanguageSpecificData(struct _Unwind_Context*); 100227972Stheraven 101227972Stheraventypedef enum 102227972Stheraven{ 103227972Stheraven _UVRSR_OK = 0, 104227972Stheraven _UVRSR_NOT_IMPLEMENTED = 1, 105227972Stheraven _UVRSR_FAILED = 2 106227972Stheraven} _Unwind_VRS_Result; 107227972Stheraventypedef enum 108227972Stheraven{ 109227972Stheraven _UVRSC_CORE = 0, 110227972Stheraven _UVRSC_VFP = 1, 111227972Stheraven _UVRSC_WMMXD = 3, 112227972Stheraven _UVRSC_WMMXC = 4 113227972Stheraven} _Unwind_VRS_RegClass; 114227972Stheraventypedef enum 115227972Stheraven{ 116227972Stheraven _UVRSD_UINT32 = 0, 117227972Stheraven _UVRSD_VFPX = 1, 118227972Stheraven _UVRSD_UINT64 = 3, 119227972Stheraven _UVRSD_FLOAT = 4, 120227972Stheraven _UVRSD_DOUBLE = 5 121227972Stheraven} _Unwind_VRS_DataRepresentation; 122227972Stheraven 123227972Stheraven_Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *context, 124227972Stheraven _Unwind_VRS_RegClass regclass, 125227972Stheraven uint32_t regno, 126227972Stheraven _Unwind_VRS_DataRepresentation representation, 127227972Stheraven void *valuep); 128227972Stheraven_Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, 129227972Stheraven _Unwind_VRS_RegClass regclass, 130227972Stheraven uint32_t regno, 131227972Stheraven _Unwind_VRS_DataRepresentation representation, 132227972Stheraven void *valuep); 133227972Stheraven 134227972Stheraven/* Return the base-address for data references. */ 135227972Stheravenextern unsigned long _Unwind_GetDataRelBase(struct _Unwind_Context *); 136227972Stheraven 137227972Stheraven/* Return the base-address for text references. */ 138227972Stheravenextern unsigned long _Unwind_GetTextRelBase(struct _Unwind_Context *); 139227972Stheravenextern unsigned long _Unwind_GetRegionStart(struct _Unwind_Context *); 140227972Stheraven 141227972Stheraventypedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *, 142227972Stheraven void *); 143227972Stheravenextern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); 144227972Stheravenextern _Unwind_Reason_Code 145227972Stheraven _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *); 146227972Stheraven 147227972Stheraven/** 148227972Stheraven * The next set of functions are compatibility extensions, implementing Itanium 149227972Stheraven * ABI functions on top of ARM ones. 150227972Stheraven */ 151227972Stheraven 152227972Stheraven#define _UA_SEARCH_PHASE 1 153227972Stheraven#define _UA_CLEANUP_PHASE 2 154227972Stheraven#define _UA_HANDLER_FRAME 4 155227972Stheraven#define _UA_FORCE_UNWIND 8 156227972Stheraven 157227972Stheravenstatic inline unsigned long _Unwind_GetGR(struct _Unwind_Context *context, int reg) 158227972Stheraven{ 159227972Stheraven unsigned long val; 160227972Stheraven _Unwind_VRS_Get(context, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); 161227972Stheraven return val; 162227972Stheraven} 163227972Stheravenstatic inline void _Unwind_SetGR(struct _Unwind_Context *context, int reg, unsigned long val) 164227972Stheraven{ 165227972Stheraven _Unwind_VRS_Set(context, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); 166227972Stheraven} 167227972Stheravenstatic inline unsigned long _Unwind_GetIP(_Unwind_Context *context) 168227972Stheraven{ 169227972Stheraven // Low bit store the thumb state - discard it 170227972Stheraven return _Unwind_GetGR(context, 15) & ~1; 171227972Stheraven} 172227972Stheravenstatic inline void _Unwind_SetIP(_Unwind_Context *context, unsigned long val) 173227972Stheraven{ 174227972Stheraven // The lowest bit of the instruction pointer indicates whether we're in 175227972Stheraven // thumb or ARM mode. This is assumed to be fixed throughout a function, 176227972Stheraven // so must be propagated when setting the program counter. 177227972Stheraven unsigned long thumbState = _Unwind_GetGR(context, 15) & 1; 178227972Stheraven _Unwind_SetGR(context, 15, (val | thumbState)); 179227972Stheraven} 180227972Stheraven 181227972Stheraven/** GNU API function that unwinds the frame */ 182227972Stheraven_Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception*, struct _Unwind_Context*); 183227972Stheraven 184227972Stheraven 185227972Stheraven#define DECLARE_PERSONALITY_FUNCTION(name) \ 186227972Stheraven_Unwind_Reason_Code name(_Unwind_State state,\ 187227972Stheraven struct _Unwind_Exception *exceptionObject,\ 188227972Stheraven struct _Unwind_Context *context); 189227972Stheraven 190227972Stheraven#define BEGIN_PERSONALITY_FUNCTION(name) \ 191227972Stheraven_Unwind_Reason_Code name(_Unwind_State state,\ 192227972Stheraven struct _Unwind_Exception *exceptionObject,\ 193227972Stheraven struct _Unwind_Context *context)\ 194227972Stheraven{\ 195227972Stheraven int version = 1;\ 196227972Stheraven uint64_t exceptionClass = exceptionObject->exception_class;\ 197227972Stheraven int actions;\ 198227972Stheraven switch (state)\ 199227972Stheraven {\ 200227972Stheraven default: return _URC_FAILURE;\ 201227972Stheraven case _US_VIRTUAL_UNWIND_FRAME:\ 202227972Stheraven {\ 203227972Stheraven actions = _UA_SEARCH_PHASE;\ 204227972Stheraven break;\ 205227972Stheraven }\ 206227972Stheraven case _US_UNWIND_FRAME_STARTING:\ 207227972Stheraven {\ 208227972Stheraven actions = _UA_CLEANUP_PHASE;\ 209227972Stheraven if (exceptionObject->barrier_cache.sp == _Unwind_GetGR(context, 13))\ 210227972Stheraven {\ 211227972Stheraven actions |= _UA_HANDLER_FRAME;\ 212227972Stheraven }\ 213227972Stheraven break;\ 214227972Stheraven }\ 215227972Stheraven case _US_UNWIND_FRAME_RESUME:\ 216227972Stheraven {\ 217227972Stheraven return continueUnwinding(exceptionObject, context);\ 218227972Stheraven break;\ 219227972Stheraven }\ 220227972Stheraven }\ 221227972Stheraven _Unwind_SetGR (context, 12, (unsigned long)exceptionObject);\ 222227972Stheraven 223227972Stheraven#define CALL_PERSONALITY_FUNCTION(name) name(state,exceptionObject,context) 224