Path: blob/main/system/lib/libunwind/src/UnwindLevel1.c
6178 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//7// Implements C++ ABI Exception Handling Level 1 as documented at:8// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html9// using libunwind10//11//===----------------------------------------------------------------------===//1213// ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}(). Thus, we are14// defining inline functions to delegate the function calls to15// _Unwind_VRS_{Get,Set}(). However, some applications might declare the16// function protetype directly (instead of including <unwind.h>), thus we need17// to export these functions from libunwind.so as well.18#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 11920#include <inttypes.h>21#include <stdint.h>22#include <stdbool.h>23#include <stdlib.h>24#include <stdio.h>25#include <string.h>2627#include "config.h"28#include "libunwind.h"29#include "libunwind_ext.h"30#include "shadow_stack_unwind.h"31#include "unwind.h"3233#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) && \34!defined(__wasm__)3536#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND3738// When shadow stack is enabled, a separate stack containing only return39// addresses would be maintained. On function return, the return address would40// be compared to the popped address from shadow stack to ensure the return41// target is not tempered with. When unwinding, we're skipping the normal return42// procedure for multiple frames and thus need to pop the return addresses of43// the skipped frames from shadow stack to avoid triggering an exception (using44// `_LIBUNWIND_POP_SHSTK_SSP()`). Also, some architectures, like the x86-family45// CET, push the return adddresses onto shadow stack with common call46// instructions, so for these architectures, normal function calls should be47// avoided when invoking the `jumpto()` function. To do this, we use inline48// assemblies to "goto" the `jumpto()` for these architectures.49#if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS)50#define __unw_phase2_resume(cursor, fn) \51do { \52(void)fn; \53__unw_resume((cursor)); \54} while (0)55#elif defined(_LIBUNWIND_TARGET_I386)56#define __shstk_step_size (4)57#define __unw_phase2_resume(cursor, fn) \58do { \59_LIBUNWIND_POP_SHSTK_SSP((fn)); \60void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \61void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \62__asm__ volatile("push %%edi\n\t" \63"sub $4, %%esp\n\t" \64"jmp *%%edx\n\t" ::"D"(shstkRegContext), \65"d"(shstkJumpAddress)); \66} while (0)67#elif defined(_LIBUNWIND_TARGET_X86_64)68#define __shstk_step_size (8)69#define __unw_phase2_resume(cursor, fn) \70do { \71_LIBUNWIND_POP_SHSTK_SSP((fn)); \72void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \73void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \74__asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext), \75"d"(shstkJumpAddress)); \76} while (0)77#elif defined(_LIBUNWIND_TARGET_AARCH64)78#define __shstk_step_size (8)79#define __unw_phase2_resume(cursor, fn) \80do { \81_LIBUNWIND_POP_SHSTK_SSP((fn)); \82void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \83void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \84__asm__ volatile("mov x0, %0\n\t" \85"br %1\n\t" \86: \87: "r"(shstkRegContext), "r"(shstkJumpAddress) \88: "x0"); \89} while (0)90#endif9192static _Unwind_Reason_Code93unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {94__unw_init_local(cursor, uc);9596// Walk each frame looking for a place to stop.97while (true) {98// Ask libunwind to get next frame (skip over first which is99// _Unwind_RaiseException).100int stepResult = __unw_step(cursor);101if (stepResult == 0) {102_LIBUNWIND_TRACE_UNWINDING(103"unwind_phase1(ex_obj=%p): __unw_step() reached "104"bottom => _URC_END_OF_STACK",105(void *)exception_object);106return _URC_END_OF_STACK;107} else if (stepResult < 0) {108_LIBUNWIND_TRACE_UNWINDING(109"unwind_phase1(ex_obj=%p): __unw_step failed => "110"_URC_FATAL_PHASE1_ERROR",111(void *)exception_object);112return _URC_FATAL_PHASE1_ERROR;113}114115// See if frame has code to run (has personality routine).116unw_proc_info_t frameInfo;117unw_word_t sp;118if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {119_LIBUNWIND_TRACE_UNWINDING(120"unwind_phase1(ex_obj=%p): __unw_get_proc_info "121"failed => _URC_FATAL_PHASE1_ERROR",122(void *)exception_object);123return _URC_FATAL_PHASE1_ERROR;124}125126#ifndef NDEBUG127// When tracing, print state information.128if (_LIBUNWIND_TRACING_UNWINDING) {129char functionBuf[512];130const char *functionName = functionBuf;131unw_word_t offset;132if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),133&offset) != UNW_ESUCCESS) ||134(frameInfo.start_ip + offset > frameInfo.end_ip))135functionName = ".anonymous.";136unw_word_t pc;137__unw_get_reg(cursor, UNW_REG_IP, &pc);138_LIBUNWIND_TRACE_UNWINDING(139"unwind_phase1(ex_obj=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR140", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "",141(void *)exception_object, pc, frameInfo.start_ip, functionName,142frameInfo.lsda, frameInfo.handler);143}144#endif145146// If there is a personality routine, ask it if it will want to stop at147// this frame.148if (frameInfo.handler != 0) {149_Unwind_Personality_Fn p =150(_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);151_LIBUNWIND_TRACE_UNWINDING(152"unwind_phase1(ex_obj=%p): calling personality function %p",153(void *)exception_object, (void *)(uintptr_t)p);154_Unwind_Reason_Code personalityResult =155(*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,156exception_object, (struct _Unwind_Context *)(cursor));157switch (personalityResult) {158case _URC_HANDLER_FOUND:159// found a catch clause or locals that need destructing in this frame160// stop search and remember stack pointer at the frame161__unw_get_reg(cursor, UNW_REG_SP, &sp);162exception_object->private_2 = (uintptr_t)sp;163_LIBUNWIND_TRACE_UNWINDING(164"unwind_phase1(ex_obj=%p): _URC_HANDLER_FOUND",165(void *)exception_object);166return _URC_NO_REASON;167168case _URC_CONTINUE_UNWIND:169_LIBUNWIND_TRACE_UNWINDING(170"unwind_phase1(ex_obj=%p): _URC_CONTINUE_UNWIND",171(void *)exception_object);172// continue unwinding173break;174175default:176// something went wrong177_LIBUNWIND_TRACE_UNWINDING(178"unwind_phase1(ex_obj=%p): _URC_FATAL_PHASE1_ERROR",179(void *)exception_object);180return _URC_FATAL_PHASE1_ERROR;181}182}183}184return _URC_NO_REASON;185}186extern int __unw_step_stage2(unw_cursor_t *);187188#if defined(_LIBUNWIND_USE_GCS)189// Enable the GCS target feature to permit gcspop instructions to be used.190__attribute__((target("+gcs")))191#endif192static _Unwind_Reason_Code193unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,194_Unwind_Exception *exception_object) {195__unw_init_local(cursor, uc);196197_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",198(void *)exception_object);199200// uc is initialized by __unw_getcontext in the parent frame. The first stack201// frame walked is unwind_phase2.202unsigned framesWalked = 1;203#if defined(_LIBUNWIND_USE_CET)204unsigned long shadowStackTop = _get_ssp();205#elif defined(_LIBUNWIND_USE_GCS)206unsigned long shadowStackTop = 0;207if (__chkfeat(_CHKFEAT_GCS))208shadowStackTop = (unsigned long)__gcspr();209#endif210// Walk each frame until we reach where search phase said to stop.211while (true) {212213// Ask libunwind to get next frame (skip over first which is214// _Unwind_RaiseException).215int stepResult = __unw_step_stage2(cursor);216if (stepResult == 0) {217_LIBUNWIND_TRACE_UNWINDING(218"unwind_phase2(ex_obj=%p): __unw_step_stage2() reached "219"bottom => _URC_END_OF_STACK",220(void *)exception_object);221return _URC_END_OF_STACK;222} else if (stepResult < 0) {223_LIBUNWIND_TRACE_UNWINDING(224"unwind_phase2(ex_obj=%p): __unw_step_stage2 failed => "225"_URC_FATAL_PHASE1_ERROR",226(void *)exception_object);227return _URC_FATAL_PHASE2_ERROR;228}229230// Get info about this frame.231unw_word_t sp;232unw_proc_info_t frameInfo;233__unw_get_reg(cursor, UNW_REG_SP, &sp);234if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {235_LIBUNWIND_TRACE_UNWINDING(236"unwind_phase2(ex_obj=%p): __unw_get_proc_info "237"failed => _URC_FATAL_PHASE1_ERROR",238(void *)exception_object);239return _URC_FATAL_PHASE2_ERROR;240}241242#ifndef NDEBUG243// When tracing, print state information.244if (_LIBUNWIND_TRACING_UNWINDING) {245char functionBuf[512];246const char *functionName = functionBuf;247unw_word_t offset;248if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),249&offset) != UNW_ESUCCESS) ||250(frameInfo.start_ip + offset > frameInfo.end_ip))251functionName = ".anonymous.";252_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): start_ip=0x%" PRIxPTR253", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR254", personality=0x%" PRIxPTR,255(void *)exception_object, frameInfo.start_ip,256functionName, sp, frameInfo.lsda,257frameInfo.handler);258}259#endif260261// In shadow stack enabled environment, we check return address stored in normal262// stack against return address stored in shadow stack, if the 2 addresses don't263// match, it means return address in normal stack has been corrupted, we return264// _URC_FATAL_PHASE2_ERROR.265#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)266if (shadowStackTop != 0) {267unw_word_t retInNormalStack;268__unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack);269unsigned long retInShadowStack =270*(unsigned long *)(shadowStackTop + __shstk_step_size * framesWalked);271if (retInNormalStack != retInShadowStack)272return _URC_FATAL_PHASE2_ERROR;273}274#endif275++framesWalked;276// If there is a personality routine, tell it we are unwinding.277if (frameInfo.handler != 0) {278_Unwind_Personality_Fn p =279(_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);280_Unwind_Action action = _UA_CLEANUP_PHASE;281if (sp == exception_object->private_2) {282// Tell personality this was the frame it marked in phase 1.283action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);284}285_Unwind_Reason_Code personalityResult =286(*p)(1, action, exception_object->exception_class, exception_object,287(struct _Unwind_Context *)(cursor));288switch (personalityResult) {289case _URC_CONTINUE_UNWIND:290// Continue unwinding291_LIBUNWIND_TRACE_UNWINDING(292"unwind_phase2(ex_obj=%p): _URC_CONTINUE_UNWIND",293(void *)exception_object);294if (sp == exception_object->private_2) {295// Phase 1 said we would stop at this frame, but we did not...296_LIBUNWIND_ABORT("during phase1 personality function said it would "297"stop here, but now in phase2 it did not stop here");298}299break;300case _URC_INSTALL_CONTEXT:301_LIBUNWIND_TRACE_UNWINDING(302"unwind_phase2(ex_obj=%p): _URC_INSTALL_CONTEXT",303(void *)exception_object);304// Personality routine says to transfer control to landing pad.305// We may get control back if landing pad calls _Unwind_Resume().306if (_LIBUNWIND_TRACING_UNWINDING) {307unw_word_t pc;308__unw_get_reg(cursor, UNW_REG_IP, &pc);309__unw_get_reg(cursor, UNW_REG_SP, &sp);310_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): re-entering "311"user code with ip=0x%" PRIxPTR312", sp=0x%" PRIxPTR,313(void *)exception_object, pc, sp);314}315316__unw_phase2_resume(cursor, framesWalked);317// __unw_phase2_resume() only returns if there was an error.318return _URC_FATAL_PHASE2_ERROR;319default:320// Personality routine returned an unknown result code.321_LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",322personalityResult);323return _URC_FATAL_PHASE2_ERROR;324}325}326}327328// Clean up phase did not resume at the frame that the search phase329// said it would...330return _URC_FATAL_PHASE2_ERROR;331}332333#if defined(_LIBUNWIND_USE_GCS)334// Enable the GCS target feature to permit gcspop instructions to be used.335__attribute__((target("+gcs")))336#endif337static _Unwind_Reason_Code338unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,339_Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,340void *stop_parameter) {341__unw_init_local(cursor, uc);342343// uc is initialized by __unw_getcontext in the parent frame. The first stack344// frame walked is unwind_phase2_forced.345unsigned framesWalked = 1;346// Walk each frame until we reach where search phase said to stop347while (__unw_step_stage2(cursor) > 0) {348349// Update info about this frame.350unw_proc_info_t frameInfo;351if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {352_LIBUNWIND_TRACE_UNWINDING(353"unwind_phase2_forced(ex_obj=%p): __unw_get_proc_info "354"failed => _URC_END_OF_STACK",355(void *)exception_object);356return _URC_FATAL_PHASE2_ERROR;357}358359#ifndef NDEBUG360// When tracing, print state information.361if (_LIBUNWIND_TRACING_UNWINDING) {362char functionBuf[512];363const char *functionName = functionBuf;364unw_word_t offset;365if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),366&offset) != UNW_ESUCCESS) ||367(frameInfo.start_ip + offset > frameInfo.end_ip))368functionName = ".anonymous.";369_LIBUNWIND_TRACE_UNWINDING(370"unwind_phase2_forced(ex_obj=%p): start_ip=0x%" PRIxPTR371", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,372(void *)exception_object, frameInfo.start_ip, functionName,373frameInfo.lsda, frameInfo.handler);374}375#endif376377// Call stop function at each frame.378_Unwind_Action action =379(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);380_Unwind_Reason_Code stopResult =381(*stop)(1, action, exception_object->exception_class, exception_object,382(struct _Unwind_Context *)(cursor), stop_parameter);383_LIBUNWIND_TRACE_UNWINDING(384"unwind_phase2_forced(ex_obj=%p): stop function returned %d",385(void *)exception_object, stopResult);386if (stopResult != _URC_NO_REASON) {387_LIBUNWIND_TRACE_UNWINDING(388"unwind_phase2_forced(ex_obj=%p): stopped by stop function",389(void *)exception_object);390return _URC_FATAL_PHASE2_ERROR;391}392393++framesWalked;394// If there is a personality routine, tell it we are unwinding.395if (frameInfo.handler != 0) {396_Unwind_Personality_Fn p =397(_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);398_LIBUNWIND_TRACE_UNWINDING(399"unwind_phase2_forced(ex_obj=%p): calling personality function %p",400(void *)exception_object, (void *)(uintptr_t)p);401_Unwind_Reason_Code personalityResult =402(*p)(1, action, exception_object->exception_class, exception_object,403(struct _Unwind_Context *)(cursor));404switch (personalityResult) {405case _URC_CONTINUE_UNWIND:406_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "407"personality returned "408"_URC_CONTINUE_UNWIND",409(void *)exception_object);410// Destructors called, continue unwinding411break;412case _URC_INSTALL_CONTEXT:413_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "414"personality returned "415"_URC_INSTALL_CONTEXT",416(void *)exception_object);417// We may get control back if landing pad calls _Unwind_Resume().418__unw_phase2_resume(cursor, framesWalked);419break;420default:421// Personality routine returned an unknown result code.422_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "423"personality returned %d, "424"_URC_FATAL_PHASE2_ERROR",425(void *)exception_object, personalityResult);426return _URC_FATAL_PHASE2_ERROR;427}428}429}430431// Call stop function one last time and tell it we've reached the end432// of the stack.433_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): calling stop "434"function with _UA_END_OF_STACK",435(void *)exception_object);436_Unwind_Action lastAction =437(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);438(*stop)(1, lastAction, exception_object->exception_class, exception_object,439(struct _Unwind_Context *)(cursor), stop_parameter);440441// Clean up phase did not resume at the frame that the search phase said it442// would.443return _URC_FATAL_PHASE2_ERROR;444}445446/// Called by __cxa_throw. Only returns if there is a fatal error.447_LIBUNWIND_EXPORT _Unwind_Reason_Code448_Unwind_RaiseException(_Unwind_Exception *exception_object) {449_LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",450(void *)exception_object);451unw_context_t uc;452unw_cursor_t cursor;453__unw_getcontext(&uc);454455// Mark that this is a non-forced unwind, so _Unwind_Resume()456// can do the right thing.457exception_object->private_1 = 0;458exception_object->private_2 = 0;459460// phase 1: the search phase461_Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);462if (phase1 != _URC_NO_REASON)463return phase1;464465// phase 2: the clean up phase466return unwind_phase2(&uc, &cursor, exception_object);467}468469470471/// When _Unwind_RaiseException() is in phase2, it hands control472/// to the personality function at each frame. The personality473/// may force a jump to a landing pad in that function, the landing474/// pad code may then call _Unwind_Resume() to continue with the475/// unwinding. Note: the call to _Unwind_Resume() is from compiler476/// generated user code. All other _Unwind_* routines are called477/// by the C++ runtime __cxa_* routines.478///479/// Note: re-throwing an exception (as opposed to continuing the unwind)480/// is implemented by having the code call __cxa_rethrow() which481/// in turn calls _Unwind_Resume_or_Rethrow().482_LIBUNWIND_EXPORT void483_Unwind_Resume(_Unwind_Exception *exception_object) {484_LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);485unw_context_t uc;486unw_cursor_t cursor;487__unw_getcontext(&uc);488489if (exception_object->private_1 != 0)490unwind_phase2_forced(&uc, &cursor, exception_object,491(_Unwind_Stop_Fn) exception_object->private_1,492(void *)exception_object->private_2);493else494unwind_phase2(&uc, &cursor, exception_object);495496// Clients assume _Unwind_Resume() does not return, so all we can do is abort.497_LIBUNWIND_ABORT("_Unwind_Resume() can't return");498}499500501502/// Not used by C++.503/// Unwinds stack, calling "stop" function at each frame.504/// Could be used to implement longjmp().505_LIBUNWIND_EXPORT _Unwind_Reason_Code506_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,507_Unwind_Stop_Fn stop, void *stop_parameter) {508_LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",509(void *)exception_object, (void *)(uintptr_t)stop);510unw_context_t uc;511unw_cursor_t cursor;512__unw_getcontext(&uc);513514// Mark that this is a forced unwind, so _Unwind_Resume() can do515// the right thing.516exception_object->private_1 = (uintptr_t) stop;517exception_object->private_2 = (uintptr_t) stop_parameter;518519// do it520return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter);521}522523524/// Called by personality handler during phase 2 to get LSDA for current frame.525_LIBUNWIND_EXPORT uintptr_t526_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {527unw_cursor_t *cursor = (unw_cursor_t *)context;528unw_proc_info_t frameInfo;529uintptr_t result = 0;530if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)531result = (uintptr_t)frameInfo.lsda;532_LIBUNWIND_TRACE_API(533"_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,534(void *)context, result);535#if !defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)536if (result != 0) {537if (*((uint8_t *)result) != 0xFF)538_LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF",539result);540}541#endif542return result;543}544545546/// Called by personality handler during phase 2 to find the start of the547/// function.548_LIBUNWIND_EXPORT uintptr_t549_Unwind_GetRegionStart(struct _Unwind_Context *context) {550unw_cursor_t *cursor = (unw_cursor_t *)context;551unw_proc_info_t frameInfo;552uintptr_t result = 0;553if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)554result = (uintptr_t)frameInfo.start_ip;555_LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,556(void *)context, result);557return result;558}559560#endif // !_LIBUNWIND_SUPPORT_SEH_UNWIND561562/// Called by personality handler during phase 2 if a foreign exception563// is caught.564_LIBUNWIND_EXPORT void565_Unwind_DeleteException(_Unwind_Exception *exception_object) {566_LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",567(void *)exception_object);568if (exception_object->exception_cleanup != NULL)569(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,570exception_object);571}572573/// Called by personality handler during phase 2 to get register values.574_LIBUNWIND_EXPORT uintptr_t575_Unwind_GetGR(struct _Unwind_Context *context, int index) {576unw_cursor_t *cursor = (unw_cursor_t *)context;577unw_word_t result;578__unw_get_reg(cursor, index, &result);579_LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIxPTR,580(void *)context, index, result);581return (uintptr_t)result;582}583584/// Called by personality handler during phase 2 to alter register values.585_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,586uintptr_t value) {587_LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIxPTR588")",589(void *)context, index, value);590unw_cursor_t *cursor = (unw_cursor_t *)context;591__unw_set_reg(cursor, index, value);592}593594/// Called by personality handler during phase 2 to get instruction pointer.595_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {596unw_cursor_t *cursor = (unw_cursor_t *)context;597unw_word_t result;598__unw_get_reg(cursor, UNW_REG_IP, &result);599_LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,600(void *)context, result);601return (uintptr_t)result;602}603604/// Called by personality handler during phase 2 to alter instruction pointer,605/// such as setting where the landing pad is, so _Unwind_Resume() will606/// start executing in the landing pad.607_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,608uintptr_t value) {609_LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIxPTR ")",610(void *)context, value);611unw_cursor_t *cursor = (unw_cursor_t *)context;612__unw_set_reg(cursor, UNW_REG_IP, value);613}614615#endif // !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)616617618