brintos

brintos / llvm-project-archived public Read only

0
0
Text · 26.7 KiB · 73a2792 Raw
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