PR rtl-optimization/82913
[official-gcc.git] / gcc / ada / raise-gcc.c
blob62a85dac12bbb753062a40e216cab361b983936e
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * R A I S E - G C C *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 1992-2017, Free Software Foundation, Inc. *
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 3, 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. *
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/>. *
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 ****************************************************************************/
32 /* Code related to the integration of the GCC mechanism for exception
33 handling. */
35 #ifndef IN_RTS
36 /* For gnat1/gnatbind compilation: use host headers. */
37 # include "config.h"
38 # include "system.h"
39 /* Don't use fancy_abort. */
40 # undef abort
41 #else
42 # ifndef CERT
43 # include "tconfig.h"
44 # include "tsystem.h"
45 # else
46 # define ATTRIBUTE_UNUSED __attribute__((unused))
47 # define HAVE_GETIPINFO 1
48 # endif
49 #endif
51 #include <stdarg.h>
53 #ifdef __cplusplus
54 # include <cstdlib>
55 #else
56 typedef char bool;
57 # define true 1
58 # define false 0
59 #endif
61 #include "raise.h"
63 #ifdef __APPLE__
64 /* On MacOS X, versions older than 10.5 don't export _Unwind_GetIPInfo. */
65 #undef HAVE_GETIPINFO
66 #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
67 #define HAVE_GETIPINFO 1
68 #endif
69 #endif
71 #if defined (__hpux__) && defined (USE_LIBUNWIND_EXCEPTIONS)
72 /* HP-UX B.11.31 ia64 libunwind doesn't have _Unwind_GetIPInfo. */
73 #undef HAVE_GETIPINFO
74 #define _UA_END_OF_STACK 0
75 #endif
77 /* The names of a couple of "standard" routines for unwinding/propagation
78 actually vary depending on the underlying GCC scheme for exception handling
79 (SJLJ or DWARF). We need a consistently named interface to import from
80 a-except, so wrappers are defined here. */
82 #ifndef IN_RTS
83 /* For gnat1/gnatbind compilation: cannot use unwind.h, as it is for the
84 target. So mimic configure...
85 This is a hack ???, the real fix is to link gnat1/gnatbind with the
86 runtime of the build compiler. */
87 # ifdef EH_MECHANISM_arm
88 # include "config/arm/unwind-arm.h"
89 # else
90 # include "unwind-generic.h"
91 # endif
92 #else
93 # include "unwind.h"
94 #endif
96 #ifdef __cplusplus
97 extern "C" {
98 #endif
100 typedef struct _Unwind_Context _Unwind_Context;
101 typedef struct _Unwind_Exception _Unwind_Exception;
103 _Unwind_Reason_Code
104 __gnat_Unwind_RaiseException (_Unwind_Exception *);
106 _Unwind_Reason_Code
107 __gnat_Unwind_ForcedUnwind (_Unwind_Exception *, _Unwind_Stop_Fn, void *);
109 extern struct Exception_Occurrence *__gnat_setup_current_excep
110 (_Unwind_Exception *);
111 extern void __gnat_unhandled_except_handler (_Unwind_Exception *);
113 #ifdef CERT
114 /* Called in case of error during propagation. */
115 extern void __gnat_raise_abort (void) __attribute__ ((noreturn));
116 #define abort() __gnat_raise_abort()
117 #endif
119 #include "unwind-pe.h"
121 #ifdef __ARM_EABI_UNWINDER__
122 /* for memcmp */
123 #include <string.h>
124 #endif
126 /* The known and handled exception classes. */
128 #ifdef __ARM_EABI_UNWINDER__
129 #define CXX_EXCEPTION_CLASS "GNUCC++"
130 #define GNAT_EXCEPTION_CLASS "GNU-Ada"
131 #else
132 #define CXX_EXCEPTION_CLASS 0x474e5543432b2b00ULL
133 #define GNAT_EXCEPTION_CLASS 0x474e552d41646100ULL
134 #endif
136 /* Structure of a C++ exception, represented as a C structure... See
137 unwind-cxx.h for the full definition. */
139 struct __cxa_exception
141 void *exceptionType;
142 void (*exceptionDestructor)(void *);
144 void (*unexpectedHandler)();
145 void (*terminateHandler)();
147 struct __cxa_exception *nextException;
149 int handlerCount;
151 #ifdef __ARM_EABI_UNWINDER__
152 struct __cxa_exception* nextPropagatingException;
154 int propagationCount;
155 #else
156 int handlerSwitchValue;
157 const unsigned char *actionRecord;
158 const unsigned char *languageSpecificData;
159 _Unwind_Ptr catchTemp;
160 void *adjustedPtr;
161 #endif
163 _Unwind_Exception unwindHeader;
166 /* --------------------------------------------------------------
167 -- The DB stuff below is there for debugging purposes only. --
168 -------------------------------------------------------------- */
170 #ifndef inhibit_libc
172 #define DB_PHASES 0x1
173 #define DB_CSITE 0x2
174 #define DB_ACTIONS 0x4
175 #define DB_REGIONS 0x8
177 #define DB_ERR 0x1000
179 /* The "action" stuff below is also there for debugging purposes only. */
181 typedef struct
183 _Unwind_Action phase;
184 const char * description;
185 } phase_descriptor;
187 static const phase_descriptor phase_descriptors[]
188 = {{ _UA_SEARCH_PHASE, "SEARCH_PHASE" },
189 { _UA_CLEANUP_PHASE, "CLEANUP_PHASE" },
190 { _UA_HANDLER_FRAME, "HANDLER_FRAME" },
191 { _UA_FORCE_UNWIND, "FORCE_UNWIND" },
192 { -1, 0}};
194 static int
195 db_accepted_codes (void)
197 static int accepted_codes = -1;
199 if (accepted_codes == -1)
201 char * db_env = (char *) getenv ("EH_DEBUG");
203 accepted_codes = db_env ? (atoi (db_env) | DB_ERR) : 0;
204 /* Arranged for ERR stuff to always be visible when the variable
205 is defined. One may just set the variable to 0 to see the ERR
206 stuff only. */
209 return accepted_codes;
212 #define DB_INDENT_INCREASE 0x01
213 #define DB_INDENT_DECREASE 0x02
214 #define DB_INDENT_OUTPUT 0x04
215 #define DB_INDENT_NEWLINE 0x08
216 #define DB_INDENT_RESET 0x10
218 #define DB_INDENT_UNIT 8
220 static void
221 db_indent (int requests)
223 static int current_indentation_level = 0;
225 if (requests & DB_INDENT_RESET)
226 current_indentation_level = 0;
228 if (requests & DB_INDENT_INCREASE)
229 current_indentation_level ++;
231 if (requests & DB_INDENT_DECREASE)
232 current_indentation_level --;
234 if (requests & DB_INDENT_NEWLINE)
235 fprintf (stderr, "\n");
237 if (requests & DB_INDENT_OUTPUT)
238 fprintf (stderr, "%*s", current_indentation_level * DB_INDENT_UNIT, " ");
241 static void ATTRIBUTE_PRINTF_2
242 db (int db_code, const char * msg_format, ...)
244 if (db_accepted_codes () & db_code)
246 va_list msg_args;
248 db_indent (DB_INDENT_OUTPUT);
250 va_start (msg_args, msg_format);
251 vfprintf (stderr, msg_format, msg_args);
252 va_end (msg_args);
256 static void
257 db_phases (int phases)
259 const phase_descriptor *a = phase_descriptors;
261 if (! (db_accepted_codes () & DB_PHASES))
262 return;
264 db (DB_PHASES, "\n");
266 for (; a->description != 0; a++)
267 if (phases & a->phase)
268 db (DB_PHASES, "%s ", a->description);
270 db (DB_PHASES, " :\n");
272 #else /* !inhibit_libc */
273 #define db_phases(X)
274 #define db_indent(X)
275 #define db(X, ...)
276 #endif /* !inhibit_libc */
278 /* ---------------------------------------------------------------
279 -- Now come a set of useful structures and helper routines. --
280 --------------------------------------------------------------- */
282 /* There are three major runtime tables involved, generated by the
283 GCC back-end. Contents slightly vary depending on the underlying
284 implementation scheme (dwarf zero cost / sjlj).
286 =======================================
287 * Tables for the dwarf zero cost case *
288 =======================================
290 They are fully documented in:
291 http://sourcery.mentor.com/public/cxx-abi/exceptions.pdf
292 Here is a shorter presentation, with some specific comments for Ada.
294 call_site []
295 -------------------------------------------------------------------
296 * region-start | region-length | landing-pad | first-action-index *
297 -------------------------------------------------------------------
299 Identify possible actions to be taken and where to resume control
300 for that when an exception propagates through a pc inside the region
301 delimited by start and length.
303 A null landing-pad indicates that nothing is to be done.
305 Otherwise, first-action-index provides an entry into the action[]
306 table which heads a list of possible actions to be taken (see below).
308 If it is determined that indeed an action should be taken, that
309 is, if one action filter matches the exception being propagated,
310 then control should be transferred to landing-pad.
312 A null first-action-index indicates that there are only cleanups
313 to run there.
315 action []
316 -------------------------------
317 * action-filter | next-action *
318 -------------------------------
320 This table contains lists (called action chains) of possible actions
321 associated with call-site entries described in the call-site [] table.
322 There is at most one action list per call-site entry. It is SLEB128
323 encoded.
325 A null action-filter indicates a cleanup.
327 Non null action-filters provide an index into the ttypes [] table
328 (see below), from which information may be retrieved to check if it
329 matches the exception being propagated.
331 * action-filter > 0:
332 means there is a regular handler to be run The value is also passed
333 to the landing pad to dispatch the exception.
335 * action-filter < 0:
336 means there is a some "exception_specification" data to retrieve,
337 which is only relevant for C++ and should never show up for Ada.
338 (Exception specification specifies which exceptions can be thrown
339 by a function. Such filter is emitted around the body of C++
340 functions defined like:
341 void foo ([...]) throw (A, B) { [...] }
342 These can be viewed as negativ filter: the landing pad is branched
343 to for exceptions that doesn't match the filter and usually aborts
344 the program).
346 * next-action
347 points to the next entry in the list using a relative byte offset. 0
348 indicates there is no other entry.
350 ttypes []
351 ---------------
352 * ttype-value *
353 ---------------
355 This table is an array of addresses.
357 A null value indicates a catch-all handler. (Not used by Ada)
359 Non null values are used to match the exception being propagated:
360 In C++ this is a pointer to some rtti data, while in Ada this is an
361 exception id (with a fake id for others).
363 For C++, this table is actually also used to store "exception
364 specification" data. The differentiation between the two kinds
365 of entries is made by the sign of the associated action filter,
366 which translates into positive or negative offsets from the
367 so called base of the table:
369 Exception Specification data is stored at positive offsets from
370 the ttypes table base, which Exception Type data is stored at
371 negative offsets:
373 ---------------------------------------------------------------------------
375 Here is a quick summary of the tables organization:
377 +-- Unwind_Context (pc, ...)
379 |(pc)
381 | CALL-SITE[]
383 | +=============================================================+
384 | | region-start + length | landing-pad | first-action-index |
385 | +=============================================================+
386 +-> | pc range 0 => no-action 0 => cleanups only |
387 | !0 => jump @ N --+ |
388 +====================================================== | ====+
391 ACTION [] |
393 +==========================================================+ |
394 | action-filter | next-action | |
395 +==========================================================+ |
396 | 0 => cleanup | |
397 | >0 => ttype index for handler ------+ 0 => end of chain | <-+
398 | <0 => ttype index for spec data | |
399 +==================================== | ===================+
402 TTYPES [] |
403 | Offset negated from
404 +=====================+ | the actual base.
405 | ttype-value | |
406 +============+=====================+ |
407 | | ... | |
408 | ... | exception id | <---+
409 | | ... |
410 | handlers +---------------------+
411 | | ... |
412 | ... | ... |
413 | | ... |
414 +============+=====================+ <<------ Table base
415 | ... | ... |
416 | specs | ... | (should not see negative filter
417 | ... | ... | values for Ada).
418 +============+=====================+
421 ============================
422 * Tables for the sjlj case *
423 ============================
425 So called "function contexts" are pushed on a context stack by calls to
426 _Unwind_SjLj_Register on function entry, and popped off at exit points by
427 calls to _Unwind_SjLj_Unregister. The current call_site for a function is
428 updated in the function context as the function's code runs along.
430 The generic unwinding engine in _Unwind_RaiseException walks the function
431 context stack and not the actual call chain.
433 The ACTION and TTYPES tables remain unchanged, which allows to search them
434 during the propagation phase to determine whether or not the propagated
435 exception is handled somewhere. When it is, we only "jump" up once directly
436 to the context where the handler will be found. Besides, this allows "break
437 exception unhandled" to work also
439 The CALL-SITE table is setup differently, though: the pc attached to the
440 unwind context is a direct index into the table, so the entries in this
441 table do not hold region bounds any more.
443 A special index (-1) is used to indicate that no action is possibly
444 connected with the context at hand, so null landing pads cannot appear
445 in the table.
447 Additionally, landing pad values in the table do not represent code address
448 to jump at, but so called "dispatch" indices used by a common landing pad
449 for the function to switch to the appropriate post-landing-pad.
451 +-- Unwind_Context (pc, ...)
453 | pc = call-site index
454 | 0 => terminate (should not see this for Ada)
455 | -1 => no-action
457 | CALL-SITE[]
459 | +=====================================+
460 | | landing-pad | first-action-index |
461 | +=====================================+
462 +-> | 0 => cleanups only |
463 | dispatch index N |
464 +=====================================+
467 ===================================
468 * Basic organization of this unit *
469 ===================================
471 The major point of this unit is to provide an exception propagation
472 personality routine for Ada. This is __gnat_personality_v0.
474 It is provided with a pointer to the propagated exception, an unwind
475 context describing a location the propagation is going through, and a
476 couple of other arguments including a description of the current
477 propagation phase.
479 It shall return to the generic propagation engine what is to be performed
480 next, after possible context adjustments, depending on what it finds in the
481 traversed context (a handler for the exception, a cleanup, nothing, ...),
482 and on the propagation phase.
484 A number of structures and subroutines are used for this purpose, as
485 sketched below:
487 o region_descriptor: General data associated with the context (base pc,
488 call-site table, action table, ttypes table, ...)
490 o action_descriptor: Data describing the action to be taken for the
491 propagated exception in the provided context (kind of action: nothing,
492 handler, cleanup; pointer to the action table entry, ...).
494 raise
496 ... (a-except.adb)
498 Propagate_Exception (a-exexpr.adb)
501 _Unwind_RaiseException (libgcc)
503 | (Ada frame)
505 +--> __gnat_personality_v0 (context, exception)
507 +--> get_region_description_for (context)
509 +--> get_action_description_for (ip, exception, region)
511 | +--> get_call_site_action_for (context, region)
512 | (one version for each underlying scheme)
514 +--> setup_to_install (context)
516 This unit is inspired from the C++ version found in eh_personality.cc,
517 part of libstdc++-v3.
522 /* This is an incomplete "proxy" of the structure of exception objects as
523 built by the GNAT runtime library. Accesses to other fields than the common
524 header are performed through subprogram calls to alleviate the need of an
525 exact counterpart here and potential alignment/size issues for the common
526 header. See a-exexpr.adb. */
528 typedef struct
530 _Unwind_Exception common;
531 /* ABI header, maximally aligned. */
532 } _GNAT_Exception;
534 /* The two constants below are specific ttype identifiers for special
535 exception ids. Their type should match what a-exexpr exports. */
537 extern const int __gnat_others_value;
538 #define GNAT_OTHERS ((_Unwind_Ptr) &__gnat_others_value)
540 extern const int __gnat_all_others_value;
541 #define GNAT_ALL_OTHERS ((_Unwind_Ptr) &__gnat_all_others_value)
543 extern const int __gnat_unhandled_others_value;
544 #define GNAT_UNHANDLED_OTHERS ((_Unwind_Ptr) &__gnat_unhandled_others_value)
546 /* Describe the useful region data associated with an unwind context. */
548 typedef struct
550 /* The base pc of the region. */
551 _Unwind_Ptr base;
553 /* Pointer to the Language Specific Data for the region. */
554 _Unwind_Ptr lsda;
556 /* Call-Site data associated with this region. */
557 unsigned char call_site_encoding;
558 const unsigned char *call_site_table;
560 /* The base to which are relative landing pad offsets inside the call-site
561 entries . */
562 _Unwind_Ptr lp_base;
564 /* Action-Table associated with this region. */
565 const unsigned char *action_table;
567 /* Ttype data associated with this region. */
568 unsigned char ttype_encoding;
569 const unsigned char *ttype_table;
570 _Unwind_Ptr ttype_base;
572 } region_descriptor;
574 /* Extract and adjust the IP (instruction pointer) from an exception
575 context. */
577 static _Unwind_Ptr
578 get_ip_from_context (_Unwind_Context *uw_context)
580 int ip_before_insn = 0;
581 #ifdef HAVE_GETIPINFO
582 _Unwind_Ptr ip = _Unwind_GetIPInfo (uw_context, &ip_before_insn);
583 #else
584 _Unwind_Ptr ip = _Unwind_GetIP (uw_context);
585 #endif
586 /* Subtract 1 if necessary because GetIPInfo yields a call return address
587 in this case, while we are interested in information for the call point.
588 This does not always yield the exact call instruction address but always
589 brings the IP back within the corresponding region. */
590 if (!ip_before_insn)
591 ip--;
593 return ip;
596 static void
597 db_region_for (region_descriptor *region, _Unwind_Ptr ip)
599 #ifndef inhibit_libc
600 if (! (db_accepted_codes () & DB_REGIONS))
601 return;
603 db (DB_REGIONS, "For ip @ %p => ", (void *)ip);
605 if (region->lsda)
606 db (DB_REGIONS, "lsda @ %p", (void *)region->lsda);
607 else
608 db (DB_REGIONS, "no lsda");
610 db (DB_REGIONS, "\n");
611 #endif
614 /* Retrieve the ttype entry associated with FILTER in the REGION's
615 ttype table. */
617 static _Unwind_Ptr
618 get_ttype_entry_for (region_descriptor *region, long filter)
620 _Unwind_Ptr ttype_entry;
622 filter *= size_of_encoded_value (region->ttype_encoding);
623 read_encoded_value_with_base
624 (region->ttype_encoding, region->ttype_base,
625 region->ttype_table - filter, &ttype_entry);
627 return ttype_entry;
630 /* Fill out the REGION descriptor for the provided UW_CONTEXT. */
632 static void
633 get_region_description_for (_Unwind_Context *uw_context,
634 region_descriptor *region)
636 const unsigned char * p;
637 _uleb128_t tmp;
638 unsigned char lpbase_encoding;
640 /* Get the base address of the lsda information. If the provided context
641 is null or if there is no associated language specific data, there's
642 nothing we can/should do. */
643 region->lsda
644 = (_Unwind_Ptr) (uw_context
645 ? _Unwind_GetLanguageSpecificData (uw_context) : 0);
647 if (! region->lsda)
648 return;
650 /* Parse the lsda and fill the region descriptor. */
651 p = (const unsigned char *)region->lsda;
653 region->base = _Unwind_GetRegionStart (uw_context);
655 /* Find @LPStart, the base to which landing pad offsets are relative. */
656 lpbase_encoding = *p++;
657 if (lpbase_encoding != DW_EH_PE_omit)
658 p = read_encoded_value
659 (uw_context, lpbase_encoding, p, &region->lp_base);
660 else
661 region->lp_base = region->base;
663 /* Find @TType, the base of the handler and exception spec type data. */
664 region->ttype_encoding = *p++;
665 if (region->ttype_encoding != DW_EH_PE_omit)
667 p = read_uleb128 (p, &tmp);
668 region->ttype_table = p + tmp;
670 else
671 region->ttype_table = 0;
673 region->ttype_base
674 = base_of_encoded_value (region->ttype_encoding, uw_context);
676 /* Get the encoding and length of the call-site table; the action table
677 immediately follows. */
678 region->call_site_encoding = *p++;
679 region->call_site_table = read_uleb128 (p, &tmp);
681 region->action_table = region->call_site_table + tmp;
685 /* Describe an action to be taken when propagating an exception up to
686 some context. */
688 enum action_kind
690 /* Found some call site base data, but need to analyze further
691 before being able to decide. */
692 unknown,
694 /* There is nothing relevant in the context at hand. */
695 nothing,
697 /* There are only cleanups to run in this context. */
698 cleanup,
700 /* There is a handler for the exception in this context. */
701 handler,
703 /* There is a handler for the exception, but it is only for catching
704 unhandled exceptions. */
705 unhandler
708 /* filter value for cleanup actions. */
709 static const int cleanup_filter = 0;
711 typedef struct
713 /* The kind of action to be taken. */
714 enum action_kind kind;
716 /* A pointer to the action record entry. */
717 const unsigned char *table_entry;
719 /* Where we should jump to actually take an action (trigger a cleanup or an
720 exception handler). */
721 _Unwind_Ptr landing_pad;
723 /* If we have a handler matching our exception, these are the filter to
724 trigger it and the corresponding id. */
725 _Unwind_Sword ttype_filter;
727 } action_descriptor;
729 static void
730 db_action_for (action_descriptor *action, _Unwind_Ptr ip)
732 #ifndef inhibit_libc
733 db (DB_ACTIONS, "For ip @ %p => ", (void *)ip);
735 switch (action->kind)
737 case unknown:
738 db (DB_ACTIONS, "lpad @ %p, record @ %p\n",
739 (void *) action->landing_pad, action->table_entry);
740 break;
742 case nothing:
743 db (DB_ACTIONS, "Nothing\n");
744 break;
746 case cleanup:
747 db (DB_ACTIONS, "Cleanup\n");
748 break;
750 case handler:
751 db (DB_ACTIONS, "Handler, filter = %d\n", (int) action->ttype_filter);
752 break;
754 default:
755 db (DB_ACTIONS, "Err? Unexpected action kind !\n");
756 break;
758 #endif
761 /* Search the call_site_table of REGION for an entry appropriate for the
762 UW_CONTEXT's IP. If one is found, store the associated landing_pad
763 and action_table entry, and set the ACTION kind to unknown for further
764 analysis. Otherwise, set the ACTION kind to nothing.
766 There are two variants of this routine, depending on the underlying
767 mechanism (DWARF/SJLJ), which account for differences in the tables. */
769 #ifdef __USING_SJLJ_EXCEPTIONS__
771 #define __builtin_eh_return_data_regno(x) x
773 static void
774 get_call_site_action_for (_Unwind_Ptr call_site,
775 region_descriptor *region,
776 action_descriptor *action)
778 /* call_site is a direct index into the call-site table, with two special
779 values : -1 for no-action and 0 for "terminate". The latter should never
780 show up for Ada. To test for the former, beware that _Unwind_Ptr might
781 be unsigned. */
783 if ((int)call_site < 0)
785 action->kind = nothing;
787 else if (call_site == 0)
789 db (DB_ERR, "========> Err, null call_site for Ada/sjlj\n");
790 action->kind = nothing;
792 else
794 _uleb128_t cs_lp, cs_action;
795 const unsigned char *p;
797 /* Let the caller know there may be an action to take, but let it
798 determine the kind. */
799 action->kind = unknown;
801 /* We have a direct index into the call-site table, but this table is
802 made of leb128 values, the encoding length of which is variable. We
803 can't merely compute an offset from the index, then, but have to read
804 all the entries before the one of interest. */
805 p = region->call_site_table;
808 p = read_uleb128 (p, &cs_lp);
809 p = read_uleb128 (p, &cs_action);
811 while (--call_site);
813 action->landing_pad = cs_lp + 1;
815 if (cs_action)
816 action->table_entry = region->action_table + cs_action - 1;
817 else
818 action->table_entry = 0;
822 #else /* !__USING_SJLJ_EXCEPTIONS__ */
824 static void
825 get_call_site_action_for (_Unwind_Ptr ip,
826 region_descriptor *region,
827 action_descriptor *action)
829 const unsigned char *p = region->call_site_table;
831 /* Unless we are able to determine otherwise... */
832 action->kind = nothing;
834 db (DB_CSITE, "\n");
836 while (p < region->action_table)
838 _Unwind_Ptr cs_start, cs_len, cs_lp;
839 _uleb128_t cs_action;
841 /* Note that all call-site encodings are "absolute" displacements. */
842 p = read_encoded_value (0, region->call_site_encoding, p, &cs_start);
843 p = read_encoded_value (0, region->call_site_encoding, p, &cs_len);
844 p = read_encoded_value (0, region->call_site_encoding, p, &cs_lp);
845 p = read_uleb128 (p, &cs_action);
847 db (DB_CSITE,
848 "c_site @ %p (+%p), len = %p, lpad @ %p (+%p)\n",
849 (char *)region->base + cs_start, (void *)cs_start, (void *)cs_len,
850 (char *)region->lp_base + cs_lp, (void *)cs_lp);
852 /* The table is sorted, so if we've passed the IP, stop. */
853 if (ip < region->base + cs_start)
854 break;
856 /* If we have a match, fill the ACTION fields accordingly. */
857 else if (ip < region->base + cs_start + cs_len)
859 /* Let the caller know there may be an action to take, but let it
860 determine the kind. */
861 action->kind = unknown;
863 if (cs_lp)
864 action->landing_pad = region->lp_base + cs_lp;
865 else
866 action->landing_pad = 0;
868 if (cs_action)
869 action->table_entry = region->action_table + cs_action - 1;
870 else
871 action->table_entry = 0;
873 db (DB_CSITE, "+++\n");
874 return;
878 db (DB_CSITE, "---\n");
881 #endif /* __USING_SJLJ_EXCEPTIONS__ */
883 /* With CHOICE an exception choice representing an "exception - when"
884 argument, and PROPAGATED_EXCEPTION a pointer to the currently propagated
885 occurrence, return true if the latter matches the former, that is, if
886 PROPAGATED_EXCEPTION is caught by the handling code controlled by CHOICE.
887 This takes care of the special Non_Ada_Error case on VMS. */
889 #define Is_Handled_By_Others __gnat_is_handled_by_others
890 #define Language_For __gnat_language_for
891 #define Foreign_Data_For __gnat_foreign_data_for
892 #define EID_For __gnat_eid_for
894 extern bool Is_Handled_By_Others (_Unwind_Ptr eid);
895 extern char Language_For (_Unwind_Ptr eid);
897 extern void *Foreign_Data_For (_Unwind_Ptr eid);
899 extern Exception_Id EID_For (_GNAT_Exception * e);
901 #define Foreign_Exception system__exceptions__foreign_exception
902 extern struct Exception_Data Foreign_Exception;
904 #ifdef VMS
905 #define Non_Ada_Error system__aux_dec__non_ada_error
906 extern struct Exception_Data Non_Ada_Error;
907 #endif
909 /* Return true iff the exception class of EXCEPT is EC. */
911 static int
912 exception_class_eq (const _GNAT_Exception *except,
913 const _Unwind_Exception_Class ec)
915 #ifdef __ARM_EABI_UNWINDER__
916 return memcmp (except->common.exception_class, ec, 8) == 0;
917 #else
918 return except->common.exception_class == ec;
919 #endif
922 /* Return how CHOICE matches PROPAGATED_EXCEPTION. */
924 static enum action_kind
925 is_handled_by (_Unwind_Ptr choice, _GNAT_Exception *propagated_exception)
927 /* All others choice match everything. */
928 if (choice == GNAT_ALL_OTHERS)
929 return handler;
931 /* GNAT exception occurrence. */
932 if (exception_class_eq (propagated_exception, GNAT_EXCEPTION_CLASS))
934 /* Pointer to the GNAT exception data corresponding to the propagated
935 occurrence. */
936 _Unwind_Ptr E = (_Unwind_Ptr) EID_For (propagated_exception);
938 if (choice == GNAT_UNHANDLED_OTHERS)
939 return unhandler;
941 E = (_Unwind_Ptr) EID_For (propagated_exception);
943 /* Base matching rules: An exception data (id) matches itself, "when
944 all_others" matches anything and "when others" matches anything
945 unless explicitly stated otherwise in the propagated occurrence. */
946 if (choice == E || (choice == GNAT_OTHERS && Is_Handled_By_Others (E)))
947 return handler;
949 #ifdef VMS
950 /* In addition, on OpenVMS, Non_Ada_Error matches VMS exceptions, and we
951 may have different exception data pointers that should match for the
952 same condition code, if both an export and an import have been
953 registered. The import code for both the choice and the propagated
954 occurrence are expected to have been masked off regarding severity
955 bits already (at registration time for the former and from within the
956 low level exception vector for the latter). */
957 if ((Language_For (E) == 'V'
958 && choice != GNAT_OTHERS
959 && ((Language_For (choice) == 'V'
960 && Foreign_Data_For (choice) != 0
961 && Foreign_Data_For (choice) == Foreign_Data_For (E))
962 || choice == (_Unwind_Ptr)&Non_Ada_Error)))
963 return handler;
964 #endif
966 /* Otherwise, it doesn't match an Ada choice. */
967 return nothing;
970 /* All others and others choice match any foreign exception. */
971 if (choice == GNAT_ALL_OTHERS
972 || choice == GNAT_OTHERS
973 #ifndef CERT
974 || choice == (_Unwind_Ptr) &Foreign_Exception
975 #endif
977 return handler;
979 #ifndef CERT
980 /* C++ exception occurrences. */
981 if (exception_class_eq (propagated_exception, CXX_EXCEPTION_CLASS)
982 && Language_For (choice) == 'C')
984 void *choice_typeinfo = Foreign_Data_For (choice);
985 void *except_typeinfo =
986 (((struct __cxa_exception *)
987 ((_Unwind_Exception *)propagated_exception + 1)) - 1)
988 ->exceptionType;
990 /* Typeinfo are directly compared, which might not be correct if they
991 aren't merged. ??? We should call the == operator if this module is
992 compiled in C++. */
993 if (choice_typeinfo == except_typeinfo)
994 return handler;
996 #endif
998 return nothing;
1001 /* Fill out the ACTION to be taken from propagating UW_EXCEPTION up to
1002 UW_CONTEXT in REGION. */
1004 static void
1005 get_action_description_for (_Unwind_Ptr ip,
1006 _Unwind_Exception *uw_exception,
1007 _Unwind_Action uw_phase,
1008 region_descriptor *region,
1009 action_descriptor *action)
1011 _GNAT_Exception *gnat_exception = (_GNAT_Exception *) uw_exception;
1013 /* Search the call site table first, which may get us a landing pad as well
1014 as the head of an action record list. */
1015 get_call_site_action_for (ip, region, action);
1016 db_action_for (action, ip);
1018 /* If there is not even a call_site entry, we are done. */
1019 if (action->kind == nothing)
1020 return;
1022 /* Otherwise, check what we have at the place of the call site. */
1024 /* No landing pad => no cleanups or handlers. */
1025 if (action->landing_pad == 0)
1027 action->kind = nothing;
1028 return;
1031 /* Landing pad + null table entry => only cleanups. */
1032 else if (action->table_entry == 0)
1034 action->kind = cleanup;
1035 action->ttype_filter = cleanup_filter;
1036 /* The filter initialization is not strictly necessary, as cleanup-only
1037 landing pads don't look at the filter value. It is there to ensure
1038 we don't pass random values and so trigger potential confusion when
1039 installing the context later on. */
1040 return;
1043 /* Landing pad + Table entry => handlers + possible cleanups. */
1044 else
1046 const unsigned char * p = action->table_entry;
1047 _sleb128_t ar_filter, ar_disp;
1049 action->kind = nothing;
1051 while (1)
1053 p = read_sleb128 (p, &ar_filter);
1054 read_sleb128 (p, &ar_disp);
1055 /* Don't assign p here, as it will be incremented by ar_disp
1056 below. */
1058 /* Null filters are for cleanups. */
1059 if (ar_filter == cleanup_filter)
1061 action->kind = cleanup;
1062 action->ttype_filter = cleanup_filter;
1063 /* The filter initialization is required here, to ensure
1064 the target landing pad branches to the cleanup code if
1065 we happen not to find a matching handler. */
1068 /* Positive filters are for regular handlers. */
1069 else if (ar_filter > 0)
1071 /* Do not catch an exception if the _UA_FORCE_UNWIND flag is
1072 passed (to follow the ABI). */
1073 if (!(uw_phase & _UA_FORCE_UNWIND))
1075 enum action_kind act;
1077 /* See if the filter we have is for an exception which
1078 matches the one we are propagating. */
1079 _Unwind_Ptr choice =
1080 get_ttype_entry_for (region, ar_filter);
1082 act = is_handled_by (choice, gnat_exception);
1083 if (act != nothing)
1085 action->kind = act;
1086 action->ttype_filter = ar_filter;
1087 return;
1092 /* Negative filter values are for C++ exception specifications.
1093 Should not be there for Ada :/ */
1094 else
1095 db (DB_ERR, "========> Err, filter < 0 for Ada/dwarf\n");
1097 if (ar_disp == 0)
1098 return;
1100 p += ar_disp;
1105 /* Setup in UW_CONTEXT the eh return target IP and data registers, which will
1106 be restored with the others and retrieved by the landing pad once the jump
1107 occurred. */
1109 static void
1110 setup_to_install (_Unwind_Context *uw_context,
1111 _Unwind_Exception *uw_exception,
1112 _Unwind_Ptr uw_landing_pad,
1113 int uw_filter)
1115 /* 1/ exception object pointer, which might be provided back to
1116 _Unwind_Resume (and thus to this personality routine) if we are jumping
1117 to a cleanup. */
1118 _Unwind_SetGR (uw_context, __builtin_eh_return_data_regno (0),
1119 (_Unwind_Word)uw_exception);
1121 /* 2/ handler switch value register, which will also be used by the target
1122 landing pad to decide what action it shall take. */
1123 _Unwind_SetGR (uw_context, __builtin_eh_return_data_regno (1),
1124 (_Unwind_Word)uw_filter);
1126 /* Setup the address we should jump at to reach the code where there is the
1127 "something" we found. */
1128 _Unwind_SetIP (uw_context, uw_landing_pad);
1131 /* The following is defined from a-except.adb. Its purpose is to enable
1132 automatic backtraces upon exception raise, as provided through the
1133 GNAT.Traceback facilities. */
1134 extern void __gnat_notify_handled_exception (struct Exception_Occurrence *);
1135 extern void __gnat_notify_unhandled_exception (struct Exception_Occurrence *);
1137 /* Below is the eh personality routine per se. We currently assume that only
1138 GNU-Ada exceptions are met. */
1140 /* By default, the personality routine is public. */
1141 #define PERSONALITY_STORAGE
1143 #ifdef __USING_SJLJ_EXCEPTIONS__
1144 #define PERSONALITY_FUNCTION __gnat_personality_sj0
1145 #elif defined (__SEH__)
1146 #define PERSONALITY_FUNCTION __gnat_personality_imp
1147 /* The public personality routine for seh is __gnat_personality_seh0, defined
1148 below using the SEH convention. This is a wrapper around the GNU routine,
1149 which is static. */
1150 #undef PERSONALITY_STORAGE
1151 #define PERSONALITY_STORAGE static
1152 #else
1153 #define PERSONALITY_FUNCTION __gnat_personality_v0
1154 #endif
1156 /* Code executed to continue unwinding. With the ARM unwinder, the
1157 personality routine must unwind one frame (per EHABI 7.3 4.). */
1159 static _Unwind_Reason_Code
1160 continue_unwind (struct _Unwind_Exception* ue_header ATTRIBUTE_UNUSED,
1161 struct _Unwind_Context* uw_context ATTRIBUTE_UNUSED)
1163 #ifdef __ARM_EABI_UNWINDER__
1164 if (__gnu_unwind_frame (ue_header, uw_context) != _URC_OK)
1165 return _URC_FAILURE;
1166 #endif
1167 return _URC_CONTINUE_UNWIND;
1170 /* Common code for the body of GNAT personality routine. This code is shared
1171 between all unwinders. */
1173 static _Unwind_Reason_Code
1174 personality_body (_Unwind_Action uw_phases,
1175 _Unwind_Exception *uw_exception,
1176 _Unwind_Context *uw_context)
1178 region_descriptor region;
1179 action_descriptor action;
1180 _Unwind_Ptr ip;
1182 /* Debug traces. */
1183 db_indent (DB_INDENT_RESET);
1184 db_phases (uw_phases);
1185 db_indent (DB_INDENT_INCREASE);
1187 /* Get the region description for the context we were provided with. This
1188 will tell us if there is some lsda, call_site, action and/or ttype data
1189 for the associated ip. */
1190 get_region_description_for (uw_context, &region);
1192 /* No LSDA => no handlers or cleanups => we shall unwind further up. */
1193 if (! region.lsda)
1194 return continue_unwind (uw_exception, uw_context);
1196 /* Get the instruction pointer. */
1197 ip = get_ip_from_context (uw_context);
1198 db_region_for (&region, ip);
1200 /* Search the call-site and action-record tables for the action associated
1201 with this IP. */
1202 get_action_description_for (ip, uw_exception, uw_phases, &region, &action);
1203 db_action_for (&action, ip);
1205 /* Whatever the phase, if there is nothing relevant in this frame,
1206 unwinding should just go on. */
1207 if (action.kind == nothing)
1208 return continue_unwind (uw_exception, uw_context);
1210 /* If we found something in search phase, we should return a code indicating
1211 what to do next depending on what we found. If we only have cleanups
1212 around, we shall try to unwind further up to find a handler, otherwise,
1213 tell we have a handler, which will trigger the second phase. */
1214 if (uw_phases & _UA_SEARCH_PHASE)
1216 if (action.kind == cleanup)
1218 return continue_unwind (uw_exception, uw_context);
1220 else
1222 #ifndef CERT
1223 struct Exception_Occurrence *excep;
1225 /* Trigger the appropriate notification routines before the second
1226 phase starts, which ensures the stack is still intact.
1227 First, setup the Ada occurrence. */
1228 excep = __gnat_setup_current_excep (uw_exception);
1229 if (action.kind == unhandler)
1230 __gnat_notify_unhandled_exception (excep);
1231 else
1232 __gnat_notify_handled_exception (excep);
1233 #endif
1235 return _URC_HANDLER_FOUND;
1239 /* We found something in cleanup/handler phase, which might be the handler
1240 or a cleanup for a handled occurrence, or a cleanup for an unhandled
1241 occurrence (we are in a FORCED_UNWIND phase in this case). Install the
1242 context to get there. */
1244 setup_to_install
1245 (uw_context, uw_exception, action.landing_pad, action.ttype_filter);
1247 #ifndef CERT
1248 /* Write current exception, so that it can be retrieved from Ada. It was
1249 already done during phase 1 (just above), but in between, one or several
1250 exceptions may have been raised (in cleanup handlers). */
1251 __gnat_setup_current_excep (uw_exception);
1252 #endif
1254 return _URC_INSTALL_CONTEXT;
1257 #ifndef __ARM_EABI_UNWINDER__
1258 /* Major tweak for ia64-vms : the CHF propagation phase calls this personality
1259 routine with sigargs/mechargs arguments and has very specific expectations
1260 on possible return values.
1262 We handle this with a number of specific tricks:
1264 1. We tweak the personality routine prototype to have the "version" and
1265 "phases" two first arguments be void * instead of int and _Unwind_Action
1266 as nominally expected in the GCC context.
1268 This allows us to access the full range of bits passed in every case and
1269 has no impact on the callers side since each argument remains assigned
1270 the same single 64bit slot.
1272 2. We retrieve the corresponding int and _Unwind_Action values within the
1273 routine for regular use with truncating conversions. This is a noop when
1274 called from the libgcc unwinder.
1276 3. We assume we're called by the VMS CHF when unexpected bits are set in
1277 both those values. The incoming arguments are then real sigargs and
1278 mechargs pointers, which we then redirect to __gnat_handle_vms_condition
1279 for proper processing.
1281 #if defined (VMS) && defined (__IA64)
1282 typedef void * version_arg_t;
1283 typedef void * phases_arg_t;
1284 #else
1285 typedef int version_arg_t;
1286 typedef _Unwind_Action phases_arg_t;
1287 #endif
1289 PERSONALITY_STORAGE _Unwind_Reason_Code
1290 PERSONALITY_FUNCTION (version_arg_t, phases_arg_t,
1291 _Unwind_Exception_Class, _Unwind_Exception *,
1292 _Unwind_Context *);
1294 PERSONALITY_STORAGE _Unwind_Reason_Code
1295 PERSONALITY_FUNCTION (version_arg_t version_arg,
1296 phases_arg_t phases_arg,
1297 _Unwind_Exception_Class uw_exception_class
1298 ATTRIBUTE_UNUSED,
1299 _Unwind_Exception *uw_exception,
1300 _Unwind_Context *uw_context)
1302 /* Fetch the version and phases args with their nominal ABI types for later
1303 use. This is a noop everywhere except on ia64-vms when called from the
1304 Condition Handling Facility. */
1305 int uw_version = (int) version_arg;
1306 _Unwind_Action uw_phases = (_Unwind_Action) phases_arg;
1308 /* Check that we're called from the ABI context we expect, with a major
1309 possible variation on VMS for IA64. */
1310 if (uw_version != 1)
1312 #if defined (VMS) && defined (__IA64)
1314 /* Assume we're called with sigargs/mechargs arguments if really
1315 unexpected bits are set in our first two formals. Redirect to the
1316 GNAT condition handling code in this case. */
1318 extern long __gnat_handle_vms_condition (void *, void *);
1320 unsigned int version_unexpected_bits_mask = 0xffffff00U;
1321 unsigned int phases_unexpected_bits_mask = 0xffffff00U;
1323 if ((unsigned int)uw_version & version_unexpected_bits_mask
1324 && (unsigned int)uw_phases & phases_unexpected_bits_mask)
1325 return __gnat_handle_vms_condition (version_arg, phases_arg);
1326 #endif
1328 return _URC_FATAL_PHASE1_ERROR;
1331 return personality_body (uw_phases, uw_exception, uw_context);
1334 #else /* __ARM_EABI_UNWINDER__ */
1336 PERSONALITY_STORAGE _Unwind_Reason_Code
1337 PERSONALITY_FUNCTION (_Unwind_State state,
1338 struct _Unwind_Exception* ue_header,
1339 struct _Unwind_Context* uw_context);
1341 PERSONALITY_STORAGE _Unwind_Reason_Code
1342 PERSONALITY_FUNCTION (_Unwind_State state,
1343 struct _Unwind_Exception* uw_exception,
1344 struct _Unwind_Context* uw_context)
1346 _Unwind_Action uw_phases;
1348 switch (state & _US_ACTION_MASK)
1350 case _US_VIRTUAL_UNWIND_FRAME:
1351 /* Phase 1. */
1352 uw_phases = _UA_SEARCH_PHASE;
1353 break;
1355 case _US_UNWIND_FRAME_STARTING:
1356 /* Phase 2, to call a cleanup. */
1357 uw_phases = _UA_CLEANUP_PHASE;
1358 #if 0
1359 /* ??? We don't use UA_HANDLER_FRAME (except to debug). Futhermore,
1360 barrier_cache.sp isn't yet set. */
1361 if (!(state & _US_FORCE_UNWIND)
1362 && (uw_exception->barrier_cache.sp
1363 == _Unwind_GetGR (uw_context, UNWIND_STACK_REG)))
1364 uw_phases |= _UA_HANDLER_FRAME;
1365 #endif
1366 break;
1368 case _US_UNWIND_FRAME_RESUME:
1369 /* Phase 2, called at the return of a cleanup. In the GNU
1370 implementation, there is nothing left to do, so we simply go on. */
1371 return continue_unwind (uw_exception, uw_context);
1373 default:
1374 return _URC_FAILURE;
1376 uw_phases |= (state & _US_FORCE_UNWIND);
1378 /* The dwarf unwinder assumes the context structure holds things like the
1379 function and LSDA pointers. The ARM implementation caches these in
1380 the exception header (UCB). To avoid rewriting everything we make a
1381 virtual scratch register point at the UCB. This is a GNU specific
1382 requirement. */
1383 _Unwind_SetGR (uw_context, UNWIND_POINTER_REG, (_Unwind_Ptr) uw_exception);
1385 return personality_body (uw_phases, uw_exception, uw_context);
1387 #endif /* __ARM_EABI_UNWINDER__ */
1389 /* Callback routine called by Unwind_ForcedUnwind to execute all the cleanup
1390 before exiting the task. */
1392 #ifndef CERT
1393 _Unwind_Reason_Code
1394 __gnat_cleanupunwind_handler (int version ATTRIBUTE_UNUSED,
1395 _Unwind_Action phases,
1396 _Unwind_Exception_Class eclass ATTRIBUTE_UNUSED,
1397 struct _Unwind_Exception *exception,
1398 struct _Unwind_Context *context ATTRIBUTE_UNUSED,
1399 void *arg ATTRIBUTE_UNUSED)
1401 /* Terminate when the end of the stack is reached. */
1402 if ((phases & _UA_END_OF_STACK) != 0
1403 #if defined (__ia64__) && defined (__hpux__) && defined (USE_LIBUNWIND_EXCEPTIONS)
1404 /* Strictely follow the ia64 ABI: when end of stack is reached,
1405 the callback will be called with a NULL stack pointer.
1406 No need for that when using libgcc unwinder. */
1407 || _Unwind_GetGR (context, 12) == 0
1408 #endif
1410 __gnat_unhandled_except_handler (exception);
1412 /* We know there is at least one cleanup further up. Return so that it
1413 is searched and entered, after which Unwind_Resume will be called
1414 and this hook will gain control again. */
1415 return _URC_NO_REASON;
1417 #endif
1419 /* Define the consistently named wrappers imported by Propagate_Exception. */
1421 _Unwind_Reason_Code
1422 __gnat_Unwind_RaiseException (_Unwind_Exception *e)
1424 #ifdef __USING_SJLJ_EXCEPTIONS__
1425 return _Unwind_SjLj_RaiseException (e);
1426 #else
1427 return _Unwind_RaiseException (e);
1428 #endif
1431 _Unwind_Reason_Code
1432 __gnat_Unwind_ForcedUnwind (_Unwind_Exception *e ATTRIBUTE_UNUSED,
1433 _Unwind_Stop_Fn handler ATTRIBUTE_UNUSED,
1434 void *argument ATTRIBUTE_UNUSED)
1436 #ifdef __USING_SJLJ_EXCEPTIONS__
1438 # if defined (__APPLE__) && defined (__arm__)
1439 /* There is not ForcedUnwind routine in arm-darwin system library. */
1440 return _URC_FATAL_PHASE1_ERROR;
1441 # else
1442 return _Unwind_SjLj_ForcedUnwind (e, handler, argument);
1443 # endif
1445 #else
1446 return _Unwind_ForcedUnwind (e, handler, argument);
1447 #endif
1450 #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__)
1452 #define STATUS_USER_DEFINED (1U << 29)
1454 /* From unwind-seh.c. */
1455 #define GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C')
1456 #define GCC_EXCEPTION(TYPE) \
1457 (STATUS_USER_DEFINED | ((TYPE) << 24) | GCC_MAGIC)
1458 #define STATUS_GCC_THROW GCC_EXCEPTION (0)
1460 EXCEPTION_DISPOSITION __gnat_SEH_error_handler
1461 (struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*);
1463 struct Exception_Data *
1464 __gnat_map_SEH (EXCEPTION_RECORD* ExceptionRecord, const char **msg);
1466 struct _Unwind_Exception *
1467 __gnat_create_machine_occurrence_from_signal_handler (Exception_Id,
1468 const char *);
1470 /* Unwind opcodes. */
1471 #define UWOP_PUSH_NONVOL 0
1472 #define UWOP_ALLOC_LARGE 1
1473 #define UWOP_ALLOC_SMALL 2
1474 #define UWOP_SET_FPREG 3
1475 #define UWOP_SAVE_NONVOL 4
1476 #define UWOP_SAVE_NONVOL_FAR 5
1477 #define UWOP_SAVE_XMM128 8
1478 #define UWOP_SAVE_XMM128_FAR 9
1479 #define UWOP_PUSH_MACHFRAME 10
1481 /* Modify the IP value saved in the machine frame. This is really a kludge,
1482 that will be removed if we could propagate the Windows exception (and not
1483 the GCC one).
1484 What is very wrong is that the Windows unwinder will try to decode the
1485 instruction at IP, which isn't valid anymore after the adjust. */
1487 static void
1488 __gnat_adjust_context (unsigned char *unw, ULONG64 rsp)
1490 unsigned int len;
1492 /* Version = 1, no flags, no prologue. */
1493 if (unw[0] != 1 || unw[1] != 0)
1494 return;
1495 len = unw[2];
1496 /* No frame pointer. */
1497 if (unw[3] != 0)
1498 return;
1499 unw += 4;
1500 while (len > 0)
1502 /* Offset in prologue = 0. */
1503 if (unw[0] != 0)
1504 return;
1505 switch (unw[1] & 0xf)
1507 case UWOP_ALLOC_LARGE:
1508 /* Expect < 512KB. */
1509 if ((unw[1] & 0xf0) != 0)
1510 return;
1511 rsp += *(unsigned short *)(unw + 2) * 8;
1512 len--;
1513 unw += 2;
1514 break;
1515 case UWOP_SAVE_NONVOL:
1516 case UWOP_SAVE_XMM128:
1517 len--;
1518 unw += 2;
1519 break;
1520 case UWOP_PUSH_MACHFRAME:
1522 ULONG64 *rip;
1523 rip = (ULONG64 *)rsp;
1524 if ((unw[1] & 0xf0) == 0x10)
1525 rip++;
1526 /* Adjust rip. */
1527 (*rip)++;
1529 return;
1530 default:
1531 /* Unexpected. */
1532 return;
1534 unw += 2;
1535 len--;
1539 EXCEPTION_DISPOSITION
1540 __gnat_personality_seh0 (PEXCEPTION_RECORD ms_exc, void *this_frame,
1541 PCONTEXT ms_orig_context,
1542 PDISPATCHER_CONTEXT ms_disp)
1544 /* Possibly transform run-time errors into Ada exceptions. As a small
1545 optimization, we call __gnat_SEH_error_handler only on non-user
1546 exceptions. */
1547 if (!(ms_exc->ExceptionCode & STATUS_USER_DEFINED))
1549 struct Exception_Data *exception;
1550 const char *msg;
1551 ULONG64 excpip = (ULONG64) ms_exc->ExceptionAddress;
1553 if (excpip != 0
1554 && excpip >= (ms_disp->ImageBase
1555 + ms_disp->FunctionEntry->BeginAddress)
1556 && excpip < (ms_disp->ImageBase
1557 + ms_disp->FunctionEntry->EndAddress))
1559 /* This is a fault in this function. We need to adjust the return
1560 address before raising the GCC exception. */
1561 CONTEXT context;
1562 PRUNTIME_FUNCTION mf_func = NULL;
1563 ULONG64 mf_imagebase;
1564 ULONG64 mf_rsp = 0;
1566 /* Get the context. */
1567 RtlCaptureContext (&context);
1569 while (1)
1571 PRUNTIME_FUNCTION RuntimeFunction;
1572 ULONG64 ImageBase;
1573 VOID *HandlerData;
1574 ULONG64 EstablisherFrame;
1576 /* Get function metadata. */
1577 RuntimeFunction = RtlLookupFunctionEntry
1578 (context.Rip, &ImageBase, ms_disp->HistoryTable);
1579 if (RuntimeFunction == ms_disp->FunctionEntry)
1580 break;
1581 mf_func = RuntimeFunction;
1582 mf_imagebase = ImageBase;
1583 mf_rsp = context.Rsp;
1585 if (!RuntimeFunction)
1587 /* In case of failure, assume this is a leaf function. */
1588 context.Rip = *(ULONG64 *) context.Rsp;
1589 context.Rsp += 8;
1591 else
1593 /* Unwind. */
1594 RtlVirtualUnwind (0, ImageBase, context.Rip, RuntimeFunction,
1595 &context, &HandlerData, &EstablisherFrame,
1596 NULL);
1599 /* 0 means bottom of the stack. */
1600 if (context.Rip == 0)
1602 mf_func = NULL;
1603 break;
1606 if (mf_func != NULL)
1607 __gnat_adjust_context
1608 ((unsigned char *)(mf_imagebase + mf_func->UnwindData), mf_rsp);
1611 exception = __gnat_map_SEH (ms_exc, &msg);
1612 if (exception != NULL)
1614 struct _Unwind_Exception *exc;
1616 /* Directly convert the system exception to a GCC one.
1617 This is really breaking the API, but is necessary for stack size
1618 reasons: the normal way is to call Raise_From_Signal_Handler,
1619 which build the exception and calls _Unwind_RaiseException, which
1620 unwinds the stack and will call this personality routine. But
1621 the Windows unwinder needs about 2KB of stack. */
1622 exc = __gnat_create_machine_occurrence_from_signal_handler
1623 (exception, msg);
1624 memset (exc->private_, 0, sizeof (exc->private_));
1625 ms_exc->ExceptionCode = STATUS_GCC_THROW;
1626 ms_exc->NumberParameters = 1;
1627 ms_exc->ExceptionInformation[0] = (ULONG_PTR)exc;
1632 return _GCC_specific_handler (ms_exc, this_frame, ms_orig_context,
1633 ms_disp, __gnat_personality_imp);
1635 #endif /* SEH */
1637 #if !defined (__USING_SJLJ_EXCEPTIONS__)
1638 /* Size of the _Unwind_Exception structure. This is used by g-cppexc to get
1639 the offset to the C++ object. */
1641 const int __gnat_unwind_exception_size = sizeof (_Unwind_Exception);
1642 #endif
1644 #ifdef __cplusplus
1646 #endif