cxa_personality.cpp revision 85bc82e6d9dd6447c2eb8414cd3ce650cfa0091a
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 wtih 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 117Notes: 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 135namespace __cxxabiv1 136{ 137 138extern "C" 139{ 140 141// private API 142 143// Heavily borrowed from llvm/examples/ExceptionDemo/ExceptionDemo.cpp 144 145// DWARF Constants 146enum 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 171static 172uintptr_t 173readULEB128(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 Applendix 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 194static 195intptr_t 196readSLEB128(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 220static 221uintptr_t 222readEncodedPointer(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 296static 297void 298call_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 310static 311const __shim_type_info* 312get_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 posibly 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*/ 355static 356bool 357exception_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 389static 390void* 391get_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/* 402 There are 3 types of scans needed: 403 404 1. Scan for handler with native or foreign exception. If handler found, 405 save state and return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND. 406 May also report an error on invalid input. 407 May terminate for invalid exception table. 408 _UA_SEARCH_PHASE 409 410 2. Scan for handler with foreign exception. Must return _URC_HANDLER_FOUND, 411 or call terminate. 412 _UA_CLEANUP_PHASE && _UA_HANDLER_FRAME && !native_exception 413 414 3. Scan for cleanups. If a handler is found and this isn't forced unwind, 415 then terminate, otherwise ignore the handler and keep looking for cleanup. 416 If a cleanup is found, return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND. 417 May also report an error on invalid input. 418 May terminate for invalid exception table. 419 _UA_CLEANUP_PHASE && !_UA_HANDLER_FRAME 420*/ 421 422namespace 423{ 424 425struct scan_results 426{ 427 int64_t ttypeIndex; // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup 428 const uint8_t* actionRecord; // Currently unused. Retained to ease future maintenance. 429 const uint8_t* languageSpecificData; // Needed only for __cxa_call_unexpected 430 uintptr_t landingPad; // null -> nothing found, else something found 431 void* adjustedPtr; // Used in cxa_exception.cpp 432 _Unwind_Reason_Code reason; // One of _URC_FATAL_PHASE1_ERROR, 433 // _URC_FATAL_PHASE2_ERROR, 434 // _URC_CONTINUE_UNWIND, 435 // _URC_HANDLER_FOUND 436}; 437 438} // unnamed namespace 439 440static 441void 442scan_eh_tab(scan_results& results, _Unwind_Action actions, bool native_exception, 443 _Unwind_Exception* unwind_exception, _Unwind_Context* context) 444{ 445 // Initialize results to found nothing but an error 446 results.ttypeIndex = 0; 447 results.actionRecord = 0; 448 results.languageSpecificData = 0; 449 results.landingPad = 0; 450 results.adjustedPtr = 0; 451 results.reason = _URC_FATAL_PHASE1_ERROR; 452 // Check for consistent actions 453 if (actions & _UA_SEARCH_PHASE) 454 { 455 // Do Phase 1 456 if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND)) 457 { 458 // None of these flags should be set during Phase 1 459 // Client error 460 results.reason = _URC_FATAL_PHASE1_ERROR; 461 return; 462 } 463 } 464 else if (actions & _UA_CLEANUP_PHASE) 465 { 466 if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND)) 467 { 468 // _UA_HANDLER_FRAME should only be set if phase 1 found a handler. 469 // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened. 470 // Client error 471 results.reason = _URC_FATAL_PHASE2_ERROR; 472 return; 473 } 474 } 475 else // Niether _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set 476 { 477 // One of these should be set. 478 // Client error 479 results.reason = _URC_FATAL_PHASE1_ERROR; 480 return; 481 } 482 // Start scan by getting exception table address 483 const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context); 484 if (lsda == 0) 485 { 486 // There is no exception table 487 results.reason = _URC_CONTINUE_UNWIND; 488 return; 489 } 490 results.languageSpecificData = lsda; 491 // Get the current instruction pointer and offset it before next 492 // instruction in the current frame which threw the exception. 493 uintptr_t ip = _Unwind_GetIP(context) - 1; 494 // Get beginning current frame's code (as defined by the 495 // emitted dwarf code) 496 uintptr_t funcStart = _Unwind_GetRegionStart(context); 497#if __arm__ 498 if (ip == uintptr_t(-1)) 499 { 500 // no action 501 results.reason = _URC_CONTINUE_UNWIND; 502 return; 503 } 504 else if (ip == 0) 505 call_terminate(native_exception, unwind_exception); 506 // ip is 1-based index into call site table 507#else // __arm__ 508 uintptr_t ipOffset = ip - funcStart; 509#endif // __arm__ 510 const uint8_t* classInfo = NULL; 511 // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding 512 // dwarf emission 513 // Parse LSDA header. 514 uint8_t lpStartEncoding = *lsda++; 515 const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); 516 if (lpStart == 0) 517 lpStart = (const uint8_t*)funcStart; 518 uint8_t ttypeEncoding = *lsda++; 519 if (ttypeEncoding != DW_EH_PE_omit) 520 { 521 // Calculate type info locations in emitted dwarf code which 522 // were flagged by type info arguments to llvm.eh.selector 523 // intrinsic 524 uintptr_t classInfoOffset = readULEB128(&lsda); 525 classInfo = lsda + classInfoOffset; 526 } 527 // Walk call-site table looking for range that 528 // includes current PC. 529 uint8_t callSiteEncoding = *lsda++; 530 uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda)); 531 const uint8_t* callSiteTableStart = lsda; 532 const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; 533 const uint8_t* actionTableStart = callSiteTableEnd; 534 const uint8_t* callSitePtr = callSiteTableStart; 535 while (true) 536 { 537 // There is one entry per call site. 538#if !__arm__ 539 // The call sites are non-overlapping in [start, start+length) 540 // The call sites are ordered in increasing value of start 541 uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); 542 uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding); 543 uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); 544 uintptr_t actionEntry = readULEB128(&callSitePtr); 545 if ((start <= ipOffset) && (ipOffset < (start + length))) 546#else // __arm__ 547 // ip is 1-based index into this table 548 uintptr_t landingPad = readULEB128(&callSitePtr); 549 uintptr_t actionEntry = readULEB128(&callSitePtr); 550 if (--ip == 0) 551#endif // __arm__ 552 { 553 // Found the call site containing ip. 554 if (landingPad == 0) 555 { 556 // No handler here 557 results.reason = _URC_CONTINUE_UNWIND; 558 return; 559 } 560 landingPad = (uintptr_t)lpStart + landingPad; 561 if (actionEntry == 0) 562 { 563 // Found a cleanup 564 // If this is a type 1 or type 2 search, there are no handlers 565 // If this is a type 3 search, you want to install the cleanup. 566 if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) 567 { 568 results.ttypeIndex = 0; // Redundant but clarifying 569 results.landingPad = landingPad; 570 results.reason = _URC_HANDLER_FOUND; 571 return; 572 } 573 // No handler here 574 results.reason = _URC_CONTINUE_UNWIND; 575 return; 576 } 577 // Convert 1-based byte offset into 578 const uint8_t* action = actionTableStart + (actionEntry - 1); 579 // Scan action entries until you find a matching handler, cleanup, or the end of action list 580 while (true) 581 { 582 const uint8_t* actionRecord = action; 583 int64_t ttypeIndex = readSLEB128(&action); 584 if (ttypeIndex > 0) 585 { 586 // Found a catch, does it actually catch? 587 // First check for catch (...) 588 const __shim_type_info* catchType = 589 get_shim_type_info(static_cast<uint64_t>(ttypeIndex), 590 classInfo, ttypeEncoding, 591 native_exception, unwind_exception); 592 if (catchType == 0) 593 { 594 // Found catch (...) catches everything, including foreign exceptions 595 // If this is a type 1 search save state and return _URC_HANDLER_FOUND 596 // If this is a type 2 search save state and return _URC_HANDLER_FOUND 597 // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! 598 // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan 599 if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) 600 { 601 // Save state and return _URC_HANDLER_FOUND 602 results.ttypeIndex = ttypeIndex; 603 results.actionRecord = actionRecord; 604 results.landingPad = landingPad; 605 results.adjustedPtr = get_thrown_object_ptr(unwind_exception); 606 results.reason = _URC_HANDLER_FOUND; 607 return; 608 } 609 else if (!(actions & _UA_FORCE_UNWIND)) 610 { 611 // It looks like the exception table has changed 612 // on us. Likely stack corruption! 613 call_terminate(native_exception, unwind_exception); 614 } 615 } 616 // Else this is a catch (T) clause and will never 617 // catch a foreign exception 618 else if (native_exception) 619 { 620 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; 621 void* adjustedPtr = get_thrown_object_ptr(unwind_exception); 622 const __shim_type_info* excpType = 623 static_cast<const __shim_type_info*>(exception_header->exceptionType); 624 if (adjustedPtr == 0 || excpType == 0) 625 { 626 // Something very bad happened 627 call_terminate(native_exception, unwind_exception); 628 } 629 if (catchType->can_catch(excpType, adjustedPtr)) 630 { 631 // Found a matching handler 632 // If this is a type 1 search save state and return _URC_HANDLER_FOUND 633 // If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1! 634 // If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan 635 if (actions & _UA_SEARCH_PHASE) 636 { 637 // Save state and return _URC_HANDLER_FOUND 638 results.ttypeIndex = ttypeIndex; 639 results.actionRecord = actionRecord; 640 results.landingPad = landingPad; 641 results.adjustedPtr = adjustedPtr; 642 results.reason = _URC_HANDLER_FOUND; 643 return; 644 } 645 else if (!(actions & _UA_FORCE_UNWIND)) 646 { 647 // It looks like the exception table has changed 648 // on us. Likely stack corruption! 649 call_terminate(native_exception, unwind_exception); 650 } 651 } 652 } 653 // Scan next action ... 654 } 655 else if (ttypeIndex < 0) 656 { 657 // Found an exception spec. If this is a foreign exception, 658 // it is always caught. 659 if (native_exception) 660 { 661 // Does the exception spec catch this native exception? 662 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; 663 void* adjustedPtr = get_thrown_object_ptr(unwind_exception); 664 const __shim_type_info* excpType = 665 static_cast<const __shim_type_info*>(exception_header->exceptionType); 666 if (adjustedPtr == 0 || excpType == 0) 667 { 668 // Something very bad happened 669 call_terminate(native_exception, unwind_exception); 670 } 671 if (exception_spec_can_catch(ttypeIndex, classInfo, 672 ttypeEncoding, excpType, 673 adjustedPtr, unwind_exception)) 674 { 675 // native exception caught by exception spec 676 // If this is a type 1 search, save state and return _URC_HANDLER_FOUND 677 // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! 678 // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan 679 if (actions & _UA_SEARCH_PHASE) 680 { 681 // Save state and return _URC_HANDLER_FOUND 682 results.ttypeIndex = ttypeIndex; 683 results.actionRecord = actionRecord; 684 results.landingPad = landingPad; 685 results.adjustedPtr = adjustedPtr; 686 results.reason = _URC_HANDLER_FOUND; 687 return; 688 } 689 else if (!(actions & _UA_FORCE_UNWIND)) 690 { 691 // It looks like the exception table has changed 692 // on us. Likely stack corruption! 693 call_terminate(native_exception, unwind_exception); 694 } 695 } 696 } 697 else 698 { 699 // foreign 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 2 search, save state and return _URC_HANDLER_FOUND 702 // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! 703 // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan 704 if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) 705 { 706 // Save state and return _URC_HANDLER_FOUND 707 results.ttypeIndex = ttypeIndex; 708 results.actionRecord = actionRecord; 709 results.landingPad = landingPad; 710 results.adjustedPtr = get_thrown_object_ptr(unwind_exception); 711 results.reason = _URC_HANDLER_FOUND; 712 return; 713 } 714 else if (!(actions & _UA_FORCE_UNWIND)) 715 { 716 // It looks like the exception table has changed 717 // on us. Likely stack corruption! 718 call_terminate(native_exception, unwind_exception); 719 } 720 } 721 // Scan next action ... 722 } 723 else // ttypeIndex == 0 724 { 725 // Found a cleanup 726 // If this is a type 1 search, ignore it and continue scan 727 // If this is a type 2 search, ignore it and continue scan 728 // If this is a type 3 search, save state and return _URC_HANDLER_FOUND 729 if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) 730 { 731 // Save state and return _URC_HANDLER_FOUND 732 results.ttypeIndex = ttypeIndex; 733 results.actionRecord = actionRecord; 734 results.landingPad = landingPad; 735 results.adjustedPtr = get_thrown_object_ptr(unwind_exception); 736 results.reason = _URC_HANDLER_FOUND; 737 return; 738 } 739 } 740 const uint8_t* temp = action; 741 int64_t actionOffset = readSLEB128(&temp); 742 if (actionOffset == 0) 743 { 744 // End of action list, no matching handler or cleanup found 745 results.reason = _URC_CONTINUE_UNWIND; 746 return; 747 } 748 // Go to next action 749 action += actionOffset; 750 } // there is no break out of this loop, only return 751 } 752#if !__arm__ 753 else if (ipOffset < start) 754 { 755 // There is no call site for this ip 756 // Something bad has happened. We should never get here. 757 // Possible stack corruption. 758 call_terminate(native_exception, unwind_exception); 759 } 760#endif // !__arm__ 761 } // there is no break out of this loop, only return 762} 763 764// public API 765 766/* 767The personality function branches on actions like so: 768 769_UA_SEARCH_PHASE 770 771 If _UA_CLEANUP_PHASE or _UA_HANDLER_FRAME or _UA_FORCE_UNWIND there's 772 an error from above, return _URC_FATAL_PHASE1_ERROR. 773 774 Scan for anything that could stop unwinding: 775 776 1. A catch clause that will catch this exception 777 (will never catch foreign). 778 2. A catch (...) (will always catch foreign). 779 3. An exception spec that will catch this exception 780 (will always catch foreign). 781 If a handler is found 782 If not foreign 783 Save state in header 784 return _URC_HANDLER_FOUND 785 Else a handler not found 786 return _URC_CONTINUE_UNWIND 787 788_UA_CLEANUP_PHASE 789 790 If _UA_HANDLER_FRAME 791 If _UA_FORCE_UNWIND 792 How did this happen? return _URC_FATAL_PHASE2_ERROR 793 If foreign 794 Do _UA_SEARCH_PHASE to recover state 795 else 796 Recover state from header 797 Transfer control to landing pad. return _URC_INSTALL_CONTEXT 798 799 Else 800 801 This branch handles both normal C++ non-catching handlers (cleanups) 802 and forced unwinding. 803 Scan for anything that can not stop unwinding: 804 805 1. A cleanup. 806 807 If a cleanup is found 808 transfer control to it. return _URC_INSTALL_CONTEXT 809 Else a cleanup is not found: return _URC_CONTINUE_UNWIND 810*/ 811 812_Unwind_Reason_Code 813#if __arm__ 814__gxx_personality_sj0 815#else 816__gxx_personality_v0 817#endif 818 (int version, _Unwind_Action actions, uint64_t exceptionClass, 819 _Unwind_Exception* unwind_exception, _Unwind_Context* context) 820{ 821 if (version != 1 || unwind_exception == 0 || context == 0) 822 return _URC_FATAL_PHASE1_ERROR; 823 bool native_exception = (exceptionClass & get_vendor_and_language) == 824 (kOurExceptionClass & get_vendor_and_language); 825 scan_results results; 826 if (actions & _UA_SEARCH_PHASE) 827 { 828 // Phase 1 search: All we're looking for in phase 1 is a handler that 829 // halts unwinding 830 scan_eh_tab(results, actions, native_exception, unwind_exception, context); 831 if (results.reason == _URC_HANDLER_FOUND) 832 { 833 // Found one. Can we cache the results somewhere to optimize phase 2? 834 if (native_exception) 835 { 836 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; 837 exception_header->handlerSwitchValue = static_cast<int>(results.ttypeIndex); 838 exception_header->actionRecord = results.actionRecord; 839 exception_header->languageSpecificData = results.languageSpecificData; 840 exception_header->catchTemp = reinterpret_cast<void*>(results.landingPad); 841 exception_header->adjustedPtr = results.adjustedPtr; 842 } 843 return _URC_HANDLER_FOUND; 844 } 845 // Did not find a catching-handler. Return the results of the scan 846 // (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE1_ERROR 847 // if we were called improperly). 848 return results.reason; 849 } 850 if (actions & _UA_CLEANUP_PHASE) 851 { 852 // Phase 2 search: 853 // Did we find a catching handler in phase 1? 854 if (actions & _UA_HANDLER_FRAME) 855 { 856 // Yes, phase 1 said we have a catching handler here. 857 // Did we cache the results of the scan? 858 if (native_exception) 859 { 860 // Yes, reload the results from the cache. 861 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; 862 results.ttypeIndex = exception_header->handlerSwitchValue; 863 results.actionRecord = exception_header->actionRecord; 864 results.languageSpecificData = exception_header->languageSpecificData; 865 results.landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp); 866 results.adjustedPtr = exception_header->adjustedPtr; 867 } 868 else 869 { 870 // No, do the scan again to reload the results. 871 scan_eh_tab(results, actions, native_exception, unwind_exception, context); 872 // Phase 1 told us we would find a handler. Now in Phase 2 we 873 // didn't find a handler. The eh table should not be changing! 874 if (results.reason != _URC_HANDLER_FOUND) 875 call_terminate(native_exception, unwind_exception); 876 } 877 // Jump to the handler 878 _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)unwind_exception); 879 _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), (uintptr_t)results.ttypeIndex); 880 _Unwind_SetIP(context, results.landingPad); 881 return _URC_INSTALL_CONTEXT; 882 } 883 // Either we didn't do a phase 1 search (due to forced unwinding), or 884 // phase 1 reported no catching-handlers. 885 // Search for a (non-catching) cleanup 886 scan_eh_tab(results, actions, native_exception, unwind_exception, context); 887 if (results.reason == _URC_HANDLER_FOUND) 888 { 889 // Found a non-catching handler. Jump to it: 890 _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)unwind_exception); 891 _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), (uintptr_t)results.ttypeIndex); 892 _Unwind_SetIP(context, results.landingPad); 893 return _URC_INSTALL_CONTEXT; 894 } 895 // Did not find a cleanup. Return the results of the scan 896 // (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR 897 // if we were called improperly). 898 return results.reason; 899 } 900 // We were called improperly: neither a phase 1 or phase 2 search 901 return _URC_FATAL_PHASE1_ERROR; 902} 903 904__attribute__((noreturn)) 905void 906__cxa_call_unexpected(void* arg) 907{ 908 _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg); 909 if (unwind_exception == 0) 910 call_terminate(false, unwind_exception); 911 __cxa_begin_catch(unwind_exception); 912 bool native_old_exception = 913 (unwind_exception->exception_class & get_vendor_and_language) == 914 (kOurExceptionClass & get_vendor_and_language); 915 std::unexpected_handler u_handler; 916 std::terminate_handler t_handler; 917 __cxa_exception* old_exception_header = 0; 918 int64_t ttypeIndex; 919 const uint8_t* lsda; 920 if (native_old_exception) 921 { 922 old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1; 923 t_handler = old_exception_header->terminateHandler; 924 u_handler = old_exception_header->unexpectedHandler; 925 // If std::__unexpected(u_handler) rethrows the same exception, 926 // these values get overwritten by the rethrow. So save them now: 927 ttypeIndex = old_exception_header->handlerSwitchValue; 928 lsda = old_exception_header->languageSpecificData; 929 } 930 else 931 { 932 t_handler = std::get_terminate(); 933 u_handler = std::get_unexpected(); 934 } 935 try 936 { 937 std::__unexpected(u_handler); 938 } 939 catch (...) 940 { 941 // If the old exception is foreign, then all we can do is terminate. 942 // We have no way to recover the needed old exception spec. There's 943 // no way to pass that information here. And the personality routine 944 // can't call us directly and do anything but terminate() if we throw 945 // from here. 946 if (native_old_exception) 947 { 948 // Have: 949 // old_exception_header->languageSpecificData 950 // old_exception_header->actionRecord 951 // Need 952 // const uint8_t* classInfo 953 // uint8_t ttypeEncoding 954 uint8_t lpStartEncoding = *lsda++; 955 const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); 956 uint8_t ttypeEncoding = *lsda++; 957 if (ttypeEncoding == DW_EH_PE_omit) 958 std::__terminate(t_handler); 959 uintptr_t classInfoOffset = readULEB128(&lsda); 960 const uint8_t* classInfo = lsda + classInfoOffset; 961 // Is this new exception catchable by the exception spec at ttypeIndex? 962 // The answer is obviously yes if the new and old exceptions are the same exception 963 // If no 964 // throw; 965 __cxa_eh_globals* globals = __cxa_get_globals_fast(); 966 __cxa_exception* new_exception_header = globals->caughtExceptions; 967 if (new_exception_header == 0) 968 // This shouldn't be able to happen! 969 std::__terminate(t_handler); 970 bool native_new_exception = 971 (new_exception_header->unwindHeader.exception_class & get_vendor_and_language) == 972 (kOurExceptionClass & get_vendor_and_language); 973 void* adjustedPtr; 974 if (native_new_exception && (new_exception_header != old_exception_header)) 975 { 976 const __shim_type_info* excpType = 977 static_cast<const __shim_type_info*>(new_exception_header->exceptionType); 978 adjustedPtr = 979 new_exception_header->unwindHeader.exception_class == kOurDependentExceptionClass ? 980 ((__cxa_dependent_exception*)new_exception_header)->primaryException : 981 new_exception_header + 1; 982 if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, 983 excpType, adjustedPtr, unwind_exception)) 984 { 985 // We need to __cxa_end_catch, but for the old exception, 986 // not the new one. This is a little tricky ... 987 // Disguise new_exception_header as a rethrown exception, but 988 // don't actually rethrow it. This means you can temporarily 989 // end the catch clause enclosing new_exception_header without 990 // __cxa_end_catch destroying new_exception_header. 991 new_exception_header->handlerCount = -new_exception_header->handlerCount; 992 globals->uncaughtExceptions += 1; 993 // Call __cxa_end_catch for new_exception_header 994 __cxa_end_catch(); 995 // Call __cxa_end_catch for old_exception_header 996 __cxa_end_catch(); 997 // Renter this catch clause with new_exception_header 998 __cxa_begin_catch(&new_exception_header->unwindHeader); 999 // Rethrow new_exception_header 1000 throw; 1001 } 1002 } 1003 // Will a std::bad_exception be catchable by the exception spec at 1004 // ttypeIndex? 1005 // If no 1006 // throw std::bad_exception(); 1007 const __shim_type_info* excpType = 1008 static_cast<const __shim_type_info*>(&typeid(std::bad_exception)); 1009 std::bad_exception be; 1010 adjustedPtr = &be; 1011 if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, 1012 excpType, adjustedPtr, unwind_exception)) 1013 { 1014 // We need to __cxa_end_catch for both the old exception and the 1015 // new exception. Technically we should do it in that order. 1016 // But it is expedent to do it in the opposite order: 1017 // Call __cxa_end_catch for new_exception_header 1018 __cxa_end_catch(); 1019 // Throw std::bad_exception will __cxa_end_catch for 1020 // old_exception_header 1021 throw be; 1022 } 1023 } 1024 } 1025 std::__terminate(t_handler); 1026} 1027 1028} // extern "C" 1029 1030} // __cxxabiv1 1031