Subversion Repositories Kolibri OS

Rev

Rev 4383 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4383 Serge 1
/* Exception handling and frame unwind runtime interface routines. -*- C -*-
5963 serge 2
   Copyright (C) 2001-2013 Free Software Foundation, Inc.
4383 Serge 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
/* This is derived from the C++ ABI for IA-64.  Where we diverge
26
   for cross-architecture compatibility are noted with "@@@".
27
   This file is included from unwind-dw2.c, unwind-sjlj.c or
28
   unwind-ia64.c.  */
29
 
30
/* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume.
31
 
32
   Unwind the stack calling the personality routine to find both the
33
   exception handler and intermediary cleanup code.  We'll only locate
34
   the first such frame here.  Cleanup code will call back into
35
   _Unwind_Resume and we'll continue Phase 2 there.  */
36
 
37
static _Unwind_Reason_Code
38
_Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc,
39
			      struct _Unwind_Context *context)
40
{
41
  _Unwind_Reason_Code code;
42
 
43
  while (1)
44
    {
45
      _Unwind_FrameState fs;
46
      int match_handler;
47
 
48
      code = uw_frame_state_for (context, &fs);
49
 
50
      /* Identify when we've reached the designated handler context.  */
51
      match_handler = (uw_identify_context (context) == exc->private_2
52
		       ? _UA_HANDLER_FRAME : 0);
53
 
54
      if (code != _URC_NO_REASON)
55
	/* Some error encountered.  Usually the unwinder doesn't
56
	   diagnose these and merely crashes.  */
57
	return _URC_FATAL_PHASE2_ERROR;
58
 
59
      /* Unwind successful.  Run the personality routine, if any.  */
60
      if (fs.personality)
61
	{
62
	  code = (*fs.personality) (1, _UA_CLEANUP_PHASE | match_handler,
63
				    exc->exception_class, exc, context);
64
	  if (code == _URC_INSTALL_CONTEXT)
65
	    break;
66
	  if (code != _URC_CONTINUE_UNWIND)
67
	    return _URC_FATAL_PHASE2_ERROR;
68
	}
69
 
70
      /* Don't let us unwind past the handler context.  */
71
      gcc_assert (!match_handler);
72
 
73
      uw_update_context (context, &fs);
74
    }
75
 
76
  return code;
77
}
78
 
79
/* Raise an exception, passing along the given exception object.  */
80
 
81
_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
82
_Unwind_RaiseException(struct _Unwind_Exception *exc)
83
{
84
  struct _Unwind_Context this_context, cur_context;
85
  _Unwind_Reason_Code code;
86
 
87
  /* Set up this_context to describe the current stack frame.  */
88
  uw_init_context (&this_context);
89
  cur_context = this_context;
90
 
91
  /* Phase 1: Search.  Unwind the stack, calling the personality routine
92
     with the _UA_SEARCH_PHASE flag set.  Do not modify the stack yet.  */
93
  while (1)
94
    {
95
      _Unwind_FrameState fs;
96
 
97
      /* Set up fs to describe the FDE for the caller of cur_context.  The
98
	 first time through the loop, that means __cxa_throw.  */
99
      code = uw_frame_state_for (&cur_context, &fs);
100
 
101
      if (code == _URC_END_OF_STACK)
102
	/* Hit end of stack with no handler found.  */
103
	return _URC_END_OF_STACK;
104
 
105
      if (code != _URC_NO_REASON)
106
	/* Some error encountered.  Usually the unwinder doesn't
107
	   diagnose these and merely crashes.  */
108
	return _URC_FATAL_PHASE1_ERROR;
109
 
110
      /* Unwind successful.  Run the personality routine, if any.  */
111
      if (fs.personality)
112
	{
113
	  code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class,
114
				    exc, &cur_context);
115
	  if (code == _URC_HANDLER_FOUND)
116
	    break;
117
	  else if (code != _URC_CONTINUE_UNWIND)
118
	    return _URC_FATAL_PHASE1_ERROR;
119
	}
120
 
121
      /* Update cur_context to describe the same frame as fs.  */
122
      uw_update_context (&cur_context, &fs);
123
    }
124
 
125
  /* Indicate to _Unwind_Resume and associated subroutines that this
126
     is not a forced unwind.  Further, note where we found a handler.  */
127
  exc->private_1 = 0;
128
  exc->private_2 = uw_identify_context (&cur_context);
129
 
130
  cur_context = this_context;
131
  code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
132
  if (code != _URC_INSTALL_CONTEXT)
133
    return code;
134
 
135
  uw_install_context (&this_context, &cur_context);
136
}
137
 
138
 
139
/* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume.  */
140
 
141
static _Unwind_Reason_Code
142
_Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc,
143
			     struct _Unwind_Context *context)
