xref: /dflybsd-src/contrib/gcc-8.0/libgcc/unwind-sjlj.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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