]>
Commit | Line | Data |
---|---|---|
19235870 RK |
1 | /**************************************************************************** |
2 | * * | |
3 | * GNAT COMPILER COMPONENTS * | |
4 | * * | |
5 | * R A I S E * | |
6 | * * | |
7 | * C Implementation File * | |
8 | * * | |
fbf5a39b | 9 | * Copyright (C) 1992-2003, Free Software Foundation, Inc. * |
19235870 RK |
10 | * * |
11 | * GNAT is free software; you can redistribute it and/or modify it under * | |
12 | * terms of the GNU General Public License as published by the Free Soft- * | |
13 | * ware Foundation; either version 2, or (at your option) any later ver- * | |
14 | * sion. GNAT is distributed in the hope that it will be useful, but WITH- * | |
15 | * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * | |
16 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * | |
17 | * for more details. You should have received a copy of the GNU General * | |
18 | * Public License distributed with GNAT; see file COPYING. If not, write * | |
19 | * to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, * | |
20 | * MA 02111-1307, USA. * | |
21 | * * | |
22 | * As a special exception, if you link this file with other files to * | |
23 | * produce an executable, this file does not by itself cause the resulting * | |
24 | * executable to be covered by the GNU General Public License. This except- * | |
25 | * ion does not however invalidate any other reasons why the executable * | |
26 | * file might be covered by the GNU Public License. * | |
27 | * * | |
28 | * GNAT was originally developed by the GNAT team at New York University. * | |
71ff80dc | 29 | * Extensive contributions were provided by Ada Core Technologies Inc. * |
19235870 RK |
30 | * * |
31 | ****************************************************************************/ | |
32 | ||
33 | /* Routines to support runtime exception handling */ | |
34 | ||
35 | #ifdef IN_RTS | |
36 | #include "tconfig.h" | |
fbf5a39b AC |
37 | /* In the top-of-tree GCC, tconfig does not include tm.h, but in GCC 3.2 |
38 | it does. To avoid branching raise.c just for that purpose, we kludge by | |
39 | looking for a symbol always defined by tm.h and if it's not defined, | |
40 | we include it. */ | |
41 | #ifndef FIRST_PSEUDO_REGISTER | |
42 | #include "coretypes.h" | |
43 | #include "tm.h" | |
44 | #endif | |
19235870 RK |
45 | #include "tsystem.h" |
46 | #include <sys/stat.h> | |
07fc65c4 GB |
47 | typedef char bool; |
48 | # define true 1 | |
49 | # define false 0 | |
19235870 RK |
50 | #else |
51 | #include "config.h" | |
52 | #include "system.h" | |
53 | #endif | |
54 | ||
55 | #include "adaint.h" | |
56 | #include "raise.h" | |
57 | ||
58 | /* We have not yet figured out how to import this directly */ | |
59 | ||
60 | void | |
61 | _gnat_builtin_longjmp (ptr, flag) | |
62 | void *ptr; | |
63 | int flag ATTRIBUTE_UNUSED; | |
64 | { | |
65 | __builtin_longjmp (ptr, 1); | |
66 | } | |
67 | ||
68 | /* When an exception is raised for which no handler exists, the procedure | |
69 | Ada.Exceptions.Unhandled_Exception is called, which performs the call to | |
70 | adafinal to complete finalization, and then prints out the error messages | |
71 | for the unhandled exception. The final step is to call this routine, which | |
72 | performs any system dependent cleanup required. */ | |
73 | ||
74 | void | |
75 | __gnat_unhandled_terminate () | |
76 | { | |
77 | /* Special termination handling for VMS */ | |
78 | ||
79 | #ifdef VMS | |
80 | { | |
81 | long prvhnd; | |
82 | ||
83 | /* Remove the exception vector so it won't intercept any errors | |
84 | in the call to exit, and go into and endless loop */ | |
85 | ||
86 | SYS$SETEXV (1, 0, 3, &prvhnd); | |
87 | __gnat_os_exit (1); | |
88 | } | |
89 | ||
90 | /* Termination handling for all other systems. */ | |
91 | ||
92 | #elif !defined (__RT__) | |
93 | __gnat_os_exit (1); | |
94 | #endif | |
95 | } | |
17c5c8a5 | 96 | |
07fc65c4 | 97 | /* Below is the code related to the integration of the GCC mechanism for |
fbf5a39b | 98 | exception handling. */ |
07fc65c4 GB |
99 | |
100 | #include "unwind.h" | |
101 | ||
fbf5a39b AC |
102 | /* The names of a couple of "standard" routines for unwinding/propagation |
103 | actually vary depending on the underlying GCC scheme for exception handling | |
104 | (SJLJ or DWARF). We need a consistently named interface to import from | |
105 | a-except, so stubs are defined here. */ | |
3d713bb8 | 106 | |
fbf5a39b AC |
107 | typedef struct _Unwind_Context _Unwind_Context; |
108 | typedef struct _Unwind_Exception _Unwind_Exception; | |
3d713bb8 | 109 | |
fbf5a39b AC |
110 | _Unwind_Reason_Code |
111 | __gnat_Unwind_RaiseException PARAMS ((_Unwind_Exception *)); | |
3d713bb8 | 112 | |
fbf5a39b AC |
113 | _Unwind_Reason_Code |
114 | __gnat_Unwind_ForcedUnwind PARAMS ((_Unwind_Exception *, void *, void *)); | |
17c5c8a5 | 115 | |
17c5c8a5 GB |
116 | |
117 | #ifdef IN_RTS /* For eh personality routine */ | |
118 | ||
17c5c8a5 | 119 | #include "dwarf2.h" |
17c5c8a5 GB |
120 | #include "unwind-dw2-fde.h" |
121 | #include "unwind-pe.h" | |
122 | ||
17c5c8a5 | 123 | |
fbf5a39b AC |
124 | /* -------------------------------------------------------------- |
125 | -- The DB stuff below is there for debugging purposes only. -- | |
126 | -------------------------------------------------------------- */ | |
17c5c8a5 | 127 | |
fbf5a39b AC |
128 | #define DB_PHASES 0x1 |
129 | #define DB_CSITE 0x2 | |
130 | #define DB_ACTIONS 0x4 | |
131 | #define DB_REGIONS 0x8 | |
132 | ||
133 | #define DB_ERR 0x1000 | |
134 | ||
135 | /* The "action" stuff below is also there for debugging purposes only. */ | |
136 | ||
137 | typedef struct | |
17c5c8a5 | 138 | { |
fbf5a39b AC |
139 | _Unwind_Action phase; |
140 | char * description; | |
141 | } phase_descriptor; | |
17c5c8a5 | 142 | |
fbf5a39b AC |
143 | static phase_descriptor phase_descriptors[] |
144 | = {{ _UA_SEARCH_PHASE, "SEARCH_PHASE" }, | |
145 | { _UA_CLEANUP_PHASE, "CLEANUP_PHASE" }, | |
146 | { _UA_HANDLER_FRAME, "HANDLER_FRAME" }, | |
147 | { _UA_FORCE_UNWIND, "FORCE_UNWIND" }, | |
148 | { -1, 0}}; | |
17c5c8a5 | 149 | |
fbf5a39b AC |
150 | static int |
151 | db_accepted_codes (void) | |
17c5c8a5 | 152 | { |
fbf5a39b | 153 | static int accepted_codes = -1; |
17c5c8a5 | 154 | |
fbf5a39b AC |
155 | if (accepted_codes == -1) |
156 | { | |
157 | char * db_env = getenv ("EH_DEBUG"); | |
17c5c8a5 | 158 | |
fbf5a39b AC |
159 | accepted_codes = db_env ? (atoi (db_env) | DB_ERR) : 0; |
160 | /* Arranged for ERR stuff to always be visible when the variable | |
161 | is defined. One may just set the variable to 0 to see the ERR | |
162 | stuff only. */ | |
163 | } | |
07fc65c4 | 164 | |
fbf5a39b AC |
165 | return accepted_codes; |
166 | } | |
167 | ||
168 | #define DB_INDENT_INCREASE 0x01 | |
169 | #define DB_INDENT_DECREASE 0x02 | |
170 | #define DB_INDENT_OUTPUT 0x04 | |
171 | #define DB_INDENT_NEWLINE 0x08 | |
172 | #define DB_INDENT_RESET 0x10 | |
173 | ||
174 | #define DB_INDENT_UNIT 8 | |
175 | ||
176 | static void | |
177 | db_indent (int requests) | |
178 | { | |
179 | static int current_indentation_level = 0; | |
180 | ||
181 | if (requests & DB_INDENT_RESET) | |
17c5c8a5 | 182 | { |
fbf5a39b | 183 | current_indentation_level = 0; |
17c5c8a5 | 184 | } |
17c5c8a5 | 185 | |
fbf5a39b AC |
186 | if (requests & DB_INDENT_INCREASE) |
187 | { | |
188 | current_indentation_level ++; | |
189 | } | |
190 | ||
191 | if (requests & DB_INDENT_DECREASE) | |
192 | { | |
193 | current_indentation_level --; | |
194 | } | |
195 | ||
196 | if (requests & DB_INDENT_NEWLINE) | |
197 | { | |
198 | fprintf (stderr, "\n"); | |
199 | } | |
200 | ||
201 | if (requests & DB_INDENT_OUTPUT) | |
202 | { | |
203 | fprintf (stderr, "%*s", | |
204 | current_indentation_level * DB_INDENT_UNIT, " "); | |
205 | } | |
17c5c8a5 | 206 | |
17c5c8a5 GB |
207 | } |
208 | ||
fbf5a39b AC |
209 | static void |
210 | db (int db_code, char * msg_format, ...) | |
211 | { | |
212 | if (db_accepted_codes () & db_code) | |
213 | { | |
214 | va_list msg_args; | |
215 | ||
216 | db_indent (DB_INDENT_OUTPUT); | |
217 | ||
218 | va_start (msg_args, msg_format); | |
219 | vfprintf (stderr, msg_format, msg_args); | |
220 | va_end (msg_args); | |
221 | } | |
222 | } | |
223 | ||
224 | static void | |
225 | db_phases (int phases) | |
17c5c8a5 | 226 | { |
fbf5a39b AC |
227 | phase_descriptor *a = phase_descriptors; |
228 | ||
229 | if (! (db_accepted_codes() & DB_PHASES)) | |
230 | return; | |
17c5c8a5 | 231 | |
fbf5a39b AC |
232 | db (DB_PHASES, "\n"); |
233 | ||
234 | for (; a->description != 0; a++) | |
235 | if (phases & a->phase) | |
236 | db (DB_PHASES, "%s ", a->description); | |
17c5c8a5 | 237 | |
fbf5a39b | 238 | db (DB_PHASES, " :\n"); |
17c5c8a5 GB |
239 | } |
240 | ||
fbf5a39b AC |
241 | |
242 | /* --------------------------------------------------------------- | |
243 | -- Now come a set of useful structures and helper routines. -- | |
244 | --------------------------------------------------------------- */ | |
245 | ||
246 | /* There are three major runtime tables involved, generated by the | |
247 | GCC back-end. Contents slightly vary depending on the underlying | |
248 | implementation scheme (dwarf zero cost / sjlj). | |
249 | ||
250 | ======================================= | |
251 | * Tables for the dwarf zero cost case * | |
252 | ======================================= | |
253 | ||
254 | call_site [] | |
255 | ------------------------------------------------------------------- | |
256 | * region-start | region-length | landing-pad | first-action-index * | |
257 | ------------------------------------------------------------------- | |
258 | ||
259 | Identify possible actions to be taken and where to resume control | |
260 | for that when an exception propagates through a pc inside the region | |
261 | delimited by start and length. | |
262 | ||
263 | A null landing-pad indicates that nothing is to be done. | |
264 | ||
265 | Otherwise, first-action-index provides an entry into the action[] | |
266 | table which heads a list of possible actions to be taken (see below). | |
267 | ||
268 | If it is determined that indeed an action should be taken, that | |
269 | is, if one action filter matches the exception beeing propagated, | |
270 | then control should be transfered to landing-pad. | |
271 | ||
272 | A null first-action-index indicates that there are only cleanups | |
273 | to run there. | |
274 | ||
275 | action [] | |
276 | ------------------------------- | |
277 | * action-filter | next-action * | |
278 | ------------------------------- | |
279 | ||
280 | This table contains lists (called action chains) of possible actions | |
281 | associated with call-site entries described in the call-site [] table. | |
282 | There is at most one action list per call-site entry. | |
283 | ||
284 | A null action-filter indicates a cleanup. | |
285 | ||
286 | Non null action-filters provide an index into the ttypes [] table | |
287 | (see below), from which information may be retrieved to check if it | |
288 | matches the exception beeing propagated. | |
289 | ||
290 | action-filter > 0 means there is a regular handler to be run, | |
291 | ||
292 | action-filter < 0 means there is a some "exception_specification" | |
293 | data to retrieve, which is only relevant for C++ | |
294 | and should never show up for Ada. | |
295 | ||
296 | next-action indexes the next entry in the list. 0 indicates there is | |
297 | no other entry. | |
298 | ||
299 | ttypes [] | |
300 | --------------- | |
301 | * ttype-value * | |
302 | --------------- | |
303 | ||
304 | A null value indicates a catch-all handler in C++, and an "others" | |
305 | handler in Ada. | |
306 | ||
307 | Non null values are used to match the exception beeing propagated: | |
308 | In C++ this is a pointer to some rtti data, while in Ada this is an | |
309 | exception id. | |
310 | ||
311 | The special id value 1 indicates an "all_others" handler. | |
312 | ||
313 | For C++, this table is actually also used to store "exception | |
314 | specification" data. The differentiation between the two kinds | |
315 | of entries is made by the sign of the associated action filter, | |
316 | which translates into positive or negative offsets from the | |
317 | so called base of the table: | |
318 | ||
319 | Exception Specification data is stored at positive offsets from | |
320 | the ttypes table base, which Exception Type data is stored at | |
321 | negative offsets: | |
322 | ||
323 | --------------------------------------------------------------------------- | |
324 | ||
325 | Here is a quick summary of the tables organization: | |
326 | ||
327 | +-- Unwind_Context (pc, ...) | |
328 | | | |
329 | |(pc) | |
330 | | | |
331 | | CALL-SITE[] | |
332 | | | |
333 | | +=============================================================+ | |
334 | | | region-start + length | landing-pad | first-action-index | | |
335 | | +=============================================================+ | |
336 | +-> | pc range 0 => no-action 0 => cleanups only | | |
337 | | !0 => jump @ N --+ | | |
338 | +====================================================== | ====+ | |
339 | | | |
340 | | | |
341 | ACTION [] | | |
342 | | | |
343 | +==========================================================+ | | |
344 | | action-filter | next-action | | | |
345 | +==========================================================+ | | |
346 | | 0 => cleanup | | | |
347 | | >0 => ttype index for handler ------+ 0 => end of chain | <-+ | |
348 | | <0 => ttype index for spec data | | | |
349 | +==================================== | ===================+ | |
350 | | | |
351 | | | |
352 | TTYPES [] | | |
353 | | Offset negated from | |
354 | +=====================+ | the actual base. | |
355 | | ttype-value | | | |
356 | +============+=====================+ | | |
357 | | | 0 => "others" | | | |
358 | | ... | 1 => "all others" | <---+ | |
359 | | | X => exception id | | |
360 | | handlers +---------------------+ | |
361 | | | ... | | |
362 | | ... | ... | | |
363 | | | ... | | |
364 | +============+=====================+ <<------ Table base | |
365 | | ... | ... | | |
366 | | specs | ... | (should not see negative filter | |
367 | | ... | ... | values for Ada). | |
368 | +============+=====================+ | |
369 | ||
370 | ||
371 | ============================ | |
372 | * Tables for the sjlj case * | |
373 | ============================ | |
374 | ||
375 | So called "function contexts" are pushed on a context stack by calls to | |
376 | _Unwind_SjLj_Register on function entry, and popped off at exit points by | |
377 | calls to _Unwind_SjLj_Unregister. The current call_site for a function is | |
378 | updated in the function context as the function's code runs along. | |
379 | ||
380 | The generic unwinding engine in _Unwind_RaiseException walks the function | |
381 | context stack and not the actual call chain. | |
382 | ||
383 | The ACTION and TTYPES tables remain unchanged, which allows to search them | |
384 | during the propagation phase to determine wether or not the propagated | |
385 | exception is handled somewhere. When it is, we only "jump" up once directly | |
386 | to the context where the handler will be found. Besides, this allows "break | |
387 | exception unhandled" to work also | |
388 | ||
389 | The CALL-SITE table is setup differently, though: the pc attached to the | |
390 | unwind context is a direct index into the table, so the entries in this | |
391 | table do not hold region bounds any more. | |
392 | ||
393 | A special index (-1) is used to indicate that no action is possibly | |
394 | connected with the context at hand, so null landing pads cannot appear | |
395 | in the table. | |
396 | ||
397 | Additionally, landing pad values in the table do not represent code address | |
398 | to jump at, but so called "dispatch" indices used by a common landing pad | |
399 | for the function to switch to the appropriate post-landing-pad. | |
400 | ||
401 | +-- Unwind_Context (pc, ...) | |
402 | | | |
403 | | pc = call-site index | |
404 | | 0 => terminate (should not see this for Ada) | |
405 | | -1 => no-action | |
406 | | | |
407 | | CALL-SITE[] | |
408 | | | |
409 | | +=====================================+ | |
410 | | | landing-pad | first-action-index | | |
411 | | +=====================================+ | |
412 | +-> | 0 => cleanups only | | |
413 | | dispatch index N | | |
414 | +=====================================+ | |
415 | ||
416 | ||
417 | =================================== | |
418 | * Basic organization of this unit * | |
419 | =================================== | |
420 | ||
421 | The major point of this unit is to provide an exception propagation | |
422 | personality routine for Ada. This is __gnat_eh_personality. | |
423 | ||
424 | It is provided with a pointer to the propagated exception, an unwind | |
425 | context describing a location the propagation is going through, and a | |
426 | couple of other arguments including a description of the current | |
427 | propagation phase. | |
428 | ||
429 | It shall return to the generic propagation engine what is to be performed | |
430 | next, after possible context adjustments, depending on what it finds in the | |
431 | traversed context (a handler for the exception, a cleanup, nothing, ...), | |
432 | and on the propagation phase. | |
433 | ||
434 | A number of structures and subroutines are used for this purpose, as | |
435 | sketched below: | |
436 | ||
437 | o region_descriptor: General data associated with the context (base pc, | |
438 | call-site table, action table, ttypes table, ...) | |
439 | ||
440 | o action_descriptor: Data describing the action to be taken for the | |
441 | propagated exception in the provided context (kind of action: nothing, | |
442 | handler, cleanup; pointer to the action table entry, ...). | |
443 | ||
444 | raise | |
445 | | | |
446 | ... (a-except.adb) | |
447 | | | |
448 | Propagate_Exception (a-exexpr.adb) | |
449 | | | |
450 | | | |
451 | _Unwind_RaiseException (libgcc) | |
452 | | | |
453 | | (Ada frame) | |
454 | | | |
455 | +--> __gnat_eh_personality (context, exception) | |
456 | | | |
457 | +--> get_region_descriptor_for (context) | |
458 | | | |
459 | +--> get_action_descriptor_for (context, exception, region) | |
460 | | | | |
461 | | +--> get_call_site_action_for (context, region) | |
462 | | (one version for each underlying scheme) | |
463 | | | |
464 | +--> setup_to_install (context) | |
465 | ||
466 | This unit is inspired from the C++ version found in eh_personality.cc, | |
467 | part of libstdc++-v3. | |
468 | ||
469 | */ | |
470 | ||
471 | ||
17c5c8a5 | 472 | /* This is the structure of exception objects as built by the GNAT runtime |
fbf5a39b | 473 | library (a-exexpr.adb). The layouts should exactly match, and the "common" |
17c5c8a5 GB |
474 | header is mandated by the exception handling ABI. */ |
475 | ||
fbf5a39b | 476 | typedef struct |
07fc65c4 | 477 | { |
fbf5a39b AC |
478 | _Unwind_Exception common; |
479 | /* ABI header, maximally aligned. */ | |
480 | ||
17c5c8a5 | 481 | _Unwind_Ptr id; |
fbf5a39b AC |
482 | /* Id of the exception beeing propagated, filled by Propagate_Exception. |
483 | ||
484 | This is compared against the ttype entries associated with actions in the | |
485 | examined context to see if one of these actions matches. */ | |
486 | ||
487 | bool handled_by_others; | |
488 | /* Indicates wether a "when others" may catch this exception, also filled by | |
489 | Propagate_Exception. | |
490 | ||
491 | This is used to decide if a GNAT_OTHERS ttype entry matches. */ | |
17c5c8a5 | 492 | |
fbf5a39b AC |
493 | int n_cleanups_to_trigger; |
494 | /* Number of cleanups on the propagation way for the occurrence. This is | |
495 | initialized to 0 by Propagate_Exception and computed by the personality | |
496 | routine during the first phase of the propagation (incremented for each | |
497 | context in which only cleanup actions match). | |
498 | ||
499 | This is used by Propagate_Exception when the occurrence is not handled, | |
500 | to control a forced unwinding phase aimed at triggering all the cleanups | |
501 | before calling Unhandled_Exception_Terminate. | |
502 | ||
503 | This is also used by __gnat_eh_personality to identify the point at which | |
504 | the notification routine shall be called for a handled occurrence. */ | |
505 | } _GNAT_Exception; | |
17c5c8a5 GB |
506 | |
507 | /* The two constants below are specific ttype identifiers for special | |
508 | exception ids. Their value is currently hardcoded at the gigi level | |
509 | (see N_Exception_Handler). */ | |
510 | ||
fbf5a39b AC |
511 | #define GNAT_OTHERS ((_Unwind_Ptr) 0x0) |
512 | #define GNAT_ALL_OTHERS ((_Unwind_Ptr) 0x1) | |
17c5c8a5 | 513 | |
fbf5a39b | 514 | /* Describe the useful region data associated with an unwind context. */ |
17c5c8a5 | 515 | |
fbf5a39b AC |
516 | typedef struct |
517 | { | |
518 | /* The base pc of the region. */ | |
519 | _Unwind_Ptr base; | |
17c5c8a5 | 520 | |
fbf5a39b AC |
521 | /* Pointer to the Language Specific Data for the region. */ |
522 | _Unwind_Ptr lsda; | |
17c5c8a5 | 523 | |
fbf5a39b AC |
524 | /* Call-Site data associated with this region. */ |
525 | unsigned char call_site_encoding; | |
526 | const unsigned char *call_site_table; | |
17c5c8a5 | 527 | |
fbf5a39b AC |
528 | /* The base to which are relative landing pad offsets inside the call-site |
529 | entries . */ | |
530 | _Unwind_Ptr lp_base; | |
17c5c8a5 | 531 | |
fbf5a39b AC |
532 | /* Action-Table associated with this region. */ |
533 | const unsigned char *action_table; | |
17c5c8a5 | 534 | |
fbf5a39b AC |
535 | /* Ttype data associated with this region. */ |
536 | unsigned char ttype_encoding; | |
537 | const unsigned char *ttype_table; | |
538 | _Unwind_Ptr ttype_base; | |
539 | ||
540 | } region_descriptor; | |
541 | ||
542 | static void | |
543 | db_region_for (region, uw_context) | |
544 | region_descriptor *region; | |
545 | _Unwind_Context *uw_context; | |
546 | { | |
547 | _Unwind_Ptr ip = _Unwind_GetIP (uw_context) - 1; | |
548 | ||
549 | if (! (db_accepted_codes () & DB_REGIONS)) | |
550 | return; | |
551 | ||
552 | db (DB_REGIONS, "For ip @ 0x%08x => ", ip); | |
553 | ||
554 | if (region->lsda) | |
555 | db (DB_REGIONS, "lsda @ 0x%x", region->lsda); | |
556 | else | |
557 | db (DB_REGIONS, "no lsda"); | |
558 | ||
559 | db (DB_REGIONS, "\n"); | |
560 | } | |
561 | ||
562 | /* Retrieve the ttype entry associated with FILTER in the REGION's | |
563 | ttype table. */ | |
564 | ||
565 | static const _Unwind_Ptr | |
566 | get_ttype_entry_for (region, filter) | |
567 | region_descriptor *region; | |
568 | long filter; | |
569 | { | |
570 | _Unwind_Ptr ttype_entry; | |
571 | ||
572 | filter *= size_of_encoded_value (region->ttype_encoding); | |
573 | read_encoded_value_with_base | |
574 | (region->ttype_encoding, region->ttype_base, | |
575 | region->ttype_table - filter, &ttype_entry); | |
576 | ||
577 | return ttype_entry; | |
578 | } | |
579 | ||
580 | /* Fill out the REGION descriptor for the provided UW_CONTEXT. */ | |
581 | ||
582 | static void | |
583 | get_region_description_for (uw_context, region) | |
584 | _Unwind_Context *uw_context; | |
585 | region_descriptor *region; | |
586 | { | |
587 | const unsigned char * p; | |
588 | _Unwind_Word tmp; | |
589 | unsigned char lpbase_encoding; | |
590 | ||
591 | /* Get the base address of the lsda information. If the provided context | |
592 | is null or if there is no associated language specific data, there's | |
593 | nothing we can/should do. */ | |
594 | region->lsda | |
595 | = (_Unwind_Ptr) (uw_context | |
596 | ? _Unwind_GetLanguageSpecificData (uw_context) : 0); | |
597 | ||
598 | if (! region->lsda) | |
599 | return; | |
600 | ||
601 | /* Parse the lsda and fill the region descriptor. */ | |
602 | p = (char *)region->lsda; | |
603 | ||
604 | region->base = _Unwind_GetRegionStart (uw_context); | |
605 | ||
606 | /* Find @LPStart, the base to which landing pad offsets are relative. */ | |
607 | lpbase_encoding = *p++; | |
608 | if (lpbase_encoding != DW_EH_PE_omit) | |
609 | p = read_encoded_value | |
610 | (uw_context, lpbase_encoding, p, ®ion->lp_base); | |
611 | else | |
612 | region->lp_base = region->base; | |
613 | ||
614 | /* Find @TType, the base of the handler and exception spec type data. */ | |
615 | region->ttype_encoding = *p++; | |
616 | if (region->ttype_encoding != DW_EH_PE_omit) | |
617 | { | |
618 | p = read_uleb128 (p, &tmp); | |
619 | region->ttype_table = p + tmp; | |
620 | } | |
621 | else | |
622 | region->ttype_table = 0; | |
623 | ||
624 | region->ttype_base | |
625 | = base_of_encoded_value (region->ttype_encoding, uw_context); | |
626 | ||
627 | /* Get the encoding and length of the call-site table; the action table | |
628 | immediately follows. */ | |
629 | region->call_site_encoding = *p++; | |
630 | region->call_site_table = read_uleb128 (p, &tmp); | |
631 | ||
632 | region->action_table = region->call_site_table + tmp; | |
633 | } | |
634 | ||
635 | ||
636 | /* Describe an action to be taken when propagating an exception up to | |
637 | some context. */ | |
638 | ||
639 | typedef enum | |
640 | { | |
641 | /* Found some call site base data, but need to analyze further | |
642 | before beeing able to decide. */ | |
643 | unknown, | |
644 | ||
645 | /* There is nothing relevant in the context at hand. */ | |
646 | nothing, | |
647 | ||
648 | /* There are only cleanups to run in this context. */ | |
649 | cleanup, | |
650 | ||
651 | /* There is a handler for the exception in this context. */ | |
652 | handler | |
653 | } action_kind; | |
17c5c8a5 | 654 | |
17c5c8a5 | 655 | |
07fc65c4 GB |
656 | typedef struct |
657 | { | |
fbf5a39b AC |
658 | /* The kind of action to be taken. */ |
659 | action_kind kind; | |
660 | ||
661 | /* A pointer to the action record entry. */ | |
662 | const unsigned char *table_entry; | |
663 | ||
664 | /* Where we should jump to actually take an action (trigger a cleanup or an | |
665 | exception handler). */ | |
666 | _Unwind_Ptr landing_pad; | |
667 | ||
668 | /* If we have a handler matching our exception, these are the filter to | |
669 | trigger it and the corresponding id. */ | |
670 | _Unwind_Sword ttype_filter; | |
671 | _Unwind_Ptr ttype_entry; | |
672 | ||
673 | } action_descriptor; | |
07fc65c4 | 674 | |
17c5c8a5 GB |
675 | |
676 | static void | |
fbf5a39b AC |
677 | db_action_for (action, uw_context) |
678 | action_descriptor *action; | |
679 | _Unwind_Context *uw_context; | |
17c5c8a5 | 680 | { |
fbf5a39b | 681 | _Unwind_Ptr ip = _Unwind_GetIP (uw_context) - 1; |
17c5c8a5 | 682 | |
fbf5a39b | 683 | db (DB_ACTIONS, "For ip @ 0x%08x => ", ip); |
17c5c8a5 | 684 | |
fbf5a39b AC |
685 | switch (action->kind) |
686 | { | |
687 | case unknown: | |
688 | db (DB_ACTIONS, "lpad @ 0x%x, record @ 0x%x\n", | |
689 | ip, action->landing_pad, action->table_entry); | |
690 | break; | |
691 | ||
692 | case nothing: | |
693 | db (DB_ACTIONS, "Nothing\n"); | |
694 | break; | |
695 | ||
696 | case cleanup: | |
697 | db (DB_ACTIONS, "Cleanup\n"); | |
698 | break; | |
699 | ||
700 | case handler: | |
701 | db (DB_ACTIONS, "Handler, filter = %d\n", action->ttype_filter); | |
702 | break; | |
703 | ||
704 | default: | |
705 | db (DB_ACTIONS, "Err? Unexpected action kind !\n"); | |
706 | break; | |
707 | } | |
17c5c8a5 | 708 | |
fbf5a39b | 709 | return; |
17c5c8a5 GB |
710 | } |
711 | ||
17c5c8a5 | 712 | |
fbf5a39b AC |
713 | /* Search the call_site_table of REGION for an entry appropriate for the |
714 | UW_CONTEXT's ip. If one is found, store the associated landing_pad and | |
715 | action_table entry, and set the ACTION kind to unknown for further | |
716 | analysis. Otherwise, set the ACTION kind to nothing. | |
17c5c8a5 | 717 | |
fbf5a39b AC |
718 | There are two variants of this routine, depending on the underlying |
719 | mechanism (dwarf/sjlj), which account for differences in the tables | |
720 | organization. | |
721 | */ | |
722 | ||
723 | #ifdef __USING_SJLJ_EXCEPTIONS__ | |
724 | ||
725 | #define __builtin_eh_return_data_regno(x) x | |
726 | ||
727 | static void | |
728 | get_call_site_action_for (uw_context, region, action) | |
729 | _Unwind_Context *uw_context; | |
730 | region_descriptor *region; | |
731 | action_descriptor *action; | |
17c5c8a5 | 732 | { |
fbf5a39b AC |
733 | _Unwind_Ptr call_site |
734 | = _Unwind_GetIP (uw_context) - 1; | |
735 | /* Subtract 1 because GetIP returns the actual call_site value + 1. */ | |
17c5c8a5 | 736 | |
fbf5a39b AC |
737 | /* call_site is a direct index into the call-site table, with two special |
738 | values : -1 for no-action and 0 for "terminate". The latter should never | |
739 | show up for Ada. To test for the former, beware that _Unwind_Ptr might be | |
740 | unsigned. */ | |
07fc65c4 | 741 | |
fbf5a39b | 742 | if ((int)call_site < 0) |
17c5c8a5 | 743 | { |
fbf5a39b AC |
744 | action->kind = nothing; |
745 | return; | |
17c5c8a5 | 746 | } |
fbf5a39b AC |
747 | else if (call_site == 0) |
748 | { | |
749 | db (DB_ERR, "========> Err, null call_site for Ada/sjlj\n"); | |
750 | action->kind = nothing; | |
751 | return; | |
752 | } | |
753 | else | |
754 | { | |
755 | _Unwind_Word cs_lp, cs_action; | |
17c5c8a5 | 756 | |
fbf5a39b AC |
757 | /* Let the caller know there may be an action to take, but let it |
758 | determine the kind. */ | |
759 | action->kind = unknown; | |
17c5c8a5 | 760 | |
fbf5a39b AC |
761 | /* We have a direct index into the call-site table, but this table is |
762 | made of leb128 values, the encoding length of which is variable. We | |
763 | can't merely compute an offset from the index, then, but have to read | |
764 | all the entries before the one of interest. */ | |
17c5c8a5 | 765 | |
fbf5a39b | 766 | const unsigned char * p = region->call_site_table; |
17c5c8a5 | 767 | |
fbf5a39b AC |
768 | do { |
769 | p = read_uleb128 (p, &cs_lp); | |
770 | p = read_uleb128 (p, &cs_action); | |
771 | } while (--call_site); | |
772 | ||
773 | ||
774 | action->landing_pad = cs_lp + 1; | |
775 | ||
776 | if (cs_action) | |
777 | action->table_entry = region->action_table + cs_action - 1; | |
778 | else | |
779 | action->table_entry = 0; | |
780 | ||
781 | return; | |
17c5c8a5 | 782 | } |
fbf5a39b AC |
783 | } |
784 | ||
785 | #else | |
786 | /* ! __USING_SJLJ_EXCEPTIONS__ */ | |
787 | ||
788 | static void | |
789 | get_call_site_action_for (uw_context, region, action) | |
790 | _Unwind_Context *uw_context; | |
791 | region_descriptor *region; | |
792 | action_descriptor *action; | |
793 | { | |
794 | _Unwind_Ptr ip | |
795 | = _Unwind_GetIP (uw_context) - 1; | |
796 | /* Substract 1 because GetIP yields a call return address while we are | |
797 | interested in information for the call point. This does not always yield | |
798 | the exact call instruction address but always brings the ip back within | |
799 | the corresponding region. | |
800 | ||
801 | ??? When unwinding up from a signal handler triggered by a trap on some | |
802 | instruction, we usually have the faulting instruction address here and | |
803 | subtracting 1 might get us into the wrong region. */ | |
07fc65c4 | 804 | |
fbf5a39b AC |
805 | const unsigned char * p |
806 | = region->call_site_table; | |
17c5c8a5 | 807 | |
fbf5a39b AC |
808 | /* Unless we are able to determine otherwise ... */ |
809 | action->kind = nothing; | |
810 | ||
811 | db (DB_CSITE, "\n"); | |
812 | ||
813 | while (p < region->action_table) | |
17c5c8a5 | 814 | { |
07fc65c4 GB |
815 | _Unwind_Ptr cs_start, cs_len, cs_lp; |
816 | _Unwind_Word cs_action; | |
17c5c8a5 GB |
817 | |
818 | /* Note that all call-site encodings are "absolute" displacements. */ | |
fbf5a39b AC |
819 | p = read_encoded_value (0, region->call_site_encoding, p, &cs_start); |
820 | p = read_encoded_value (0, region->call_site_encoding, p, &cs_len); | |
821 | p = read_encoded_value (0, region->call_site_encoding, p, &cs_lp); | |
17c5c8a5 GB |
822 | p = read_uleb128 (p, &cs_action); |
823 | ||
fbf5a39b AC |
824 | db (DB_CSITE, |
825 | "c_site @ 0x%08x (+0x%03x), len = %3d, lpad @ 0x%08x (+0x%03x)\n", | |
826 | region->base+cs_start, cs_start, cs_len, | |
827 | region->lp_base+cs_lp, cs_lp); | |
828 | ||
17c5c8a5 | 829 | /* The table is sorted, so if we've passed the ip, stop. */ |
fbf5a39b AC |
830 | if (ip < region->base + cs_start) |
831 | break; | |
832 | ||
833 | /* If we have a match, fill the ACTION fields accordingly. */ | |
834 | else if (ip < region->base + cs_start + cs_len) | |
17c5c8a5 | 835 | { |
fbf5a39b AC |
836 | /* Let the caller know there may be an action to take, but let it |
837 | determine the kind. */ | |
838 | action->kind = unknown; | |
839 | ||
17c5c8a5 | 840 | if (cs_lp) |
fbf5a39b AC |
841 | action->landing_pad = region->lp_base + cs_lp; |
842 | else | |
843 | action->landing_pad = 0; | |
844 | ||
17c5c8a5 | 845 | if (cs_action) |
fbf5a39b AC |
846 | action->table_entry = region->action_table + cs_action - 1; |
847 | else | |
848 | action->table_entry = 0; | |
849 | ||
850 | db (DB_CSITE, "+++\n"); | |
851 | return; | |
17c5c8a5 GB |
852 | } |
853 | } | |
854 | ||
fbf5a39b AC |
855 | db (DB_CSITE, "---\n"); |
856 | } | |
17c5c8a5 | 857 | |
fbf5a39b | 858 | #endif |
07fc65c4 | 859 | |
fbf5a39b AC |
860 | /* Fill out the ACTION to be taken from propagating UW_EXCEPTION up to |
861 | UW_CONTEXT in REGION. */ | |
07fc65c4 | 862 | |
fbf5a39b AC |
863 | static void |
864 | get_action_description_for (uw_context, uw_exception, region, action) | |
865 | _Unwind_Context *uw_context; | |
866 | _Unwind_Exception *uw_exception; | |
867 | region_descriptor *region; | |
868 | action_descriptor *action; | |
869 | { | |
870 | _GNAT_Exception * gnat_exception = (_GNAT_Exception *) uw_exception; | |
17c5c8a5 | 871 | |
fbf5a39b AC |
872 | /* Search the call site table first, which may get us a landing pad as well |
873 | as the head of an action record list. */ | |
874 | get_call_site_action_for (uw_context, region, action); | |
875 | db_action_for (action, uw_context); | |
17c5c8a5 | 876 | |
fbf5a39b AC |
877 | /* If there is not even a call_site entry, we are done. */ |
878 | if (action->kind == nothing) | |
879 | return; | |
17c5c8a5 | 880 | |
fbf5a39b | 881 | /* Otherwise, check what we have at the place of the call site */ |
07fc65c4 | 882 | |
fbf5a39b AC |
883 | /* No landing pad => no cleanups or handlers. */ |
884 | if (action->landing_pad == 0) | |
17c5c8a5 | 885 | { |
fbf5a39b AC |
886 | action->kind = nothing; |
887 | return; | |
17c5c8a5 | 888 | } |
fbf5a39b AC |
889 | |
890 | /* Landing pad + null table entry => only cleanups. */ | |
891 | else if (action->table_entry == 0) | |
17c5c8a5 | 892 | { |
fbf5a39b AC |
893 | action->kind = cleanup; |
894 | return; | |
17c5c8a5 | 895 | } |
fbf5a39b AC |
896 | |
897 | /* Landing pad + Table entry => handlers + possible cleanups. */ | |
17c5c8a5 GB |
898 | else |
899 | { | |
fbf5a39b | 900 | const unsigned char * p = action->table_entry; |
17c5c8a5 | 901 | |
fbf5a39b | 902 | _Unwind_Sword ar_filter, ar_disp; |
17c5c8a5 | 903 | |
fbf5a39b | 904 | action->kind = nothing; |
17c5c8a5 GB |
905 | |
906 | while (1) | |
907 | { | |
fbf5a39b AC |
908 | p = read_sleb128 (p, &ar_filter); |
909 | read_sleb128 (p, &ar_disp); | |
910 | /* Don't assign p here, as it will be incremented by ar_disp | |
911 | below. */ | |
17c5c8a5 | 912 | |
fbf5a39b | 913 | /* Null filters are for cleanups. */ |
17c5c8a5 | 914 | if (ar_filter == 0) |
fbf5a39b AC |
915 | action->kind = cleanup; |
916 | ||
917 | /* Positive filters are for regular handlers. */ | |
17c5c8a5 GB |
918 | else if (ar_filter > 0) |
919 | { | |
fbf5a39b AC |
920 | /* See if the filter we have is for an exception which matches |
921 | the one we are propagating. */ | |
922 | _Unwind_Ptr eid = get_ttype_entry_for (region, ar_filter); | |
17c5c8a5 | 923 | |
fbf5a39b AC |
924 | if (eid == gnat_exception->id |
925 | || eid == GNAT_ALL_OTHERS | |
926 | || (eid == GNAT_OTHERS && gnat_exception->handled_by_others)) | |
17c5c8a5 | 927 | { |
fbf5a39b AC |
928 | action->ttype_filter = ar_filter; |
929 | action->ttype_entry = eid; | |
930 | action->kind = handler; | |
931 | return; | |
17c5c8a5 GB |
932 | } |
933 | } | |
fbf5a39b AC |
934 | |
935 | /* Negative filter values are for C++ exception specifications. | |
936 | Should not be there for Ada :/ */ | |
17c5c8a5 | 937 | else |
fbf5a39b | 938 | db (DB_ERR, "========> Err, filter < 0 for Ada/dwarf\n"); |
17c5c8a5 | 939 | |
fbf5a39b AC |
940 | if (ar_disp == 0) |
941 | return; | |
17c5c8a5 | 942 | |
fbf5a39b AC |
943 | p += ar_disp; |
944 | } | |
945 | } | |
946 | } | |
17c5c8a5 | 947 | |
fbf5a39b AC |
948 | /* Setup in UW_CONTEXT the eh return target IP and data registers, which will |
949 | be restored with the others and retrieved by the landing pad once the jump | |
950 | occured. */ | |
07fc65c4 | 951 | |
fbf5a39b AC |
952 | static void |
953 | setup_to_install (uw_context, uw_exception, uw_landing_pad, uw_filter) | |
954 | _Unwind_Context *uw_context; | |
955 | _Unwind_Exception *uw_exception; | |
956 | int uw_filter; | |
957 | _Unwind_Ptr uw_landing_pad; | |
958 | { | |
959 | #ifndef EH_RETURN_DATA_REGNO | |
960 | /* We should not be called if the appropriate underlying support is not | |
961 | there. */ | |
962 | abort (); | |
963 | #else | |
964 | /* 1/ exception object pointer, which might be provided back to | |
965 | _Unwind_Resume (and thus to this personality routine) if we are jumping | |
966 | to a cleanup. */ | |
967 | _Unwind_SetGR (uw_context, __builtin_eh_return_data_regno (0), | |
968 | (_Unwind_Word)uw_exception); | |
969 | ||
970 | /* 2/ handler switch value register, which will also be used by the target | |
971 | landing pad to decide what action it shall take. */ | |
972 | _Unwind_SetGR (uw_context, __builtin_eh_return_data_regno (1), | |
973 | (_Unwind_Word)uw_filter); | |
974 | ||
975 | /* Setup the address we should jump at to reach the code where there is the | |
976 | "something" we found. */ | |
977 | _Unwind_SetIP (uw_context, uw_landing_pad); | |
978 | #endif | |
979 | } | |
17c5c8a5 | 980 | |
fbf5a39b AC |
981 | /* The following is defined from a-except.adb. Its purpose is to enable |
982 | automatic backtraces upon exception raise, as provided through the | |
983 | GNAT.Traceback facilities. */ | |
984 | extern void __gnat_notify_handled_exception PARAMS ((void)); | |
985 | extern void __gnat_notify_unhandled_exception PARAMS ((void)); | |
07fc65c4 | 986 | |
fbf5a39b AC |
987 | /* Below is the eh personality routine per se. We currently assume that only |
988 | GNU-Ada exceptions are met. */ | |
17c5c8a5 | 989 | |
fbf5a39b AC |
990 | _Unwind_Reason_Code |
991 | __gnat_eh_personality (uw_version, uw_phases, | |
992 | uw_exception_class, uw_exception, uw_context) | |
993 | int uw_version; | |
994 | _Unwind_Action uw_phases; | |
995 | _Unwind_Exception_Class uw_exception_class; | |
996 | _Unwind_Exception *uw_exception; | |
997 | _Unwind_Context *uw_context; | |
998 | { | |
999 | _GNAT_Exception * gnat_exception = (_GNAT_Exception *) uw_exception; | |
17c5c8a5 | 1000 | |
fbf5a39b AC |
1001 | region_descriptor region; |
1002 | action_descriptor action; | |
17c5c8a5 | 1003 | |
fbf5a39b AC |
1004 | if (uw_version != 1) |
1005 | return _URC_FATAL_PHASE1_ERROR; | |
17c5c8a5 | 1006 | |
fbf5a39b AC |
1007 | db_indent (DB_INDENT_RESET); |
1008 | db_phases (uw_phases); | |
1009 | db_indent (DB_INDENT_INCREASE); | |
1010 | ||
1011 | /* Get the region description for the context we were provided with. This | |
1012 | will tell us if there is some lsda, call_site, action and/or ttype data | |
1013 | for the associated ip. */ | |
1014 | get_region_description_for (uw_context, ®ion); | |
1015 | db_region_for (®ion, uw_context); | |
1016 | ||
1017 | /* No LSDA => no handlers or cleanups => we shall unwind further up. */ | |
1018 | if (! region.lsda) | |
1019 | return _URC_CONTINUE_UNWIND; | |
1020 | ||
1021 | /* Search the call-site and action-record tables for the action associated | |
1022 | with this IP. */ | |
1023 | get_action_description_for (uw_context, uw_exception, ®ion, &action); | |
1024 | db_action_for (&action, uw_context); | |
1025 | ||
1026 | /* Whatever the phase, if there is nothing relevant in this frame, | |
1027 | unwinding should just go on. */ | |
1028 | if (action.kind == nothing) | |
1029 | return _URC_CONTINUE_UNWIND; | |
1030 | ||
1031 | /* If we found something in search phase, we should return a code indicating | |
1032 | what to do next depending on what we found. If we only have cleanups | |
1033 | around, we shall try to unwind further up to find a handler, otherwise, | |
1034 | tell we have a handler, which will trigger the second phase. */ | |
1035 | if (uw_phases & _UA_SEARCH_PHASE) | |
1036 | { | |
1037 | if (action.kind == cleanup) | |
17c5c8a5 | 1038 | { |
fbf5a39b | 1039 | gnat_exception->n_cleanups_to_trigger ++; |
17c5c8a5 GB |
1040 | return _URC_CONTINUE_UNWIND; |
1041 | } | |
fbf5a39b AC |
1042 | else |
1043 | { | |
1044 | /* Trigger the appropriate notification routines before the second | |
1045 | phase starts, which ensures the stack is still intact. */ | |
1046 | __gnat_notify_handled_exception (); | |
17c5c8a5 | 1047 | |
fbf5a39b AC |
1048 | return _URC_HANDLER_FOUND; |
1049 | } | |
17c5c8a5 GB |
1050 | } |
1051 | ||
fbf5a39b AC |
1052 | /* We found something in cleanup/handler phase, which might be the handler |
1053 | or a cleanup for a handled occurrence, or a cleanup for an unhandled | |
1054 | occurrence (we are in a FORCED_UNWIND phase in this case). Install the | |
1055 | context to get there. */ | |
07fc65c4 | 1056 | |
fbf5a39b AC |
1057 | /* If we are going to install a cleanup context, decrement the cleanup |
1058 | count. This is required in a FORCED_UNWINDing phase (for an unhandled | |
1059 | exception), as this is used from the forced unwinding handler in | |
1060 | Ada.Exceptions.Exception_Propagation to decide wether unwinding should | |
1061 | proceed further or Unhandled_Exception_Terminate should be called. */ | |
1062 | if (action.kind == cleanup) | |
1063 | gnat_exception->n_cleanups_to_trigger --; | |
17c5c8a5 | 1064 | |
fbf5a39b AC |
1065 | setup_to_install |
1066 | (uw_context, uw_exception, action.landing_pad, action.ttype_filter); | |
17c5c8a5 | 1067 | |
fbf5a39b AC |
1068 | return _URC_INSTALL_CONTEXT; |
1069 | } | |
07fc65c4 | 1070 | |
fbf5a39b | 1071 | /* Define the consistently named stubs imported by Propagate_Exception. */ |
17c5c8a5 | 1072 | |
fbf5a39b | 1073 | #ifdef __USING_SJLJ_EXCEPTIONS__ |
07fc65c4 | 1074 | |
fbf5a39b | 1075 | #undef _Unwind_RaiseException |
17c5c8a5 | 1076 | |
fbf5a39b AC |
1077 | _Unwind_Reason_Code |
1078 | __gnat_Unwind_RaiseException (e) | |
1079 | _Unwind_Exception *e; | |
1080 | { | |
1081 | return _Unwind_SjLj_RaiseException (e); | |
1082 | } | |
17c5c8a5 | 1083 | |
17c5c8a5 | 1084 | |
fbf5a39b | 1085 | #undef _Unwind_ForcedUnwind |
17c5c8a5 | 1086 | |
fbf5a39b AC |
1087 | _Unwind_Reason_Code |
1088 | __gnat_Unwind_ForcedUnwind (e, handler, argument) | |
1089 | _Unwind_Exception *e; | |
1090 | void * handler; | |
1091 | void * argument; | |
1092 | { | |
1093 | return _Unwind_SjLj_ForcedUnwind (e, handler, argument); | |
17c5c8a5 GB |
1094 | } |
1095 | ||
1096 | ||
fbf5a39b | 1097 | #else /* __USING_SJLJ_EXCEPTIONS__ */ |
23cae84f OH |
1098 | |
1099 | _Unwind_Reason_Code | |
1100 | __gnat_Unwind_RaiseException (e) | |
fbf5a39b | 1101 | _Unwind_Exception *e; |
23cae84f | 1102 | { |
fbf5a39b | 1103 | return _Unwind_RaiseException (e); |
23cae84f OH |
1104 | } |
1105 | ||
3d713bb8 | 1106 | _Unwind_Reason_Code |
fbf5a39b AC |
1107 | __gnat_Unwind_ForcedUnwind (e, handler, argument) |
1108 | _Unwind_Exception *e; | |
1109 | void * handler; | |
1110 | void * argument; | |
23cae84f | 1111 | { |
fbf5a39b | 1112 | return _Unwind_ForcedUnwind (e, handler, argument); |
23cae84f | 1113 | } |
fbf5a39b AC |
1114 | |
1115 | #endif /* __USING_SJLJ_EXCEPTIONS__ */ | |
23cae84f OH |
1116 | |
1117 | #else | |
fbf5a39b | 1118 | /* ! IN_RTS */ |
07fc65c4 GB |
1119 | |
1120 | /* The calls to the GCC runtime interface for exception raising are currently | |
fbf5a39b AC |
1121 | issued from a-exexpr.adb, which is used by both the runtime library and the |
1122 | compiler. | |
07fc65c4 | 1123 | |
fbf5a39b AC |
1124 | As the compiler binary is not linked against the GCC runtime library, we |
1125 | need also need stubs for this interface in the compiler case. We should not | |
1126 | be using the GCC eh mechanism for the compiler, however, so expect these | |
1127 | functions never to be called. */ | |
07fc65c4 GB |
1128 | |
1129 | _Unwind_Reason_Code | |
23cae84f | 1130 | __gnat_Unwind_RaiseException (e) |
fbf5a39b | 1131 | _Unwind_Exception *e ATTRIBUTE_UNUSED; |
07fc65c4 | 1132 | { |
07fc65c4 GB |
1133 | abort (); |
1134 | } | |
1135 | ||
fbf5a39b AC |
1136 | |
1137 | _Unwind_Reason_Code | |
1138 | __gnat_Unwind_ForcedUnwind (e, handler, argument) | |
1139 | _Unwind_Exception *e ATTRIBUTE_UNUSED; | |
1140 | void * handler ATTRIBUTE_UNUSED; | |
1141 | void * argument ATTRIBUTE_UNUSED; | |
1142 | { | |
1143 | abort (); | |
1144 | } | |
1145 | ||
1146 | #endif /* IN_RTS */ |