From fde4a5bd965b128318e17a3b8ba1dc0fcf8df4a0 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 28 May 2026 16:55:57 -0700 Subject: [PATCH 1/2] Guard unused llvm-libunwind symbols to avoid duplicates on Android NativeAOT uses llvm-libunwind's internal C++ classes directly (DwarfInstructions, CompactUnwinder, UnwindCursor, LocalAddressSpace) and does not call the public unw_* C API. These symbols conflict with platform libunwind on Android NDK r29. Add a _LIBUNWIND_NATIVEAOT define that guards out the public API symbols NativeAOT does not use: - libunwind.cpp: wrap the entire file (except debug logging) in #if !defined(_LIBUNWIND_NATIVEAOT) as a purely additive patch, making it resilient to upstream llvm-libunwind updates - Unwind-EHABI.cpp: the C++ exception dispatch functions are also guarded because they depend on the now-guarded unw_* functions and would cause undefined symbol errors on ARM32 Switch UnixNativeCodeManager to use a new UnwindHelpers::FindUnwindSections() accessor instead of the now-guarded sThisAddressSpace singleton. This delegates to the existing file-local LocalAddressSpace instance in UnwindHelpers.cpp. Co-authored-by: Jan Kotas Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/coreclr/nativeaot/Runtime/CMakeLists.txt | 8 ++++++-- .../nativeaot/Runtime/unix/UnixNativeCodeManager.cpp | 2 +- src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp | 5 +++++ src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.h | 1 + src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp | 8 ++++++++ src/native/external/llvm-libunwind/src/libunwind.cpp | 4 ++++ 6 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt index e491f54a562445..7b7eaf49ed1f35 100644 --- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt @@ -149,8 +149,12 @@ else() include_directories($ENV{EMSCRIPTEN/system/lib/libcxxabi/include}) endif() - # Disable building _Unwind_XXX style APIs of libunwind, since we don't use them. - add_definitions(-D_LIBUNWIND_DISABLE_ZERO_COST_APIS=1) + # Guard out the public unw_* C API, C++ exception dispatch entry points, + # and the LocalAddressSpace singleton from llvm-libunwind. NativeAOT does + # not use these - it uses the internal C++ classes directly. Omitting them + # avoids exporting symbols that conflict with platform libunwind (e.g. + # Android NDK r29). + add_definitions(-D_LIBUNWIND_NATIVEAOT=1) # Compile unwinding only for the current compilation target architecture add_definitions(-D_LIBUNWIND_IS_NATIVE_ONLY) diff --git a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp index 266b56bd1f6e4e..982c541c7014f6 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp @@ -56,7 +56,7 @@ UnixNativeCodeManager::UnixNativeCodeManager(TADDR moduleBase, m_pClasslibFunctions(pClasslibFunctions), m_nClasslibFunctions(nClasslibFunctions) { // Cache the location of unwind sections - libunwind::LocalAddressSpace::sThisAddressSpace.findUnwindSections( + UnwindHelpers::FindUnwindSections( (uintptr_t)pvManagedCodeStartRange, m_UnwindInfoSections); } diff --git a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp index b1e51f8cad6782..be27ac18f65826 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp @@ -1396,6 +1396,11 @@ bool UnwindHelpers::GetUnwindProcInfo(PCODE pc, UnwindInfoSections &uwInfoSectio return true; } +bool UnwindHelpers::FindUnwindSections(uintptr_t pc, UnwindInfoSections §ions) +{ + return _addressSpace.findUnwindSections(pc, sections); +} + #if defined(TARGET_APPLE) // Apple considers _dyld_find_unwind_sections to be private API that cannot be used // by apps submitted to App Store and TestFlight, both for iOS-like and macOS platforms. diff --git a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.h b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.h index 2e9d7a299e0e01..a185c990648b62 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.h +++ b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.h @@ -15,4 +15,5 @@ class UnwindHelpers public: static bool StepFrame(REGDISPLAY *regs, unw_word_t start_ip, uint32_t format, unw_word_t unwind_info); static bool GetUnwindProcInfo(PCODE ip, libunwind::UnwindInfoSections &uwInfoSections, unw_proc_info_t *procInfo); + static bool FindUnwindSections(uintptr_t pc, libunwind::UnwindInfoSections §ions); }; diff --git a/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp b/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp index 338c853bca780e..5292bc55d37823 100644 --- a/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp +++ b/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp @@ -443,6 +443,12 @@ _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. +#if !defined(_LIBUNWIND_NATIVEAOT) + extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code __aeabi_unwind_cpp_pr0(_Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context) { @@ -1210,4 +1216,6 @@ __gnu_unwind_frame(_Unwind_Exception *exception_object, } } +#endif // !defined(_LIBUNWIND_NATIVEAOT) + #endif // defined(_LIBUNWIND_ARM_EHABI) diff --git a/src/native/external/llvm-libunwind/src/libunwind.cpp b/src/native/external/llvm-libunwind/src/libunwind.cpp index 2f2032c6c28147..0dfd6cf49b1134 100644 --- a/src/native/external/llvm-libunwind/src/libunwind.cpp +++ b/src/native/external/llvm-libunwind/src/libunwind.cpp @@ -26,6 +26,8 @@ #include #endif +#if !defined(_LIBUNWIND_NATIVEAOT) + #if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) #include "AddressSpace.hpp" #include "UnwindCursor.hpp" @@ -547,6 +549,8 @@ int __unw_remove_find_dynamic_unwind_sections( #endif // __APPLE__ +#endif // !defined(_LIBUNWIND_NATIVEAOT) + // Add logging hooks in Debug builds only #ifndef NDEBUG #include From 1004d9fdf274dc23deca312bdead94128c89d8e1 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 28 May 2026 16:56:16 -0700 Subject: [PATCH 2/2] Update llvm-libunwind-version.txt Reference fde4a5bd965 (Guard unused llvm-libunwind symbols). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/native/external/llvm-libunwind-version.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/native/external/llvm-libunwind-version.txt b/src/native/external/llvm-libunwind-version.txt index 8d9b9e900e6bcb..b2b238ba74ab9b 100644 --- a/src/native/external/llvm-libunwind-version.txt +++ b/src/native/external/llvm-libunwind-version.txt @@ -3,3 +3,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