1//===------------------------- cxa_exception.cpp --------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is dual licensed under the MIT and the University of Illinois Open 6// Source Licenses. See LICENSE.TXT for details. 7// 8// 9// This file implements the "Exception Handling APIs" 10// http://mentorembedded.github.io/cxx-abi/abi-eh.html 11// http://www.intel.com/design/itanium/downloads/245358.htm 12// 13//===----------------------------------------------------------------------===// 14 15#include <assert.h> 16#include <stdlib.h> 17#include <string.h> 18#include <typeinfo> 19 20#include "config.h" 21#include "cxa_exception.hpp" 22#include "cxa_handlers.hpp" 23#include "private_typeinfo.h" 24#include "unwind.h" 25 26/* 27 Exception Header Layout: 28 29+---------------------------+-----------------------------+---------------+ 30| __cxa_exception | _Unwind_Exception CLNGC++\0 | thrown object | 31+---------------------------+-----------------------------+---------------+ 32 ^ 33 | 34 +-------------------------------------------------------+ 35 | 36+---------------------------+-----------------------------+ 37| __cxa_dependent_exception | _Unwind_Exception CLNGC++\1 | 38+---------------------------+-----------------------------+ 39 40 Exception Handling Table Layout: 41 42+-----------------+--------+ 43| lpStartEncoding | (char) | 44+---------+-------+--------+---------------+-----------------------+ 45| lpStart | (encoded with lpStartEncoding) | defaults to funcStart | 46+---------+-----+--------+-----------------+---------------+-------+ 47| ttypeEncoding | (char) | Encoding of the type_info table | 48+---------------+-+------+----+----------------------------+----------------+ 49| classInfoOffset | (ULEB128) | Offset to type_info table, defaults to null | 50+-----------------++--------+-+----------------------------+----------------+ 51| callSiteEncoding | (char) | Encoding for Call Site Table | 52+------------------+--+-----+-----+------------------------+--------------------------+ 53| callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table | 54+---------------------+-----------+---------------------------------------------------+ 55#ifndef __USING_SJLJ_EXCEPTIONS__ 56+---------------------+-----------+------------------------------------------------+ 57| Beginning of Call Site Table The current ip lies within the | 58| ... (start, length) range of one of these | 59| call sites. There may be action needed. | 60| +-------------+---------------------------------+------------------------------+ | 61| | start | (encoded with callSiteEncoding) | offset relative to funcStart | | 62| | length | (encoded with callSiteEncoding) | length of code fragment | | 63| | landingPad | (encoded with callSiteEncoding) | offset relative to lpStart | | 64| | actionEntry | (ULEB128) | Action Table Index 1-based | | 65| | | | actionEntry == 0 -> cleanup | | 66| +-------------+---------------------------------+------------------------------+ | 67| ... | 68+----------------------------------------------------------------------------------+ 69#else // __USING_SJLJ_EXCEPTIONS__ 70+---------------------+-----------+------------------------------------------------+ 71| Beginning of Call Site Table The current ip is a 1-based index into | 72| ... this table. Or it is -1 meaning no | 73| action is needed. Or it is 0 meaning | 74| terminate. | 75| +-------------+---------------------------------+------------------------------+ | 76| | landingPad | (ULEB128) | offset relative to lpStart | | 77| | actionEntry | (ULEB128) | Action Table Index 1-based | | 78| | | | actionEntry == 0 -> cleanup | | 79| +-------------+---------------------------------+------------------------------+ | 80| ... | 81+----------------------------------------------------------------------------------+ 82#endif // __USING_SJLJ_EXCEPTIONS__ 83+---------------------------------------------------------------------+ 84| Beginning of Action Table ttypeIndex == 0 : cleanup | 85| ... ttypeIndex > 0 : catch | 86| ttypeIndex < 0 : exception spec | 87| +--------------+-----------+--------------------------------------+ | 88| | ttypeIndex | (SLEB128) | Index into type_info Table (1-based) | | 89| | actionOffset | (SLEB128) | Offset into next Action Table entry | | 90| +--------------+-----------+--------------------------------------+ | 91| ... | 92+---------------------------------------------------------------------+-----------------+ 93| type_info Table, but classInfoOffset does *not* point here! | 94| +----------------+------------------------------------------------+-----------------+ | 95| | Nth type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == N | | 96| +----------------+------------------------------------------------+-----------------+ | 97| ... | 98| +----------------+------------------------------------------------+-----------------+ | 99| | 1st type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == 1 | | 100| +----------------+------------------------------------------------+-----------------+ | 101| +---------------------------------------+-----------+------------------------------+ | 102| | 1st ttypeIndex for 1st exception spec | (ULEB128) | classInfoOffset points here! | | 103| | ... | (ULEB128) | | | 104| | Mth ttypeIndex for 1st exception spec | (ULEB128) | | | 105| | 0 | (ULEB128) | | | 106| +---------------------------------------+------------------------------------------+ | 107| ... | 108| +---------------------------------------+------------------------------------------+ | 109| | 0 | (ULEB128) | throw() | | 110| +---------------------------------------+------------------------------------------+ | 111| ... | 112| +---------------------------------------+------------------------------------------+ | 113| | 1st ttypeIndex for Nth exception spec | (ULEB128) | | | 114| | ... | (ULEB128) | | | 115| | Mth ttypeIndex for Nth exception spec | (ULEB128) | | | 116| | 0 | (ULEB128) | | | 117| +---------------------------------------+------------------------------------------+ | 118+---------------------------------------------------------------------------------------+ 119 120Notes: 121 122* ttypeIndex in the Action Table, and in the exception spec table, is an index, 123 not a byte count, if positive. It is a negative index offset of 124 classInfoOffset and the sizeof entry depends on ttypeEncoding. 125 But if ttypeIndex is negative, it is a positive 1-based byte offset into the 126 type_info Table. 127 And if ttypeIndex is zero, it refers to a catch (...). 128 129* landingPad can be 0, this implies there is nothing to be done. 130 131* landingPad != 0 and actionEntry == 0 implies a cleanup needs to be done 132 @landingPad. 133 134* A cleanup can also be found under landingPad != 0 and actionEntry != 0 in 135 the Action Table with ttypeIndex == 0. 136*/ 137 138namespace __cxxabiv1 139{ 140 141namespace 142{ 143 144template <class AsType> 145uintptr_t readPointerHelper(const uint8_t*& p) { 146 AsType value; 147 memcpy(&value, p, sizeof(AsType)); 148 p += sizeof(AsType); 149 return static_cast<uintptr_t>(value); 150} 151 152} // end namespace 153 154extern "C" 155{ 156 157// private API 158 159// Heavily borrowed from llvm/examples/ExceptionDemo/ExceptionDemo.cpp 160 161// DWARF Constants 162enum 163{ 164 DW_EH_PE_absptr = 0x00, 165 DW_EH_PE_uleb128 = 0x01, 166 DW_EH_PE_udata2 = 0x02, 167 DW_EH_PE_udata4 = 0x03, 168 DW_EH_PE_udata8 = 0x04, 169 DW_EH_PE_sleb128 = 0x09, 170 DW_EH_PE_sdata2 = 0x0A, 171 DW_EH_PE_sdata4 = 0x0B, 172 DW_EH_PE_sdata8 = 0x0C, 173 DW_EH_PE_pcrel = 0x10, 174 DW_EH_PE_textrel = 0x20, 175 DW_EH_PE_datarel = 0x30, 176 DW_EH_PE_funcrel = 0x40, 177 DW_EH_PE_aligned = 0x50, 178 DW_EH_PE_indirect = 0x80, 179 DW_EH_PE_omit = 0xFF 180}; 181 182/// Read a uleb128 encoded value and advance pointer 183/// See Variable Length Data Appendix C in: 184/// @link http://dwarfstd.org/Dwarf4.pdf @unlink 185/// @param data reference variable holding memory pointer to decode from 186/// @returns decoded value 187static 188uintptr_t 189readULEB128(const uint8_t** data) 190{ 191 uintptr_t result = 0; 192 uintptr_t shift = 0; 193 unsigned char byte; 194 const uint8_t *p = *data; 195 do 196 { 197 byte = *p++; 198 result |= static_cast<uintptr_t>(byte & 0x7F) << shift; 199 shift += 7; 200 } while (byte & 0x80); 201 *data = p; 202 return result; 203} 204 205/// Read a sleb128 encoded value and advance pointer 206/// See Variable Length Data Appendix C in: 207/// @link http://dwarfstd.org/Dwarf4.pdf @unlink 208/// @param data reference variable holding memory pointer to decode from 209/// @returns decoded value 210static 211intptr_t 212readSLEB128(const uint8_t** data) 213{ 214 uintptr_t result = 0; 215 uintptr_t shift = 0; 216 unsigned char byte; 217 const uint8_t *p = *data; 218 do 219 { 220 byte = *p++; 221 result |= static_cast<uintptr_t>(byte & 0x7F) << shift; 222 shift += 7; 223 } while (byte & 0x80); 224 *data = p; 225 if ((byte & 0x40) && (shift < (sizeof(result) << 3))) 226 result |= static_cast<uintptr_t>(~0) << shift; 227 return static_cast<intptr_t>(result); 228} 229 230/// Read a pointer encoded value and advance pointer 231/// See Variable Length Data in: 232/// @link http://dwarfstd.org/Dwarf3.pdf @unlink 233/// @param data reference variable holding memory pointer to decode from 234/// @param encoding dwarf encoding type 235/// @returns decoded value 236static 237uintptr_t 238readEncodedPointer(const uint8_t** data, uint8_t encoding) 239{ 240 uintptr_t result = 0; 241 if (encoding == DW_EH_PE_omit) 242 return result; 243 const uint8_t* p = *data; 244 // first get value 245 switch (encoding & 0x0F) 246 { 247 case DW_EH_PE_absptr: 248 result = readPointerHelper<uintptr_t>(p); 249 break; 250 case DW_EH_PE_uleb128: 251 result = readULEB128(&p); 252 break; 253 case DW_EH_PE_sleb128: 254 result = static_cast<uintptr_t>(readSLEB128(&p)); 255 break; 256 case DW_EH_PE_udata2: 257 result = readPointerHelper<uint16_t>(p); 258 break; 259 case DW_EH_PE_udata4: 260 result = readPointerHelper<uint32_t>(p); 261 break; 262 case DW_EH_PE_udata8: 263 result = readPointerHelper<uint64_t>(p); 264 break; 265 case DW_EH_PE_sdata2: 266 result = readPointerHelper<int16_t>(p); 267 break; 268 case DW_EH_PE_sdata4: 269 result = readPointerHelper<int32_t>(p); 270 break; 271 case DW_EH_PE_sdata8: 272 result = readPointerHelper<int64_t>(p); 273 break; 274 default: 275 // not supported 276 abort(); 277 break; 278 } 279 // then add relative offset 280 switch (encoding & 0x70) 281 { 282 case DW_EH_PE_absptr: 283 // do nothing 284 break; 285 case DW_EH_PE_pcrel: 286 if (result) 287 result += (uintptr_t)(*data); 288 break; 289 case DW_EH_PE_textrel: 290 case DW_EH_PE_datarel: 291 case DW_EH_PE_funcrel: 292 case DW_EH_PE_aligned: 293 default: 294 // not supported 295 abort(); 296 break; 297 } 298 // then apply indirection 299 if (result && (encoding & DW_EH_PE_indirect)) 300 result = *((uintptr_t*)result); 301 *data = p; 302 return result; 303} 304 305static 306void 307call_terminate(bool native_exception, _Unwind_Exception* unwind_exception) 308{ 309 __cxa_begin_catch(unwind_exception); 310 if (native_exception) 311 { 312 // Use the stored terminate_handler if possible 313 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; 314 std::__terminate(exception_header->terminateHandler); 315 } 316 std::terminate(); 317} 318 319#if LIBCXXABI_ARM_EHABI 320static const void* read_target2_value(const void* ptr) 321{ 322 uintptr_t offset = *reinterpret_cast<const uintptr_t*>(ptr); 323 if (!offset) 324 return 0; 325 // "ARM EABI provides a TARGET2 relocation to describe these typeinfo 326 // pointers. The reason being it allows their precise semantics to be 327 // deferred to the linker. For bare-metal they turn into absolute 328 // relocations. For linux they turn into GOT-REL relocations." 329 // https://gcc.gnu.org/ml/gcc-patches/2009-08/msg00264.html 330#if LIBCXXABI_BAREMETAL 331 return reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(ptr) + 332 offset); 333#else 334 return *reinterpret_cast<const void **>(reinterpret_cast<uintptr_t>(ptr) + 335 offset); 336#endif 337} 338 339static const __shim_type_info* 340get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo, 341 uint8_t ttypeEncoding, bool native_exception, 342 _Unwind_Exception* unwind_exception) 343{ 344 if (classInfo == 0) 345 { 346 // this should not happen. Indicates corrupted eh_table. 347 call_terminate(native_exception, unwind_exception); 348 } 349 350 assert(ttypeEncoding == DW_EH_PE_absptr && "Unexpected TTypeEncoding"); 351 (void)ttypeEncoding; 352 353 const uint8_t* ttypePtr = classInfo - ttypeIndex * sizeof(uintptr_t); 354 return reinterpret_cast<const __shim_type_info *>( 355 read_target2_value(ttypePtr)); 356} 357#else // !LIBCXXABI_ARM_EHABI 358static 359const __shim_type_info* 360get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo, 361 uint8_t ttypeEncoding, bool native_exception, 362 _Unwind_Exception* unwind_exception) 363{ 364 if (classInfo == 0) 365 { 366 // this should not happen. Indicates corrupted eh_table. 367 call_terminate(native_exception, unwind_exception); 368 } 369 switch (ttypeEncoding & 0x0F) 370 { 371 case DW_EH_PE_absptr: 372 ttypeIndex *= sizeof(void*); 373 break; 374 case DW_EH_PE_udata2: 375 case DW_EH_PE_sdata2: 376 ttypeIndex *= 2; 377 break; 378 case DW_EH_PE_udata4: 379 case DW_EH_PE_sdata4: 380 ttypeIndex *= 4; 381 break; 382 case DW_EH_PE_udata8: 383 case DW_EH_PE_sdata8: 384 ttypeIndex *= 8; 385 break; 386 default: 387 // this should not happen. Indicates corrupted eh_table. 388 call_terminate(native_exception, unwind_exception); 389 } 390 classInfo -= ttypeIndex; 391 return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding); 392} 393#endif // !LIBCXXABI_ARM_EHABI 394 395/* 396 This is checking a thrown exception type, excpType, against a possibly empty 397 list of catchType's which make up an exception spec. 398 399 An exception spec acts like a catch handler, but in reverse. This "catch 400 handler" will catch an excpType if and only if none of the catchType's in 401 the list will catch a excpType. If any catchType in the list can catch an 402 excpType, then this exception spec does not catch the excpType. 403*/ 404#if LIBCXXABI_ARM_EHABI 405static 406bool 407exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo, 408 uint8_t ttypeEncoding, const __shim_type_info* excpType, 409 void* adjustedPtr, _Unwind_Exception* unwind_exception) 410{ 411 if (classInfo == 0) 412 { 413 // this should not happen. Indicates corrupted eh_table. 414 call_terminate(false, unwind_exception); 415 } 416 417 assert(ttypeEncoding == DW_EH_PE_absptr && "Unexpected TTypeEncoding"); 418 (void)ttypeEncoding; 419 420 // specIndex is negative of 1-based byte offset into classInfo; 421 specIndex = -specIndex; 422 --specIndex; 423 const void** temp = reinterpret_cast<const void**>( 424 reinterpret_cast<uintptr_t>(classInfo) + 425 static_cast<uintptr_t>(specIndex) * sizeof(uintptr_t)); 426 // If any type in the spec list can catch excpType, return false, else return true 427 // adjustments to adjustedPtr are ignored. 428 while (true) 429 { 430 // ARM EHABI exception specification table (filter table) consists of 431 // several pointers which will directly point to the type info object 432 // (instead of ttypeIndex). The table will be terminated with 0. 433 const void** ttypePtr = temp++; 434 if (*ttypePtr == 0) 435 break; 436 // We can get the __shim_type_info simply by performing a 437 // R_ARM_TARGET2 relocation, and cast the result to __shim_type_info. 438 const __shim_type_info* catchType = 439 static_cast<const __shim_type_info*>(read_target2_value(ttypePtr)); 440 void* tempPtr = adjustedPtr; 441 if (catchType->can_catch(excpType, tempPtr)) 442 return false; 443 } 444 return true; 445} 446#else 447static 448bool 449exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo, 450 uint8_t ttypeEncoding, const __shim_type_info* excpType, 451 void* adjustedPtr, _Unwind_Exception* unwind_exception) 452{ 453 if (classInfo == 0) 454 { 455 // this should not happen. Indicates corrupted eh_table. 456 call_terminate(false, unwind_exception); 457 } 458 // specIndex is negative of 1-based byte offset into classInfo; 459 specIndex = -specIndex; 460 --specIndex; 461 const uint8_t* temp = classInfo + specIndex; 462 // If any type in the spec list can catch excpType, return false, else return true 463 // adjustments to adjustedPtr are ignored. 464 while (true) 465 { 466 uint64_t ttypeIndex = readULEB128(&temp); 467 if (ttypeIndex == 0) 468 break; 469 const __shim_type_info* catchType = get_shim_type_info(ttypeIndex, 470 classInfo, 471 ttypeEncoding, 472 true, 473 unwind_exception); 474 void* tempPtr = adjustedPtr; 475 if (catchType->can_catch(excpType, tempPtr)) 476 return false; 477 } 478 return true; 479} 480#endif 481 482static 483void* 484get_thrown_object_ptr(_Unwind_Exception* unwind_exception) 485{ 486 // Even for foreign exceptions, the exception object is *probably* at unwind_exception + 1 487 // Regardless, this library is prohibited from touching a foreign exception 488 void* adjustedPtr = unwind_exception + 1; 489 if (unwind_exception->exception_class == kOurDependentExceptionClass) 490 adjustedPtr = ((__cxa_dependent_exception*)adjustedPtr - 1)->primaryException; 491 return adjustedPtr; 492} 493 494namespace 495{ 496 497struct scan_results 498{ 499 int64_t ttypeIndex; // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup 500 const uint8_t* actionRecord; // Currently unused. Retained to ease future maintenance. 501 const uint8_t* languageSpecificData; // Needed only for __cxa_call_unexpected 502 uintptr_t landingPad; // null -> nothing found, else something found 503 void* adjustedPtr; // Used in cxa_exception.cpp 504 _Unwind_Reason_Code reason; // One of _URC_FATAL_PHASE1_ERROR, 505 // _URC_FATAL_PHASE2_ERROR, 506 // _URC_CONTINUE_UNWIND, 507 // _URC_HANDLER_FOUND 508}; 509 510} // unnamed namespace 511 512static 513void 514set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context, 515 const scan_results& results) 516{ 517 _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), 518 reinterpret_cast<uintptr_t>(unwind_exception)); 519 _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 520 static_cast<uintptr_t>(results.ttypeIndex)); 521 _Unwind_SetIP(context, results.landingPad); 522} 523 524/* 525 There are 3 types of scans needed: 526 527 1. Scan for handler with native or foreign exception. If handler found, 528 save state and return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND. 529 May also report an error on invalid input. 530 May terminate for invalid exception table. 531 _UA_SEARCH_PHASE 532 533 2. Scan for handler with foreign exception. Must return _URC_HANDLER_FOUND, 534 or call terminate. 535 _UA_CLEANUP_PHASE && _UA_HANDLER_FRAME && !native_exception 536 537 3. Scan for cleanups. If a handler is found and this isn't forced unwind, 538 then terminate, otherwise ignore the handler and keep looking for cleanup. 539 If a cleanup is found, return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND. 540 May also report an error on invalid input. 541 May terminate for invalid exception table. 542 _UA_CLEANUP_PHASE && !_UA_HANDLER_FRAME 543*/ 544 545static void scan_eh_tab(scan_results &results, _Unwind_Action actions, 546 bool native_exception, 547 _Unwind_Exception *unwind_exception, 548 _Unwind_Context *context) { 549 // Initialize results to found nothing but an error 550 results.ttypeIndex = 0; 551 results.actionRecord = 0; 552 results.languageSpecificData = 0; 553 results.landingPad = 0; 554 results.adjustedPtr = 0; 555 results.reason = _URC_FATAL_PHASE1_ERROR; 556 // Check for consistent actions 557 if (actions & _UA_SEARCH_PHASE) 558 { 559 // Do Phase 1 560 if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND)) 561 { 562 // None of these flags should be set during Phase 1 563 // Client error 564 results.reason = _URC_FATAL_PHASE1_ERROR; 565 return; 566 } 567 } 568 else if (actions & _UA_CLEANUP_PHASE) 569 { 570 if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND)) 571 { 572 // _UA_HANDLER_FRAME should only be set if phase 1 found a handler. 573 // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened. 574 // Client error 575 results.reason = _URC_FATAL_PHASE2_ERROR; 576 return; 577 } 578 } 579 else // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set 580 { 581 // One of these should be set. 582 // Client error 583 results.reason = _URC_FATAL_PHASE1_ERROR; 584 return; 585 } 586 // Start scan by getting exception table address 587 const uint8_t *lsda = (const uint8_t *)_Unwind_GetLanguageSpecificData(context); 588 if (lsda == 0) 589 { 590 // There is no exception table 591 results.reason = _URC_CONTINUE_UNWIND; 592 return; 593 } 594 results.languageSpecificData = lsda; 595 // Get the current instruction pointer and offset it before next 596 // instruction in the current frame which threw the exception. 597 uintptr_t ip = _Unwind_GetIP(context) - 1; 598 // Get beginning current frame's code (as defined by the 599 // emitted dwarf code) 600 uintptr_t funcStart = _Unwind_GetRegionStart(context); 601#ifdef __USING_SJLJ_EXCEPTIONS__ 602 if (ip == uintptr_t(-1)) 603 { 604 // no action 605 results.reason = _URC_CONTINUE_UNWIND; 606 return; 607 } 608 else if (ip == 0) 609 call_terminate(native_exception, unwind_exception); 610 // ip is 1-based index into call site table 611#else // !__USING_SJLJ_EXCEPTIONS__ 612 uintptr_t ipOffset = ip - funcStart; 613#endif // !defined(_USING_SLJL_EXCEPTIONS__) 614 const uint8_t* classInfo = NULL; 615 // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding 616 // dwarf emission 617 // Parse LSDA header. 618 uint8_t lpStartEncoding = *lsda++; 619 const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); 620 if (lpStart == 0) 621 lpStart = (const uint8_t*)funcStart; 622 uint8_t ttypeEncoding = *lsda++; 623 if (ttypeEncoding != DW_EH_PE_omit) 624 { 625 // Calculate type info locations in emitted dwarf code which 626 // were flagged by type info arguments to llvm.eh.selector 627 // intrinsic 628 uintptr_t classInfoOffset = readULEB128(&lsda); 629 classInfo = lsda + classInfoOffset; 630 } 631 // Walk call-site table looking for range that 632 // includes current PC. 633 uint8_t callSiteEncoding = *lsda++; 634#ifdef __USING_SJLJ_EXCEPTIONS__ 635 (void)callSiteEncoding; // When using SjLj exceptions, callSiteEncoding is never used 636#endif 637 uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda)); 638 const uint8_t* callSiteTableStart = lsda; 639 const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; 640 const uint8_t* actionTableStart = callSiteTableEnd; 641 const uint8_t* callSitePtr = callSiteTableStart; 642 while (callSitePtr < callSiteTableEnd) 643 { 644 // There is one entry per call site. 645#ifndef __USING_SJLJ_EXCEPTIONS__ 646 // The call sites are non-overlapping in [start, start+length) 647 // The call sites are ordered in increasing value of start 648 uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); 649 uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding); 650 uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); 651 uintptr_t actionEntry = readULEB128(&callSitePtr); 652 if ((start <= ipOffset) && (ipOffset < (start + length))) 653#else // __USING_SJLJ_EXCEPTIONS__ 654 // ip is 1-based index into this table 655 uintptr_t landingPad = readULEB128(&callSitePtr); 656 uintptr_t actionEntry = readULEB128(&callSitePtr); 657 if (--ip == 0) 658#endif // __USING_SJLJ_EXCEPTIONS__ 659 { 660 // Found the call site containing ip. 661#ifndef __USING_SJLJ_EXCEPTIONS__ 662 if (landingPad == 0) 663 { 664 // No handler here 665 results.reason = _URC_CONTINUE_UNWIND; 666 return; 667 } 668 landingPad = (uintptr_t)lpStart + landingPad; 669#else // __USING_SJLJ_EXCEPTIONS__ 670 ++landingPad; 671#endif // __USING_SJLJ_EXCEPTIONS__ 672 if (actionEntry == 0) 673 { 674 // Found a cleanup 675 // If this is a type 1 or type 2 search, there are no handlers 676 // If this is a type 3 search, you want to install the cleanup. 677 if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) 678 { 679 results.ttypeIndex = 0; // Redundant but clarifying 680 results.landingPad = landingPad; 681 results.reason = _URC_HANDLER_FOUND; 682 return; 683 } 684 // No handler here 685 results.reason = _URC_CONTINUE_UNWIND; 686 return; 687 } 688 // Convert 1-based byte offset into 689 const uint8_t* action = actionTableStart + (actionEntry - 1); 690 // Scan action entries until you find a matching handler, cleanup, or the end of action list 691 while (true) 692 { 693 const uint8_t* actionRecord = action; 694 int64_t ttypeIndex = readSLEB128(&action); 695 if (ttypeIndex > 0) 696 { 697 // Found a catch, does it actually catch? 698 // First check for catch (...) 699 const __shim_type_info* catchType = 700 get_shim_type_info(static_cast<uint64_t>(ttypeIndex), 701 classInfo, ttypeEncoding, 702 native_exception, unwind_exception); 703 if (catchType == 0) 704 { 705 // Found catch (...) catches everything, including foreign exceptions 706 // If this is a type 1 search save state and return _URC_HANDLER_FOUND 707 // If this is a type 2 search save state and return _URC_HANDLER_FOUND 708 // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! 709 // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan 710 if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) 711 { 712 // Save state and return _URC_HANDLER_FOUND 713 results.ttypeIndex = ttypeIndex; 714 results.actionRecord = actionRecord; 715 results.landingPad = landingPad; 716 results.adjustedPtr = get_thrown_object_ptr(unwind_exception); 717 results.reason = _URC_HANDLER_FOUND; 718 return; 719 } 720 else if (!(actions & _UA_FORCE_UNWIND)) 721 { 722 // It looks like the exception table has changed 723 // on us. Likely stack corruption! 724 call_terminate(native_exception, unwind_exception); 725 } 726 } 727 // Else this is a catch (T) clause and will never 728 // catch a foreign exception 729 else if (native_exception) 730 { 731 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; 732 void* adjustedPtr = get_thrown_object_ptr(unwind_exception); 733 const __shim_type_info* excpType = 734 static_cast<const __shim_type_info*>(exception_header->exceptionType); 735 if (adjustedPtr == 0 || excpType == 0) 736 { 737 // Something very bad happened 738 call_terminate(native_exception, unwind_exception); 739 } 740 if (catchType->can_catch(excpType, adjustedPtr)) 741 { 742 // Found a matching handler 743 // If this is a type 1 search save state and return _URC_HANDLER_FOUND 744 // If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1! 745 // If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan 746 if (actions & _UA_SEARCH_PHASE) 747 { 748 // Save state and return _URC_HANDLER_FOUND 749 results.ttypeIndex = ttypeIndex; 750 results.actionRecord = actionRecord; 751 results.landingPad = landingPad; 752 results.adjustedPtr = adjustedPtr; 753 results.reason = _URC_HANDLER_FOUND; 754 return; 755 } 756 else if (!(actions & _UA_FORCE_UNWIND)) 757 { 758 // It looks like the exception table has changed 759 // on us. Likely stack corruption! 760 call_terminate(native_exception, unwind_exception); 761 } 762 } 763 } 764 // Scan next action ... 765 } 766 else if (ttypeIndex < 0) 767 { 768 // Found an exception spec. If this is a foreign exception, 769 // it is always caught. 770 if (native_exception) 771 { 772 // Does the exception spec catch this native exception? 773 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; 774 void* adjustedPtr = get_thrown_object_ptr(unwind_exception); 775 const __shim_type_info* excpType = 776 static_cast<const __shim_type_info*>(exception_header->exceptionType); 777 if (adjustedPtr == 0 || excpType == 0) 778 { 779 // Something very bad happened 780 call_terminate(native_exception, unwind_exception); 781 } 782 if (exception_spec_can_catch(ttypeIndex, classInfo, 783 ttypeEncoding, excpType, 784 adjustedPtr, unwind_exception)) 785 { 786 // native exception caught by exception spec 787 // If this is a type 1 search, save state and return _URC_HANDLER_FOUND 788 // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! 789 // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan 790 if (actions & _UA_SEARCH_PHASE) 791 { 792 // Save state and return _URC_HANDLER_FOUND 793 results.ttypeIndex = ttypeIndex; 794 results.actionRecord = actionRecord; 795 results.landingPad = landingPad; 796 results.adjustedPtr = adjustedPtr; 797 results.reason = _URC_HANDLER_FOUND; 798 return; 799 } 800 else if (!(actions & _UA_FORCE_UNWIND)) 801 { 802 // It looks like the exception table has changed 803 // on us. Likely stack corruption! 804 call_terminate(native_exception, unwind_exception); 805 } 806 } 807 } 808 else 809 { 810 // foreign exception caught by exception spec 811 // If this is a type 1 search, save state and return _URC_HANDLER_FOUND 812 // If this is a type 2 search, save state and return _URC_HANDLER_FOUND 813 // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! 814 // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan 815 if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) 816 { 817 // Save state and return _URC_HANDLER_FOUND 818 results.ttypeIndex = ttypeIndex; 819 results.actionRecord = actionRecord; 820 results.landingPad = landingPad; 821 results.adjustedPtr = get_thrown_object_ptr(unwind_exception); 822 results.reason = _URC_HANDLER_FOUND; 823 return; 824 } 825 else if (!(actions & _UA_FORCE_UNWIND)) 826 { 827 // It looks like the exception table has changed 828 // on us. Likely stack corruption! 829 call_terminate(native_exception, unwind_exception); 830 } 831 } 832 // Scan next action ... 833 } 834 else // ttypeIndex == 0 835 { 836 // Found a cleanup 837 // If this is a type 1 search, ignore it and continue scan 838 // If this is a type 2 search, ignore it and continue scan 839 // If this is a type 3 search, save state and return _URC_HANDLER_FOUND 840 if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) 841 { 842 // Save state and return _URC_HANDLER_FOUND 843 results.ttypeIndex = ttypeIndex; 844 results.actionRecord = actionRecord; 845 results.landingPad = landingPad; 846 results.adjustedPtr = get_thrown_object_ptr(unwind_exception); 847 results.reason = _URC_HANDLER_FOUND; 848 return; 849 } 850 } 851 const uint8_t* temp = action; 852 int64_t actionOffset = readSLEB128(&temp); 853 if (actionOffset == 0) 854 { 855 // End of action list, no matching handler or cleanup found 856 results.reason = _URC_CONTINUE_UNWIND; 857 return; 858 } 859 // Go to next action 860 action += actionOffset; 861 } // there is no break out of this loop, only return 862 } 863#ifndef __USING_SJLJ_EXCEPTIONS__ 864 else if (ipOffset < start) 865 { 866 // There is no call site for this ip 867 // Something bad has happened. We should never get here. 868 // Possible stack corruption. 869 call_terminate(native_exception, unwind_exception); 870 } 871#endif // !__USING_SJLJ_EXCEPTIONS__ 872 } // there might be some tricky cases which break out of this loop 873 874 // It is possible that no eh table entry specify how to handle 875 // this exception. By spec, terminate it immediately. 876 call_terminate(native_exception, unwind_exception); 877} 878 879// public API 880 881/* 882The personality function branches on actions like so: 883 884_UA_SEARCH_PHASE 885 886 If _UA_CLEANUP_PHASE or _UA_HANDLER_FRAME or _UA_FORCE_UNWIND there's 887 an error from above, return _URC_FATAL_PHASE1_ERROR. 888 889 Scan for anything that could stop unwinding: 890 891 1. A catch clause that will catch this exception 892 (will never catch foreign). 893 2. A catch (...) (will always catch foreign). 894 3. An exception spec that will catch this exception 895 (will always catch foreign). 896 If a handler is found 897 If not foreign 898 Save state in header 899 return _URC_HANDLER_FOUND 900 Else a handler not found 901 return _URC_CONTINUE_UNWIND 902 903_UA_CLEANUP_PHASE 904 905 If _UA_HANDLER_FRAME 906 If _UA_FORCE_UNWIND 907 How did this happen? return _URC_FATAL_PHASE2_ERROR 908 If foreign 909 Do _UA_SEARCH_PHASE to recover state 910 else 911 Recover state from header 912 Transfer control to landing pad. return _URC_INSTALL_CONTEXT 913 914 Else 915 916 This branch handles both normal C++ non-catching handlers (cleanups) 917 and forced unwinding. 918 Scan for anything that can not stop unwinding: 919 920 1. A cleanup. 921 922 If a cleanup is found 923 transfer control to it. return _URC_INSTALL_CONTEXT 924 Else a cleanup is not found: return _URC_CONTINUE_UNWIND 925*/ 926 927#if !LIBCXXABI_ARM_EHABI 928_Unwind_Reason_Code 929#ifdef __USING_SJLJ_EXCEPTIONS__ 930__gxx_personality_sj0 931#else 932__gxx_personality_v0 933#endif 934 (int version, _Unwind_Action actions, uint64_t exceptionClass, 935 _Unwind_Exception* unwind_exception, _Unwind_Context* context) 936{ 937 if (version != 1 || unwind_exception == 0 || context == 0) 938 return _URC_FATAL_PHASE1_ERROR; 939 940 bool native_exception = (exceptionClass & get_vendor_and_language) == 941 (kOurExceptionClass & get_vendor_and_language); 942 scan_results results; 943 if (actions & _UA_SEARCH_PHASE) 944 { 945 // Phase 1 search: All we're looking for in phase 1 is a handler that 946 // halts unwinding 947 scan_eh_tab(results, actions, native_exception, unwind_exception, context); 948 if (results.reason == _URC_HANDLER_FOUND) 949 { 950 // Found one. Can we cache the results somewhere to optimize phase 2? 951 if (native_exception) 952 { 953 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; 954 exception_header->handlerSwitchValue = static_cast<int>(results.ttypeIndex); 955 exception_header->actionRecord = results.actionRecord; 956 exception_header->languageSpecificData = results.languageSpecificData; 957 exception_header->catchTemp = reinterpret_cast<void*>(results.landingPad); 958 exception_header->adjustedPtr = results.adjustedPtr; 959 } 960 return _URC_HANDLER_FOUND; 961 } 962 // Did not find a catching-handler. Return the results of the scan 963 // (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE1_ERROR 964 // if we were called improperly). 965 return results.reason; 966 } 967 if (actions & _UA_CLEANUP_PHASE) 968 { 969 // Phase 2 search: 970 // Did we find a catching handler in phase 1? 971 if (actions & _UA_HANDLER_FRAME) 972 { 973 // Yes, phase 1 said we have a catching handler here. 974 // Did we cache the results of the scan? 975 if (native_exception) 976 { 977 // Yes, reload the results from the cache. 978 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; 979 results.ttypeIndex = exception_header->handlerSwitchValue; 980 results.actionRecord = exception_header->actionRecord; 981 results.languageSpecificData = exception_header->languageSpecificData; 982 results.landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp); 983 results.adjustedPtr = exception_header->adjustedPtr; 984 } 985 else 986 { 987 // No, do the scan again to reload the results. 988 scan_eh_tab(results, actions, native_exception, unwind_exception, context); 989 // Phase 1 told us we would find a handler. Now in Phase 2 we 990 // didn't find a handler. The eh table should not be changing! 991 if (results.reason != _URC_HANDLER_FOUND) 992 call_terminate(native_exception, unwind_exception); 993 } 994 // Jump to the handler 995 set_registers(unwind_exception, context, results); 996 return _URC_INSTALL_CONTEXT; 997 } 998 // Either we didn't do a phase 1 search (due to forced unwinding), or 999 // phase 1 reported no catching-handlers. 1000 // Search for a (non-catching) cleanup 1001 scan_eh_tab(results, actions, native_exception, unwind_exception, context); 1002 if (results.reason == _URC_HANDLER_FOUND) 1003 { 1004 // Found a non-catching handler. Jump to it: 1005 set_registers(unwind_exception, context, results); 1006 return _URC_INSTALL_CONTEXT; 1007 } 1008 // Did not find a cleanup. Return the results of the scan 1009 // (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR 1010 // if we were called improperly). 1011 return results.reason; 1012 } 1013 // We were called improperly: neither a phase 1 or phase 2 search 1014 return _URC_FATAL_PHASE1_ERROR; 1015} 1016#else 1017 1018extern "C" _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception*, 1019 _Unwind_Context*); 1020 1021// Helper function to unwind one frame. 1022// ARM EHABI 7.3 and 7.4: If the personality function returns _URC_CONTINUE_UNWIND, the 1023// personality routine should update the virtual register set (VRS) according to the 1024// corresponding frame unwinding instructions (ARM EHABI 9.3.) 1025static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception, 1026 _Unwind_Context* context) 1027{ 1028 if (__gnu_unwind_frame(unwind_exception, context) != _URC_OK) 1029 return _URC_FAILURE; 1030 return _URC_CONTINUE_UNWIND; 1031} 1032 1033// ARM register names 1034#if !LIBCXXABI_USE_LLVM_UNWINDER 1035static const uint32_t REG_UCB = 12; // Register to save _Unwind_Control_Block 1036#endif 1037static const uint32_t REG_SP = 13; 1038 1039static void save_results_to_barrier_cache(_Unwind_Exception* unwind_exception, 1040 const scan_results& results) 1041{ 1042 unwind_exception->barrier_cache.bitpattern[0] = (uint32_t)results.adjustedPtr; 1043 unwind_exception->barrier_cache.bitpattern[1] = (uint32_t)results.actionRecord; 1044 unwind_exception->barrier_cache.bitpattern[2] = (uint32_t)results.languageSpecificData; 1045 unwind_exception->barrier_cache.bitpattern[3] = (uint32_t)results.landingPad; 1046 unwind_exception->barrier_cache.bitpattern[4] = (uint32_t)results.ttypeIndex; 1047} 1048 1049static void load_results_from_barrier_cache(scan_results& results, 1050 const _Unwind_Exception* unwind_exception) 1051{ 1052 results.adjustedPtr = (void*)unwind_exception->barrier_cache.bitpattern[0]; 1053 results.actionRecord = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[1]; 1054 results.languageSpecificData = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[2]; 1055 results.landingPad = (uintptr_t)unwind_exception->barrier_cache.bitpattern[3]; 1056 results.ttypeIndex = (int64_t)(int32_t)unwind_exception->barrier_cache.bitpattern[4]; 1057} 1058 1059extern "C" _Unwind_Reason_Code 1060__gxx_personality_v0(_Unwind_State state, 1061 _Unwind_Exception* unwind_exception, 1062 _Unwind_Context* context) 1063{ 1064 if (unwind_exception == 0 || context == 0) 1065 return _URC_FATAL_PHASE1_ERROR; 1066 1067 bool native_exception = (unwind_exception->exception_class & get_vendor_and_language) == 1068 (kOurExceptionClass & get_vendor_and_language); 1069 1070#if !LIBCXXABI_USE_LLVM_UNWINDER 1071 // Copy the address of _Unwind_Control_Block to r12 so that 1072 // _Unwind_GetLanguageSpecificData() and _Unwind_GetRegionStart() can 1073 // return correct address. 1074 _Unwind_SetGR(context, REG_UCB, reinterpret_cast<uint32_t>(unwind_exception)); 1075#endif 1076 1077 // Check the undocumented force unwinding behavior 1078 bool is_force_unwinding = state & _US_FORCE_UNWIND; 1079 state &= ~_US_FORCE_UNWIND; 1080 1081 scan_results results; 1082 switch (state) { 1083 case _US_VIRTUAL_UNWIND_FRAME: 1084 if (is_force_unwinding) 1085 return continue_unwind(unwind_exception, context); 1086 1087 // Phase 1 search: All we're looking for in phase 1 is a handler that halts unwinding 1088 scan_eh_tab(results, _UA_SEARCH_PHASE, native_exception, unwind_exception, context); 1089 if (results.reason == _URC_HANDLER_FOUND) 1090 { 1091 unwind_exception->barrier_cache.sp = _Unwind_GetGR(context, REG_SP); 1092 if (native_exception) 1093 save_results_to_barrier_cache(unwind_exception, results); 1094 return _URC_HANDLER_FOUND; 1095 } 1096 // Did not find the catch handler 1097 if (results.reason == _URC_CONTINUE_UNWIND) 1098 return continue_unwind(unwind_exception, context); 1099 return results.reason; 1100 1101 case _US_UNWIND_FRAME_STARTING: 1102 // TODO: Support force unwinding in the phase 2 search. 1103 // NOTE: In order to call the cleanup functions, _Unwind_ForcedUnwind() 1104 // will call this personality function with (_US_FORCE_UNWIND | 1105 // _US_UNWIND_FRAME_STARTING). 1106 1107 // Phase 2 search 1108 if (unwind_exception->barrier_cache.sp == _Unwind_GetGR(context, REG_SP)) 1109 { 1110 // Found a catching handler in phase 1 1111 if (native_exception) 1112 { 1113 // Load the result from the native exception barrier cache. 1114 load_results_from_barrier_cache(results, unwind_exception); 1115 results.reason = _URC_HANDLER_FOUND; 1116 } 1117 else 1118 { 1119 // Search for the catching handler again for the foreign exception. 1120 scan_eh_tab(results, static_cast<_Unwind_Action>(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME), 1121 native_exception, unwind_exception, context); 1122 if (results.reason != _URC_HANDLER_FOUND) // phase1 search should guarantee to find one 1123 call_terminate(native_exception, unwind_exception); 1124 } 1125 1126 // Install the context for the catching handler 1127 set_registers(unwind_exception, context, results); 1128 return _URC_INSTALL_CONTEXT; 1129 } 1130 1131 // Either we didn't do a phase 1 search (due to forced unwinding), or 1132 // phase 1 reported no catching-handlers. 1133 // Search for a (non-catching) cleanup 1134 scan_eh_tab(results, _UA_CLEANUP_PHASE, native_exception, unwind_exception, context); 1135 if (results.reason == _URC_HANDLER_FOUND) 1136 { 1137 // Found a non-catching handler 1138 1139 // ARM EHABI 8.4.2: Before we can jump to the cleanup handler, we have to setup some 1140 // internal data structures, so that __cxa_end_cleanup() can get unwind_exception from 1141 // __cxa_get_globals(). 1142 __cxa_begin_cleanup(unwind_exception); 1143 1144 // Install the context for the cleanup handler 1145 set_registers(unwind_exception, context, results); 1146 return _URC_INSTALL_CONTEXT; 1147 } 1148 1149 // Did not find any handler 1150 if (results.reason == _URC_CONTINUE_UNWIND) 1151 return continue_unwind(unwind_exception, context); 1152 return results.reason; 1153 1154 case _US_UNWIND_FRAME_RESUME: 1155 return continue_unwind(unwind_exception, context); 1156 } 1157 1158 // We were called improperly: neither a phase 1 or phase 2 search 1159 return _URC_FATAL_PHASE1_ERROR; 1160} 1161#endif 1162 1163 1164__attribute__((noreturn)) 1165void 1166__cxa_call_unexpected(void* arg) 1167{ 1168 _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg); 1169 if (unwind_exception == 0) 1170 call_terminate(false, unwind_exception); 1171 __cxa_begin_catch(unwind_exception); 1172 bool native_old_exception = 1173 (unwind_exception->exception_class & get_vendor_and_language) == 1174 (kOurExceptionClass & get_vendor_and_language); 1175 std::unexpected_handler u_handler; 1176 std::terminate_handler t_handler; 1177 __cxa_exception* old_exception_header = 0; 1178 int64_t ttypeIndex; 1179 const uint8_t* lsda; 1180 if (native_old_exception) 1181 { 1182 old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1; 1183 t_handler = old_exception_header->terminateHandler; 1184 u_handler = old_exception_header->unexpectedHandler; 1185 // If std::__unexpected(u_handler) rethrows the same exception, 1186 // these values get overwritten by the rethrow. So save them now: 1187#if LIBCXXABI_ARM_EHABI 1188 ttypeIndex = (int64_t)(int32_t)unwind_exception->barrier_cache.bitpattern[4]; 1189 lsda = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[2]; 1190#else 1191 ttypeIndex = old_exception_header->handlerSwitchValue; 1192 lsda = old_exception_header->languageSpecificData; 1193#endif 1194 } 1195 else 1196 { 1197 t_handler = std::get_terminate(); 1198 u_handler = std::get_unexpected(); 1199 } 1200 try 1201 { 1202 std::__unexpected(u_handler); 1203 } 1204 catch (...) 1205 { 1206 // If the old exception is foreign, then all we can do is terminate. 1207 // We have no way to recover the needed old exception spec. There's 1208 // no way to pass that information here. And the personality routine 1209 // can't call us directly and do anything but terminate() if we throw 1210 // from here. 1211 if (native_old_exception) 1212 { 1213 // Have: 1214 // old_exception_header->languageSpecificData 1215 // old_exception_header->actionRecord 1216 // Need 1217 // const uint8_t* classInfo 1218 // uint8_t ttypeEncoding 1219 uint8_t lpStartEncoding = *lsda++; 1220 const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); 1221 (void)lpStart; // purposefully unused. Just needed to increment lsda. 1222 uint8_t ttypeEncoding = *lsda++; 1223 if (ttypeEncoding == DW_EH_PE_omit) 1224 std::__terminate(t_handler); 1225 uintptr_t classInfoOffset = readULEB128(&lsda); 1226 const uint8_t* classInfo = lsda + classInfoOffset; 1227 // Is this new exception catchable by the exception spec at ttypeIndex? 1228 // The answer is obviously yes if the new and old exceptions are the same exception 1229 // If no 1230 // throw; 1231 __cxa_eh_globals* globals = __cxa_get_globals_fast(); 1232 __cxa_exception* new_exception_header = globals->caughtExceptions; 1233 if (new_exception_header == 0) 1234 // This shouldn't be able to happen! 1235 std::__terminate(t_handler); 1236 bool native_new_exception = 1237 (new_exception_header->unwindHeader.exception_class & get_vendor_and_language) == 1238 (kOurExceptionClass & get_vendor_and_language); 1239 void* adjustedPtr; 1240 if (native_new_exception && (new_exception_header != old_exception_header)) 1241 { 1242 const __shim_type_info* excpType = 1243 static_cast<const __shim_type_info*>(new_exception_header->exceptionType); 1244 adjustedPtr = 1245 new_exception_header->unwindHeader.exception_class == kOurDependentExceptionClass ? 1246 ((__cxa_dependent_exception*)new_exception_header)->primaryException : 1247 new_exception_header + 1; 1248 if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, 1249 excpType, adjustedPtr, unwind_exception)) 1250 { 1251 // We need to __cxa_end_catch, but for the old exception, 1252 // not the new one. This is a little tricky ... 1253 // Disguise new_exception_header as a rethrown exception, but 1254 // don't actually rethrow it. This means you can temporarily 1255 // end the catch clause enclosing new_exception_header without 1256 // __cxa_end_catch destroying new_exception_header. 1257 new_exception_header->handlerCount = -new_exception_header->handlerCount; 1258 globals->uncaughtExceptions += 1; 1259 // Call __cxa_end_catch for new_exception_header 1260 __cxa_end_catch(); 1261 // Call __cxa_end_catch for old_exception_header 1262 __cxa_end_catch(); 1263 // Renter this catch clause with new_exception_header 1264 __cxa_begin_catch(&new_exception_header->unwindHeader); 1265 // Rethrow new_exception_header 1266 throw; 1267 } 1268 } 1269 // Will a std::bad_exception be catchable by the exception spec at 1270 // ttypeIndex? 1271 // If no 1272 // throw std::bad_exception(); 1273 const __shim_type_info* excpType = 1274 static_cast<const __shim_type_info*>(&typeid(std::bad_exception)); 1275 std::bad_exception be; 1276 adjustedPtr = &be; 1277 if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, 1278 excpType, adjustedPtr, unwind_exception)) 1279 { 1280 // We need to __cxa_end_catch for both the old exception and the 1281 // new exception. Technically we should do it in that order. 1282 // But it is expedient to do it in the opposite order: 1283 // Call __cxa_end_catch for new_exception_header 1284 __cxa_end_catch(); 1285 // Throw std::bad_exception will __cxa_end_catch for 1286 // old_exception_header 1287 throw be; 1288 } 1289 } 1290 } 1291 std::__terminate(t_handler); 1292} 1293 1294} // extern "C" 1295 1296} // __cxxabiv1 1297