1212 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//8// Implements ARM zero-cost C++ exceptions9//10//===----------------------------------------------------------------------===//11 12#include "Unwind-EHABI.h"13 14#if defined(_LIBUNWIND_ARM_EHABI)15 16#include <inttypes.h>17#include <stdbool.h>18#include <stdint.h>19#include <stdio.h>20#include <stdlib.h>21#include <string.h>22 23#include "config.h"24#include "libunwind.h"25#include "libunwind_ext.h"26#include "unwind.h"27 28namespace {29 30// Strange order: take words in order, but inside word, take from most to least31// signinficant byte.32uint8_t getByte(const uint32_t* data, size_t offset) {33 const uint8_t* byteData = reinterpret_cast<const uint8_t*>(data);34#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__35 return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))];36#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__37 return byteData[offset];38#else39#error "Unable to determine endianess"40#endif41}42 43const char* getNextWord(const char* data, uint32_t* out) {44 *out = *reinterpret_cast<const uint32_t*>(data);45 return data + 4;46}47 48const char* getNextNibble(const char* data, uint32_t* out) {49 *out = *reinterpret_cast<const uint16_t*>(data);50 return data + 2;51}52 53struct Descriptor {54 // See # 9.255 typedef enum {56 SU16 = 0, // Short descriptor, 16-bit entries57 LU16 = 1, // Long descriptor, 16-bit entries58 LU32 = 3, // Long descriptor, 32-bit entries59 RESERVED0 = 4, RESERVED1 = 5, RESERVED2 = 6, RESERVED3 = 7,60 RESERVED4 = 8, RESERVED5 = 9, RESERVED6 = 10, RESERVED7 = 11,61 RESERVED8 = 12, RESERVED9 = 13, RESERVED10 = 14, RESERVED11 = 1562 } Format;63 64 // See # 9.265 typedef enum {66 CLEANUP = 0x0,67 FUNC = 0x1,68 CATCH = 0x2,69 INVALID = 0x470 } Kind;71};72 73_Unwind_Reason_Code ProcessDescriptors(74 _Unwind_State state,75 _Unwind_Control_Block* ucbp,76 struct _Unwind_Context* context,77 Descriptor::Format format,78 const char* descriptorStart,79 uint32_t flags) {80 81 // EHT is inlined in the index using compact form. No descriptors. #582 if (flags & 0x1)83 return _URC_CONTINUE_UNWIND;84 85 // TODO: We should check the state here, and determine whether we need to86 // perform phase1 or phase2 unwinding.87 (void)state;88 89 const char* descriptor = descriptorStart;90 uint32_t descriptorWord;91 getNextWord(descriptor, &descriptorWord);92 while (descriptorWord) {93 // Read descriptor based on # 9.2.94 uint32_t length;95 uint32_t offset;96 switch (format) {97 case Descriptor::LU32:98 descriptor = getNextWord(descriptor, &length);99 descriptor = getNextWord(descriptor, &offset);100 break;101 case Descriptor::LU16:102 descriptor = getNextNibble(descriptor, &length);103 descriptor = getNextNibble(descriptor, &offset);104 break;105 default:106 assert(false);107 return _URC_FAILURE;108 }109 110 // See # 9.2 table for decoding the kind of descriptor. It's a 2-bit value.111 Descriptor::Kind kind =112 static_cast<Descriptor::Kind>((length & 0x1) | ((offset & 0x1) << 1));113 114 // Clear off flag from last bit.115 length &= ~1u;116 offset &= ~1u;117 uintptr_t scopeStart = ucbp->pr_cache.fnstart + offset;118 uintptr_t scopeEnd = scopeStart + length;119 uintptr_t pc = _Unwind_GetIP(context);120 bool isInScope = (scopeStart <= pc) && (pc < scopeEnd);121 122 switch (kind) {123 case Descriptor::CLEANUP: {124 // TODO(ajwong): Handle cleanup descriptors.125 break;126 }127 case Descriptor::FUNC: {128 // TODO(ajwong): Handle function descriptors.129 break;130 }131 case Descriptor::CATCH: {132 // Catch descriptors require gobbling one more word.133 uint32_t landing_pad;134 descriptor = getNextWord(descriptor, &landing_pad);135 136 if (isInScope) {137 // TODO(ajwong): This is only phase1 compatible logic. Implement138 // phase2.139 landing_pad = signExtendPrel31(landing_pad & ~0x80000000);140 if (landing_pad == 0xffffffff) {141 return _URC_HANDLER_FOUND;142 } else if (landing_pad == 0xfffffffe) {143 return _URC_FAILURE;144 } else {145 /*146 bool is_reference_type = landing_pad & 0x80000000;147 void* matched_object;148 if (__cxxabiv1::__cxa_type_match(149 ucbp, reinterpret_cast<const std::type_info *>(landing_pad),150 is_reference_type,151 &matched_object) != __cxxabiv1::ctm_failed)152 return _URC_HANDLER_FOUND;153 */154 _LIBUNWIND_ABORT("Type matching not implemented");155 }156 }157 break;158 }159 default:160 _LIBUNWIND_ABORT("Invalid descriptor kind found.");161 }162 163 getNextWord(descriptor, &descriptorWord);164 }165 166 return _URC_CONTINUE_UNWIND;167}168 169static _Unwind_Reason_Code unwindOneFrame(_Unwind_State state,170 _Unwind_Control_Block* ucbp,171 struct _Unwind_Context* context) {172 // Read the compact model EHT entry's header # 6.3173 const uint32_t* unwindingData = ucbp->pr_cache.ehtp;174 assert((*unwindingData & 0xf0000000) == 0x80000000 && "Must be a compact entry");175 Descriptor::Format format =176 static_cast<Descriptor::Format>((*unwindingData & 0x0f000000) >> 24);177 178 const char *lsda =179 reinterpret_cast<const char *>(_Unwind_GetLanguageSpecificData(context));180 181 // Handle descriptors before unwinding so they are processed in the context182 // of the correct stack frame.183 _Unwind_Reason_Code result =184 ProcessDescriptors(state, ucbp, context, format, lsda,185 ucbp->pr_cache.additional);186 187 if (result != _URC_CONTINUE_UNWIND)188 return result;189 190 switch (__unw_step(reinterpret_cast<unw_cursor_t *>(context))) {191 case UNW_STEP_SUCCESS:192 return _URC_CONTINUE_UNWIND;193 case UNW_STEP_END:194 return _URC_END_OF_STACK;195 default:196 return _URC_FAILURE;197 }198}199 200// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_CORE /201// _UVRSD_UINT32.202uint32_t RegisterMask(uint8_t start, uint8_t count_minus_one) {203 return ((1U << (count_minus_one + 1)) - 1) << start;204}205 206// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_VFP /207// _UVRSD_DOUBLE.208uint32_t RegisterRange(uint8_t start, uint8_t count_minus_one) {209 return ((uint32_t)start << 16) | ((uint32_t)count_minus_one + 1);210}211 212} // end anonymous namespace213 214/**215 * Decodes an EHT entry.216 *217 * @param data Pointer to EHT.218 * @param[out] off Offset from return value (in bytes) to begin interpretation.219 * @param[out] len Number of bytes in unwind code.220 * @return Pointer to beginning of unwind code.221 */222extern "C" const uint32_t*223decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) {224 if ((*data & 0x80000000) == 0) {225 // 6.2: Generic Model226 //227 // EHT entry is a prel31 pointing to the PR, followed by data understood228 // only by the personality routine. Fortunately, all existing assembler229 // implementations, including GNU assembler, LLVM integrated assembler,230 // and ARM assembler, assume that the unwind opcodes come after the231 // personality rountine address.232 *off = 1; // First byte is size data.233 *len = (((data[1] >> 24) & 0xff) + 1) * 4;234 data++; // Skip the first word, which is the prel31 offset.235 } else {236 // 6.3: ARM Compact Model237 //238 // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeed239 // by format:240 Descriptor::Format format =241 static_cast<Descriptor::Format>((*data & 0x0f000000) >> 24);242 switch (format) {243 case Descriptor::SU16:244 *len = 4;245 *off = 1;246 break;247 case Descriptor::LU16:248 case Descriptor::LU32:249 *len = 4 + 4 * ((*data & 0x00ff0000) >> 16);250 *off = 2;251 break;252 default:253 return nullptr;254 }255 }256 return data;257}258 259_LIBUNWIND_EXPORT _Unwind_Reason_Code260_Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data,261 size_t offset, size_t len) {262 bool wrotePC = false;263 bool finish = false;264 bool hasReturnAddrAuthCode = false;265 while (offset < len && !finish) {266 uint8_t byte = getByte(data, offset++);267 if ((byte & 0x80) == 0) {268 uint32_t sp;269 _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);270 if (byte & 0x40)271 sp -= (((uint32_t)byte & 0x3f) << 2) + 4;272 else273 sp += ((uint32_t)byte << 2) + 4;274 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);275 } else {276 switch (byte & 0xf0) {277 case 0x80: {278 if (offset >= len)279 return _URC_FAILURE;280 uint32_t registers =281 (((uint32_t)byte & 0x0f) << 12) |282 (((uint32_t)getByte(data, offset++)) << 4);283 if (!registers)284 return _URC_FAILURE;285 if (registers & (1 << 15))286 wrotePC = true;287 _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);288 break;289 }290 case 0x90: {291 uint8_t reg = byte & 0x0f;292 if (reg == 13 || reg == 15)293 return _URC_FAILURE;294 uint32_t sp;295 _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg,296 _UVRSD_UINT32, &sp);297 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,298 &sp);299 break;300 }301 case 0xa0: {302 uint32_t registers = RegisterMask(4, byte & 0x07);303 if (byte & 0x08)304 registers |= 1 << 14;305 _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);306 break;307 }308 case 0xb0: {309 switch (byte) {310 case 0xb0:311 finish = true;312 break;313 case 0xb1: {314 if (offset >= len)315 return _URC_FAILURE;316 uint8_t registers = getByte(data, offset++);317 if (registers & 0xf0 || !registers)318 return _URC_FAILURE;319 _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);320 break;321 }322 case 0xb2: {323 uint32_t addend = 0;324 uint32_t shift = 0;325 // This decodes a uleb128 value.326 while (true) {327 if (offset >= len)328 return _URC_FAILURE;329 uint32_t v = getByte(data, offset++);330 addend |= (v & 0x7f) << shift;331 if ((v & 0x80) == 0)332 break;333 shift += 7;334 }335 uint32_t sp;336 _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,337 &sp);338 sp += 0x204 + (addend << 2);339 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,340 &sp);341 break;342 }343 case 0xb3: {344 uint8_t v = getByte(data, offset++);345 _Unwind_VRS_Pop(context, _UVRSC_VFP,346 RegisterRange(static_cast<uint8_t>(v >> 4),347 v & 0x0f), _UVRSD_VFPX);348 break;349 }350 case 0xb4:351 hasReturnAddrAuthCode = true;352 _Unwind_VRS_Pop(context, _UVRSC_PSEUDO,353 0 /* Return Address Auth Code */, _UVRSD_UINT32);354 break;355 case 0xb5:356 case 0xb6:357 case 0xb7:358 return _URC_FAILURE;359 default:360 _Unwind_VRS_Pop(context, _UVRSC_VFP,361 RegisterRange(8, byte & 0x07), _UVRSD_VFPX);362 break;363 }364 break;365 }366 case 0xc0: {367 switch (byte) {368#if defined(__ARM_WMMX)369 case 0xc0:370 case 0xc1:371 case 0xc2:372 case 0xc3:373 case 0xc4:374 case 0xc5:375 _Unwind_VRS_Pop(context, _UVRSC_WMMXD,376 RegisterRange(10, byte & 0x7), _UVRSD_DOUBLE);377 break;378 case 0xc6: {379 uint8_t v = getByte(data, offset++);380 uint8_t start = static_cast<uint8_t>(v >> 4);381 uint8_t count_minus_one = v & 0xf;382 if (start + count_minus_one >= 16)383 return _URC_FAILURE;384 _Unwind_VRS_Pop(context, _UVRSC_WMMXD,385 RegisterRange(start, count_minus_one),386 _UVRSD_DOUBLE);387 break;388 }389 case 0xc7: {390 uint8_t v = getByte(data, offset++);391 if (!v || v & 0xf0)392 return _URC_FAILURE;393 _Unwind_VRS_Pop(context, _UVRSC_WMMXC, v, _UVRSD_DOUBLE);394 break;395 }396#endif397 case 0xc8:398 case 0xc9: {399 uint8_t v = getByte(data, offset++);400 uint8_t start =401 static_cast<uint8_t>(((byte == 0xc8) ? 16 : 0) + (v >> 4));402 uint8_t count_minus_one = v & 0xf;403 if (start + count_minus_one >= 32)404 return _URC_FAILURE;405 _Unwind_VRS_Pop(context, _UVRSC_VFP,406 RegisterRange(start, count_minus_one),407 _UVRSD_DOUBLE);408 break;409 }410 default:411 return _URC_FAILURE;412 }413 break;414 }415 case 0xd0: {416 if (byte & 0x08)417 return _URC_FAILURE;418 _Unwind_VRS_Pop(context, _UVRSC_VFP, RegisterRange(8, byte & 0x7),419 _UVRSD_DOUBLE);420 break;421 }422 default:423 return _URC_FAILURE;424 }425 }426 }427 if (!wrotePC) {428 uint32_t lr;429 _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr);430#ifdef __ARM_FEATURE_PAUTH431 if (hasReturnAddrAuthCode) {432 uint32_t sp;433 uint32_t pac;434 _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);435 _Unwind_VRS_Get(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac);436 __asm__ __volatile__("autg %0, %1, %2" : : "r"(pac), "r"(lr), "r"(sp) :);437 }438#else439 (void)hasReturnAddrAuthCode;440#endif441 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr);442 }443 return _URC_CONTINUE_UNWIND;444}445 446extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code447__aeabi_unwind_cpp_pr0(_Unwind_State state, _Unwind_Control_Block *ucbp,448 _Unwind_Context *context) {449 return unwindOneFrame(state, ucbp, context);450}451 452extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code453__aeabi_unwind_cpp_pr1(_Unwind_State state, _Unwind_Control_Block *ucbp,454 _Unwind_Context *context) {455 return unwindOneFrame(state, ucbp, context);456}457 458extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code459__aeabi_unwind_cpp_pr2(_Unwind_State state, _Unwind_Control_Block *ucbp,460 _Unwind_Context *context) {461 return unwindOneFrame(state, ucbp, context);462}463 464static _Unwind_Reason_Code465unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {466 // EHABI #7.3 discusses preserving the VRS in a "temporary VRS" during467 // phase 1 and then restoring it to the "primary VRS" for phase 2. The468 // effect is phase 2 doesn't see any of the VRS manipulations from phase 1.469 // In this implementation, the phases don't share the VRS backing store.470 // Instead, they are passed the original |uc| and they create a new VRS471 // from scratch thus achieving the same effect.472 __unw_init_local(cursor, uc);473 474 // Walk each frame looking for a place to stop.475 for (bool handlerNotFound = true; handlerNotFound;) {476 477 // See if frame has code to run (has personality routine).478 unw_proc_info_t frameInfo;479 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {480 _LIBUNWIND_TRACE_UNWINDING(481 "unwind_phase1(ex_ojb=%p): __unw_get_proc_info "482 "failed => _URC_FATAL_PHASE1_ERROR",483 static_cast<void *>(exception_object));484 return _URC_FATAL_PHASE1_ERROR;485 }486 487#ifndef NDEBUG488 // When tracing, print state information.489 if (_LIBUNWIND_TRACING_UNWINDING) {490 char functionBuf[512];491 const char *functionName = functionBuf;492 unw_word_t offset;493 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),494 &offset) != UNW_ESUCCESS) ||495 (frameInfo.start_ip + offset > frameInfo.end_ip))496 functionName = ".anonymous.";497 unw_word_t pc;498 __unw_get_reg(cursor, UNW_REG_IP, &pc);499 _LIBUNWIND_TRACE_UNWINDING(500 "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR ", func=%s, "501 "lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,502 static_cast<void *>(exception_object), pc,503 frameInfo.start_ip, functionName,504 frameInfo.lsda, frameInfo.handler);505 }506#endif507 508 // If there is a personality routine, ask it if it will want to stop at509 // this frame.510 if (frameInfo.handler != 0) {511 _Unwind_Personality_Fn p =512 (_Unwind_Personality_Fn)(long)(frameInfo.handler);513 _LIBUNWIND_TRACE_UNWINDING(514 "unwind_phase1(ex_ojb=%p): calling personality function %p",515 static_cast<void *>(exception_object),516 reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p)));517 struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);518 exception_object->pr_cache.fnstart = frameInfo.start_ip;519 exception_object->pr_cache.ehtp =520 (_Unwind_EHT_Header *)frameInfo.unwind_info;521 exception_object->pr_cache.additional = frameInfo.flags;522 _Unwind_Reason_Code personalityResult =523 (*p)(_US_VIRTUAL_UNWIND_FRAME, exception_object, context);524 _LIBUNWIND_TRACE_UNWINDING(525 "unwind_phase1(ex_ojb=%p): personality result %d start_ip %x ehtp %p "526 "additional %x",527 static_cast<void *>(exception_object), personalityResult,528 exception_object->pr_cache.fnstart,529 static_cast<void *>(exception_object->pr_cache.ehtp),530 exception_object->pr_cache.additional);531 switch (personalityResult) {532 case _URC_HANDLER_FOUND:533 // found a catch clause or locals that need destructing in this frame534 // stop search and remember stack pointer at the frame535 handlerNotFound = false;536 // p should have initialized barrier_cache. EHABI #7.3.5537 _LIBUNWIND_TRACE_UNWINDING(538 "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND",539 static_cast<void *>(exception_object));540 return _URC_NO_REASON;541 542 case _URC_CONTINUE_UNWIND:543 _LIBUNWIND_TRACE_UNWINDING(544 "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND",545 static_cast<void *>(exception_object));546 // continue unwinding547 break;548 549 // EHABI #7.3.3550 case _URC_FAILURE:551 return _URC_FAILURE;552 553 default:554 // something went wrong555 _LIBUNWIND_TRACE_UNWINDING(556 "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",557 static_cast<void *>(exception_object));558 return _URC_FATAL_PHASE1_ERROR;559 }560 }561 }562 return _URC_NO_REASON;563}564 565static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,566 _Unwind_Exception *exception_object,567 bool resume) {568 // See comment at the start of unwind_phase1 regarding VRS integrity.569 __unw_init_local(cursor, uc);570 571 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",572 static_cast<void *>(exception_object));573 int frame_count = 0;574 575 // Walk each frame until we reach where search phase said to stop.576 while (true) {577 // Ask libunwind to get next frame (skip over first which is578 // _Unwind_RaiseException or _Unwind_Resume).579 //580 // Resume only ever makes sense for 1 frame.581 _Unwind_State state =582 resume ? _US_UNWIND_FRAME_RESUME : _US_UNWIND_FRAME_STARTING;583 if (resume && frame_count == 1) {584 // On a resume, first unwind the _Unwind_Resume() frame. The next frame585 // is now the landing pad for the cleanup from a previous execution of586 // phase2. To continue unwindingly correctly, replace VRS[15] with the587 // IP of the frame that the previous run of phase2 installed the context588 // for. After this, continue unwinding as if normal.589 //590 // See #7.4.6 for details.591 __unw_set_reg(cursor, UNW_REG_IP,592 exception_object->unwinder_cache.reserved2);593 resume = false;594 }595 596 // Get info about this frame.597 unw_word_t sp;598 unw_proc_info_t frameInfo;599 __unw_get_reg(cursor, UNW_REG_SP, &sp);600 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {601 _LIBUNWIND_TRACE_UNWINDING(602 "unwind_phase2(ex_ojb=%p): __unw_get_proc_info "603 "failed => _URC_FATAL_PHASE2_ERROR",604 static_cast<void *>(exception_object));605 return _URC_FATAL_PHASE2_ERROR;606 }607 608#ifndef NDEBUG609 // When tracing, print state information.610 if (_LIBUNWIND_TRACING_UNWINDING) {611 char functionBuf[512];612 const char *functionName = functionBuf;613 unw_word_t offset;614 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),615 &offset) != UNW_ESUCCESS) ||616 (frameInfo.start_ip + offset > frameInfo.end_ip))617 functionName = ".anonymous.";618 _LIBUNWIND_TRACE_UNWINDING(619 "unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR ", func=%s, sp=0x%" PRIxPTR ", "620 "lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "",621 static_cast<void *>(exception_object), frameInfo.start_ip,622 functionName, sp, frameInfo.lsda,623 frameInfo.handler);624 }625#endif626 627 // If there is a personality routine, tell it we are unwinding.628 if (frameInfo.handler != 0) {629 _Unwind_Personality_Fn p =630 (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);631 struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);632 // EHABI #7.2633 exception_object->pr_cache.fnstart = frameInfo.start_ip;634 exception_object->pr_cache.ehtp =635 (_Unwind_EHT_Header *)frameInfo.unwind_info;636 exception_object->pr_cache.additional = frameInfo.flags;637 _Unwind_Reason_Code personalityResult =638 (*p)(state, exception_object, context);639 switch (personalityResult) {640 case _URC_CONTINUE_UNWIND:641 // Continue unwinding642 _LIBUNWIND_TRACE_UNWINDING(643 "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",644 static_cast<void *>(exception_object));645 // EHABI #7.2646 if (sp == exception_object->barrier_cache.sp) {647 // Phase 1 said we would stop at this frame, but we did not...648 _LIBUNWIND_ABORT("during phase1 personality function said it would "649 "stop here, but now in phase2 it did not stop here");650 }651 break;652 case _URC_INSTALL_CONTEXT:653 _LIBUNWIND_TRACE_UNWINDING(654 "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT",655 static_cast<void *>(exception_object));656 // Personality routine says to transfer control to landing pad.657 // We may get control back if landing pad calls _Unwind_Resume().658 if (_LIBUNWIND_TRACING_UNWINDING) {659 unw_word_t pc;660 __unw_get_reg(cursor, UNW_REG_IP, &pc);661 __unw_get_reg(cursor, UNW_REG_SP, &sp);662 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "663 "user code with ip=0x%" PRIxPTR ", sp=0x%" PRIxPTR,664 static_cast<void *>(exception_object),665 pc, sp);666 }667 668 {669 // EHABI #7.4.1 says we need to preserve pc for when _Unwind_Resume670 // is called back, to find this same frame.671 unw_word_t pc;672 __unw_get_reg(cursor, UNW_REG_IP, &pc);673 exception_object->unwinder_cache.reserved2 = (uint32_t)pc;674 }675 __unw_resume(cursor);676 // __unw_resume() only returns if there was an error.677 return _URC_FATAL_PHASE2_ERROR;678 679 // # EHABI #7.4.3680 case _URC_FAILURE:681 abort();682 683 default:684 // Personality routine returned an unknown result code.685 _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",686 personalityResult);687 return _URC_FATAL_PHASE2_ERROR;688 }689 }690 frame_count++;691 }692 693 // Clean up phase did not resume at the frame that the search phase694 // said it would...695 return _URC_FATAL_PHASE2_ERROR;696}697 698static _Unwind_Reason_Code699unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,700 _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,701 void *stop_parameter) {702 bool endOfStack = false;703 // See comment at the start of unwind_phase1 regarding VRS integrity.704 __unw_init_local(cursor, uc);705 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_force(ex_ojb=%p)",706 static_cast<void *>(exception_object));707 // Walk each frame until we reach where search phase said to stop708 while (!endOfStack) {709 // Update info about this frame.710 unw_proc_info_t frameInfo;711 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {712 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_get_proc_info "713 "failed => _URC_END_OF_STACK",714 (void *)exception_object);715 return _URC_FATAL_PHASE2_ERROR;716 }717 718#ifndef NDEBUG719 // When tracing, print state information.720 if (_LIBUNWIND_TRACING_UNWINDING) {721 char functionBuf[512];722 const char *functionName = functionBuf;723 unw_word_t offset;724 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),725 &offset) != UNW_ESUCCESS) ||726 (frameInfo.start_ip + offset > frameInfo.end_ip))727 functionName = ".anonymous.";728 _LIBUNWIND_TRACE_UNWINDING(729 "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR730 ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,731 (void *)exception_object, frameInfo.start_ip, functionName,732 frameInfo.lsda, frameInfo.handler);733 }734#endif735 736 // Call stop function at each frame.737 _Unwind_Action action =738 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);739 _Unwind_Reason_Code stopResult =740 (*stop)(1, action, exception_object->exception_class, exception_object,741 (_Unwind_Context *)(cursor), stop_parameter);742 _LIBUNWIND_TRACE_UNWINDING(743 "unwind_phase2_forced(ex_ojb=%p): stop function returned %d",744 (void *)exception_object, stopResult);745 if (stopResult != _URC_NO_REASON) {746 _LIBUNWIND_TRACE_UNWINDING(747 "unwind_phase2_forced(ex_ojb=%p): stopped by stop function",748 (void *)exception_object);749 return _URC_FATAL_PHASE2_ERROR;750 }751 752 // If there is a personality routine, tell it we are unwinding.753 if (frameInfo.handler != 0) {754 _Unwind_Personality_Fn p =755 (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);756 struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);757 // EHABI #7.2758 exception_object->pr_cache.fnstart = frameInfo.start_ip;759 exception_object->pr_cache.ehtp =760 (_Unwind_EHT_Header *)frameInfo.unwind_info;761 exception_object->pr_cache.additional = frameInfo.flags;762 _Unwind_Reason_Code personalityResult =763 (*p)(_US_FORCE_UNWIND | _US_UNWIND_FRAME_STARTING, exception_object,764 context);765 switch (personalityResult) {766 case _URC_CONTINUE_UNWIND:767 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "768 "personality returned "769 "_URC_CONTINUE_UNWIND",770 (void *)exception_object);771 // Destructors called, continue unwinding772 break;773 case _URC_INSTALL_CONTEXT:774 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "775 "personality returned "776 "_URC_INSTALL_CONTEXT",777 (void *)exception_object);778 // We may get control back if landing pad calls _Unwind_Resume().779 __unw_resume(cursor);780 break;781 case _URC_END_OF_STACK:782 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "783 "personality returned "784 "_URC_END_OF_STACK",785 (void *)exception_object);786 // Personalty routine did the step and it can't step forward.787 endOfStack = true;788 break;789 default:790 // Personality routine returned an unknown result code.791 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "792 "personality returned %d, "793 "_URC_FATAL_PHASE2_ERROR",794 (void *)exception_object, personalityResult);795 return _URC_FATAL_PHASE2_ERROR;796 }797 }798 }799 800 // Call stop function one last time and tell it we've reached the end801 // of the stack.802 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "803 "function with _UA_END_OF_STACK",804 (void *)exception_object);805 _Unwind_Action lastAction =806 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);807 (*stop)(1, lastAction, exception_object->exception_class, exception_object,808 (struct _Unwind_Context *)(cursor), stop_parameter);809 810 // Clean up phase did not resume at the frame that the search phase said it811 // would.812 return _URC_FATAL_PHASE2_ERROR;813}814 815/// Called by __cxa_throw. Only returns if there is a fatal error.816_LIBUNWIND_EXPORT _Unwind_Reason_Code817_Unwind_RaiseException(_Unwind_Exception *exception_object) {818 _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",819 static_cast<void *>(exception_object));820 unw_context_t uc;821 unw_cursor_t cursor;822 __unw_getcontext(&uc);823 824 // This field for is for compatibility with GCC to say this isn't a forced825 // unwind. EHABI #7.2826 exception_object->unwinder_cache.reserved1 = 0;827 828 // phase 1: the search phase829 _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);830 if (phase1 != _URC_NO_REASON)831 return phase1;832 833 // phase 2: the clean up phase834 return unwind_phase2(&uc, &cursor, exception_object, false);835}836 837_LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) {838 // This is to be called when exception handling completes to give us a chance839 // to perform any housekeeping. EHABI #7.2. But we have nothing to do here.840 (void)exception_object;841}842 843/// When _Unwind_RaiseException() is in phase2, it hands control844/// to the personality function at each frame. The personality845/// may force a jump to a landing pad in that function, the landing846/// pad code may then call _Unwind_Resume() to continue with the847/// unwinding. Note: the call to _Unwind_Resume() is from compiler848/// generated user code. All other _Unwind_* routines are called849/// by the C++ runtime __cxa_* routines.850///851/// Note: re-throwing an exception (as opposed to continuing the unwind)852/// is implemented by having the code call __cxa_rethrow() which853/// in turn calls _Unwind_Resume_or_Rethrow().854_LIBUNWIND_EXPORT void855_Unwind_Resume(_Unwind_Exception *exception_object) {856 _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)",857 static_cast<void *>(exception_object));858 unw_context_t uc;859 unw_cursor_t cursor;860 __unw_getcontext(&uc);861 862 if (exception_object->unwinder_cache.reserved1)863 unwind_phase2_forced(864 &uc, &cursor, exception_object,865 (_Unwind_Stop_Fn)exception_object->unwinder_cache.reserved1,866 (void *)exception_object->unwinder_cache.reserved3);867 else868 unwind_phase2(&uc, &cursor, exception_object, true);869 870 // Clients assume _Unwind_Resume() does not return, so all we can do is abort.871 _LIBUNWIND_ABORT("_Unwind_Resume() can't return");872}873 874/// Called by personality handler during phase 2 to get LSDA for current frame.875_LIBUNWIND_EXPORT uintptr_t876_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {877 unw_cursor_t *cursor = (unw_cursor_t *)context;878 unw_proc_info_t frameInfo;879 uintptr_t result = 0;880 if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)881 result = (uintptr_t)frameInfo.lsda;882 _LIBUNWIND_TRACE_API(883 "_Unwind_GetLanguageSpecificData(context=%p) => 0x%llx",884 static_cast<void *>(context), (long long)result);885 return result;886}887 888// Only used in _LIBUNWIND_TRACE_API, which is a no-op when assertions are889// disabled.890[[gnu::unused]] static uint64_t891ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,892 const void *valuep) {893 uint64_t value = 0;894 switch (representation) {895 case _UVRSD_UINT32:896 case _UVRSD_FLOAT:897 memcpy(&value, valuep, sizeof(uint32_t));898 break;899 900 case _UVRSD_VFPX:901 case _UVRSD_UINT64:902 case _UVRSD_DOUBLE:903 memcpy(&value, valuep, sizeof(uint64_t));904 break;905 }906 return value;907}908 909_LIBUNWIND_EXPORT _Unwind_VRS_Result910_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,911 uint32_t regno, _Unwind_VRS_DataRepresentation representation,912 void *valuep) {913 _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, "914 "rep=%d, value=0x%llX)",915 static_cast<void *>(context), regclass, regno,916 representation,917 ValueAsBitPattern(representation, valuep));918 unw_cursor_t *cursor = (unw_cursor_t *)context;919 switch (regclass) {920 case _UVRSC_CORE:921 if (representation != _UVRSD_UINT32 || regno > 15)922 return _UVRSR_FAILED;923 return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno),924 *(unw_word_t *)valuep) == UNW_ESUCCESS925 ? _UVRSR_OK926 : _UVRSR_FAILED;927 case _UVRSC_VFP:928 if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)929 return _UVRSR_FAILED;930 if (representation == _UVRSD_VFPX) {931 // Can only touch d0-15 with FSTMFDX.932 if (regno > 15)933 return _UVRSR_FAILED;934 __unw_save_vfp_as_X(cursor);935 } else {936 if (regno > 31)937 return _UVRSR_FAILED;938 }939 return __unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno),940 *(unw_fpreg_t *)valuep) == UNW_ESUCCESS941 ? _UVRSR_OK942 : _UVRSR_FAILED;943#if defined(__ARM_WMMX)944 case _UVRSC_WMMXC:945 if (representation != _UVRSD_UINT32 || regno > 3)946 return _UVRSR_FAILED;947 return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),948 *(unw_word_t *)valuep) == UNW_ESUCCESS949 ? _UVRSR_OK950 : _UVRSR_FAILED;951 case _UVRSC_WMMXD:952 if (representation != _UVRSD_DOUBLE || regno > 31)953 return _UVRSR_FAILED;954 return __unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno),955 *(unw_fpreg_t *)valuep) == UNW_ESUCCESS956 ? _UVRSR_OK957 : _UVRSR_FAILED;958#else959 case _UVRSC_WMMXC:960 case _UVRSC_WMMXD:961 break;962#endif963 case _UVRSC_PSEUDO:964 // There's only one pseudo-register, PAC, with regno == 0.965 if (representation != _UVRSD_UINT32 || regno != 0)966 return _UVRSR_FAILED;967 return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE),968 *(unw_word_t *)valuep) == UNW_ESUCCESS969 ? _UVRSR_OK970 : _UVRSR_FAILED;971 break;972 }973 _LIBUNWIND_ABORT("unsupported register class");974}975 976static _Unwind_VRS_Result977_Unwind_VRS_Get_Internal(_Unwind_Context *context,978 _Unwind_VRS_RegClass regclass, uint32_t regno,979 _Unwind_VRS_DataRepresentation representation,980 void *valuep) {981 unw_cursor_t *cursor = (unw_cursor_t *)context;982 switch (regclass) {983 case _UVRSC_CORE:984 if (representation != _UVRSD_UINT32 || regno > 15)985 return _UVRSR_FAILED;986 return __unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno),987 (unw_word_t *)valuep) == UNW_ESUCCESS988 ? _UVRSR_OK989 : _UVRSR_FAILED;990 case _UVRSC_VFP:991 if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)992 return _UVRSR_FAILED;993 if (representation == _UVRSD_VFPX) {994 // Can only touch d0-15 with FSTMFDX.995 if (regno > 15)996 return _UVRSR_FAILED;997 __unw_save_vfp_as_X(cursor);998 } else {999 if (regno > 31)1000 return _UVRSR_FAILED;1001 }1002 return __unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno),1003 (unw_fpreg_t *)valuep) == UNW_ESUCCESS1004 ? _UVRSR_OK1005 : _UVRSR_FAILED;1006#if defined(__ARM_WMMX)1007 case _UVRSC_WMMXC:1008 if (representation != _UVRSD_UINT32 || regno > 3)1009 return _UVRSR_FAILED;1010 return __unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),1011 (unw_word_t *)valuep) == UNW_ESUCCESS1012 ? _UVRSR_OK1013 : _UVRSR_FAILED;1014 case _UVRSC_WMMXD:1015 if (representation != _UVRSD_DOUBLE || regno > 31)1016 return _UVRSR_FAILED;1017 return __unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno),1018 (unw_fpreg_t *)valuep) == UNW_ESUCCESS1019 ? _UVRSR_OK1020 : _UVRSR_FAILED;1021#else1022 case _UVRSC_WMMXC:1023 case _UVRSC_WMMXD:1024 break;1025#endif1026 case _UVRSC_PSEUDO:1027 // There's only one pseudo-register, PAC, with regno == 0.1028 if (representation != _UVRSD_UINT32 || regno != 0)1029 return _UVRSR_FAILED;1030 return __unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE),1031 (unw_word_t *)valuep) == UNW_ESUCCESS1032 ? _UVRSR_OK1033 : _UVRSR_FAILED;1034 break;1035 }1036 _LIBUNWIND_ABORT("unsupported register class");1037}1038 1039_LIBUNWIND_EXPORT _Unwind_VRS_Result1040_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,1041 uint32_t regno, _Unwind_VRS_DataRepresentation representation,1042 void *valuep) {1043 _Unwind_VRS_Result result =1044 _Unwind_VRS_Get_Internal(context, regclass, regno, representation,1045 valuep);1046 _LIBUNWIND_TRACE_API("_Unwind_VRS_Get(context=%p, regclass=%d, reg=%d, "1047 "rep=%d, value=0x%llX, result = %d)",1048 static_cast<void *>(context), regclass, regno,1049 representation,1050 ValueAsBitPattern(representation, valuep), result);1051 return result;1052}1053 1054_Unwind_VRS_Result1055_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,1056 uint32_t discriminator,1057 _Unwind_VRS_DataRepresentation representation) {1058 _LIBUNWIND_TRACE_API("_Unwind_VRS_Pop(context=%p, regclass=%d, "1059 "discriminator=%d, representation=%d)",1060 static_cast<void *>(context), regclass, discriminator,1061 representation);1062 switch (regclass) {1063 case _UVRSC_WMMXC:1064#if !defined(__ARM_WMMX)1065 break;1066#endif1067 case _UVRSC_CORE: {1068 if (representation != _UVRSD_UINT32)1069 return _UVRSR_FAILED;1070 // When popping SP from the stack, we don't want to override it from the1071 // computed new stack location. See EHABI #7.5.4 table 3.1072 bool poppedSP = false;1073 uint32_t* sp;1074 if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP,1075 _UVRSD_UINT32, &sp) != _UVRSR_OK) {1076 return _UVRSR_FAILED;1077 }1078 for (uint32_t i = 0; i < 16; ++i) {1079 if (!(discriminator & static_cast<uint32_t>(1 << i)))1080 continue;1081 uint32_t value = *sp++;1082 if (regclass == _UVRSC_CORE && i == 13)1083 poppedSP = true;1084 if (_Unwind_VRS_Set(context, regclass, i,1085 _UVRSD_UINT32, &value) != _UVRSR_OK) {1086 return _UVRSR_FAILED;1087 }1088 }1089 if (!poppedSP) {1090 return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP,1091 _UVRSD_UINT32, &sp);1092 }1093 return _UVRSR_OK;1094 }1095 case _UVRSC_WMMXD:1096#if !defined(__ARM_WMMX)1097 break;1098#endif1099 case _UVRSC_VFP: {1100 if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)1101 return _UVRSR_FAILED;1102 uint32_t first = discriminator >> 16;1103 uint32_t count = discriminator & 0xffff;1104 uint32_t end = first+count;1105 uint32_t* sp;1106 if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP,1107 _UVRSD_UINT32, &sp) != _UVRSR_OK) {1108 return _UVRSR_FAILED;1109 }1110 // For _UVRSD_VFPX, we're assuming the data is stored in FSTMX "standard1111 // format 1", which is equivalent to FSTMD + a padding word.1112 for (uint32_t i = first; i < end; ++i) {1113 // SP is only 32-bit aligned so don't copy 64-bit at a time.1114 uint64_t w0 = *sp++;1115 uint64_t w1 = *sp++;1116#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__1117 uint64_t value = (w1 << 32) | w0;1118#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__1119 uint64_t value = (w0 << 32) | w1;1120#else1121#error "Unable to determine endianess"1122#endif1123 if (_Unwind_VRS_Set(context, regclass, i, representation, &value) !=1124 _UVRSR_OK)1125 return _UVRSR_FAILED;1126 }1127 if (representation == _UVRSD_VFPX)1128 ++sp;1129 return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,1130 &sp);1131 }1132 case _UVRSC_PSEUDO: {1133 if (representation != _UVRSD_UINT32 || discriminator != 0)1134 return _UVRSR_FAILED;1135 // Return Address Authentication code (PAC) - discriminator 01136 uint32_t *sp;1137 if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,1138 &sp) != _UVRSR_OK) {1139 return _UVRSR_FAILED;1140 }1141 uint32_t pac = *sp++;1142 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);1143 return _Unwind_VRS_Set(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac);1144 }1145 }1146 _LIBUNWIND_ABORT("unsupported register class");1147}1148 1149/// Not used by C++.1150/// Unwinds stack, calling "stop" function at each frame.1151/// Could be used to implement longjmp().1152_LIBUNWIND_EXPORT _Unwind_Reason_Code1153_Unwind_ForcedUnwind(_Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,1154 void *stop_parameter) {1155 _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",1156 (void *)exception_object, (void *)(uintptr_t)stop);1157 unw_context_t uc;1158 unw_cursor_t cursor;1159 __unw_getcontext(&uc);1160 1161 // Mark that this is a forced unwind, so _Unwind_Resume() can do1162 // the right thing.1163 exception_object->unwinder_cache.reserved1 = (uintptr_t)stop;1164 exception_object->unwinder_cache.reserved3 = (uintptr_t)stop_parameter;1165 1166 return unwind_phase2_forced(&uc, &cursor, exception_object, stop,1167 stop_parameter);1168}1169 1170/// Called by personality handler during phase 2 to find the start of the1171/// function.1172_LIBUNWIND_EXPORT uintptr_t1173_Unwind_GetRegionStart(struct _Unwind_Context *context) {1174 unw_cursor_t *cursor = (unw_cursor_t *)context;1175 unw_proc_info_t frameInfo;1176 uintptr_t result = 0;1177 if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)1178 result = (uintptr_t)frameInfo.start_ip;1179 _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%llX",1180 static_cast<void *>(context), (long long)result);1181 return result;1182}1183 1184 1185/// Called by personality handler during phase 2 if a foreign exception1186// is caught.1187_LIBUNWIND_EXPORT void1188_Unwind_DeleteException(_Unwind_Exception *exception_object) {1189 _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",1190 static_cast<void *>(exception_object));1191 if (exception_object->exception_cleanup != NULL)1192 (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,1193 exception_object);1194}1195 1196extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code1197__gnu_unwind_frame(_Unwind_Exception *exception_object,1198 struct _Unwind_Context *context) {1199 (void)exception_object;1200 unw_cursor_t *cursor = (unw_cursor_t *)context;1201 switch (__unw_step(cursor)) {1202 case UNW_STEP_SUCCESS:1203 return _URC_OK;1204 case UNW_STEP_END:1205 return _URC_END_OF_STACK;1206 default:1207 return _URC_FAILURE;1208 }1209}1210 1211#endif // defined(_LIBUNWIND_ARM_EHABI)1212