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