Mercurial > hg > CbC > CbC_gcc
comparison libstdc++-v3/libsupc++/eh_personality.cc @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 // -*- C++ -*- The GNU C++ exception personality routine. | |
2 // Copyright (C) 2001-2017 Free Software Foundation, Inc. | |
3 // | |
4 // This file is part of GCC. | |
5 // | |
6 // GCC is free software; you can redistribute it and/or modify | |
7 // it under the terms of the GNU General Public License as published by | |
8 // the Free Software Foundation; either version 3, or (at your option) | |
9 // any later version. | |
10 // | |
11 // GCC is distributed in the hope that it will be useful, | |
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 // GNU General Public License for more details. | |
15 // | |
16 // Under Section 7 of GPL version 3, you are granted additional | |
17 // permissions described in the GCC Runtime Library Exception, version | |
18 // 3.1, as published by the Free Software Foundation. | |
19 | |
20 // You should have received a copy of the GNU General Public License and | |
21 // a copy of the GCC Runtime Library Exception along with this program; | |
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 // <http://www.gnu.org/licenses/>. | |
24 | |
25 #include <bits/c++config.h> | |
26 #include <cstdlib> | |
27 #include <bits/exception_defines.h> | |
28 #include <cxxabi.h> | |
29 #include "unwind-cxx.h" | |
30 | |
31 | |
32 using namespace __cxxabiv1; | |
33 | |
34 #include "unwind-pe.h" | |
35 | |
36 | |
37 struct lsda_header_info | |
38 { | |
39 _Unwind_Ptr Start; | |
40 _Unwind_Ptr LPStart; | |
41 _Unwind_Ptr ttype_base; | |
42 const unsigned char *TType; | |
43 const unsigned char *action_table; | |
44 unsigned char ttype_encoding; | |
45 unsigned char call_site_encoding; | |
46 }; | |
47 | |
48 static const unsigned char * | |
49 parse_lsda_header (_Unwind_Context *context, const unsigned char *p, | |
50 lsda_header_info *info) | |
51 { | |
52 _uleb128_t tmp; | |
53 unsigned char lpstart_encoding; | |
54 | |
55 info->Start = (context ? _Unwind_GetRegionStart (context) : 0); | |
56 | |
57 // Find @LPStart, the base to which landing pad offsets are relative. | |
58 lpstart_encoding = *p++; | |
59 if (lpstart_encoding != DW_EH_PE_omit) | |
60 p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart); | |
61 else | |
62 info->LPStart = info->Start; | |
63 | |
64 // Find @TType, the base of the handler and exception spec type data. | |
65 info->ttype_encoding = *p++; | |
66 if (info->ttype_encoding != DW_EH_PE_omit) | |
67 { | |
68 #if _GLIBCXX_OVERRIDE_TTYPE_ENCODING | |
69 /* Older ARM EABI toolchains set this value incorrectly, so use a | |
70 hardcoded OS-specific format. */ | |
71 info->ttype_encoding = _GLIBCXX_OVERRIDE_TTYPE_ENCODING; | |
72 #endif | |
73 p = read_uleb128 (p, &tmp); | |
74 info->TType = p + tmp; | |
75 } | |
76 else | |
77 info->TType = 0; | |
78 | |
79 // The encoding and length of the call-site table; the action table | |
80 // immediately follows. | |
81 info->call_site_encoding = *p++; | |
82 p = read_uleb128 (p, &tmp); | |
83 info->action_table = p + tmp; | |
84 | |
85 return p; | |
86 } | |
87 | |
88 // Return an element from a type table. | |
89 | |
90 static const std::type_info * | |
91 get_ttype_entry (lsda_header_info *info, _uleb128_t i) | |
92 { | |
93 _Unwind_Ptr ptr; | |
94 | |
95 i *= size_of_encoded_value (info->ttype_encoding); | |
96 read_encoded_value_with_base (info->ttype_encoding, info->ttype_base, | |
97 info->TType - i, &ptr); | |
98 | |
99 return reinterpret_cast<const std::type_info *>(ptr); | |
100 } | |
101 | |
102 #ifdef __ARM_EABI_UNWINDER__ | |
103 | |
104 // The ABI provides a routine for matching exception object types. | |
105 typedef _Unwind_Control_Block _throw_typet; | |
106 #define get_adjusted_ptr(catch_type, throw_type, thrown_ptr_p) \ | |
107 (__cxa_type_match (throw_type, catch_type, false, thrown_ptr_p) \ | |
108 != ctm_failed) | |
109 | |
110 // Return true if THROW_TYPE matches one if the filter types. | |
111 | |
112 static bool | |
113 check_exception_spec(lsda_header_info* info, _throw_typet* throw_type, | |
114 void* thrown_ptr, _sleb128_t filter_value) | |
115 { | |
116 const _uleb128_t* e = ((const _uleb128_t*) info->TType) | |
117 - filter_value - 1; | |
118 | |
119 while (1) | |
120 { | |
121 const std::type_info* catch_type; | |
122 _uleb128_t tmp; | |
123 | |
124 tmp = *e; | |
125 | |
126 // Zero signals the end of the list. If we've not found | |
127 // a match by now, then we've failed the specification. | |
128 if (tmp == 0) | |
129 return false; | |
130 | |
131 tmp = _Unwind_decode_typeinfo_ptr(info->ttype_base, (_Unwind_Word) e); | |
132 | |
133 // Match a ttype entry. | |
134 catch_type = reinterpret_cast<const std::type_info*>(tmp); | |
135 | |
136 // ??? There is currently no way to ask the RTTI code about the | |
137 // relationship between two types without reference to a specific | |
138 // object. There should be; then we wouldn't need to mess with | |
139 // thrown_ptr here. | |
140 if (get_adjusted_ptr(catch_type, throw_type, &thrown_ptr)) | |
141 return true; | |
142 | |
143 // Advance to the next entry. | |
144 e++; | |
145 } | |
146 } | |
147 | |
148 | |
149 // Save stage1 handler information in the exception object | |
150 | |
151 static inline void | |
152 save_caught_exception(struct _Unwind_Exception* ue_header, | |
153 struct _Unwind_Context* context, | |
154 void* thrown_ptr, | |
155 int handler_switch_value, | |
156 const unsigned char* language_specific_data, | |
157 _Unwind_Ptr landing_pad, | |
158 const unsigned char* action_record | |
159 __attribute__((__unused__))) | |
160 { | |
161 ue_header->barrier_cache.sp = _Unwind_GetGR(context, UNWIND_STACK_REG); | |
162 ue_header->barrier_cache.bitpattern[0] = (_uw) thrown_ptr; | |
163 ue_header->barrier_cache.bitpattern[1] | |
164 = (_uw) handler_switch_value; | |
165 ue_header->barrier_cache.bitpattern[2] | |
166 = (_uw) language_specific_data; | |
167 ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad; | |
168 } | |
169 | |
170 | |
171 // Restore the catch handler data saved during phase1. | |
172 | |
173 static inline void | |
174 restore_caught_exception(struct _Unwind_Exception* ue_header, | |
175 int& handler_switch_value, | |
176 const unsigned char*& language_specific_data, | |
177 _Unwind_Ptr& landing_pad) | |
178 { | |
179 handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1]; | |
180 language_specific_data = | |
181 (const unsigned char*) ue_header->barrier_cache.bitpattern[2]; | |
182 landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3]; | |
183 } | |
184 | |
185 #define CONTINUE_UNWINDING \ | |
186 do \ | |
187 { \ | |
188 if (__gnu_unwind_frame(ue_header, context) != _URC_OK) \ | |
189 return _URC_FAILURE; \ | |
190 return _URC_CONTINUE_UNWIND; \ | |
191 } \ | |
192 while (0) | |
193 | |
194 // Return true if the filter spec is empty, ie throw(). | |
195 | |
196 static bool | |
197 empty_exception_spec (lsda_header_info *info, _Unwind_Sword filter_value) | |
198 { | |
199 const _Unwind_Word* e = ((const _Unwind_Word*) info->TType) | |
200 - filter_value - 1; | |
201 | |
202 return *e == 0; | |
203 } | |
204 | |
205 #else | |
206 typedef const std::type_info _throw_typet; | |
207 | |
208 | |
209 // Given the thrown type THROW_TYPE, pointer to a variable containing a | |
210 // pointer to the exception object THROWN_PTR_P and a type CATCH_TYPE to | |
211 // compare against, return whether or not there is a match and if so, | |
212 // update *THROWN_PTR_P. | |
213 | |
214 static bool | |
215 get_adjusted_ptr (const std::type_info *catch_type, | |
216 const std::type_info *throw_type, | |
217 void **thrown_ptr_p) | |
218 { | |
219 void *thrown_ptr = *thrown_ptr_p; | |
220 | |
221 // Pointer types need to adjust the actual pointer, not | |
222 // the pointer to pointer that is the exception object. | |
223 // This also has the effect of passing pointer types | |
224 // "by value" through the __cxa_begin_catch return value. | |
225 if (throw_type->__is_pointer_p ()) | |
226 thrown_ptr = *(void **) thrown_ptr; | |
227 | |
228 if (catch_type->__do_catch (throw_type, &thrown_ptr, 1)) | |
229 { | |
230 *thrown_ptr_p = thrown_ptr; | |
231 return true; | |
232 } | |
233 | |
234 return false; | |
235 } | |
236 | |
237 // Return true if THROW_TYPE matches one if the filter types. | |
238 | |
239 static bool | |
240 check_exception_spec(lsda_header_info* info, _throw_typet* throw_type, | |
241 void* thrown_ptr, _sleb128_t filter_value) | |
242 { | |
243 const unsigned char *e = info->TType - filter_value - 1; | |
244 | |
245 while (1) | |
246 { | |
247 const std::type_info *catch_type; | |
248 _uleb128_t tmp; | |
249 | |
250 e = read_uleb128 (e, &tmp); | |
251 | |
252 // Zero signals the end of the list. If we've not found | |
253 // a match by now, then we've failed the specification. | |
254 if (tmp == 0) | |
255 return false; | |
256 | |
257 // Match a ttype entry. | |
258 catch_type = get_ttype_entry (info, tmp); | |
259 | |
260 // ??? There is currently no way to ask the RTTI code about the | |
261 // relationship between two types without reference to a specific | |
262 // object. There should be; then we wouldn't need to mess with | |
263 // thrown_ptr here. | |
264 if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr)) | |
265 return true; | |
266 } | |
267 } | |
268 | |
269 | |
270 // Save stage1 handler information in the exception object | |
271 | |
272 static inline void | |
273 save_caught_exception(struct _Unwind_Exception* ue_header, | |
274 struct _Unwind_Context* context | |
275 __attribute__((__unused__)), | |
276 void* thrown_ptr, | |
277 int handler_switch_value, | |
278 const unsigned char* language_specific_data, | |
279 _Unwind_Ptr landing_pad __attribute__((__unused__)), | |
280 const unsigned char* action_record) | |
281 { | |
282 __cxa_exception* xh = __get_exception_header_from_ue(ue_header); | |
283 | |
284 xh->handlerSwitchValue = handler_switch_value; | |
285 xh->actionRecord = action_record; | |
286 xh->languageSpecificData = language_specific_data; | |
287 xh->adjustedPtr = thrown_ptr; | |
288 | |
289 // ??? Completely unknown what this field is supposed to be for. | |
290 // ??? Need to cache TType encoding base for call_unexpected. | |
291 xh->catchTemp = landing_pad; | |
292 } | |
293 | |
294 | |
295 // Restore the catch handler information saved during phase1. | |
296 | |
297 static inline void | |
298 restore_caught_exception(struct _Unwind_Exception* ue_header, | |
299 int& handler_switch_value, | |
300 const unsigned char*& language_specific_data, | |
301 _Unwind_Ptr& landing_pad) | |
302 { | |
303 __cxa_exception* xh = __get_exception_header_from_ue(ue_header); | |
304 handler_switch_value = xh->handlerSwitchValue; | |
305 language_specific_data = xh->languageSpecificData; | |
306 landing_pad = (_Unwind_Ptr) xh->catchTemp; | |
307 } | |
308 | |
309 #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND | |
310 | |
311 // Return true if the filter spec is empty, ie throw(). | |
312 | |
313 static bool | |
314 empty_exception_spec (lsda_header_info *info, _Unwind_Sword filter_value) | |
315 { | |
316 const unsigned char *e = info->TType - filter_value - 1; | |
317 _uleb128_t tmp; | |
318 | |
319 e = read_uleb128 (e, &tmp); | |
320 return tmp == 0; | |
321 } | |
322 | |
323 #endif // !__ARM_EABI_UNWINDER__ | |
324 | |
325 namespace __cxxabiv1 | |
326 { | |
327 | |
328 // Using a different personality function name causes link failures | |
329 // when trying to mix code using different exception handling models. | |
330 #ifdef __USING_SJLJ_EXCEPTIONS__ | |
331 #define PERSONALITY_FUNCTION __gxx_personality_sj0 | |
332 #define __builtin_eh_return_data_regno(x) x | |
333 #elif defined(__SEH__) | |
334 #define PERSONALITY_FUNCTION __gxx_personality_imp | |
335 #else | |
336 #define PERSONALITY_FUNCTION __gxx_personality_v0 | |
337 #endif | |
338 | |
339 #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__) | |
340 static | |
341 #else | |
342 extern "C" | |
343 #endif | |
344 _Unwind_Reason_Code | |
345 #ifdef __ARM_EABI_UNWINDER__ | |
346 PERSONALITY_FUNCTION (_Unwind_State state, | |
347 struct _Unwind_Exception* ue_header, | |
348 struct _Unwind_Context* context) | |
349 #else | |
350 PERSONALITY_FUNCTION (int version, | |
351 _Unwind_Action actions, | |
352 _Unwind_Exception_Class exception_class, | |
353 struct _Unwind_Exception *ue_header, | |
354 struct _Unwind_Context *context) | |
355 #endif | |
356 { | |
357 enum found_handler_type | |
358 { | |
359 found_nothing, | |
360 found_terminate, | |
361 found_cleanup, | |
362 found_handler | |
363 } found_type; | |
364 | |
365 lsda_header_info info; | |
366 const unsigned char *language_specific_data; | |
367 const unsigned char *action_record; | |
368 const unsigned char *p; | |
369 _Unwind_Ptr landing_pad, ip; | |
370 int handler_switch_value; | |
371 void* thrown_ptr = 0; | |
372 bool foreign_exception; | |
373 int ip_before_insn = 0; | |
374 | |
375 #ifdef __ARM_EABI_UNWINDER__ | |
376 _Unwind_Action actions; | |
377 | |
378 switch (state & _US_ACTION_MASK) | |
379 { | |
380 case _US_VIRTUAL_UNWIND_FRAME: | |
381 // If the unwind state pattern is | |
382 // _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND | |
383 // then we don't need to search for any handler as it is not a real | |
384 // exception. Just unwind the stack. | |
385 if (state & _US_FORCE_UNWIND) | |
386 CONTINUE_UNWINDING; | |
387 actions = _UA_SEARCH_PHASE; | |
388 break; | |
389 | |
390 case _US_UNWIND_FRAME_STARTING: | |
391 actions = _UA_CLEANUP_PHASE; | |
392 if (!(state & _US_FORCE_UNWIND) | |
393 && ue_header->barrier_cache.sp == _Unwind_GetGR(context, | |
394 UNWIND_STACK_REG)) | |
395 actions |= _UA_HANDLER_FRAME; | |
396 break; | |
397 | |
398 case _US_UNWIND_FRAME_RESUME: | |
399 CONTINUE_UNWINDING; | |
400 break; | |
401 | |
402 default: | |
403 std::abort(); | |
404 } | |
405 actions |= state & _US_FORCE_UNWIND; | |
406 | |
407 // We don't know which runtime we're working with, so can't check this. | |
408 // However the ABI routines hide this from us, and we don't actually need | |
409 // to know. | |
410 foreign_exception = false; | |
411 | |
412 // The dwarf unwinder assumes the context structure holds things like the | |
413 // function and LSDA pointers. The ARM implementation caches these in | |
414 // the exception header (UCB). To avoid rewriting everything we make a | |
415 // virtual scratch register point at the UCB. | |
416 ip = (_Unwind_Ptr) ue_header; | |
417 _Unwind_SetGR(context, UNWIND_POINTER_REG, ip); | |
418 #else | |
419 __cxa_exception* xh = __get_exception_header_from_ue(ue_header); | |
420 | |
421 // Interface version check. | |
422 if (version != 1) | |
423 return _URC_FATAL_PHASE1_ERROR; | |
424 foreign_exception = !__is_gxx_exception_class(exception_class); | |
425 #endif | |
426 | |
427 // Shortcut for phase 2 found handler for domestic exception. | |
428 if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME) | |
429 && !foreign_exception) | |
430 { | |
431 restore_caught_exception(ue_header, handler_switch_value, | |
432 language_specific_data, landing_pad); | |
433 found_type = (landing_pad == 0 ? found_terminate : found_handler); | |
434 goto install_context; | |
435 } | |
436 | |
437 language_specific_data = (const unsigned char *) | |
438 _Unwind_GetLanguageSpecificData (context); | |
439 | |
440 // If no LSDA, then there are no handlers or cleanups. | |
441 if (! language_specific_data) | |
442 CONTINUE_UNWINDING; | |
443 | |
444 // Parse the LSDA header. | |
445 p = parse_lsda_header (context, language_specific_data, &info); | |
446 info.ttype_base = base_of_encoded_value (info.ttype_encoding, context); | |
447 #ifdef _GLIBCXX_HAVE_GETIPINFO | |
448 ip = _Unwind_GetIPInfo (context, &ip_before_insn); | |
449 #else | |
450 ip = _Unwind_GetIP (context); | |
451 #endif | |
452 if (! ip_before_insn) | |
453 --ip; | |
454 landing_pad = 0; | |
455 action_record = 0; | |
456 handler_switch_value = 0; | |
457 | |
458 #ifdef __USING_SJLJ_EXCEPTIONS__ | |
459 // The given "IP" is an index into the call-site table, with two | |
460 // exceptions -- -1 means no-action, and 0 means terminate. But | |
461 // since we're using uleb128 values, we've not got random access | |
462 // to the array. | |
463 if ((int) ip < 0) | |
464 return _URC_CONTINUE_UNWIND; | |
465 else if (ip == 0) | |
466 { | |
467 // Fall through to set found_terminate. | |
468 } | |
469 else | |
470 { | |
471 _uleb128_t cs_lp, cs_action; | |
472 do | |
473 { | |
474 p = read_uleb128 (p, &cs_lp); | |
475 p = read_uleb128 (p, &cs_action); | |
476 } | |
477 while (--ip); | |
478 | |
479 // Can never have null landing pad for sjlj -- that would have | |
480 // been indicated by a -1 call site index. | |
481 landing_pad = cs_lp + 1; | |
482 if (cs_action) | |
483 action_record = info.action_table + cs_action - 1; | |
484 goto found_something; | |
485 } | |
486 #else | |
487 // Search the call-site table for the action associated with this IP. | |
488 while (p < info.action_table) | |
489 { | |
490 _Unwind_Ptr cs_start, cs_len, cs_lp; | |
491 _uleb128_t cs_action; | |
492 | |
493 // Note that all call-site encodings are "absolute" displacements. | |
494 p = read_encoded_value (0, info.call_site_encoding, p, &cs_start); | |
495 p = read_encoded_value (0, info.call_site_encoding, p, &cs_len); | |
496 p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp); | |
497 p = read_uleb128 (p, &cs_action); | |
498 | |
499 // The table is sorted, so if we've passed the ip, stop. | |
500 if (ip < info.Start + cs_start) | |
501 p = info.action_table; | |
502 else if (ip < info.Start + cs_start + cs_len) | |
503 { | |
504 if (cs_lp) | |
505 landing_pad = info.LPStart + cs_lp; | |
506 if (cs_action) | |
507 action_record = info.action_table + cs_action - 1; | |
508 goto found_something; | |
509 } | |
510 } | |
511 #endif // __USING_SJLJ_EXCEPTIONS__ | |
512 | |
513 // If ip is not present in the table, call terminate. This is for | |
514 // a destructor inside a cleanup, or a library routine the compiler | |
515 // was not expecting to throw. | |
516 found_type = found_terminate; | |
517 goto do_something; | |
518 | |
519 found_something: | |
520 if (landing_pad == 0) | |
521 { | |
522 // If ip is present, and has a null landing pad, there are | |
523 // no cleanups or handlers to be run. | |
524 found_type = found_nothing; | |
525 } | |
526 else if (action_record == 0) | |
527 { | |
528 // If ip is present, has a non-null landing pad, and a null | |
529 // action table offset, then there are only cleanups present. | |
530 // Cleanups use a zero switch value, as set above. | |
531 found_type = found_cleanup; | |
532 } | |
533 else | |
534 { | |
535 // Otherwise we have a catch handler or exception specification. | |
536 | |
537 _sleb128_t ar_filter, ar_disp; | |
538 const std::type_info* catch_type; | |
539 _throw_typet* throw_type; | |
540 bool saw_cleanup = false; | |
541 bool saw_handler = false; | |
542 | |
543 #ifdef __ARM_EABI_UNWINDER__ | |
544 // ??? How does this work - more importantly, how does it interact with | |
545 // dependent exceptions? | |
546 throw_type = ue_header; | |
547 if (actions & _UA_FORCE_UNWIND) | |
548 { | |
549 __GXX_INIT_FORCED_UNWIND_CLASS(ue_header->exception_class); | |
550 } | |
551 else if (!foreign_exception) | |
552 thrown_ptr = __get_object_from_ue (ue_header); | |
553 #else | |
554 #if __cpp_rtti | |
555 // During forced unwinding, match a magic exception type. | |
556 if (actions & _UA_FORCE_UNWIND) | |
557 { | |
558 throw_type = &typeid(abi::__forced_unwind); | |
559 } | |
560 // With a foreign exception class, there's no exception type. | |
561 // ??? What to do about GNU Java and GNU Ada exceptions? | |
562 else if (foreign_exception) | |
563 { | |
564 throw_type = &typeid(abi::__foreign_exception); | |
565 } | |
566 else | |
567 #endif | |
568 { | |
569 thrown_ptr = __get_object_from_ue (ue_header); | |
570 throw_type = __get_exception_header_from_obj | |
571 (thrown_ptr)->exceptionType; | |
572 } | |
573 #endif | |
574 | |
575 while (1) | |
576 { | |
577 p = action_record; | |
578 p = read_sleb128 (p, &ar_filter); | |
579 read_sleb128 (p, &ar_disp); | |
580 | |
581 if (ar_filter == 0) | |
582 { | |
583 // Zero filter values are cleanups. | |
584 saw_cleanup = true; | |
585 } | |
586 else if (ar_filter > 0) | |
587 { | |
588 // Positive filter values are handlers. | |
589 catch_type = get_ttype_entry (&info, ar_filter); | |
590 | |
591 // Null catch type is a catch-all handler; we can catch foreign | |
592 // exceptions with this. Otherwise we must match types. | |
593 if (! catch_type | |
594 || (throw_type | |
595 && get_adjusted_ptr (catch_type, throw_type, | |
596 &thrown_ptr))) | |
597 { | |
598 saw_handler = true; | |
599 break; | |
600 } | |
601 } | |
602 else | |
603 { | |
604 // Negative filter values are exception specifications. | |
605 // ??? How do foreign exceptions fit in? As far as I can | |
606 // see we can't match because there's no __cxa_exception | |
607 // object to stuff bits in for __cxa_call_unexpected to use. | |
608 // Allow them iff the exception spec is non-empty. I.e. | |
609 // a throw() specification results in __unexpected. | |
610 if ((throw_type | |
611 && !(actions & _UA_FORCE_UNWIND) | |
612 && !foreign_exception) | |
613 ? ! check_exception_spec (&info, throw_type, thrown_ptr, | |
614 ar_filter) | |
615 : empty_exception_spec (&info, ar_filter)) | |
616 { | |
617 saw_handler = true; | |
618 break; | |
619 } | |
620 } | |
621 | |
622 if (ar_disp == 0) | |
623 break; | |
624 action_record = p + ar_disp; | |
625 } | |
626 | |
627 if (saw_handler) | |
628 { | |
629 handler_switch_value = ar_filter; | |
630 found_type = found_handler; | |
631 } | |
632 else | |
633 found_type = (saw_cleanup ? found_cleanup : found_nothing); | |
634 } | |
635 | |
636 do_something: | |
637 if (found_type == found_nothing) | |
638 CONTINUE_UNWINDING; | |
639 | |
640 if (actions & _UA_SEARCH_PHASE) | |
641 { | |
642 if (found_type == found_cleanup) | |
643 CONTINUE_UNWINDING; | |
644 | |
645 // For domestic exceptions, we cache data from phase 1 for phase 2. | |
646 if (!foreign_exception) | |
647 { | |
648 save_caught_exception(ue_header, context, thrown_ptr, | |
649 handler_switch_value, language_specific_data, | |
650 landing_pad, action_record); | |
651 } | |
652 return _URC_HANDLER_FOUND; | |
653 } | |
654 | |
655 install_context: | |
656 | |
657 // We can't use any of the cxa routines with foreign exceptions, | |
658 // because they all expect ue_header to be a struct __cxa_exception. | |
659 // So in that case, call terminate or unexpected directly. | |
660 if ((actions & _UA_FORCE_UNWIND) | |
661 || foreign_exception) | |
662 { | |
663 if (found_type == found_terminate) | |
664 std::terminate (); | |
665 else if (handler_switch_value < 0) | |
666 { | |
667 __try | |
668 { std::unexpected (); } | |
669 __catch(...) | |
670 { std::terminate (); } | |
671 } | |
672 } | |
673 else | |
674 { | |
675 if (found_type == found_terminate) | |
676 __cxa_call_terminate(ue_header); | |
677 | |
678 // Cache the TType base value for __cxa_call_unexpected, as we won't | |
679 // have an _Unwind_Context then. | |
680 if (handler_switch_value < 0) | |
681 { | |
682 parse_lsda_header (context, language_specific_data, &info); | |
683 info.ttype_base = base_of_encoded_value (info.ttype_encoding, | |
684 context); | |
685 | |
686 #ifdef __ARM_EABI_UNWINDER__ | |
687 const _Unwind_Word* e; | |
688 _Unwind_Word n; | |
689 | |
690 e = ((const _Unwind_Word*) info.TType) - handler_switch_value - 1; | |
691 // Count the number of rtti objects. | |
692 n = 0; | |
693 while (e[n] != 0) | |
694 n++; | |
695 | |
696 // Count. | |
697 ue_header->barrier_cache.bitpattern[1] = n; | |
698 // Base | |
699 ue_header->barrier_cache.bitpattern[2] = info.ttype_base; | |
700 // Stride. | |
701 ue_header->barrier_cache.bitpattern[3] = 4; | |
702 // List head. | |
703 ue_header->barrier_cache.bitpattern[4] = (_Unwind_Word) e; | |
704 #else | |
705 xh->catchTemp = base_of_encoded_value (info.ttype_encoding, context); | |
706 #endif | |
707 } | |
708 } | |
709 | |
710 /* For targets with pointers smaller than the word size, we must extend the | |
711 pointer, and this extension is target dependent. */ | |
712 _Unwind_SetGR (context, __builtin_eh_return_data_regno (0), | |
713 __builtin_extend_pointer (ue_header)); | |
714 _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), | |
715 handler_switch_value); | |
716 _Unwind_SetIP (context, landing_pad); | |
717 #ifdef __ARM_EABI_UNWINDER__ | |
718 if (found_type == found_cleanup) | |
719 __cxa_begin_cleanup(ue_header); | |
720 #endif | |
721 return _URC_INSTALL_CONTEXT; | |
722 } | |
723 | |
724 /* The ARM EABI implementation of __cxa_call_unexpected is in a | |
725 different file so that the personality routine (PR) can be used | |
726 standalone. The generic routine shared datastructures with the PR | |
727 so it is most convenient to implement it here. */ | |
728 #ifndef __ARM_EABI_UNWINDER__ | |
729 extern "C" void | |
730 __cxa_call_unexpected (void *exc_obj_in) | |
731 { | |
732 _Unwind_Exception *exc_obj | |
733 = reinterpret_cast <_Unwind_Exception *>(exc_obj_in); | |
734 | |
735 __cxa_begin_catch (exc_obj); | |
736 | |
737 // This function is a handler for our exception argument. If we exit | |
738 // by throwing a different exception, we'll need the original cleaned up. | |
739 struct end_catch_protect | |
740 { | |
741 end_catch_protect() { } | |
742 ~end_catch_protect() { __cxa_end_catch(); } | |
743 } end_catch_protect_obj; | |
744 | |
745 lsda_header_info info; | |
746 __cxa_exception *xh = __get_exception_header_from_ue (exc_obj); | |
747 const unsigned char *xh_lsda; | |
748 _Unwind_Sword xh_switch_value; | |
749 std::terminate_handler xh_terminate_handler; | |
750 | |
751 // If the unexpectedHandler rethrows the exception (e.g. to categorize it), | |
752 // it will clobber data about the current handler. So copy the data out now. | |
753 xh_lsda = xh->languageSpecificData; | |
754 xh_switch_value = xh->handlerSwitchValue; | |
755 xh_terminate_handler = xh->terminateHandler; | |
756 info.ttype_base = (_Unwind_Ptr) xh->catchTemp; | |
757 | |
758 __try | |
759 { __unexpected (xh->unexpectedHandler); } | |
760 __catch(...) | |
761 { | |
762 // Get the exception thrown from unexpected. | |
763 | |
764 __cxa_eh_globals *globals = __cxa_get_globals_fast (); | |
765 __cxa_exception *new_xh = globals->caughtExceptions; | |
766 void *new_ptr = __get_object_from_ambiguous_exception (new_xh); | |
767 | |
768 // We don't quite have enough stuff cached; re-parse the LSDA. | |
769 parse_lsda_header (0, xh_lsda, &info); | |
770 | |
771 // If this new exception meets the exception spec, allow it. | |
772 if (check_exception_spec (&info, __get_exception_header_from_obj | |
773 (new_ptr)->exceptionType, | |
774 new_ptr, xh_switch_value)) | |
775 { __throw_exception_again; } | |
776 | |
777 // If the exception spec allows std::bad_exception, throw that. | |
778 // We don't have a thrown object to compare against, but since | |
779 // bad_exception doesn't have virtual bases, that's OK; just pass 0. | |
780 #if __cpp_exceptions && __cpp_rtti | |
781 const std::type_info &bad_exc = typeid (std::bad_exception); | |
782 if (check_exception_spec (&info, &bad_exc, 0, xh_switch_value)) | |
783 throw std::bad_exception(); | |
784 #endif | |
785 | |
786 // Otherwise, die. | |
787 __terminate (xh_terminate_handler); | |
788 } | |
789 } | |
790 #endif | |
791 | |
792 #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__) | |
793 extern "C" | |
794 EXCEPTION_DISPOSITION | |
795 __gxx_personality_seh0 (PEXCEPTION_RECORD ms_exc, void *this_frame, | |
796 PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp) | |
797 { | |
798 return _GCC_specific_handler (ms_exc, this_frame, ms_orig_context, | |
799 ms_disp, __gxx_personality_imp); | |
800 } | |
801 #endif /* SEH */ | |
802 | |
803 } // namespace __cxxabiv1 |