144
{
145
  _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1;
146
  void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2;
147
  _Unwind_Reason_Code code, stop_code;
148
 
149
  while (1)
150
    {
151
      _Unwind_FrameState fs;
152
      int action;
153
 
154
      /* Set up fs to describe the FDE for the caller of cur_context.  */
155
      code = uw_frame_state_for (context, &fs);
156
      if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
157
	return _URC_FATAL_PHASE2_ERROR;
158
 
159
      /* Unwind successful.  */
160
      action = _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE;
161
      if (code == _URC_END_OF_STACK)
162
	action |= _UA_END_OF_STACK;
163
      stop_code = (*stop) (1, action, exc->exception_class, exc,
164
			   context, stop_argument);
165
      if (stop_code != _URC_NO_REASON)
166
	return _URC_FATAL_PHASE2_ERROR;
167
 
168
      /* Stop didn't want to do anything.  Invoke the personality
169
	 handler, if applicable, to run cleanups.  */
170
      if (code == _URC_END_OF_STACK)
171
	break;
172
 
173
      if (fs.personality)
174
	{
175
	  code = (*fs.personality) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
176
				    exc->exception_class, exc, context);
177
	  if (code == _URC_INSTALL_CONTEXT)
178
	    break;
179
	  if (code != _URC_CONTINUE_UNWIND)
180
	    return _URC_FATAL_PHASE2_ERROR;
181
	}
182
 
183
      /* Update cur_context to describe the same frame as fs, and discard
184
	 the previous context if necessary.  */
185
      uw_advance_context (context, &fs);
186
    }
187
 
188
  return code;
189
}
190
 
191
 
192
/* Raise an exception for forced unwinding.  */
193
 
194
_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
195
_Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
196
		      _Unwind_Stop_Fn stop, void * stop_argument)
197
{
198
  struct _Unwind_Context this_context, cur_context;
199
  _Unwind_Reason_Code code;
200
 
201
  uw_init_context (&this_context);
202
  cur_context = this_context;
203
 
204
  exc->private_1 = (_Unwind_Ptr) stop;
205
  exc->private_2 = (_Unwind_Ptr) stop_argument;
206
 
207
  code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
208
  if (code != _URC_INSTALL_CONTEXT)
209
    return code;
210
 
211
  uw_install_context (&this_context, &cur_context);
212
}
213
 
214
 
215
/* Resume propagation of an existing exception.  This is used after
216
   e.g. executing cleanup code, and not to implement rethrowing.  */
217
 
218
void LIBGCC2_UNWIND_ATTRIBUTE
219
_Unwind_Resume (struct _Unwind_Exception *exc)
220
{
221
  struct _Unwind_Context this_context, cur_context;
222
  _Unwind_Reason_Code code;
223
 
224
  uw_init_context (&this_context);
225
  cur_context = this_context;
226
 
227
  /* Choose between continuing to process _Unwind_RaiseException
228
     or _Unwind_ForcedUnwind.  */
229
  if (exc->private_1 == 0)
230
    code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
231
  else
232
    code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
233
 
234
  gcc_assert (code == _URC_INSTALL_CONTEXT);
235
 
236
  uw_install_context (&this_context, &cur_context);
237
}
238
 
239
 
240
/* Resume propagation of an FORCE_UNWIND exception, or to rethrow
241
   a normal exception that was handled.  */
242
 
243
_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
244
_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
245
{
246
  struct _Unwind_Context this_context, cur_context;
247
  _Unwind_Reason_Code code;
248
 
249
  /* Choose between continuing to process _Unwind_RaiseException
250
     or _Unwind_ForcedUnwind.  */
251
  if (exc->private_1 == 0)
252
    return _Unwind_RaiseException (exc);
253
 
254
  uw_init_context (&this_context);
255
  cur_context = this_context;
256
 
257
  code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
258
 
259
  gcc_assert (code == _URC_INSTALL_CONTEXT);
260
 
261
  uw_install_context (&this_context, &cur_context);
262
}
263
 
264
 
265
/* A convenience function that calls the exception_cleanup field.  */
266
 
267
void
268
_Unwind_DeleteException (struct _Unwind_Exception *exc)
269
{
270
  if (exc->exception_cleanup)
271
    (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
272
}
273
 
274
 
275
/* Perform stack backtrace through unwind data.  */
276
 
277
_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
278
_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument)
279
{
280
  struct _Unwind_Context context;
281
  _Unwind_Reason_Code code;
282
 
283
  uw_init_context (&context);
284
 
285
  while (1)
286
    {
287
      _Unwind_FrameState fs;
288
 
289
      /* Set up fs to describe the FDE for the caller of context.  */
290
      code = uw_frame_state_for (&context, &fs);
291
      if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
292
	return _URC_FATAL_PHASE1_ERROR;
293
 
294
      /* Call trace function.  */
295
      if ((*trace) (&context, trace_argument) != _URC_NO_REASON)
296
	return _URC_FATAL_PHASE1_ERROR;
297
 
298
      /* We're done at end of stack.  */
299
      if (code == _URC_END_OF_STACK)
300
	break;
301
 
302
      /* Update context to describe the same frame as fs.  */
303
      uw_update_context (&context, &fs);
304
    }
305
 
306
  return code;
307
}