Skip to content

Remove unused code from nativeaot libunwind dependency#128415

Open
sbomer wants to merge 6 commits into
dotnet:mainfrom
sbomer:libunwind-reduce
Open

Remove unused code from nativeaot libunwind dependency#128415
sbomer wants to merge 6 commits into
dotnet:mainfrom
sbomer:libunwind-reduce

Conversation

@sbomer
Copy link
Copy Markdown
Member

@sbomer sbomer commented May 20, 2026

Trying another approach for #121172.

sbomer and others added 3 commits May 18, 2026 09:54
NativeAOT's llvm-libunwind dependency includes many files that are never
compiled or used. This reduces the vendored copy to only what's needed.

Removed source files not compiled by NativeAOT (not in llvm-libunwind.cmake):
- UnwindLevel1.c (zero-cost exception APIs)
- UnwindLevel1-gcc-ext.c (GCC extension APIs)
- Unwind-seh.cpp (SEH unwinding)
- Unwind-sjlj.c (setjmp/longjmp exceptions)
- Unwind-wasm.c (WASM exceptions)
- Unwind_AIXExtras.cpp (AIX-specific)

Removed directories and files not used in the dotnet build:
- test/ (llvm test suite)
- docs/ (llvm documentation)
- cmake/ (standalone CMake modules)
- CMakeLists.txt files (standalone build system)
- .clang-format, libunwind.modulemap

Removed dead _LIBUNWIND_DISABLE_ZERO_COST_APIS define from NativeAOT
CMakeLists.txt - this macro is not referenced anywhere in llvm-libunwind
source. The zero-cost API files (UnwindLevel1.c, UnwindLevel1-gcc-ext.c)
were never compiled in the first place.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude:claude-opus-4.6-1m
NativeAOT uses llvm-libunwind's internal C++ classes directly
(DwarfInstructions, CompactUnwinder, UnwindCursor, LocalAddressSpace)
and does not call any of the public unw_* C API functions defined in
libunwind.cpp. Removing it from the build eliminates 20 globally-visible
symbols that conflict with platform libunwind on Android NDK r29.

The only symbol from libunwind.cpp that NativeAOT references is
LocalAddressSpace::sThisAddressSpace (a static singleton). This is now
defined directly in UnixNativeCodeManager.cpp.

Eliminated symbols: __unw_init_local, __unw_step, __unw_step_stage2,
__unw_get_reg, __unw_set_reg, __unw_get_fpreg, __unw_set_fpreg,
__unw_get_proc_info, __unw_get_proc_name, __unw_resume, __unw_is_fpreg,
__unw_is_signal_frame, __unw_regname, __unw_iterate_dwarf_unwind_cache,
__unw_add_dynamic_fde, __unw_remove_dynamic_fde,
__unw_add_dynamic_eh_frame_section, __unw_remove_dynamic_eh_frame_section,
unw_local_addr_space, and their weak aliases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude:claude-opus-4.6-1m
The static member LocalAddressSpace::sThisAddressSpace conflicts with
the same symbol in Android NDK r29's libunwind.a. Remove the static
member declaration from AddressSpace.hpp and switch
UnixNativeCodeManager.cpp to use the existing _addressSpace instance
from UnwindHelpers.cpp via an extern declaration. Both are instances
of the same stateless type.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude:claude-opus-4.6-1m
@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.

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 reduces the vendored llvm-libunwind footprint used by NativeAOT and adjusts NativeAOT’s unwinding integration to avoid Android link failures caused by duplicate libunwind symbols.

Changes:

  • Removes large portions of upstream llvm-libunwind (tests/docs/CMake scaffolding and several source files) from the repo.
  • Stops building llvm-libunwind/src/libunwind.cpp via src/native/external/llvm-libunwind.cmake and switches NativeAOT’s unwind-section discovery to use a LocalAddressSpace instance defined in UnwindHelpers.cpp.
  • Drops an unused NativeAOT CMake definition related to disabling _Unwind_*-style APIs.
