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