xref: /dflybsd-src/contrib/gcc-4.7/libgcc/unwind-sjlj.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* SJLJ exception handling and frame unwind runtime interface routines.
2*e4b17023SJohn Marino    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006,
3*e4b17023SJohn Marino    2009, 2011 Free Software Foundation, Inc.
4*e4b17023SJohn Marino 
5*e4b17023SJohn Marino    This file is part of GCC.
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino    GCC is free software; you can redistribute it and/or modify it
8*e4b17023SJohn Marino    under the terms of the GNU General Public License as published by
9*e4b17023SJohn Marino    the Free Software Foundation; either version 3, or (at your option)
10*e4b17023SJohn Marino    any later version.
11*e4b17023SJohn Marino 
12*e4b17023SJohn Marino    GCC is distributed in the hope that it will be useful, but WITHOUT
13*e4b17023SJohn Marino    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14*e4b17023SJohn Marino    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15*e4b17023SJohn Marino    License for more details.
16*e4b17023SJohn Marino 
17*e4b17023SJohn Marino    Under Section 7 of GPL version 3, you are granted additional
18*e4b17023SJohn Marino    permissions described in the GCC Runtime Library Exception, version
19*e4b17023SJohn Marino    3.1, as published by the Free Software Foundation.
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino    You should have received a copy of the GNU General Public License and
22*e4b17023SJohn Marino    a copy of the GCC Runtime Library Exception along with this program;
23*e4b17023SJohn Marino    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24*e4b17023SJohn Marino    <http://www.gnu.org/licenses/>.  */
25*e4b17023SJohn Marino 
26*e4b17023SJohn Marino #include "tconfig.h"
27*e4b17023SJohn Marino #include "tsystem.h"
28*e4b17023SJohn Marino #include "coretypes.h"
29*e4b17023SJohn Marino #include "tm.h"
30*e4b17023SJohn Marino #include "libgcc_tm.h"
31*e4b17023SJohn Marino #include "unwind.h"
32*e4b17023SJohn Marino #include "gthr.h"
33*e4b17023SJohn Marino 
34*e4b17023SJohn Marino #ifdef __USING_SJLJ_EXCEPTIONS__
35*e4b17023SJohn Marino 
36*e4b17023SJohn Marino #ifdef DONT_USE_BUILTIN_SETJMP
37*e4b17023SJohn Marino #ifndef inhibit_libc
38*e4b17023SJohn Marino #include <setjmp.h>
39*e4b17023SJohn Marino #else
40*e4b17023SJohn Marino typedef void *jmp_buf[JMP_BUF_SIZE];
41*e4b17023SJohn Marino extern void longjmp(jmp_buf, int) __attribute__((noreturn));
42*e4b17023SJohn Marino #endif
43*e4b17023SJohn Marino #else
44*e4b17023SJohn Marino #define longjmp __builtin_longjmp
45*e4b17023SJohn Marino #endif
46*e4b17023SJohn Marino 
47*e4b17023SJohn Marino /* The setjmp side is dealt with in the except.c file.  */
48*e4b17023SJohn Marino #undef setjmp
49*e4b17023SJohn Marino #define setjmp setjmp_should_not_be_used_in_this_file
50*e4b17023SJohn Marino 
51*e4b17023SJohn Marino 
52*e4b17023SJohn Marino /* This structure is allocated on the stack of the target function.
53*e4b17023SJohn Marino    This must match the definition created in except.c:init_eh.  */
54*e4b17023SJohn Marino struct SjLj_Function_Context
55*e4b17023SJohn Marino {
56*e4b17023SJohn Marino   /* This is the chain through all registered contexts.  It is
57*e4b17023SJohn Marino      filled in by _Unwind_SjLj_Register.  */
58*e4b17023SJohn Marino   struct SjLj_Function_Context *prev;
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino   /* This is assigned in by the target function before every call
61*e4b17023SJohn Marino      to the index of the call site in the lsda.  It is assigned by
62*e4b17023SJohn Marino      the personality routine to the landing pad index.  */
63*e4b17023SJohn Marino   int call_site;
64*e4b17023SJohn Marino 
65*e4b17023SJohn Marino   /* This is how data is returned from the personality routine to
66*e4b17023SJohn Marino      the target function's handler.  */
67*e4b17023SJohn Marino   _Unwind_Word data[4];
68*e4b17023SJohn Marino 
69*e4b17023SJohn Marino   /* These are filled in once by the target function before any
70*e4b17023SJohn Marino      exceptions are expected to be handled.  */
71*e4b17023SJohn Marino   _Unwind_Personality_Fn personality;
72*e4b17023SJohn Marino   void *lsda;
73*e4b17023SJohn Marino 
74*e4b17023SJohn Marino #ifdef DONT_USE_BUILTIN_SETJMP
75*e4b17023SJohn Marino   /* We don't know what sort of alignment requirements the system
76*e4b17023SJohn Marino      jmp_buf has.  We over estimated in except.c, and now we have
77*e4b17023SJohn Marino      to match that here just in case the system *didn't* have more
78*e4b17023SJohn Marino      restrictive requirements.  */
79*e4b17023SJohn Marino   jmp_buf jbuf __attribute__((aligned));
80*e4b17023SJohn Marino #else
81*e4b17023SJohn Marino   void *jbuf[];
82*e4b17023SJohn Marino #endif
83*e4b17023SJohn Marino };
84*e4b17023SJohn Marino 
85*e4b17023SJohn Marino struct _Unwind_Context
86*e4b17023SJohn Marino {
87*e4b17023SJohn Marino   struct SjLj_Function_Context *fc;
88*e4b17023SJohn Marino };
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino typedef struct
91*e4b17023SJohn Marino {
92*e4b17023SJohn Marino   _Unwind_Personality_Fn personality;
93*e4b17023SJohn Marino } _Unwind_FrameState;
94*e4b17023SJohn Marino 
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino /* Manage the chain of registered function contexts.  */
97*e4b17023SJohn Marino 
98*e4b17023SJohn Marino /* Single threaded fallback chain.  */
99*e4b17023SJohn Marino static struct SjLj_Function_Context *fc_static;
100*e4b17023SJohn Marino 
101*e4b17023SJohn Marino #if __GTHREADS
102*e4b17023SJohn Marino static __gthread_key_t fc_key;
103*e4b17023SJohn Marino static int use_fc_key = -1;
104*e4b17023SJohn Marino 
105*e4b17023SJohn Marino static void
fc_key_init(void)106*e4b17023SJohn Marino fc_key_init (void)
107*e4b17023SJohn Marino {
108*e4b17023SJohn Marino   use_fc_key = __gthread_key_create (&fc_key, 0) == 0;
109*e4b17023SJohn Marino }
110*e4b17023SJohn Marino 
111*e4b17023SJohn Marino static void
fc_key_init_once(void)112*e4b17023SJohn Marino fc_key_init_once (void)
113*e4b17023SJohn Marino {
114*e4b17023SJohn Marino   static __gthread_once_t once = __GTHREAD_ONCE_INIT;
115*e4b17023SJohn Marino   if (__gthread_once (&once, fc_key_init) != 0 || use_fc_key < 0)
116*e4b17023SJohn Marino     use_fc_key = 0;
117*e4b17023SJohn Marino }
118*e4b17023SJohn Marino #endif
119*e4b17023SJohn Marino 
120*e4b17023SJohn Marino void
_Unwind_SjLj_Register(struct SjLj_Function_Context * fc)121*e4b17023SJohn Marino _Unwind_SjLj_Register (struct SjLj_Function_Context *fc)
122*e4b17023SJohn Marino {
123*e4b17023SJohn Marino #if __GTHREADS
124*e4b17023SJohn Marino   if (use_fc_key < 0)
125*e4b17023SJohn Marino     fc_key_init_once ();
126*e4b17023SJohn Marino 
127*e4b17023SJohn Marino   if (use_fc_key)
128*e4b17023SJohn Marino     {
129*e4b17023SJohn Marino       fc->prev = __gthread_getspecific (fc_key);
130*e4b17023SJohn Marino       __gthread_setspecific (fc_key, fc);
131*e4b17023SJohn Marino     }
132*e4b17023SJohn Marino   else
133*e4b17023SJohn Marino #endif
134*e4b17023SJohn Marino     {
135*e4b17023SJohn Marino       fc->prev = fc_static;
136*e4b17023SJohn Marino       fc_static = fc;
137*e4b17023SJohn Marino     }
138*e4b17023SJohn Marino }
139*e4b17023SJohn Marino 
140*e4b17023SJohn Marino static inline struct SjLj_Function_Context *
_Unwind_SjLj_GetContext(void)141*e4b17023SJohn Marino _Unwind_SjLj_GetContext (void)
142*e4b17023SJohn Marino {
143*e4b17023SJohn Marino #if __GTHREADS
144*e4b17023SJohn Marino   if (use_fc_key < 0)
145*e4b17023SJohn Marino     fc_key_init_once ();
146*e4b17023SJohn Marino 
147*e4b17023SJohn Marino   if (use_fc_key)
148*e4b17023SJohn Marino     return __gthread_getspecific (fc_key);
149*e4b17023SJohn Marino #endif
150*e4b17023SJohn Marino   return fc_static;
151*e4b17023SJohn Marino }
152*e4b17023SJohn Marino 
153*e4b17023SJohn Marino static inline void
_Unwind_SjLj_SetContext(struct SjLj_Function_Context * fc)154*e4b17023SJohn Marino _Unwind_SjLj_SetContext (struct SjLj_Function_Context *fc)
155*e4b17023SJohn Marino {
156*e4b17023SJohn Marino #if __GTHREADS
157*e4b17023SJohn Marino   if (use_fc_key < 0)
158*e4b17023SJohn Marino     fc_key_init_once ();
159*e4b17023SJohn Marino 
160*e4b17023SJohn Marino   if (use_fc_key)
161*e4b17023SJohn Marino     __gthread_setspecific (fc_key, fc);
162*e4b17023SJohn Marino   else
163*e4b17023SJohn Marino #endif
164*e4b17023SJohn Marino     fc_static = fc;
165*e4b17023SJohn Marino }
166*e4b17023SJohn Marino 
167*e4b17023SJohn Marino void
_Unwind_SjLj_Unregister(struct SjLj_Function_Context * fc)168*e4b17023SJohn Marino _Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc)
169*e4b17023SJohn Marino {
170*e4b17023SJohn Marino   _Unwind_SjLj_SetContext (fc->prev);
171*e4b17023SJohn Marino }
172*e4b17023SJohn Marino 
173*e4b17023SJohn Marino 
174*e4b17023SJohn Marino /* Get/set the return data value at INDEX in CONTEXT.  */
175*e4b17023SJohn Marino 
176*e4b17023SJohn Marino _Unwind_Word
_Unwind_GetGR(struct _Unwind_Context * context,int index)177*e4b17023SJohn Marino _Unwind_GetGR (struct _Unwind_Context *context, int index)
178*e4b17023SJohn Marino {
179*e4b17023SJohn Marino   return context->fc->data[index];
180*e4b17023SJohn Marino }
181*e4b17023SJohn Marino 
182*e4b17023SJohn Marino /* Get the value of the CFA as saved in CONTEXT.  */
183*e4b17023SJohn Marino 
184*e4b17023SJohn Marino _Unwind_Word
_Unwind_GetCFA(struct _Unwind_Context * context)185*e4b17023SJohn Marino _Unwind_GetCFA (struct _Unwind_Context *context __attribute__((unused)))
186*e4b17023SJohn Marino {
187*e4b17023SJohn Marino   /* ??? Ideally __builtin_setjmp places the CFA in the jmpbuf.  */
188*e4b17023SJohn Marino 
189*e4b17023SJohn Marino #ifndef DONT_USE_BUILTIN_SETJMP
190*e4b17023SJohn Marino   /* This is a crude imitation of the CFA: the saved stack pointer.
191*e4b17023SJohn Marino      This is roughly the CFA of the frame before CONTEXT.  When using the
192*e4b17023SJohn Marino      DWARF-2 unwinder _Unwind_GetCFA returns the CFA of the frame described
193*e4b17023SJohn Marino      by CONTEXT instead; but for DWARF-2 the cleanups associated with
194*e4b17023SJohn Marino      CONTEXT have already been run, and for SJLJ they have not yet been.  */
195*e4b17023SJohn Marino   if (context->fc != NULL)
196*e4b17023SJohn Marino     return (_Unwind_Word) context->fc->jbuf[2];
197*e4b17023SJohn Marino #endif
198*e4b17023SJohn Marino 
199*e4b17023SJohn Marino   /* Otherwise we're out of luck for now.  */
200*e4b17023SJohn Marino   return (_Unwind_Word) 0;
201*e4b17023SJohn Marino }
202*e4b17023SJohn Marino 
203*e4b17023SJohn Marino void
_Unwind_SetGR(struct _Unwind_Context * context,int index,_Unwind_Word val)204*e4b17023SJohn Marino _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
205*e4b17023SJohn Marino {
206*e4b17023SJohn Marino   context->fc->data[index] = val;
207*e4b17023SJohn Marino }
208*e4b17023SJohn Marino 
209*e4b17023SJohn Marino /* Get the call-site index as saved in CONTEXT.  */
210*e4b17023SJohn Marino 
211*e4b17023SJohn Marino _Unwind_Ptr
_Unwind_GetIP(struct _Unwind_Context * context)212*e4b17023SJohn Marino _Unwind_GetIP (struct _Unwind_Context *context)
213*e4b17023SJohn Marino {
214*e4b17023SJohn Marino   return context->fc->call_site + 1;
215*e4b17023SJohn Marino }
216*e4b17023SJohn Marino 
217*e4b17023SJohn Marino _Unwind_Ptr
_Unwind_GetIPInfo(struct _Unwind_Context * context,int * ip_before_insn)218*e4b17023SJohn Marino _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
219*e4b17023SJohn Marino {
220*e4b17023SJohn Marino   *ip_before_insn = 0;
221*e4b17023SJohn Marino   if (context->fc != NULL)
222*e4b17023SJohn Marino     return context->fc->call_site + 1;
223*e4b17023SJohn Marino   else
224*e4b17023SJohn Marino     return 0;
225*e4b17023SJohn Marino }
226*e4b17023SJohn Marino 
227*e4b17023SJohn Marino /* Set the return landing pad index in CONTEXT.  */
228*e4b17023SJohn Marino 
229*e4b17023SJohn Marino void
_Unwind_SetIP(struct _Unwind_Context * context,_Unwind_Ptr val)230*e4b17023SJohn Marino _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
231*e4b17023SJohn Marino {
232*e4b17023SJohn Marino   context->fc->call_site = val - 1;
233*e4b17023SJohn Marino }
234*e4b17023SJohn Marino 
235*e4b17023SJohn Marino void *
_Unwind_GetLanguageSpecificData(struct _Unwind_Context * context)236*e4b17023SJohn Marino _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
237*e4b17023SJohn Marino {
238*e4b17023SJohn Marino   return context->fc->lsda;
239*e4b17023SJohn Marino }
240*e4b17023SJohn Marino 
241*e4b17023SJohn Marino _Unwind_Ptr
_Unwind_GetRegionStart(struct _Unwind_Context * context)242*e4b17023SJohn Marino _Unwind_GetRegionStart (struct _Unwind_Context *context __attribute__((unused)) )
243*e4b17023SJohn Marino {
244*e4b17023SJohn Marino   return 0;
245*e4b17023SJohn Marino }
246*e4b17023SJohn Marino 
247*e4b17023SJohn Marino void *
_Unwind_FindEnclosingFunction(void * pc)248*e4b17023SJohn Marino _Unwind_FindEnclosingFunction (void *pc __attribute__((unused)))
249*e4b17023SJohn Marino {
250*e4b17023SJohn Marino   return NULL;
251*e4b17023SJohn Marino }
252*e4b17023SJohn Marino 
253*e4b17023SJohn Marino #ifndef __ia64__
254*e4b17023SJohn Marino _Unwind_Ptr
_Unwind_GetDataRelBase(struct _Unwind_Context * context)255*e4b17023SJohn Marino _Unwind_GetDataRelBase (struct _Unwind_Context *context __attribute__((unused)) )
256*e4b17023SJohn Marino {
257*e4b17023SJohn Marino   return 0;
258*e4b17023SJohn Marino }
259*e4b17023SJohn Marino 
260*e4b17023SJohn Marino _Unwind_Ptr
_Unwind_GetTextRelBase(struct _Unwind_Context * context)261*e4b17023SJohn Marino _Unwind_GetTextRelBase (struct _Unwind_Context *context __attribute__((unused)) )
262*e4b17023SJohn Marino {
263*e4b17023SJohn Marino   return 0;
264*e4b17023SJohn Marino }
265*e4b17023SJohn Marino #endif
266*e4b17023SJohn Marino 
267*e4b17023SJohn Marino static inline _Unwind_Reason_Code
uw_frame_state_for(struct _Unwind_Context * context,_Unwind_FrameState * fs)268*e4b17023SJohn Marino uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
269*e4b17023SJohn Marino {
270*e4b17023SJohn Marino   if (context->fc == NULL)
271*e4b17023SJohn Marino     {
272*e4b17023SJohn Marino       fs->personality = NULL;
273*e4b17023SJohn Marino       return _URC_END_OF_STACK;
274*e4b17023SJohn Marino     }
275*e4b17023SJohn Marino   else
276*e4b17023SJohn Marino     {
277*e4b17023SJohn Marino       fs->personality = context->fc->personality;
278*e4b17023SJohn Marino       return _URC_NO_REASON;
279*e4b17023SJohn Marino     }
280*e4b17023SJohn Marino }
281*e4b17023SJohn Marino 
282*e4b17023SJohn Marino static inline void
uw_update_context(struct _Unwind_Context * context,_Unwind_FrameState * fs)283*e4b17023SJohn Marino uw_update_context (struct _Unwind_Context *context,
284*e4b17023SJohn Marino 		   _Unwind_FrameState *fs __attribute__((unused)) )
285*e4b17023SJohn Marino {
286*e4b17023SJohn Marino   context->fc = context->fc->prev;
287*e4b17023SJohn Marino }
288*e4b17023SJohn Marino 
289*e4b17023SJohn Marino static void
uw_advance_context(struct _Unwind_Context * context,_Unwind_FrameState * fs)290*e4b17023SJohn Marino uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
291*e4b17023SJohn Marino {
292*e4b17023SJohn Marino   _Unwind_SjLj_Unregister (context->fc);
293*e4b17023SJohn Marino   uw_update_context (context, fs);
294*e4b17023SJohn Marino }
295*e4b17023SJohn Marino 
296*e4b17023SJohn Marino static inline void
uw_init_context(struct _Unwind_Context * context)297*e4b17023SJohn Marino uw_init_context (struct _Unwind_Context *context)
298*e4b17023SJohn Marino {
299*e4b17023SJohn Marino   context->fc = _Unwind_SjLj_GetContext ();
300*e4b17023SJohn Marino }
301*e4b17023SJohn Marino 
302*e4b17023SJohn Marino static void __attribute__((noreturn))
uw_install_context(struct _Unwind_Context * current,struct _Unwind_Context * target)303*e4b17023SJohn Marino uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
304*e4b17023SJohn Marino                     struct _Unwind_Context *target)
305*e4b17023SJohn Marino {
306*e4b17023SJohn Marino   _Unwind_SjLj_SetContext (target->fc);
307*e4b17023SJohn Marino   longjmp (target->fc->jbuf, 1);
308*e4b17023SJohn Marino }
309*e4b17023SJohn Marino 
310*e4b17023SJohn Marino static inline _Unwind_Ptr
uw_identify_context(struct _Unwind_Context * context)311*e4b17023SJohn Marino uw_identify_context (struct _Unwind_Context *context)
312*e4b17023SJohn Marino {
313*e4b17023SJohn Marino   return (_Unwind_Ptr) context->fc;
314*e4b17023SJohn Marino }
315*e4b17023SJohn Marino 
316*e4b17023SJohn Marino 
317*e4b17023SJohn Marino /* Play games with unwind symbols so that we can have call frame
318*e4b17023SJohn Marino    and sjlj symbols in the same shared library.  Not that you can
319*e4b17023SJohn Marino    use them simultaneously...  */
320*e4b17023SJohn Marino #define _Unwind_RaiseException		_Unwind_SjLj_RaiseException
321*e4b17023SJohn Marino #define _Unwind_ForcedUnwind		_Unwind_SjLj_ForcedUnwind
322*e4b17023SJohn Marino #define _Unwind_Resume			_Unwind_SjLj_Resume
323*e4b17023SJohn Marino #define _Unwind_Resume_or_Rethrow	_Unwind_SjLj_Resume_or_Rethrow
324*e4b17023SJohn Marino 
325*e4b17023SJohn Marino #include "unwind.inc"
326*e4b17023SJohn Marino 
327*e4b17023SJohn Marino #endif /* USING_SJLJ_EXCEPTIONS */
328