Repository navigation
[NativeAOT] Stop linking Android NDK libunwind into applications #12146
Description
Summary
Stop linking or extracting the Android NDK's libunwind.a into NativeAOT application links.
This is the parent goal for #12139. Removing libc++/libc++abi is a prerequisite because libc++abi is currently the primary built-in _Unwind_* consumer that causes the NDK archive to be extracted.
NativeAOT's private LLVM-libunwind implementation must remain. It is required for managed stack walking, exception handling, GC, stack traces, profiling, and related runtime services.
Motivation
Android NativeAOT currently has two unwind implementations in the final link closure:
- NativeAOT's private implementation in
libRuntime.WorkstationGC.a; - the Android NDK implementation in
libunwind.a.
With .NET 10.0.9 and NDK 29.0.14206865, both archives export the same global symbols. Two independent dotnet/android PR builds reproduce the resulting linker failure:
- [Native] Add printf-style native logging #12140 —
dotnet-androidbuild #1513800 - [NativeAOT] Reduce owning C++ standard library state #12142 —
dotnet-androidbuild #1513910
Both fail:
DotNetInstallAndRunMinorAPILevels(True, "net10.0-android36.1", NativeAOT)
ld.lld reports duplicate definitions including:
__unw_init_local__unw_get_reg__unw_step__unw_resumeunw_local_addr_space
The .NET 11 fix in dotnet/runtime#128927 privatizes NativeAOT's symbols and remains valuable defense-in-depth. It does not make the second unwind implementation useful, however. Avoiding the NDK archive entirely removes duplicate code from the link closure and prevents this class of collision for runtime versions without privatization.
Dependency and sequence
- Complete [NativeAOT] Remove libc++ from libNativeAOT.so #12139 to remove
libc++_static.aandlibc++abi.afrom NativeAOT application links. - Capture the complete final link response for every supported ABI after libc++ removal.
- Identify every remaining
_Unwind_*consumer, including compiler runtime objects and supported third-party native libraries. - Prove whether the NDK
libunwind.ainput is unused without relying only on linker garbage collection. - Remove the NDK
libunwind.ainput from both the workload NativeLinker path and the legacy NDK/clang path. - Stop packaging any NDK libunwind payload that is no longer required specifically by NativeAOT.
- Add regression coverage that rejects an NDK
libunwind.aentry in NativeAOT link responses. - Measure the resulting native-library and APK size reduction.
Likely implementation surfaces include:
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targetssrc/Xamarin.Android.Build.Tasks/Utilities/NativeRuntimeComponents.cssrc/androidsdk/androidsdk.targetsbuild-tools/create-packs/Microsoft.Android.Runtime.proj
Validation
For arm64, arm32, x64, and x86 where supported, in Debug and Release:
- final link response does not contain the Android NDK's
libunwind.a; - final
libNativeAOT.sohas no unresolved_Unwind_*requirements; - NativeAOT's private unwind implementation remains present and usable;
- managed exceptions and native-to-managed exception transitions work;
- GC stack walking and repeated GC bridge processing work;
- managed stack traces, profiling, and crash reporting work;
- workload NativeLinker and legacy linker paths both succeed;
- supported third-party native-library scenarios continue to link.
Non-goals
- Removing NativeAOT's private libunwind implementation.
- Reverting or replacing Privatize NativeAOT libunwind symbols runtime#128927.
- Removing an NDK unwind dependency before [NativeAOT] Remove libc++ from libNativeAOT.so #12139 or before the complete link closure proves it is unused.
- Assuming all third-party native libraries can operate without
_Unwind_*.
Related
- [NativeAOT] Remove libc++ from libNativeAOT.so #12139 — prerequisite: remove libc++ from
libNativeAOT.so - Drop libc++ from Android NativeAOT linking #11311 — previous libc++ removal prototype
- [NAOT][android] Application linking breaks with NDK r29 because of duplicated libunwind symbols runtime#121172 — NDK r29 duplicate-libunwind discussion
- Privatize NativeAOT libunwind symbols runtime#128927 — privatize NativeAOT libunwind symbols in .NET 11
Activity
[NativeAOT] Stop linking and shipping libc++ and libunwind (#12523)