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