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