Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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