1252330Sjeff/* SJLJ exception handling and frame unwind runtime interface routines.
2252330Sjeff   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
3252330Sjeff   Free Software Foundation, Inc.
4252330Sjeff
5252330Sjeff   This file is part of GCC.
6252330Sjeff
7252330Sjeff   GCC is free software; you can redistribute it and/or modify it
8252330Sjeff   under the terms of the GNU General Public License as published by
9252330Sjeff   the Free Software Foundation; either version 2, or (at your option)
10252330Sjeff   any later version.
11252330Sjeff
12252330Sjeff   In addition to the permissions in the GNU General Public License, the
13252330Sjeff   Free Software Foundation gives you unlimited permission to link the
14252330Sjeff   compiled version of this file into combinations with other programs,
15252330Sjeff   and to distribute those combinations without any restriction coming
16252330Sjeff   from the use of this file.  (The General Public License restrictions
17252330Sjeff   do apply in other respects; for example, they cover modification of
18252330Sjeff   the file, and distribution when not linked into a combined
19252330Sjeff   executable.)
20252330Sjeff
21252330Sjeff   GCC is distributed in the hope that it will be useful, but WITHOUT
22252330Sjeff   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23252330Sjeff   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
24252330Sjeff   License for more details.
25252330Sjeff
26252330Sjeff   You should have received a copy of the GNU General Public License
27252330Sjeff   along with GCC; see the file COPYING.  If not, write to the Free
28252330Sjeff   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
29252330Sjeff   02110-1301, USA.  */
30252330Sjeff
31252330Sjeff#include "tconfig.h"
32252330Sjeff#include "tsystem.h"
33252330Sjeff#include "coretypes.h"
34252330Sjeff#include "tm.h"
35252330Sjeff#include "unwind.h"
36252330Sjeff#include "gthr.h"
37252330Sjeff
38252330Sjeff#ifdef __USING_SJLJ_EXCEPTIONS__
39252330Sjeff
40252330Sjeff#ifdef DONT_USE_BUILTIN_SETJMP
41252330Sjeff#ifndef inhibit_libc
42252330Sjeff#include <setjmp.h>
43252330Sjeff#else
44252330Sjefftypedef void *jmp_buf[JMP_BUF_SIZE];
45252330Sjeffextern void longjmp(jmp_buf, int) __attribute__((noreturn));
46252330Sjeff#endif
47252330Sjeff#else
48252330Sjeff#define longjmp __builtin_longjmp
49252330Sjeff#endif
50252330Sjeff
51252330Sjeff/* The setjmp side is dealt with in the except.c file.  */
52252330Sjeff#undef setjmp
53252330Sjeff#define setjmp setjmp_should_not_be_used_in_this_file
54252330Sjeff
55252330Sjeff
56252330Sjeff/* This structure is allocated on the stack of the target function.
57252330Sjeff   This must match the definition created in except.c:init_eh.  */
58252330Sjeffstruct SjLj_Function_Context
59252330Sjeff{
60254307Sjeff  /* This is the chain through all registered contexts.  It is
61254307Sjeff     filled in by _Unwind_SjLj_Register.  */
62252330Sjeff  struct SjLj_Function_Context *prev;
63252330Sjeff
64252330Sjeff  /* This is assigned in by the target function before every call
65252330Sjeff     to the index of the call site in the lsda.  It is assigned by
66254025Sjeff     the personality routine to the landing pad index.  */
67252330Sjeff  int call_site;
68252330Sjeff
69252330Sjeff  /* This is how data is returned from the personality routine to
70252330Sjeff     the target function's handler.  */
71252330Sjeff  _Unwind_Word data[4];
72252330Sjeff
73252330Sjeff  /* These are filled in once by the target function before any
74252330Sjeff     exceptions are expected to be handled.  */
75252330Sjeff  _Unwind_Personality_Fn personality;
76252330Sjeff  void *lsda;
77252330Sjeff
78252330Sjeff#ifdef DONT_USE_BUILTIN_SETJMP
79252330Sjeff  /* We don't know what sort of alignment requirements the system
80252330Sjeff     jmp_buf has.  We over estimated in except.c, and now we have
81252330Sjeff     to match that here just in case the system *didn't* have more
82252330Sjeff     restrictive requirements.  */
83252330Sjeff  jmp_buf jbuf __attribute__((aligned));
84252330Sjeff#else
85252330Sjeff  void *jbuf[];
86252330Sjeff#endif
87252330Sjeff};
88252330Sjeff
89252330Sjeffstruct _Unwind_Context
90252330Sjeff{
91252330Sjeff  struct SjLj_Function_Context *fc;
92252330Sjeff};
93252330Sjeff
94252330Sjefftypedef struct
95252330Sjeff{
96252330Sjeff  _Unwind_Personality_Fn personality;
97252330Sjeff} _Unwind_FrameState;
98252330Sjeff
99252330Sjeff
100252330Sjeff/* Manage the chain of registered function contexts.  */
101252330Sjeff
102252330Sjeff/* Single threaded fallback chain.  */
103252330Sjeffstatic struct SjLj_Function_Context *fc_static;
104252330Sjeff
105252330Sjeff#if __GTHREADS
106252330Sjeffstatic __gthread_key_t fc_key;
107252330Sjeffstatic int use_fc_key = -1;
108252330Sjeff
109252330Sjeffstatic void
110252330Sjefffc_key_init (void)
111252330Sjeff{
112252330Sjeff  use_fc_key = __gthread_key_create (&fc_key, 0) == 0;
113252330Sjeff}
114252330Sjeff
115252330Sjeffstatic void
116252330Sjefffc_key_init_once (void)
117252330Sjeff{
118252330Sjeff  static __gthread_once_t once = __GTHREAD_ONCE_INIT;
119252330Sjeff  if (__gthread_once (&once, fc_key_init) != 0 || use_fc_key < 0)
120252330Sjeff    use_fc_key = 0;
121252330Sjeff}
122252330Sjeff#endif
123252330Sjeff
124252330Sjeffvoid
125252330Sjeff_Unwind_SjLj_Register (struct SjLj_Function_Context *fc)
126252330Sjeff{
127252330Sjeff#if __GTHREADS
128252330Sjeff  if (use_fc_key < 0)
129252330Sjeff    fc_key_init_once ();
130252330Sjeff
131252330Sjeff  if (use_fc_key)
132252330Sjeff    {
133252330Sjeff      fc->prev = __gthread_getspecific (fc_key);
134252330Sjeff      __gthread_setspecific (fc_key, fc);
135252330Sjeff    }
136252330Sjeff  else
137252330Sjeff#endif
138252330Sjeff    {
139252330Sjeff      fc->prev = fc_static;
140252330Sjeff      fc_static = fc;
141252330Sjeff    }
142252330Sjeff}
143252330Sjeff
144252330Sjeffstatic inline struct SjLj_Function_Context *
145252330Sjeff_Unwind_SjLj_GetContext (void)
146252330Sjeff{
147252330Sjeff#if __GTHREADS
148252330Sjeff  if (use_fc_key < 0)
149252330Sjeff    fc_key_init_once ();
150252330Sjeff
151252330Sjeff  if (use_fc_key)
152252330Sjeff    return __gthread_getspecific (fc_key);
153252330Sjeff#endif
154252330Sjeff  return fc_static;
155252330Sjeff}
156252330Sjeff
157252330Sjeffstatic inline void
158252330Sjeff_Unwind_SjLj_SetContext (struct SjLj_Function_Context *fc)
159252330Sjeff{
160252330Sjeff#if __GTHREADS
161252330Sjeff  if (use_fc_key < 0)
162252330Sjeff    fc_key_init_once ();
163252330Sjeff
164252330Sjeff  if (use_fc_key)
165252330Sjeff    __gthread_setspecific (fc_key, fc);
166252330Sjeff  else
167252330Sjeff#endif
168252330Sjeff    fc_static = fc;
169252330Sjeff}
170252330Sjeff
171252330Sjeffvoid
172252330Sjeff_Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc)
173252330Sjeff{
174252330Sjeff  _Unwind_SjLj_SetContext (fc->prev);
175252330Sjeff}
176252330Sjeff
177252330Sjeff
178252330Sjeff/* Get/set the return data value at INDEX in CONTEXT.  */
179252330Sjeff
180252330Sjeff_Unwind_Word
181252330Sjeff_Unwind_GetGR (struct _Unwind_Context *context, int index)
182252330Sjeff{
183252330Sjeff  return context->fc->data[index];
184252330Sjeff}
185252330Sjeff
186252330Sjeff/* Get the value of the CFA as saved in CONTEXT.  */
187252330Sjeff
188252330Sjeff_Unwind_Word
189252330Sjeff_Unwind_GetCFA (struct _Unwind_Context *context __attribute__((unused)))
190252330Sjeff{
191252330Sjeff  /* ??? Ideally __builtin_setjmp places the CFA in the jmpbuf.  */
192252330Sjeff
193252330Sjeff#ifndef DONT_USE_BUILTIN_SETJMP
194252330Sjeff  /* This is a crude imitation of the CFA: the saved stack pointer.
195252330Sjeff     This is roughly the CFA of the frame before CONTEXT.  When using the
196252330Sjeff     DWARF-2 unwinder _Unwind_GetCFA returns the CFA of the frame described
197252330Sjeff     by CONTEXT instead; but for DWARF-2 the cleanups associated with
198252330Sjeff     CONTEXT have already been run, and for SJLJ they have not yet been.  */
199252330Sjeff  if (context->fc != NULL)
200252330Sjeff    return (_Unwind_Word) context->fc->jbuf[2];
201252330Sjeff#endif
202252330Sjeff
203252330Sjeff  /* Otherwise we're out of luck for now.  */
204252330Sjeff  return (_Unwind_Word) 0;
205252330Sjeff}
206252330Sjeff
207252330Sjeffvoid
208252330Sjeff_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
209252330Sjeff{
210252330Sjeff  context->fc->data[index] = val;
211252330Sjeff}
212252330Sjeff
213252330Sjeff/* Get the call-site index as saved in CONTEXT.  */
214252330Sjeff
215252330Sjeff_Unwind_Ptr
216252330Sjeff_Unwind_GetIP (struct _Unwind_Context *context)
217252330Sjeff{
218252330Sjeff  return context->fc->call_site + 1;
219254025Sjeff}
220254025Sjeff
221252330Sjeff_Unwind_Ptr
222252330Sjeff_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
223254025Sjeff{
224254025Sjeff  *ip_before_insn = 0;
225252330Sjeff  return context->fc->call_site + 1;
226252330Sjeff}
227252330Sjeff
228254307Sjeff/* Set the return landing pad index in CONTEXT.  */
229254307Sjeff
230254307Sjeffvoid
231254307Sjeff_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
232254307Sjeff{
233252330Sjeff  context->fc->call_site = val - 1;
234252330Sjeff}
235252330Sjeff
236252330Sjeffvoid *
237252330Sjeff_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
238252330Sjeff{
239252330Sjeff  return context->fc->lsda;
240252330Sjeff}
241252330Sjeff
242252330Sjeff_Unwind_Ptr
243252330Sjeff_Unwind_GetRegionStart (struct _Unwind_Context *context __attribute__((unused)) )
244252330Sjeff{
245252330Sjeff  return 0;
246254025Sjeff}
247254025Sjeff
248254025Sjeffvoid *
249254025Sjeff_Unwind_FindEnclosingFunction (void *pc __attribute__((unused)))
250254025Sjeff{
251254025Sjeff  return NULL;
252254025Sjeff}
253254025Sjeff
254252330Sjeff#ifndef __ia64__
255252330Sjeff_Unwind_Ptr
256252330Sjeff_Unwind_GetDataRelBase (struct _Unwind_Context *context __attribute__((unused)) )
257252330Sjeff{
258252330Sjeff  return 0;
259252330Sjeff}
260252330Sjeff
261252330Sjeff_Unwind_Ptr
262252330Sjeff_Unwind_GetTextRelBase (struct _Unwind_Context *context __attribute__((unused)) )
263252330Sjeff{
264252330Sjeff  return 0;
265252330Sjeff}
266252330Sjeff#endif
267252330Sjeff
268252330Sjeffstatic inline _Unwind_Reason_Code
269252330Sjeffuw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
270252330Sjeff{
271252330Sjeff  if (context->fc == NULL)
272252330Sjeff    {
273252330Sjeff      fs->personality = NULL;
274252330Sjeff      return _URC_END_OF_STACK;
275252330Sjeff    }
276252330Sjeff  else
277252330Sjeff    {
278252330Sjeff      fs->personality = context->fc->personality;
279252330Sjeff      return _URC_NO_REASON;
280252330Sjeff    }
281252330Sjeff}
282252330Sjeff
283252330Sjeffstatic inline void
284252330Sjeffuw_update_context (struct _Unwind_Context *context,
285252330Sjeff		   _Unwind_FrameState *fs __attribute__((unused)) )
286252330Sjeff{
287252330Sjeff  context->fc = context->fc->prev;
288252330Sjeff}
289252330Sjeff
290252330Sjeffstatic void
291252330Sjeffuw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
292252330Sjeff{
293252330Sjeff  _Unwind_SjLj_Unregister (context->fc);
294252330Sjeff  uw_update_context (context, fs);
295252330Sjeff}
296252330Sjeff
297252330Sjeffstatic inline void
298252330Sjeffuw_init_context (struct _Unwind_Context *context)
299252330Sjeff{
300252330Sjeff  context->fc = _Unwind_SjLj_GetContext ();
301252330Sjeff}
302252330Sjeff
303252330Sjeffstatic void __attribute__((noreturn))
304252330Sjeffuw_install_context (struct _Unwind_Context *current __attribute__((unused)),
305252330Sjeff                    struct _Unwind_Context *target)
306252330Sjeff{
307252330Sjeff  _Unwind_SjLj_SetContext (target->fc);
308252330Sjeff  longjmp (target->fc->jbuf, 1);
309252330Sjeff}
310252330Sjeff
311252330Sjeffstatic inline _Unwind_Ptr
312252330Sjeffuw_identify_context (struct _Unwind_Context *context)
313252330Sjeff{
314252330Sjeff  return (_Unwind_Ptr) context->fc;
315252330Sjeff}
316252330Sjeff
317252330Sjeff
318252330Sjeff/* Play games with unwind symbols so that we can have call frame
319252330Sjeff   and sjlj symbols in the same shared library.  Not that you can
320252330Sjeff   use them simultaneously...  */
321252330Sjeff#define _Unwind_RaiseException		_Unwind_SjLj_RaiseException
322252330Sjeff#define _Unwind_ForcedUnwind		_Unwind_SjLj_ForcedUnwind
323252330Sjeff#define _Unwind_Resume			_Unwind_SjLj_Resume
324252330Sjeff#define _Unwind_Resume_or_Rethrow	_Unwind_SjLj_Resume_or_Rethrow
325252330Sjeff
326252330Sjeff#include "unwind.inc"
327252330Sjeff
328252330Sjeff#endif /* USING_SJLJ_EXCEPTIONS */
329252330Sjeff