From 5ab8eb317d652ef6eb10dcb14362bfea3aa8174b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Jun 2026 04:40:16 +0000 Subject: [PATCH 1/3] Initial plan From 5697904e3c6cb08f91390440d14e1305334cec88 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Jun 2026 04:46:38 +0000 Subject: [PATCH 2/3] Fix ARM32 SIGSEGV: narrow _LIBUNWIND_NATIVEAOT guard in Unwind-EHABI.cpp Split the single #if !defined(_LIBUNWIND_NATIVEAOT) guard into two blocks so that _Unwind_VRS_Get, _Unwind_VRS_Get_Internal, _Unwind_VRS_Set, _Unwind_VRS_Pop, and ValueAsBitPattern are compiled into the NativeAOT build. These helpers are called by _Unwind_VRS_Interpret which is the ARM32 EHABI managed-frame unwinding path in NativeAOT. PR #128667 accidentally included them inside the guard, causing the linker to resolve them against libgcc_s.so.1 instead of the in-tree implementations that understand the NativeAOT ArmUnwindCursor shim, resulting in SIGSEGV during ARM32 stack unwinding. The genuinely-unused C++ exception dispatch functions (__aeabi_unwind_cpp_pr*, unwind_phase1/2, _Unwind_RaiseException, _Unwind_ForcedUnwind, etc.) that depend on __unw_step and other libunwind.cpp public API remain guarded. Co-authored-by: MichalStrehovsky <13110571+MichalStrehovsky@users.noreply.github.com> --- .../external/llvm-libunwind/src/Unwind-EHABI.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp b/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp index 5292bc55d37823..e70ba1444c41dc 100644 --- a/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp +++ b/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp @@ -443,10 +443,11 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, return _URC_CONTINUE_UNWIND; } -// The C++ exception dispatch functions below depend on __unw_step and other -// public API functions from libunwind.cpp which are guarded out when -// _LIBUNWIND_NATIVEAOT is defined. NativeAOT does not use these - it only -// uses _Unwind_VRS_Interpret above. +// The C++ exception dispatch functions in the two #if !defined(_LIBUNWIND_NATIVEAOT) +// blocks below depend on __unw_step and other public API functions from libunwind.cpp +// which are guarded out when _LIBUNWIND_NATIVEAOT is defined. NativeAOT does not use +// these - it only uses _Unwind_VRS_Interpret above, which depends on +// _Unwind_VRS_Get/Set/Pop defined between the two guard blocks. #if !defined(_LIBUNWIND_NATIVEAOT) extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code @@ -891,6 +892,8 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { return result; } +#endif // !defined(_LIBUNWIND_NATIVEAOT) + // Only used in _LIBUNWIND_TRACE_API, which is a no-op when assertions are // disabled. [[gnu::unused]] static uint64_t @@ -1154,6 +1157,8 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, _LIBUNWIND_ABORT("unsupported register class"); } +#if !defined(_LIBUNWIND_NATIVEAOT) + /// Not used by C++. /// Unwinds stack, calling "stop" function at each frame. /// Could be used to implement longjmp(). From 1cd1620334eb353d7fb4acbe91ed1c3d25bc41ca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Jun 2026 05:06:40 +0000 Subject: [PATCH 3/3] Fix ARM32 NativeAOT SIGSEGV: keep VRS helpers and __unw_*_reg outside _LIBUNWIND_NATIVEAOT guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #128667 accidentally excluded _Unwind_VRS_Get/Set/Pop (and their __unw_get/set_reg/__unw_save_vfp_as_X dependencies) from the NativeAOT build while leaving _Unwind_VRS_Interpret (their caller) in place. The linker resolved the exported VRS symbols from libgcc_s.so.1 which treats ArmUnwindCursor* as a real libgcc context → SIGSEGV on ARM32. Unwind-EHABI.cpp: Split single NATIVEAOT guard into two blocks so ValueAsBitPattern and _Unwind_VRS_Set/Get_Internal/Get/Pop sit between the two guards (always compiled). libunwind.cpp: Split single NATIVEAOT guard into smaller inner guards keeping __unw_get_reg, __unw_set_reg, __unw_get_fpreg, __unw_set_fpreg, __unw_save_vfp_as_X unconditional so they are compiled for NativeAOT. The singleton, __unw_init_local, __unw_step, __unw_resume, DWARF/FDE functions, and Apple dynamic sections remain behind the guard. Co-authored-by: MichalStrehovsky <13110571+MichalStrehovsky@users.noreply.github.com> --- .../external/llvm-libunwind-version.txt | 1 + .../external/llvm-libunwind/src/libunwind.cpp | 20 +++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/native/external/llvm-libunwind-version.txt b/src/native/external/llvm-libunwind-version.txt index b2b238ba74ab9b..22781e6d84d62c 100644 --- a/src/native/external/llvm-libunwind-version.txt +++ b/src/native/external/llvm-libunwind-version.txt @@ -4,3 +4,4 @@ https://github.com/llvm/llvm-project/releases/tag/llvmorg-22.1.1 Apply https://github.com/dotnet/runtime/commit/35b7d59fa1075ab0fefb921393409806a821d8ed Apply https://github.com/dotnet/runtime/commit/be5f98fb6702704afbaf705dce0b54d55479c6f1 Apply https://github.com/dotnet/runtime/commit/fde4a5bd965b128318e17a3b8ba1dc0fcf8df4a0 +Apply https://github.com/dotnet/runtime/commit/5697904ea1bce4dea47d2d12c89a2c82dd0d18b5 diff --git a/src/native/external/llvm-libunwind/src/libunwind.cpp b/src/native/external/llvm-libunwind/src/libunwind.cpp index 0dfd6cf49b1134..098a69dd7b713f 100644 --- a/src/native/external/llvm-libunwind/src/libunwind.cpp +++ b/src/native/external/llvm-libunwind/src/libunwind.cpp @@ -26,14 +26,19 @@ #include #endif -#if !defined(_LIBUNWIND_NATIVEAOT) - #if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) #include "AddressSpace.hpp" #include "UnwindCursor.hpp" using namespace libunwind; +// The singleton, cursor initialization, and most __unw_* functions are +// excluded from NativeAOT. The register accessors (__unw_get/set_reg, +// __unw_get/set_fpreg, __unw_save_vfp_as_X) are kept unconditional because +// they are called by _Unwind_VRS_Get/Set/Pop (Unwind-EHABI.cpp) which in +// turn are called by _Unwind_VRS_Interpret on ARM32 NativeAOT managed frames. +#if !defined(_LIBUNWIND_NATIVEAOT) + /// internal object to represent this processes address space LocalAddressSpace LocalAddressSpace::sThisAddressSpace; @@ -96,6 +101,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, } _LIBUNWIND_WEAK_ALIAS(__unw_init_local, unw_init_local) +#endif // !defined(_LIBUNWIND_NATIVEAOT) + /// Get value of specified register at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_word_t *value) { @@ -223,6 +230,8 @@ _LIBUNWIND_HIDDEN int __unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, } _LIBUNWIND_WEAK_ALIAS(__unw_set_fpreg, unw_set_fpreg) +#if !defined(_LIBUNWIND_NATIVEAOT) + /// Get location of specified register at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_get_save_loc(unw_cursor_t *cursor, int regNum, unw_save_loc_t* location) @@ -353,6 +362,8 @@ _LIBUNWIND_EXPORT uintptr_t __unw_get_data_rel_base(unw_cursor_t *cursor) { _LIBUNWIND_WEAK_ALIAS(__unw_get_data_rel_base, unw_get_data_rel_base) #endif +#endif // !defined(_LIBUNWIND_NATIVEAOT) + #ifdef __arm__ // Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD _LIBUNWIND_HIDDEN void __unw_save_vfp_as_X(unw_cursor_t *cursor) { @@ -364,6 +375,7 @@ _LIBUNWIND_HIDDEN void __unw_save_vfp_as_X(unw_cursor_t *cursor) { _LIBUNWIND_WEAK_ALIAS(__unw_save_vfp_as_X, unw_save_vfp_as_X) #endif +#if !defined(_LIBUNWIND_NATIVEAOT) #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) /// SPI: walks cached DWARF entries @@ -465,8 +477,12 @@ _LIBUNWIND_HIDDEN const char *__unw_strerror(int error_code) { } _LIBUNWIND_WEAK_ALIAS(__unw_strerror, unw_strerror) +#endif // !defined(_LIBUNWIND_NATIVEAOT) + #endif // !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) +#if !defined(_LIBUNWIND_NATIVEAOT) + #ifdef __APPLE__ namespace libunwind {