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