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