Skip to content

Guard unused llvm-libunwind symbols to avoid duplicates on Android#128667

Merged
jkotas merged 2 commits into
dotnet:mainfrom
sbomer:libunwind-ifdef
May 29, 2026
Merged

Guard unused llvm-libunwind symbols to avoid duplicates on Android#128667
jkotas merged 2 commits into
dotnet:mainfrom
sbomer:libunwind-ifdef

Conversation

@sbomer
Copy link
Copy Markdown
Member

@sbomer sbomer commented May 27, 2026

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: all unw_* functions, unw_local_addr_space, and
    the LocalAddressSpace::sThisAddressSpace singleton
  • AddressSpace.hpp: sThisAddressSpace static member declaration
  • 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

Fixes #121172

@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib
See info in area-owners.md if you want to be subscribed.

@sbomer sbomer requested review from am11 and jkotas May 27, 2026 21:32
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the NativeAOT build of the vendored llvm-libunwind to avoid duplicate symbol conflicts (notably on Android NDK r29) by compiling out libunwind’s public unw_* entrypoints and related exception-dispatch code that NativeAOT doesn’t use, and by routing NativeAOT’s unwind-section discovery through a runtime-owned helper instead of libunwind’s LocalAddressSpace::sThisAddressSpace singleton.

Changes:

  • Add _LIBUNWIND_NATIVEAOT and use it to guard out unw_* APIs (and the LocalAddressSpace::sThisAddressSpace singleton) in libunwind.cpp, plus dependent EHABI exception-dispatch exports in Unwind-EHABI.cpp.
  • Introduce UnwindHelpers::FindUnwindSections() and switch UnixNativeCodeManager to use it (avoiding the now-guarded sThisAddressSpace).
  • Record the patch application in llvm-libunwind-version.txt and enable the new define in the NativeAOT runtime CMake configuration.
Show a summary per file
File Description
src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp Guards EHABI exception-dispatch exports when _LIBUNWIND_NATIVEAOT is set to avoid references to removed __unw_* APIs.
src/native/external/llvm-libunwind/src/libunwind.cpp Guards the public unw_* API surface and the LocalAddressSpace::sThisAddressSpace singleton under _LIBUNWIND_NATIVEAOT.
src/native/external/llvm-libunwind/src/AddressSpace.hpp Guards the LocalAddressSpace::sThisAddressSpace static member declaration under _LIBUNWIND_NATIVEAOT.
src/native/external/llvm-libunwind-version.txt Notes the applied commit associated with this local patch.
src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.h Declares the new UnwindHelpers::FindUnwindSections accessor.
src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp Implements FindUnwindSections by delegating to the existing file-scope _addressSpace.
src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp Replaces use of LocalAddressSpace::sThisAddressSpace.findUnwindSections with UnwindHelpers::FindUnwindSections.
src/coreclr/nativeaot/Runtime/CMakeLists.txt Defines _LIBUNWIND_NATIVEAOT=1 for Unix NativeAOT builds to enable the guarding behavior.

Copilot's findings

  • Files reviewed: 8/8 changed files
  • Comments generated: 0

@am11
Copy link
Copy Markdown
Member

am11 commented May 27, 2026

If it's a negative if !defined(_LIBUNWIND_NATIVEAOT) check everywhere, we can just delete the code it skips. The idea of this local copy is we apply the patches and keep track of them for possible upstream.

Comment thread src/native/external/llvm-libunwind/src/AddressSpace.hpp Outdated
Comment thread src/native/external/llvm-libunwind/src/libunwind.cpp
Comment thread src/native/external/llvm-libunwind/src/libunwind.cpp
@jkotas
Copy link
Copy Markdown
Member

jkotas commented May 27, 2026

we can just delete the code it skips. The idea of this local copy is we apply the patches and keep track of them for possible upstream.

Deleting the code creates more conflicts during updates. We won't be able to upstream the deletion either. I think ifdefing is better.

Comment thread src/native/external/llvm-libunwind-version.txt Outdated
Comment thread src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp Outdated
Comment thread src/coreclr/nativeaot/Runtime/CMakeLists.txt Outdated
Copilot AI review requested due to automatic review settings May 28, 2026 20:08
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

sbomer and others added 2 commits May 28, 2026 16:55
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 <jkotas@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reference fde4a5b (Guard unused llvm-libunwind symbols).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sbomer
Copy link
Copy Markdown
Member Author

sbomer commented May 29, 2026

@jkotas can you please help merge this without squashing?

@jkotas jkotas merged commit ad724f5 into dotnet:main May 29, 2026
164 of 171 checks passed
@github-project-automation github-project-automation Bot moved this to Done in AppModel May 29, 2026
@sbomer sbomer deleted the libunwind-ifdef branch May 29, 2026 16:58
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 11.0-preview6 milestone May 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[NAOT][android] Application linking breaks with NDK r29 because of duplicated libunwind symbols

4 participants