647 lines · c
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 C++ ABI Exception Handling Level 1 as documented at:9// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html10// using libunwind11//12//===----------------------------------------------------------------------===//13 14// ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}(). Thus, we are15// defining inline functions to delegate the function calls to16// _Unwind_VRS_{Get,Set}(). However, some applications might declare the17// function protetype directly (instead of including <unwind.h>), thus we need18// to export these functions from libunwind.so as well.19#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 120 21#include <inttypes.h>22#include <stdint.h>23#include <stdbool.h>24#include <stdlib.h>25#include <stdio.h>26#include <string.h>27 28#include "config.h"29#include "libunwind.h"30#include "libunwind_ext.h"31#include "shadow_stack_unwind.h"32#include "unwind.h"33 34#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) && \35 !defined(__wasm__)36 37#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND38 39// When shadow stack is enabled, a separate stack containing only return40// addresses would be maintained. On function return, the return address would41// be compared to the popped address from shadow stack to ensure the return42// target is not tempered with. When unwinding, we're skipping the normal return43// procedure for multiple frames and thus need to pop the return addresses of44// the skipped frames from shadow stack to avoid triggering an exception (using45// `_LIBUNWIND_POP_SHSTK_SSP()`). Also, some architectures, like the x86-family46// CET, push the return adddresses onto shadow stack with common call47// instructions, so for these architectures, normal function calls should be48// avoided when invoking the `jumpto()` function. To do this, we use inline49// assemblies to "goto" the `jumpto()` for these architectures.50#if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS)51#define __unw_phase2_resume(cursor, payload) \52 do { \53 __unw_resume_with_frames_walked((cursor), (payload)); \54 } while (0)55#elif defined(_LIBUNWIND_TARGET_I386)56#define __shstk_step_size (4)57#define __unw_phase2_resume(cursor, payload) \58 do { \59 _LIBUNWIND_POP_SHSTK_SSP((payload)); \60 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \61 void *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, payload) \70 do { \71 _LIBUNWIND_POP_SHSTK_SSP((payload)); \72 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \73 void *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, payload) \80 do { \81 _LIBUNWIND_POP_SHSTK_SSP((payload)); \82 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \83 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \84 __asm__ volatile("mov x0, %0\n\t" \85 "mov x1, #0\n\t" \86 "br %1\n\t" \87 : \88 : "r"(shstkRegContext), "r"(shstkJumpAddress) \89 : "x0", "x1"); \90 } while (0)91#endif92 93// We need this helper function as the semantics of casting between integers and94// function pointers mean that we end up with a function pointer without the95// correct signature. Instead we assign to an integer with a matching schema,96// and then memmove the result into a variable of the correct type. This memmove97// is possible as `_Unwind_Personality_Fn` is a standard function pointer, and98// as such is not address diversified.99static _Unwind_Personality_Fn get_handler_function(unw_proc_info_t *frameInfo) {100 uintptr_t __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer,101 0,102 ptrauth_function_pointer_type_discriminator(_Unwind_Personality_Fn))103 reauthenticatedIntegerHandler = frameInfo->handler;104 _Unwind_Personality_Fn handler;105 memmove(&handler, (void *)&reauthenticatedIntegerHandler,106 sizeof(_Unwind_Personality_Fn));107 return handler;108}109 110static _Unwind_Reason_Code111unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {112 __unw_init_local(cursor, uc);113 114 // Walk each frame looking for a place to stop.115 while (true) {116 // Ask libunwind to get next frame (skip over first which is117 // _Unwind_RaiseException).118 int stepResult = __unw_step(cursor);119 if (stepResult == 0) {120 _LIBUNWIND_TRACE_UNWINDING(121 "unwind_phase1(ex_obj=%p): __unw_step() reached "122 "bottom => _URC_END_OF_STACK",123 (void *)exception_object);124 return _URC_END_OF_STACK;125 } else if (stepResult < 0) {126 _LIBUNWIND_TRACE_UNWINDING(127 "unwind_phase1(ex_obj=%p): __unw_step failed => "128 "_URC_FATAL_PHASE1_ERROR",129 (void *)exception_object);130 return _URC_FATAL_PHASE1_ERROR;131 }132 133 // See if frame has code to run (has personality routine).134 unw_proc_info_t frameInfo;135 unw_word_t sp;136 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {137 _LIBUNWIND_TRACE_UNWINDING(138 "unwind_phase1(ex_obj=%p): __unw_get_proc_info "139 "failed => _URC_FATAL_PHASE1_ERROR",140 (void *)exception_object);141 return _URC_FATAL_PHASE1_ERROR;142 }143 144#ifndef NDEBUG145 // When tracing, print state information.146 if (_LIBUNWIND_TRACING_UNWINDING) {147 char functionBuf[512];148 const char *functionName = functionBuf;149 unw_word_t offset;150 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),151 &offset) != UNW_ESUCCESS) ||152 (frameInfo.start_ip + offset > frameInfo.end_ip))153 functionName = ".anonymous.";154 unw_word_t pc;155 __unw_get_reg(cursor, UNW_REG_IP, &pc);156 _LIBUNWIND_TRACE_UNWINDING(157 "unwind_phase1(ex_obj=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR158 ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "",159 (void *)exception_object, pc, frameInfo.start_ip, functionName,160 frameInfo.lsda, frameInfo.handler);161 }162#endif163 164 // If there is a personality routine, ask it if it will want to stop at165 // this frame.166 if (frameInfo.handler != 0) {167 _Unwind_Personality_Fn p = get_handler_function(&frameInfo);168 _LIBUNWIND_TRACE_UNWINDING(169 "unwind_phase1(ex_obj=%p): calling personality function %p",170 (void *)exception_object, (void *)(uintptr_t)p);171 _Unwind_Reason_Code personalityResult =172 (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,173 exception_object, (struct _Unwind_Context *)(cursor));174 switch (personalityResult) {175 case _URC_HANDLER_FOUND:176 // found a catch clause or locals that need destructing in this frame177 // stop search and remember stack pointer at the frame178 __unw_get_reg(cursor, UNW_REG_SP, &sp);179 exception_object->private_2 = (uintptr_t)sp;180 _LIBUNWIND_TRACE_UNWINDING(181 "unwind_phase1(ex_obj=%p): _URC_HANDLER_FOUND",182 (void *)exception_object);183 return _URC_NO_REASON;184 185 case _URC_CONTINUE_UNWIND:186 _LIBUNWIND_TRACE_UNWINDING(187 "unwind_phase1(ex_obj=%p): _URC_CONTINUE_UNWIND",188 (void *)exception_object);189 // continue unwinding190 break;191 192 default:193 // something went wrong194 _LIBUNWIND_TRACE_UNWINDING(195 "unwind_phase1(ex_obj=%p): _URC_FATAL_PHASE1_ERROR",196 (void *)exception_object);197 return _URC_FATAL_PHASE1_ERROR;198 }199 }200 }201 return _URC_NO_REASON;202}203extern int __unw_step_stage2(unw_cursor_t *);204 205#if defined(_LIBUNWIND_USE_GCS)206// Enable the GCS target feature to permit gcspop instructions to be used.207__attribute__((target("+gcs")))208#else209_LIBUNWIND_TRACE_NO_INLINE210#endif211static _Unwind_Reason_Code212unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,213 _Unwind_Exception *exception_object) {214 __unw_init_local(cursor, uc);215 216 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",217 (void *)exception_object);218 219 // uc is initialized by __unw_getcontext in the parent frame. The first stack220 // frame walked is unwind_phase2.221 unsigned framesWalked = 1;222#if defined(_LIBUNWIND_USE_CET)223 unsigned long shadowStackTop = _get_ssp();224#elif defined(_LIBUNWIND_USE_GCS)225 unsigned long shadowStackTop = 0;226 if (__chkfeat(_CHKFEAT_GCS))227 shadowStackTop = (unsigned long)__gcspr();228#endif229 // Walk each frame until we reach where search phase said to stop.230 while (true) {231 232 // Ask libunwind to get next frame (skip over first which is233 // _Unwind_RaiseException).234 int stepResult = __unw_step_stage2(cursor);235 if (stepResult == 0) {236 _LIBUNWIND_TRACE_UNWINDING(237 "unwind_phase2(ex_obj=%p): __unw_step_stage2() reached "238 "bottom => _URC_END_OF_STACK",239 (void *)exception_object);240 return _URC_END_OF_STACK;241 } else if (stepResult < 0) {242 _LIBUNWIND_TRACE_UNWINDING(243 "unwind_phase2(ex_obj=%p): __unw_step_stage2 failed => "244 "_URC_FATAL_PHASE1_ERROR",245 (void *)exception_object);246 return _URC_FATAL_PHASE2_ERROR;247 }248 249 // Get info about this frame.250 unw_word_t sp;251 unw_proc_info_t frameInfo;252 __unw_get_reg(cursor, UNW_REG_SP, &sp);253 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {254 _LIBUNWIND_TRACE_UNWINDING(255 "unwind_phase2(ex_obj=%p): __unw_get_proc_info "256 "failed => _URC_FATAL_PHASE1_ERROR",257 (void *)exception_object);258 return _URC_FATAL_PHASE2_ERROR;259 }260 261#ifndef NDEBUG262 // When tracing, print state information.263 if (_LIBUNWIND_TRACING_UNWINDING) {264 char functionBuf[512];265 const char *functionName = functionBuf;266 unw_word_t offset;267 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),268 &offset) != UNW_ESUCCESS) ||269 (frameInfo.start_ip + offset > frameInfo.end_ip))270 functionName = ".anonymous.";271 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): start_ip=0x%" PRIxPTR272 ", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR273 ", personality=0x%" PRIxPTR,274 (void *)exception_object, frameInfo.start_ip,275 functionName, sp, frameInfo.lsda,276 frameInfo.handler);277 }278#endif279 280// In shadow stack enabled environment, we check return address stored in normal281// stack against return address stored in shadow stack, if the 2 addresses don't282// match, it means return address in normal stack has been corrupted, we return283// _URC_FATAL_PHASE2_ERROR.284#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)285 if (shadowStackTop != 0) {286 unw_word_t retInNormalStack;287 __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack);288 unsigned long retInShadowStack =289 *(unsigned long *)(shadowStackTop + __shstk_step_size * framesWalked);290 if (retInNormalStack != retInShadowStack)291 return _URC_FATAL_PHASE2_ERROR;292 }293#endif294 ++framesWalked;295 // If there is a personality routine, tell it we are unwinding.296 if (frameInfo.handler != 0) {297 _Unwind_Personality_Fn p = get_handler_function(&frameInfo);298 _Unwind_Action action = _UA_CLEANUP_PHASE;299 if (sp == exception_object->private_2) {300 // Tell personality this was the frame it marked in phase 1.301 action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);302 }303 _Unwind_Reason_Code personalityResult =304 (*p)(1, action, exception_object->exception_class, exception_object,305 (struct _Unwind_Context *)(cursor));306 switch (personalityResult) {307 case _URC_CONTINUE_UNWIND:308 // Continue unwinding309 _LIBUNWIND_TRACE_UNWINDING(310 "unwind_phase2(ex_obj=%p): _URC_CONTINUE_UNWIND",311 (void *)exception_object);312 if (sp == exception_object->private_2) {313 // Phase 1 said we would stop at this frame, but we did not...314 _LIBUNWIND_ABORT("during phase1 personality function said it would "315 "stop here, but now in phase2 it did not stop here");316 }317 break;318 case _URC_INSTALL_CONTEXT:319 _LIBUNWIND_TRACE_UNWINDING(320 "unwind_phase2(ex_obj=%p): _URC_INSTALL_CONTEXT",321 (void *)exception_object);322 // Personality routine says to transfer control to landing pad.323 // We may get control back if landing pad calls _Unwind_Resume().324 if (_LIBUNWIND_TRACING_UNWINDING) {325 unw_word_t pc;326 __unw_get_reg(cursor, UNW_REG_IP, &pc);327 __unw_get_reg(cursor, UNW_REG_SP, &sp);328 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): re-entering "329 "user code with ip=0x%" PRIxPTR330 ", sp=0x%" PRIxPTR,331 (void *)exception_object, pc, sp);332 }333 334 __unw_phase2_resume(cursor, framesWalked);335 // __unw_phase2_resume() only returns if there was an error.336 return _URC_FATAL_PHASE2_ERROR;337 default:338 // Personality routine returned an unknown result code.339 _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",340 personalityResult);341 return _URC_FATAL_PHASE2_ERROR;342 }343 }344 }345 346 // Clean up phase did not resume at the frame that the search phase347 // said it would...348 return _URC_FATAL_PHASE2_ERROR;349}350 351#if defined(_LIBUNWIND_USE_GCS)352// Enable the GCS target feature to permit gcspop instructions to be used.353__attribute__((target("+gcs")))354#else355_LIBUNWIND_TRACE_NO_INLINE356#endif357static _Unwind_Reason_Code358unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,359 _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,360 void *stop_parameter) {361 __unw_init_local(cursor, uc);362 363 // uc is initialized by __unw_getcontext in the parent frame. The first stack364 // frame walked is unwind_phase2_forced.365 unsigned framesWalked = 1;366 // Walk each frame until we reach where search phase said to stop367 while (__unw_step_stage2(cursor) > 0) {368 369 // Update info about this frame.370 unw_proc_info_t frameInfo;371 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {372 _LIBUNWIND_TRACE_UNWINDING(373 "unwind_phase2_forced(ex_obj=%p): __unw_get_proc_info "374 "failed => _URC_END_OF_STACK",375 (void *)exception_object);376 return _URC_FATAL_PHASE2_ERROR;377 }378 379#ifndef NDEBUG380 // When tracing, print state information.381 if (_LIBUNWIND_TRACING_UNWINDING) {382 char functionBuf[512];383 const char *functionName = functionBuf;384 unw_word_t offset;385 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),386 &offset) != UNW_ESUCCESS) ||387 (frameInfo.start_ip + offset > frameInfo.end_ip))388 functionName = ".anonymous.";389 _LIBUNWIND_TRACE_UNWINDING(390 "unwind_phase2_forced(ex_obj=%p): start_ip=0x%" PRIxPTR391 ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,392 (void *)exception_object, frameInfo.start_ip, functionName,393 frameInfo.lsda, frameInfo.handler);394 }395#endif396 397 // Call stop function at each frame.398 _Unwind_Action action =399 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);400 _Unwind_Reason_Code stopResult =401 (*stop)(1, action, exception_object->exception_class, exception_object,402 (struct _Unwind_Context *)(cursor), stop_parameter);403 _LIBUNWIND_TRACE_UNWINDING(404 "unwind_phase2_forced(ex_obj=%p): stop function returned %d",405 (void *)exception_object, stopResult);406 if (stopResult != _URC_NO_REASON) {407 _LIBUNWIND_TRACE_UNWINDING(408 "unwind_phase2_forced(ex_obj=%p): stopped by stop function",409 (void *)exception_object);410 return _URC_FATAL_PHASE2_ERROR;411 }412 413 ++framesWalked;414 // If there is a personality routine, tell it we are unwinding.415 if (frameInfo.handler != 0) {416 _Unwind_Personality_Fn p = get_handler_function(&frameInfo);417 _LIBUNWIND_TRACE_UNWINDING(418 "unwind_phase2_forced(ex_obj=%p): calling personality function %p",419 (void *)exception_object, (void *)(uintptr_t)p);420 _Unwind_Reason_Code personalityResult =421 (*p)(1, action, exception_object->exception_class, exception_object,422 (struct _Unwind_Context *)(cursor));423 switch (personalityResult) {424 case _URC_CONTINUE_UNWIND:425 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "426 "personality returned "427 "_URC_CONTINUE_UNWIND",428 (void *)exception_object);429 // Destructors called, continue unwinding430 break;431 case _URC_INSTALL_CONTEXT:432 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "433 "personality returned "434 "_URC_INSTALL_CONTEXT",435 (void *)exception_object);436 // We may get control back if landing pad calls _Unwind_Resume().437 __unw_phase2_resume(cursor, framesWalked);438 break;439 default:440 // Personality routine returned an unknown result code.441 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "442 "personality returned %d, "443 "_URC_FATAL_PHASE2_ERROR",444 (void *)exception_object, personalityResult);445 return _URC_FATAL_PHASE2_ERROR;446 }447 }448 }449 450 // Call stop function one last time and tell it we've reached the end451 // of the stack.452 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): calling stop "453 "function with _UA_END_OF_STACK",454 (void *)exception_object);455 _Unwind_Action lastAction =456 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);457 (*stop)(1, lastAction, exception_object->exception_class, exception_object,458 (struct _Unwind_Context *)(cursor), stop_parameter);459 460 // Clean up phase did not resume at the frame that the search phase said it461 // would.462 return _URC_FATAL_PHASE2_ERROR;463}464 465/// Called by __cxa_throw. Only returns if there is a fatal error.466_LIBUNWIND_EXPORT _Unwind_Reason_Code467_Unwind_RaiseException(_Unwind_Exception *exception_object) {468 _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",469 (void *)exception_object);470 unw_context_t uc;471 unw_cursor_t cursor;472 __unw_getcontext(&uc);473 474 // Mark that this is a non-forced unwind, so _Unwind_Resume()475 // can do the right thing.476 exception_object->private_1 = 0;477 exception_object->private_2 = 0;478 479 // phase 1: the search phase480 _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);481 if (phase1 != _URC_NO_REASON)482 return phase1;483 484 // phase 2: the clean up phase485 return unwind_phase2(&uc, &cursor, exception_object);486}487 488 489 490/// When _Unwind_RaiseException() is in phase2, it hands control491/// to the personality function at each frame. The personality492/// may force a jump to a landing pad in that function, the landing493/// pad code may then call _Unwind_Resume() to continue with the494/// unwinding. Note: the call to _Unwind_Resume() is from compiler495/// generated user code. All other _Unwind_* routines are called496/// by the C++ runtime __cxa_* routines.497///498/// Note: re-throwing an exception (as opposed to continuing the unwind)499/// is implemented by having the code call __cxa_rethrow() which500/// in turn calls _Unwind_Resume_or_Rethrow().501_LIBUNWIND_EXPORT void502_Unwind_Resume(_Unwind_Exception *exception_object) {503 _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);504 unw_context_t uc;505 unw_cursor_t cursor;506 __unw_getcontext(&uc);507 508 if (exception_object->private_1 != 0)509 unwind_phase2_forced(&uc, &cursor, exception_object,510 (_Unwind_Stop_Fn) exception_object->private_1,511 (void *)exception_object->private_2);512 else513 unwind_phase2(&uc, &cursor, exception_object);514 515 // Clients assume _Unwind_Resume() does not return, so all we can do is abort.516 _LIBUNWIND_ABORT("_Unwind_Resume() can't return");517}518 519 520 521/// Not used by C++.522/// Unwinds stack, calling "stop" function at each frame.523/// Could be used to implement longjmp().524_LIBUNWIND_EXPORT _Unwind_Reason_Code525_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,526 _Unwind_Stop_Fn stop, void *stop_parameter) {527 _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",528 (void *)exception_object, (void *)(uintptr_t)stop);529 unw_context_t uc;530 unw_cursor_t cursor;531 __unw_getcontext(&uc);532 533 // Mark that this is a forced unwind, so _Unwind_Resume() can do534 // the right thing.535 exception_object->private_1 = (uintptr_t) stop;536 exception_object->private_2 = (uintptr_t) stop_parameter;537 538 // do it539 return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter);540}541 542 543/// Called by personality handler during phase 2 to get LSDA for current frame.544_LIBUNWIND_EXPORT uintptr_t545_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {546 unw_cursor_t *cursor = (unw_cursor_t *)context;547 unw_proc_info_t frameInfo;548 uintptr_t result = 0;549 if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)550 result = (uintptr_t)frameInfo.lsda;551 _LIBUNWIND_TRACE_API(552 "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,553 (void *)context, result);554#if !defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)555 if (result != 0) {556 if (*((uint8_t *)result) != 0xFF)557 _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF",558 result);559 }560#endif561 return result;562}563 564 565/// Called by personality handler during phase 2 to find the start of the566/// function.567_LIBUNWIND_EXPORT uintptr_t568_Unwind_GetRegionStart(struct _Unwind_Context *context) {569 unw_cursor_t *cursor = (unw_cursor_t *)context;570 unw_proc_info_t frameInfo;571 uintptr_t result = 0;572 if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)573 result = (uintptr_t)frameInfo.start_ip;574 _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,575 (void *)context, result);576 return result;577}578 579#endif // !_LIBUNWIND_SUPPORT_SEH_UNWIND580 581/// Called by personality handler during phase 2 if a foreign exception582// is caught.583_LIBUNWIND_EXPORT void584_Unwind_DeleteException(_Unwind_Exception *exception_object) {585 _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",586 (void *)exception_object);587 if (exception_object->exception_cleanup != NULL)588 (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,589 exception_object);590}591 592/// Called by personality handler during phase 2 to get register values.593_LIBUNWIND_EXPORT uintptr_t594_Unwind_GetGR(struct _Unwind_Context *context, int index) {595 unw_cursor_t *cursor = (unw_cursor_t *)context;596 unw_word_t result;597 __unw_get_reg(cursor, index, &result);598 _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIxPTR,599 (void *)context, index, result);600 return (uintptr_t)result;601}602 603/// Called by personality handler during phase 2 to alter register values.604_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,605 uintptr_t value) {606 _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIxPTR607 ")",608 (void *)context, index, value);609 unw_cursor_t *cursor = (unw_cursor_t *)context;610 __unw_set_reg(cursor, index, value);611}612 613/// Called by personality handler during phase 2 to get instruction pointer.614_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {615 unw_cursor_t *cursor = (unw_cursor_t *)context;616 unw_word_t result;617 __unw_get_reg(cursor, UNW_REG_IP, &result);618 619#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)620 // If we are in an arm64e frame, then the PC should have been signed with the621 // sp622 {623 unw_word_t sp;624 __unw_get_reg(cursor, UNW_REG_SP, &sp);625 result = (unw_word_t)ptrauth_auth_data((void *)result,626 ptrauth_key_return_address, sp);627 }628#endif629 630 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,631 (void *)context, result);632 return (uintptr_t)result;633}634 635/// Called by personality handler during phase 2 to alter instruction pointer,636/// such as setting where the landing pad is, so _Unwind_Resume() will637/// start executing in the landing pad.638_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,639 uintptr_t value) {640 _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIxPTR ")",641 (void *)context, value);642 unw_cursor_t *cursor = (unw_cursor_t *)context;643 __unw_set_reg(cursor, UNW_REG_IP, value);644}645 646#endif // !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)647