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