1 // Copyright (C) 2012 The Android Open Source Project 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions 6 // are met: 7 // 1. Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // 2. Redistributions in binary form must reproduce the above copyright 10 // notice, this list of conditions and the following disclaimer in the 11 // documentation and/or other materials provided with the distribution. 12 // 3. Neither the name of the project nor the names of its contributors 13 // may be used to endorse or promote products derived from this software 14 // without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 // ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 // SUCH DAMAGE. 27 28 #ifndef __GABIXX_UNWIND_ARM_H__ 29 #define __GABIXX_UNWIND_ARM_H__ 30 31 #include <stdint.h> 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 typedef enum { 38 _URC_NO_REASON = 0, 39 _URC_FOREIGN_EXCEPTION_CAUGHT = 1, 40 _URC_FATAL_PHASE2_ERROR = 2, 41 _URC_FATAL_PHASE1_ERROR = 3, 42 _URC_END_OF_STACK = 5, 43 _URC_HANDLER_FOUND = 6, 44 _URC_INSTALL_CONTEXT = 7, 45 _URC_CONTINUE_UNWIND = 8, 46 _URC_FAILURE = 9, 47 _URC_OK = 0 48 } _Unwind_Reason_Code; 49 50 typedef uint32_t _Unwind_State; 51 static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0; 52 static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1; 53 static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2; 54 static const _Unwind_State _US_ACTION_MASK = 3; 55 56 typedef struct _Unwind_Control_Block _Unwind_Control_Block; 57 typedef struct _Unwind_Context _Unwind_Context; 58 typedef uint32_t _Unwind_EHT_Header; 59 60 struct _Unwind_Control_Block { 61 uint64_t exception_class; // Compatible with Itanium ABI 62 void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*); 63 64 struct { 65 uint32_t reserved1; // init reserved1 to 0, then don't touch 66 uint32_t reserved2; 67 uint32_t reserved3; 68 uint32_t reserved4; 69 uint32_t reserved5; 70 } unwinder_cache; 71 72 struct { 73 uint32_t sp; 74 uint32_t bitpattern[5]; 75 } barrier_cache; 76 77 struct { 78 uint32_t bitpattern[4]; 79 } cleanup_cache; 80 81 struct { 82 uint32_t fnstart; // function start address 83 _Unwind_EHT_Header* ehtp; // pointer to EHT entry header word 84 uint32_t additional; // additional data 85 uint32_t reserved1; 86 } pr_cache; 87 88 long long int : 0; // Force alignment of next item to 8-byte boundary 89 }; 90 91 // This makes our code more simple 92 typedef _Unwind_Control_Block _Unwind_Exception; 93 94 typedef enum { 95 _UVRSC_CORE = 0, // integer register 96 _UVRSC_VFP = 1, // vfp 97 _UVRSC_WMMXD = 3, // Intel WMMX data register 98 _UVRSC_WMMXC = 4 // Intel WMMX control register 99 } _Unwind_VRS_RegClass; 100 101 typedef enum { 102 _UVRSD_UINT32 = 0, 103 _UVRSD_VFPX = 1, 104 _UVRSD_UINT64 = 3, 105 _UVRSD_FLOAT = 4, 106 _UVRSD_DOUBLE = 5 107 } _Unwind_VRS_DataRepresentation; 108 109 typedef enum { 110 _UVRSR_OK = 0, 111 _UVRSR_NOT_IMPLEMENTED = 1, 112 _UVRSR_FAILED = 2 113 } _Unwind_VRS_Result; 114 115 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception* ucbp); 116 void _Unwind_Resume(_Unwind_Exception* ucbp); 117 void _Unwind_Complete(_Unwind_Exception* ucbp); 118 void _Unwind_DeleteException(_Unwind_Exception* ucbp); 119 uint64_t _Unwind_GetRegionStart(_Unwind_Context*); 120 void* _Unwind_GetLanguageSpecificData(_Unwind_Context*); 121 122 123 _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *context, 124 _Unwind_VRS_RegClass regclass, 125 uint32_t regno, 126 _Unwind_VRS_DataRepresentation representation, 127 void* valuep); 128 129 _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, 130 _Unwind_VRS_RegClass regclass, 131 uint32_t regno, 132 _Unwind_VRS_DataRepresentation representation, 133 void* valuep); 134 135 /* 136 * Implement Itanium ABI based on ARM EHABI to simplify code 137 */ 138 typedef int _Unwind_Action; 139 static const _Unwind_Action _UA_SEARCH_PHASE = 1; 140 static const _Unwind_Action _UA_CLEANUP_PHASE = 2; 141 static const _Unwind_Action _UA_HANDLER_FRAME = 4; 142 static const _Unwind_Action _UA_FORCE_UNWIND = 8; 143 144 #define UNWIND_POINTER_REG 12 145 #define UNWIND_STACK_REG 13 146 #define UNWIND_IP_REG 15 147 148 static inline uint32_t _Unwind_GetGR( _Unwind_Context* ctx, int reg) { 149 uint32_t val; 150 _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); 151 return val; 152 } 153 154 static inline void _Unwind_SetGR(_Unwind_Context* ctx, int reg, uint32_t val) { 155 _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); 156 } 157 158 static inline uint32_t _Unwind_GetIP(_Unwind_Context* ctx) { 159 return _Unwind_GetGR(ctx, UNWIND_IP_REG) & ~1; // thumb bit 160 } 161 static inline void _Unwind_SetIP(_Unwind_Context* ctx, uint32_t val) { 162 // Propagate thumb bit to instruction pointer 163 uint32_t thumbState = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1; 164 _Unwind_SetGR(ctx, UNWIND_IP_REG, (val | thumbState)); 165 } 166 167 #ifdef __cplusplus 168 } // extern "C" 169 #endif 170 171 #endif // __GABIXX_UNWIND_ARM_H__ 172