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