Show a summary per file
File Description
src/native/external/llvm-libunwind/test/unwind_scalable_vectors.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/unw_resume.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/unw_getcontext.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/signal_frame.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/remember_state_leak.pass.sh.s Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/lit.cfg.py Removed upstream lit “canary” config.
src/native/external/llvm-libunwind/test/libunwind_02.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/libunwind_01.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/frameheadercache_test.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/forceunwind.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/floatregister.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/eh_frame_fde_pc_range.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in Removed upstream test config.
src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in Removed upstream test config.
src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in Removed upstream test config.
src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in Removed upstream test config.
src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in Removed upstream test config.
src/native/external/llvm-libunwind/test/configs/ibm-libunwind-shared.cfg.in Removed upstream test config.
src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in Removed upstream test config bridge.
src/native/external/llvm-libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in Removed upstream test config.
src/native/external/llvm-libunwind/test/configs/apple-libunwind-system.cfg.in Removed upstream test config.
src/native/external/llvm-libunwind/test/CMakeLists.txt Removed upstream test suite CMake integration.
src/native/external/llvm-libunwind/test/bad_unwind_info.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/alignment.compile.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/aix_runtime_link.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/aarch64_za_unwind.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/test/aarch64_vg_unwind.pass.cpp Removed upstream libunwind test.
src/native/external/llvm-libunwind/src/UnwindLevel1.c Removed upstream zero-cost EH implementation.
src/native/external/llvm-libunwind/src/UnwindLevel1-gcc-ext.c Removed upstream gcc extension implementation.
src/native/external/llvm-libunwind/src/Unwind-wasm.c Removed upstream wasm EH implementation.
src/native/external/llvm-libunwind/src/Unwind-sjlj.c Removed upstream SJLJ EH implementation.
src/native/external/llvm-libunwind/src/Unwind-seh.cpp Removed upstream SEH EH implementation.
src/native/external/llvm-libunwind/src/Unwind_AIXExtras.cpp Removed upstream AIX extras implementation.
src/native/external/llvm-libunwind/src/CMakeLists.txt Removed upstream libunwind build definition.
src/native/external/llvm-libunwind/src/AddressSpace.hpp Removes LocalAddressSpace::sThisAddressSpace declaration.
src/native/external/llvm-libunwind/include/libunwind.modulemap Removed upstream modulemap.
src/native/external/llvm-libunwind/include/CMakeLists.txt Removed upstream include install CMake.
src/native/external/llvm-libunwind/docs/README.txt Removed upstream docs file.
src/native/external/llvm-libunwind/docs/index.rst Removed upstream docs file.
src/native/external/llvm-libunwind/docs/conf.py Removed upstream docs file.
src/native/external/llvm-libunwind/docs/CMakeLists.txt Removed upstream docs CMake integration.
src/native/external/llvm-libunwind/docs/BuildingLibunwind.rst Removed upstream docs file.
src/native/external/llvm-libunwind/CMakeLists.txt Removed upstream top-level CMake integration.
src/native/external/llvm-libunwind/cmake/Modules/HandleLibunwindFlags.cmake Removed upstream CMake module.
src/native/external/llvm-libunwind/cmake/config-ix.cmake Removed upstream CMake module.
src/native/external/llvm-libunwind/.clang-format Removed upstream formatting config.
src/native/external/llvm-libunwind.cmake Drops src/libunwind.cpp from the NativeAOT libunwind source list.
src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp Switches unwind section discovery to a shared LocalAddressSpace instance.
src/coreclr/nativeaot/Runtime/CMakeLists.txt Removes _LIBUNWIND_DISABLE_ZERO_COST_APIS definition.

Copilot's findings

  • Files reviewed: 52/52 changed files
  • Comments generated: 2

src/Unwind-EHABI.cpp
src/libunwind.cpp
)

Comment on lines +25 to +30
// Use the LocalAddressSpace instance from UnwindHelpers.cpp instead of
// the static member LocalAddressSpace::sThisAddressSpace (which was
// previously defined in libunwind.cpp). This avoids exporting a symbol
// that conflicts with platform libunwind on Android.
extern libunwind::LocalAddressSpace _addressSpace;

1. Guard EHABI zero-cost exception APIs with _LIBUNWIND_DISABLE_ZERO_COST_APIS.
   Unwind-EHABI.cpp's C++ exception dispatch functions (__aeabi_unwind_cpp_pr*,
   _Unwind_RaiseException, unwind_phase1/2, etc.) call __unw_step and other
   public unw_* functions from libunwind.cpp, which is no longer compiled.
   NativeAOT only uses _Unwind_VRS_Interpret from this file. The guard
   compiles out the unused dispatch code, avoiding undefined symbol errors
   on ARM EHABI targets.

2. Replace extern _addressSpace with UnwindHelpers::FindUnwindSections().
   Instead of exposing a cross-TU global with a generic name,
   UnixNativeCodeManager now calls a typed static method on UnwindHelpers
   which internally uses the file-local LocalAddressSpace instance.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude:claude-opus-4.6-1m
@@ -1,116 +0,0 @@
# HandleLibcxxFlags - A set of macros used to setup the flags used to compile
Copy link
Copy Markdown
Member

@jkotas jkotas May 20, 2026

Choose a reason for hiding this comment

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

We do not mind having some unused code under src/native/external to make the updates easy.

If there are large chunks of code (e.g. tests) that are worth deleting, it needs to be noted in https://github.com/dotnet/runtime/blob/main/src/native/external/llvm-libunwind-version.txt

Example of existing file with exclusions https://github.com/dotnet/runtime/blob/main/src/native/external/zlib-ng-version.txt

sbomer and others added 2 commits May 20, 2026 13:41
Delete the zero-cost exception dispatch functions that NativeAOT does
not use: __aeabi_unwind_cpp_pr0/1/2, unwindOneFrame, ProcessDescriptors,
unwind_phase1/2, _Unwind_RaiseException, and related helpers. These
depend on __unw_step and other public unw_* functions from libunwind.cpp
which is no longer compiled.

NativeAOT only uses _Unwind_VRS_Interpret (the ARM EHABI bytecode
interpreter) and decode_eht_entry from this file. The Descriptor::Format
enum is retained as it is referenced by decode_eht_entry.

Reduces Unwind-EHABI.cpp from 1,213 to 303 lines.

Also removes the _LIBUNWIND_DISABLE_ZERO_COST_APIS define that was
re-added in the previous commit, since the code it would have guarded
is now deleted.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude:claude-opus-4.6-1m
logAPIs(), logUnwinding(), and logDWARF() are declared in config.h when
NDEBUG is not defined and were previously implemented in libunwind.cpp.
Since libunwind.cpp is no longer compiled, provide these definitions in
UnwindHelpers.cpp to fix undefined symbols in Debug builds.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude:claude-opus-4.6-1m
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants