111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===------------------------- UnwindLevel1.c -----------------------------===// 211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// The LLVM Compiler Infrastructure 411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This file is dual licensed under the MIT and the University of Illinois Open 611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Source Licenses. See LICENSE.TXT for details. 711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Implements C++ ABI Exception Handling Level 1 as documented at: 1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// http://mentorembedded.github.io/cxx-abi/abi-eh.html 1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// using libunwind 1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===----------------------------------------------------------------------===// 1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <inttypes.h> 1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdint.h> 1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdbool.h> 1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdlib.h> 1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdio.h> 2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <string.h> 2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "libunwind.h" 2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "unwind.h" 2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "config.h" 2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_BUILD_ZERO_COST_APIS && !LIBCXXABI_ARM_EHABI 2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic _Unwind_Reason_Code 2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertunwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { 3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_cursor_t cursor1; 3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_init_local(&cursor1, uc); 3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Walk each frame looking for a place to stop. 3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (bool handlerNotFound = true; handlerNotFound;) { 3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Ask libuwind to get next frame (skip over first which is 3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // _Unwind_RaiseException). 3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int stepResult = unw_step(&cursor1); 3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (stepResult == 0) { 4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached " 4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "bottom => _URC_END_OF_STACK\n", 4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_END_OF_STACK; 4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (stepResult < 0) { 4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => " 4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "_URC_FATAL_PHASE1_ERROR\n", 4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE1_ERROR; 4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // See if frame has code to run (has personality routine). 5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_proc_info_t frameInfo; 5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t sp; 5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) { 5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info " 5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "failed => _URC_FATAL_PHASE1_ERROR\n", 5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE1_ERROR; 5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // When tracing, print state information. 6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_LIBUNWIND_TRACING_UNWINDING) { 6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char functionBuf[512]; 6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *functionName = functionBuf; 6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t offset; 6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((unw_get_proc_name(&cursor1, functionBuf, sizeof(functionBuf), 6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &offset) != UNW_ESUCCESS) || 6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (frameInfo.start_ip + offset > frameInfo.end_ip)) 6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert functionName = ".anonymous."; 7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t pc; 7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_get_reg(&cursor1, UNW_REG_IP, &pc); 7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING( 7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "unwind_phase1(ex_ojb=%p): pc=0x%" PRIx64 ", start_ip=0x%" PRIx64 7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n", 7511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object, pc, frameInfo.start_ip, functionName, 7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert frameInfo.lsda, frameInfo.handler); 7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If there is a personality routine, ask it if it will want to stop at 8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // this frame. 8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (frameInfo.handler != 0) { 8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __personality_routine p = 8311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (__personality_routine)(long)(frameInfo.handler); 8411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING( 8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "unwind_phase1(ex_ojb=%p): calling personality function %p\n", 8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object, (void *)(uintptr_t)p); 8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_Reason_Code personalityResult = 8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class, 8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exception_object, (struct _Unwind_Context *)(&cursor1)); 9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (personalityResult) { 9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case _URC_HANDLER_FOUND: 9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // found a catch clause or locals that need destructing in this frame 9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // stop search and remember stack pointer at the frame 9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert handlerNotFound = false; 9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_get_reg(&cursor1, UNW_REG_SP, &sp); 9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exception_object->private_2 = (uintptr_t)sp; 9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING( 9811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n", 9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_NO_REASON; 10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case _URC_CONTINUE_UNWIND: 10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING( 10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", 10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // continue unwinding 10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // something went wrong 11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING( 11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", 11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 11411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE1_ERROR; 11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_NO_REASON; 11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic _Unwind_Reason_Code 12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertunwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) { 12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_cursor_t cursor2; 12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_init_local(&cursor2, uc); 12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", 12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Walk each frame until we reach where search phase said to stop. 13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (true) { 13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Ask libuwind to get next frame (skip over first which is 13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // _Unwind_RaiseException). 13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int stepResult = unw_step(&cursor2); 13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (stepResult == 0) { 13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " 13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "bottom => _URC_END_OF_STACK\n", 13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_END_OF_STACK; 14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (stepResult < 0) { 14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => " 14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "_URC_FATAL_PHASE1_ERROR\n", 14411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE2_ERROR; 14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Get info about this frame. 14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t sp; 15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_proc_info_t frameInfo; 15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_get_reg(&cursor2, UNW_REG_SP, &sp); 15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) { 15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info " 15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "failed => _URC_FATAL_PHASE1_ERROR\n", 15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE2_ERROR; 15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // When tracing, print state information. 16011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_LIBUNWIND_TRACING_UNWINDING) { 16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char functionBuf[512]; 16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *functionName = functionBuf; 16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t offset; 16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf), 16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &offset) != UNW_ESUCCESS) || 16611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (frameInfo.start_ip + offset > frameInfo.end_ip)) 16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert functionName = ".anonymous."; 16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIx64 16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ", func=%s, sp=0x%" PRIx64 ", lsda=0x%" PRIx64 17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ", personality=0x%" PRIx64 "\n", 17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object, frameInfo.start_ip, 17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert functionName, sp, frameInfo.lsda, 17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert frameInfo.handler); 17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If there is a personality routine, tell it we are unwinding. 17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (frameInfo.handler != 0) { 17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __personality_routine p = 17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (__personality_routine)(long)(frameInfo.handler); 18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_Action action = _UA_CLEANUP_PHASE; 18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (sp == exception_object->private_2) { 18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Tell personality this was the frame it marked in phase 1. 18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME); 18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_Reason_Code personalityResult = 18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (*p)(1, action, exception_object->exception_class, exception_object, 18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (struct _Unwind_Context *)(&cursor2)); 18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (personalityResult) { 18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case _URC_CONTINUE_UNWIND: 19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Continue unwinding 19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING( 19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", 19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 19411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (sp == exception_object->private_2) { 19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Phase 1 said we would stop at this frame, but we did not... 19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("during phase1 personality function said it would " 19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "stop here, but now in phase2 it did not stop here"); 19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case _URC_INSTALL_CONTEXT: 20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING( 20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n", 20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Personality routine says to transfer control to landing pad. 20511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // We may get control back if landing pad calls _Unwind_Resume(). 20611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_LIBUNWIND_TRACING_UNWINDING) { 20711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t pc; 20811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_get_reg(&cursor2, UNW_REG_IP, &pc); 20911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_get_reg(&cursor2, UNW_REG_SP, &sp); 21011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " 21111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "user code with ip=0x%" PRIx64 21211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ", sp=0x%" PRIx64 "\n", 21311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object, pc, sp); 21411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 21511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_resume(&cursor2); 21611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // unw_resume() only returns if there was an error. 21711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE2_ERROR; 21811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 21911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Personality routine returned an unknown result code. 22011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", 22111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert personalityResult); 22211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE2_ERROR; 22311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 22411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 22511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 22611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 22711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Clean up phase did not resume at the frame that the search phase 22811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // said it would... 22911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE2_ERROR; 23011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 23111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 23211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic _Unwind_Reason_Code 23311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertunwind_phase2_forced(unw_context_t *uc, 23411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_Exception *exception_object, 23511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_Stop_Fn stop, void *stop_parameter) { 23611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_cursor_t cursor2; 23711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_init_local(&cursor2, uc); 23811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 23911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Walk each frame until we reach where search phase said to stop 24011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (unw_step(&cursor2) > 0) { 24111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 24211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Update info about this frame. 24311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_proc_info_t frameInfo; 24411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) { 24511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step " 24611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "failed => _URC_END_OF_STACK\n", 24711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 24811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE2_ERROR; 24911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 25011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 25111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // When tracing, print state information. 25211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_LIBUNWIND_TRACING_UNWINDING) { 25311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char functionBuf[512]; 25411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *functionName = functionBuf; 25511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t offset; 25611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf), 25711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &offset) != UNW_ESUCCESS) || 25811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (frameInfo.start_ip + offset > frameInfo.end_ip)) 25911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert functionName = ".anonymous."; 26011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING( 26111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64 26211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n", 26311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object, frameInfo.start_ip, functionName, 26411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert frameInfo.lsda, frameInfo.handler); 26511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 26611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 26711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Call stop function at each frame. 26811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_Action action = 26911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); 27011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_Reason_Code stopResult = 27111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (*stop)(1, action, exception_object->exception_class, exception_object, 27211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (struct _Unwind_Context *)(&cursor2), stop_parameter); 27311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING( 27411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", 27511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object, stopResult); 27611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (stopResult != _URC_NO_REASON) { 27711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING( 27811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", 27911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 28011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE2_ERROR; 28111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 28211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 28311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If there is a personality routine, tell it we are unwinding. 28411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (frameInfo.handler != 0) { 28511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __personality_routine p = 28611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (__personality_routine)(long)(frameInfo.handler); 28711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING( 28811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", 28911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object, (void *)(uintptr_t)p); 29011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_Reason_Code personalityResult = 29111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (*p)(1, action, exception_object->exception_class, exception_object, 29211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (struct _Unwind_Context *)(&cursor2)); 29311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (personalityResult) { 29411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case _URC_CONTINUE_UNWIND: 29511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 29611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "personality returned " 29711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "_URC_CONTINUE_UNWIND\n", 29811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 29911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Destructors called, continue unwinding 30011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 30111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case _URC_INSTALL_CONTEXT: 30211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 30311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "personality returned " 30411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "_URC_INSTALL_CONTEXT\n", 30511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 30611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // We may get control back if landing pad calls _Unwind_Resume(). 30711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_resume(&cursor2); 30811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 30911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 31011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Personality routine returned an unknown result code. 31111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 31211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "personality returned %d, " 31311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "_URC_FATAL_PHASE2_ERROR\n", 31411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object, personalityResult); 31511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE2_ERROR; 31611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 31711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 31811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 31911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 32011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Call stop function one last time and tell it we've reached the end 32111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // of the stack. 32211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " 32311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "function with _UA_END_OF_STACK\n", 32411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 32511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_Action lastAction = 32611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); 32711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (*stop)(1, lastAction, exception_object->exception_class, exception_object, 32811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (struct _Unwind_Context *)(&cursor2), stop_parameter); 32911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 33011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Clean up phase did not resume at the frame that the search phase said it 33111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // would. 33211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _URC_FATAL_PHASE2_ERROR; 33311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 33411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 33511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 33611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Called by __cxa_throw. Only returns if there is a fatal error. 33711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT _Unwind_Reason_Code 33811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_Unwind_RaiseException(_Unwind_Exception *exception_object) { 33911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n", 34011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 34111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_context_t uc; 34211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_getcontext(&uc); 34311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 34411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Mark that this is a non-forced unwind, so _Unwind_Resume() 34511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // can do the right thing. 34611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exception_object->private_1 = 0; 34711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exception_object->private_2 = 0; 34811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 34911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // phase 1: the search phase 35011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object); 35111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (phase1 != _URC_NO_REASON) 35211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return phase1; 35311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 35411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // phase 2: the clean up phase 35511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return unwind_phase2(&uc, exception_object); 35611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 35711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 35811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 35911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 36011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// When _Unwind_RaiseException() is in phase2, it hands control 36111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// to the personality function at each frame. The personality 36211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// may force a jump to a landing pad in that function, the landing 36311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// pad code may then call _Unwind_Resume() to continue with the 36411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// unwinding. Note: the call to _Unwind_Resume() is from compiler 36511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// geneated user code. All other _Unwind_* routines are called 36611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// by the C++ runtime __cxa_* routines. 36711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// 36811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Note: re-throwing an exception (as opposed to continuing the unwind) 36911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// is implemented by having the code call __cxa_rethrow() which 37011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// in turn calls _Unwind_Resume_or_Rethrow(). 37111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT void 37211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_Unwind_Resume(_Unwind_Exception *exception_object) { 37311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", (void *)exception_object); 37411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_context_t uc; 37511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_getcontext(&uc); 37611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 37711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (exception_object->private_1 != 0) 37811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unwind_phase2_forced(&uc, exception_object, 37911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (_Unwind_Stop_Fn) exception_object->private_1, 38011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object->private_2); 38111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert else 38211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unwind_phase2(&uc, exception_object); 38311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 38411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Clients assume _Unwind_Resume() does not return, so all we can do is abort. 38511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); 38611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 38711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 38811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 38911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 39011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Not used by C++. 39111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Unwinds stack, calling "stop" function at each frame. 39211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Could be used to implement longjmp(). 39311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT _Unwind_Reason_Code 39411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_Unwind_ForcedUnwind(_Unwind_Exception *exception_object, 39511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_Stop_Fn stop, void *stop_parameter) { 39611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n", 39711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object, (void *)(uintptr_t)stop); 39811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_context_t uc; 39911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_getcontext(&uc); 40011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 40111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Mark that this is a forced unwind, so _Unwind_Resume() can do 40211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // the right thing. 40311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exception_object->private_1 = (uintptr_t) stop; 40411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exception_object->private_2 = (uintptr_t) stop_parameter; 40511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 40611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // do it 40711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter); 40811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 40911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 41011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 41111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Called by personality handler during phase 2 to get LSDA for current frame. 41211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT uintptr_t 41311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { 41411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_cursor_t *cursor = (unw_cursor_t *)context; 41511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_proc_info_t frameInfo; 41611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uintptr_t result = 0; 41711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) 41811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = (uintptr_t)frameInfo.lsda; 41911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API( 42011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR "\n", 42111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)context, result); 42211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result != 0) { 42311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (*((uint8_t *)result) != 0xFF) 42411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF\n", 42511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result); 42611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 42711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 42811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 42911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 43011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 43111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Called by personality handler during phase 2 to find the start of the 43211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// function. 43311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT uintptr_t 43411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_Unwind_GetRegionStart(struct _Unwind_Context *context) { 43511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_cursor_t *cursor = (unw_cursor_t *)context; 43611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_proc_info_t frameInfo; 43711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uintptr_t result = 0; 43811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) 43911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = (uintptr_t)frameInfo.start_ip; 44011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR "\n", 44111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)context, result); 44211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 44311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 44411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 44511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 44611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Called by personality handler during phase 2 if a foreign exception 44711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// is caught. 44811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT void 44911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_Unwind_DeleteException(_Unwind_Exception *exception_object) { 45011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n", 45111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)exception_object); 45211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (exception_object->exception_cleanup != NULL) 45311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, 45411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exception_object); 45511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 45611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 45711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // _LIBUNWIND_BUILD_ZERO_COST_APIS && !LIBCXXABI_ARM_EHABI 45811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 45911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if LIBCXXABI_ARM_EHABI 46011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 46111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT uintptr_t 46211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_Unwind_GetGR(struct _Unwind_Context *context, int index) { 46311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uintptr_t value = 0; 46411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); 46511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64 "\n", 46611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)context, index, (uint64_t)value); 46711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return value; 46811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 46911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 47011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, 47111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uintptr_t value) { 47211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0"PRIx64")\n", 47311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)context, index, (uint64_t)value); 47411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); 47511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 47611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 47711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { 47811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // remove the thumb-bit before returning 47911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uintptr_t value = _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1); 48011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIx64 "\n", 48111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)context, (uint64_t)value); 48211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return value; 48311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 48411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 48511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, 48611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uintptr_t value) { 48711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIx64 ")\n", 48811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)context, (uint64_t)value); 48911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1); 49011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Unwind_SetGR(context, 15, value | thumb_bit); 49111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 49211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 49311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else 49411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 49511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Called by personality handler during phase 2 to get register values. 49611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT uintptr_t 49711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_Unwind_GetGR(struct _Unwind_Context *context, int index) { 49811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_cursor_t *cursor = (unw_cursor_t *)context; 49911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t result; 50011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_get_reg(cursor, index, &result); 50111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64 "\n", 50211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)context, index, (uint64_t)result); 50311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return (uintptr_t)result; 50411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 50511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 50611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Called by personality handler during phase 2 to alter register values. 50711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, 50811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uintptr_t value) { 50911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIx64 51011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ")\n", 51111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)context, index, (uint64_t)value); 51211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_cursor_t *cursor = (unw_cursor_t *)context; 51311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_set_reg(cursor, index, value); 51411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 51511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 51611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Called by personality handler during phase 2 to get instruction pointer. 51711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { 51811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_cursor_t *cursor = (unw_cursor_t *)context; 51911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t result; 52011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_get_reg(cursor, UNW_REG_IP, &result); 52111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIx64 "\n", 52211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)context, (uint64_t)result); 52311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return (uintptr_t)result; 52411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 52511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 52611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Called by personality handler during phase 2 to alter instruction pointer, 52711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// such as setting where the landing pad is, so _Unwind_Resume() will 52811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// start executing in the landing pad. 52911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, 53011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uintptr_t value) { 53111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIx64 ")\n", 53211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)context, (uint64_t)value); 53311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_cursor_t *cursor = (unw_cursor_t *)context; 53411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_set_reg(cursor, UNW_REG_IP, value); 53511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 53611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 53711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 53811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 539