Path: blob/main/system/lib/libunwind/src/Unwind-seh.cpp
6175 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//8// Implements SEH-based Itanium C++ exceptions.9//10//===----------------------------------------------------------------------===//1112#include "config.h"1314#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)1516#include <unwind.h>1718#include <stdint.h>19#include <stdbool.h>20#include <stdlib.h>2122#include <windef.h>23#include <excpt.h>24#include <winnt.h>25#include <ntstatus.h>2627#include "libunwind_ext.h"28#include "UnwindCursor.hpp"2930using namespace libunwind;3132#define STATUS_USER_DEFINED (1u << 29)3334#define STATUS_GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C')3536#define MAKE_CUSTOM_STATUS(s, c) \37((NTSTATUS)(((s) << 30) | STATUS_USER_DEFINED | (c)))38#define MAKE_GCC_EXCEPTION(c) \39MAKE_CUSTOM_STATUS(STATUS_SEVERITY_SUCCESS, STATUS_GCC_MAGIC | ((c) << 24))4041/// SEH exception raised by libunwind when the program calls42/// \c _Unwind_RaiseException.43#define STATUS_GCC_THROW MAKE_GCC_EXCEPTION(0) // 0x2047434344/// SEH exception raised by libunwind to initiate phase 2 of exception45/// handling.46#define STATUS_GCC_UNWIND MAKE_GCC_EXCEPTION(1) // 0x214743434748static int __unw_init_seh(unw_cursor_t *cursor, CONTEXT *ctx);49static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor);50static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor,51DISPATCHER_CONTEXT *disp);5253#pragma clang diagnostic push54#pragma clang diagnostic ignored "-Wgnu-anonymous-struct"55// Local redefinition of this type; mingw-w64 headers lack the56// DISPATCHER_CONTEXT_NONVOLREG_ARM64 type as of May 2025, so locally redefine57// it and use that definition, to avoid needing to test/guess whether the real58// type is available of not.59union LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM64 {60BYTE Buffer[11 * sizeof(DWORD64) + 8 * sizeof(double)];6162struct {63DWORD64 GpNvRegs[11];64double FpNvRegs[8];65};66};6768// Custom data type definition; this type is not defined in WinSDK.69union LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM {70BYTE Buffer[8 * sizeof(DWORD) + 8 * sizeof(double)];7172struct {73DWORD GpNvRegs[8];74double FpNvRegs[8];75};76};77#pragma clang diagnostic pop7879/// Common implementation of SEH-style handler functions used by Itanium-80/// style frames. Depending on how and why it was called, it may do one of:81/// a) Delegate to the given Itanium-style personality function; or82/// b) Initiate a collided unwind to halt unwinding.83_LIBUNWIND_EXPORT EXCEPTION_DISPOSITION84_GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,85DISPATCHER_CONTEXT *disp, _Unwind_Personality_Fn pers) {86unw_cursor_t cursor;87_Unwind_Exception *exc;88_Unwind_Action action;89struct _Unwind_Context *ctx = nullptr;90_Unwind_Reason_Code urc;91uintptr_t retval, target;92bool ours = false;9394_LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler(%#010lx(%lx), %p)",95ms_exc->ExceptionCode, ms_exc->ExceptionFlags,96(void *)frame);97if (ms_exc->ExceptionCode == STATUS_GCC_UNWIND) {98if (IS_TARGET_UNWIND(ms_exc->ExceptionFlags)) {99// Set up the upper return value (the lower one and the target PC100// were set in the call to RtlUnwindEx()) for the landing pad.101#ifdef __x86_64__102disp->ContextRecord->Rdx = ms_exc->ExceptionInformation[3];103#elif defined(__arm__)104disp->ContextRecord->R1 = ms_exc->ExceptionInformation[3];105#elif defined(__aarch64__)106disp->ContextRecord->X1 = ms_exc->ExceptionInformation[3];107#endif108}109// This is the collided unwind to the landing pad. Nothing to do.110return ExceptionContinueSearch;111}112113if (ms_exc->ExceptionCode == STATUS_GCC_THROW) {114// This is (probably) a libunwind-controlled exception/unwind. Recover the115// parameters which we set below, and pass them to the personality function.116ours = true;117exc = (_Unwind_Exception *)ms_exc->ExceptionInformation[0];118if (!IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) {119ctx = (struct _Unwind_Context *)ms_exc->ExceptionInformation[1];120action = (_Unwind_Action)ms_exc->ExceptionInformation[2];121}122} else {123// Foreign exception.124// We can't interact with them (we don't know the original target frame125// that we should pass on to RtlUnwindEx in _Unwind_Resume), so just126// pass without calling our destructors here.127return ExceptionContinueSearch;128}129if (!ctx) {130__unw_init_seh(&cursor, disp->ContextRecord);131__unw_seh_set_disp_ctx(&cursor, disp);132__unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc);133ctx = (struct _Unwind_Context *)&cursor;134135if (!IS_UNWINDING(ms_exc->ExceptionFlags)) {136if (ours && ms_exc->NumberParameters > 1)137action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_FORCE_UNWIND);138else139action = _UA_SEARCH_PHASE;140} else {141if (ours && ms_exc->ExceptionInformation[1] == (ULONG_PTR)frame)142action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);143else144action = _UA_CLEANUP_PHASE;145}146}147148_LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() calling personality "149"function %p(1, %d, %llx, %p, %p)",150(void *)pers, action, exc->exception_class,151(void *)exc, (void *)ctx);152urc = pers(1, action, exc->exception_class, exc, ctx);153_LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() personality returned %d", urc);154switch (urc) {155case _URC_CONTINUE_UNWIND:156// If we're in phase 2, and the personality routine said to continue157// at the target frame, we're in real trouble.158if (action & _UA_HANDLER_FRAME)159_LIBUNWIND_ABORT("Personality continued unwind at the target frame!");160return ExceptionContinueSearch;161case _URC_HANDLER_FOUND:162// If we were called by __libunwind_seh_personality(), indicate that163// a handler was found; otherwise, initiate phase 2 by unwinding.164if (ours && ms_exc->NumberParameters > 1)165return 4 /* ExceptionExecuteHandler in mingw */;166// This should never happen in phase 2.167if (IS_UNWINDING(ms_exc->ExceptionFlags))168_LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!");169exc->private_[1] = (ULONG_PTR)frame;170if (ours) {171ms_exc->NumberParameters = 4;172ms_exc->ExceptionInformation[1] = (ULONG_PTR)frame;173}174// FIXME: Indicate target frame in foreign case!175// phase 2: the clean up phase176RtlUnwindEx(frame, (PVOID)disp->ControlPc, ms_exc, exc, disp->ContextRecord,177disp->HistoryTable);178_LIBUNWIND_ABORT("RtlUnwindEx() failed");179case _URC_INSTALL_CONTEXT: {180// If we were called by __libunwind_seh_personality(), indicate that181// a handler was found; otherwise, it's time to initiate a collided182// unwind to the target.183if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1)184return 4 /* ExceptionExecuteHandler in mingw */;185// This should never happen in phase 1.186if (!IS_UNWINDING(ms_exc->ExceptionFlags))187_LIBUNWIND_ABORT("Personality installed context during phase 1!");188#ifdef __x86_64__189exc->private_[2] = disp->TargetIp;190__unw_get_reg(&cursor, UNW_X86_64_RAX, &retval);191__unw_get_reg(&cursor, UNW_X86_64_RDX, &exc->private_[3]);192#elif defined(__arm__)193exc->private_[2] = disp->TargetPc;194__unw_get_reg(&cursor, UNW_ARM_R0, &retval);195__unw_get_reg(&cursor, UNW_ARM_R1, &exc->private_[3]);196#elif defined(__aarch64__)197exc->private_[2] = disp->TargetPc;198__unw_get_reg(&cursor, UNW_AARCH64_X0, &retval);199__unw_get_reg(&cursor, UNW_AARCH64_X1, &exc->private_[3]);200#endif201__unw_get_reg(&cursor, UNW_REG_IP, &target);202ms_exc->ExceptionCode = STATUS_GCC_UNWIND;203#ifdef __x86_64__204ms_exc->ExceptionInformation[2] = disp->TargetIp;205#elif defined(__arm__) || defined(__aarch64__)206ms_exc->ExceptionInformation[2] = disp->TargetPc;207#endif208ms_exc->ExceptionInformation[3] = exc->private_[3];209// Give NTRTL some scratch space to keep track of the collided unwind.210// Don't use the one that was passed in; we don't want to overwrite the211// context in the DISPATCHER_CONTEXT.212CONTEXT new_ctx;213RtlUnwindEx(frame, (PVOID)target, ms_exc, (PVOID)retval, &new_ctx, disp->HistoryTable);214_LIBUNWIND_ABORT("RtlUnwindEx() failed");215}216// Anything else indicates a serious problem.217default: return ExceptionContinueExecution;218}219}220221/// Personality function returned by \c __unw_get_proc_info() in SEH contexts.222/// This is a wrapper that calls the real SEH handler function, which in223/// turn (at least, for Itanium-style frames) calls the real Itanium224/// personality function (see \c _GCC_specific_handler()).225extern "C" _Unwind_Reason_Code226__libunwind_seh_personality(int version, _Unwind_Action state,227uint64_t klass, _Unwind_Exception *exc,228struct _Unwind_Context *context) {229(void)version;230(void)klass;231EXCEPTION_RECORD ms_exc;232bool phase2 = (state & (_UA_SEARCH_PHASE|_UA_CLEANUP_PHASE)) == _UA_CLEANUP_PHASE;233ms_exc.ExceptionCode = STATUS_GCC_THROW;234ms_exc.ExceptionFlags = 0;235ms_exc.NumberParameters = 3;236ms_exc.ExceptionInformation[0] = (ULONG_PTR)exc;237ms_exc.ExceptionInformation[1] = (ULONG_PTR)context;238ms_exc.ExceptionInformation[2] = state;239DISPATCHER_CONTEXT *disp_ctx =240__unw_seh_get_disp_ctx((unw_cursor_t *)context);241#if defined(__aarch64__)242LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM64 nonvol;243memcpy(&nonvol.GpNvRegs, &disp_ctx->ContextRecord->X19,244sizeof(nonvol.GpNvRegs));245for (int i = 0; i < 8; i++)246nonvol.FpNvRegs[i] = disp_ctx->ContextRecord->V[i + 8].D[0];247disp_ctx->NonVolatileRegisters = nonvol.Buffer;248#elif defined(__arm__)249LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM nonvol;250memcpy(&nonvol.GpNvRegs, &disp_ctx->ContextRecord->R4,251sizeof(nonvol.GpNvRegs));252memcpy(&nonvol.FpNvRegs, &disp_ctx->ContextRecord->D[8],253sizeof(nonvol.FpNvRegs));254disp_ctx->NonVolatileRegisters = nonvol.Buffer;255#endif256_LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() calling "257"LanguageHandler %p(%p, %p, %p, %p)",258(void *)disp_ctx->LanguageHandler, (void *)&ms_exc,259(void *)disp_ctx->EstablisherFrame,260(void *)disp_ctx->ContextRecord, (void *)disp_ctx);261EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc,262(PVOID)disp_ctx->EstablisherFrame,263disp_ctx->ContextRecord,264disp_ctx);265_LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() LanguageHandler "266"returned %d",267(int)ms_act);268switch (ms_act) {269case ExceptionContinueExecution: return _URC_END_OF_STACK;270case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND;271case 4 /*ExceptionExecuteHandler*/:272return phase2 ? _URC_INSTALL_CONTEXT : _URC_HANDLER_FOUND;273default:274return phase2 ? _URC_FATAL_PHASE2_ERROR : _URC_FATAL_PHASE1_ERROR;275}276}277278static _Unwind_Reason_Code279unwind_phase2_forced(unw_context_t *uc,280_Unwind_Exception *exception_object,281_Unwind_Stop_Fn stop, void *stop_parameter) {282unw_cursor_t cursor2;283__unw_init_local(&cursor2, uc);284285// Walk each frame until we reach where search phase said to stop286while (__unw_step(&cursor2) > 0) {287288// Update info about this frame.289unw_proc_info_t frameInfo;290if (__unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {291_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_get_proc_info "292"failed => _URC_END_OF_STACK",293(void *)exception_object);294return _URC_FATAL_PHASE2_ERROR;295}296297#ifndef NDEBUG298// When tracing, print state information.299if (_LIBUNWIND_TRACING_UNWINDING) {300char functionBuf[512];301const char *functionName = functionBuf;302unw_word_t offset;303if ((__unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),304&offset) != UNW_ESUCCESS) ||305(frameInfo.start_ip + offset > frameInfo.end_ip))306functionName = ".anonymous.";307_LIBUNWIND_TRACE_UNWINDING(308"unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR309", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,310(void *)exception_object, frameInfo.start_ip, functionName,311frameInfo.lsda, frameInfo.handler);312}313#endif314315// Call stop function at each frame.316_Unwind_Action action =317(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);318_Unwind_Reason_Code stopResult =319(*stop)(1, action, exception_object->exception_class, exception_object,320(struct _Unwind_Context *)(&cursor2), stop_parameter);321_LIBUNWIND_TRACE_UNWINDING(322"unwind_phase2_forced(ex_ojb=%p): stop function returned %d",323(void *)exception_object, stopResult);324if (stopResult != _URC_NO_REASON) {325_LIBUNWIND_TRACE_UNWINDING(326"unwind_phase2_forced(ex_ojb=%p): stopped by stop function",327(void *)exception_object);328return _URC_FATAL_PHASE2_ERROR;329}330331// If there is a personality routine, tell it we are unwinding.332if (frameInfo.handler != 0) {333_Unwind_Personality_Fn p =334(_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);335_LIBUNWIND_TRACE_UNWINDING(336"unwind_phase2_forced(ex_ojb=%p): calling personality function %p",337(void *)exception_object, (void *)(uintptr_t)p);338_Unwind_Reason_Code personalityResult =339(*p)(1, action, exception_object->exception_class, exception_object,340(struct _Unwind_Context *)(&cursor2));341switch (personalityResult) {342case _URC_CONTINUE_UNWIND:343_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "344"personality returned "345"_URC_CONTINUE_UNWIND",346(void *)exception_object);347// Destructors called, continue unwinding348break;349case _URC_INSTALL_CONTEXT:350_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "351"personality returned "352"_URC_INSTALL_CONTEXT",353(void *)exception_object);354// We may get control back if landing pad calls _Unwind_Resume().355__unw_resume(&cursor2);356break;357case _URC_END_OF_STACK:358_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "359"personality returned "360"_URC_END_OF_STACK",361(void *)exception_object);362break;363default:364// Personality routine returned an unknown result code.365_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "366"personality returned %d, "367"_URC_FATAL_PHASE2_ERROR",368(void *)exception_object, personalityResult);369return _URC_FATAL_PHASE2_ERROR;370}371if (personalityResult == _URC_END_OF_STACK)372break;373}374}375376// Call stop function one last time and tell it we've reached the end377// of the stack.378_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "379"function with _UA_END_OF_STACK",380(void *)exception_object);381_Unwind_Action lastAction =382(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);383(*stop)(1, lastAction, exception_object->exception_class, exception_object,384(struct _Unwind_Context *)(&cursor2), stop_parameter);385386// Clean up phase did not resume at the frame that the search phase said it387// would.388return _URC_FATAL_PHASE2_ERROR;389}390391/// Called by \c __cxa_throw(). Only returns if there is a fatal error.392_LIBUNWIND_EXPORT _Unwind_Reason_Code393_Unwind_RaiseException(_Unwind_Exception *exception_object) {394_LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",395(void *)exception_object);396397// Mark that this is a non-forced unwind, so _Unwind_Resume()398// can do the right thing.399memset(exception_object->private_, 0, sizeof(exception_object->private_));400401// phase 1: the search phase402// We'll let the system do that for us.403RaiseException(STATUS_GCC_THROW, 0, 1, (ULONG_PTR *)&exception_object);404405// If we get here, either something went horribly wrong or we reached the406// top of the stack. Either way, let libc++abi call std::terminate().407return _URC_END_OF_STACK;408}409410/// When \c _Unwind_RaiseException() is in phase2, it hands control411/// to the personality function at each frame. The personality412/// may force a jump to a landing pad in that function; the landing413/// pad code may then call \c _Unwind_Resume() to continue with the414/// unwinding. Note: the call to \c _Unwind_Resume() is from compiler415/// generated user code. All other \c _Unwind_* routines are called416/// by the C++ runtime \c __cxa_* routines.417///418/// Note: re-throwing an exception (as opposed to continuing the unwind)419/// is implemented by having the code call \c __cxa_rethrow() which420/// in turn calls \c _Unwind_Resume_or_Rethrow().421_LIBUNWIND_EXPORT void422_Unwind_Resume(_Unwind_Exception *exception_object) {423_LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);424425if (exception_object->private_[0] != 0) {426unw_context_t uc;427428__unw_getcontext(&uc);429unwind_phase2_forced(&uc, exception_object,430(_Unwind_Stop_Fn) exception_object->private_[0],431(void *)exception_object->private_[4]);432} else {433// Recover the parameters for the unwind from the exception object434// so we can start unwinding again.435EXCEPTION_RECORD ms_exc;436CONTEXT ms_ctx;437UNWIND_HISTORY_TABLE hist;438439memset(&ms_exc, 0, sizeof(ms_exc));440memset(&hist, 0, sizeof(hist));441ms_exc.ExceptionCode = STATUS_GCC_THROW;442ms_exc.ExceptionFlags = EXCEPTION_NONCONTINUABLE;443ms_exc.NumberParameters = 4;444ms_exc.ExceptionInformation[0] = (ULONG_PTR)exception_object;445ms_exc.ExceptionInformation[1] = exception_object->private_[1];446ms_exc.ExceptionInformation[2] = exception_object->private_[2];447ms_exc.ExceptionInformation[3] = exception_object->private_[3];448RtlUnwindEx((PVOID)exception_object->private_[1],449(PVOID)exception_object->private_[2], &ms_exc,450exception_object, &ms_ctx, &hist);451}452453// Clients assume _Unwind_Resume() does not return, so all we can do is abort.454_LIBUNWIND_ABORT("_Unwind_Resume() can't return");455}456457/// Not used by C++.458/// Unwinds stack, calling "stop" function at each frame.459/// Could be used to implement \c longjmp().460_LIBUNWIND_EXPORT _Unwind_Reason_Code461_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,462_Unwind_Stop_Fn stop, void *stop_parameter) {463_LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",464(void *)exception_object, (void *)(uintptr_t)stop);465unw_context_t uc;466__unw_getcontext(&uc);467468// Mark that this is a forced unwind, so _Unwind_Resume() can do469// the right thing.470exception_object->private_[0] = (uintptr_t) stop;471exception_object->private_[4] = (uintptr_t) stop_parameter;472473// do it474return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);475}476477/// Called by personality handler during phase 2 to get LSDA for current frame.478_LIBUNWIND_EXPORT uintptr_t479_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {480uintptr_t result =481(uintptr_t)__unw_seh_get_disp_ctx((unw_cursor_t *)context)->HandlerData;482_LIBUNWIND_TRACE_API(483"_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,484(void *)context, result);485return result;486}487488/// Called by personality handler during phase 2 to find the start of the489/// function.490_LIBUNWIND_EXPORT uintptr_t491_Unwind_GetRegionStart(struct _Unwind_Context *context) {492DISPATCHER_CONTEXT *disp = __unw_seh_get_disp_ctx((unw_cursor_t *)context);493uintptr_t result = (uintptr_t)disp->FunctionEntry->BeginAddress + disp->ImageBase;494_LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,495(void *)context, result);496return result;497}498499static int __unw_init_seh(unw_cursor_t *cursor, CONTEXT *context) {500#ifdef _LIBUNWIND_TARGET_X86_64501new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor))502UnwindCursor<LocalAddressSpace, Registers_x86_64>(503context, LocalAddressSpace::sThisAddressSpace);504auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);505co->setInfoBasedOnIPRegister();506return UNW_ESUCCESS;507#elif defined(_LIBUNWIND_TARGET_ARM)508new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor))509UnwindCursor<LocalAddressSpace, Registers_arm>(510context, LocalAddressSpace::sThisAddressSpace);511auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);512co->setInfoBasedOnIPRegister();513return UNW_ESUCCESS;514#elif defined(_LIBUNWIND_TARGET_AARCH64)515new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor))516UnwindCursor<LocalAddressSpace, Registers_arm64>(517context, LocalAddressSpace::sThisAddressSpace);518auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);519co->setInfoBasedOnIPRegister();520return UNW_ESUCCESS;521#else522return UNW_EINVAL;523#endif524}525526static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor) {527#ifdef _LIBUNWIND_TARGET_X86_64528return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->getDispatcherContext();529#elif defined(_LIBUNWIND_TARGET_ARM)530return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->getDispatcherContext();531#elif defined(_LIBUNWIND_TARGET_AARCH64)532return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->getDispatcherContext();533#else534return nullptr;535#endif536}537538static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor,539DISPATCHER_CONTEXT *disp) {540#ifdef _LIBUNWIND_TARGET_X86_64541reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->setDispatcherContext(disp);542#elif defined(_LIBUNWIND_TARGET_ARM)543reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->setDispatcherContext(disp);544#elif defined(_LIBUNWIND_TARGET_AARCH64)545reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->setDispatcherContext(disp);546#endif547}548549#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)550551552