• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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