Repository navigation
[NAOT][android] Application linking breaks with NDK r29 because of duplicated libunwind symbols #121172
Copy link
Copy link
Description
Description
Attempting to link the .NET for Android NAOT sample breaks when NDK r29 is installed, with the following error (output broken up into lines to make it easier to read):
Android (13989888, +pgo, +bolt, +lto, +mlgo, based on r563880c) clang version 21.0.0 (https://android.googlesource.com/toolchain/llvm-project 5e96669f06077099aa41290cdb4c5e6fa0f59349)
Target: aarch64-unknown-linux-android21
Thread model: posix
InstalledDir: ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin
"~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" -EL
--fix-cortex-a53-843419 -z now -z relro -z max-page-size=16384 --no-rosegment --hash-style=both
--eh-frame-hdr -m aarch64linux -shared
-o bin/Release/net10.0-android/android-arm64/native/NativeAOT.so
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/lib/aarch64-linux-android/21/crtbegin_so.o
-L~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64
-L~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/lib/aarch64-linux-android/21
-L~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/lib/aarch64-linux-android
-L~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/lib
--compress-debug-sections=zlib obj/Release/net10.0-android/android-arm64/native/NativeAOT.o
--version-script=obj/Release/net10.0-android/android-arm64/native/NativeAOT.exports
--export-dynamic
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libSystem.Native.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libSystem.Globalization.Native.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libSystem.IO.Compression.Native.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libSystem.Security.Cryptography.Native.Android.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libbootstrapperdll.o
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libeventpipe-disabled.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libstandalonegc-disabled.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libaotminipal.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libbrotlienc.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libbrotlidec.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libbrotlicommon.a
--build-id=sha1 --as-needed -e 0x0 -ldl -lz -llog -lm -z relro -z now --eh-frame-hdr -z
max-page-size=16384 -soname libNativeAOT.so --error-unresolved-symbols --no-undefined
~/vc/xamarin/xamarin-android-worktrees/ndk-r29/bin/Debug/lib/packs/Microsoft.Android.Runtime.NativeAOT.36.android-arm64/36.1.99/runtimes/android-arm64/native/libnaot-android.release-static-release.a
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_static.a
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
obj/Release/net10.0-android/android-arm64/android/jni_init_funcs.arm64-v8a.o
obj/Release/net10.0-android/android-arm64/android/environment.arm64-v8a.o --discard-all
--gc-sections -T obj/Release/net10.0-android/android-arm64/native/sections.ld
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/libclang_rt.builtins-aarch64-android.a
-l:libunwind.a -ldl -lc
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/libclang_rt.builtins-aarch64-android.a
-l:libunwind.a -ldl
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/lib/aarch64-linux-android/21/crtend_so.o
ld.lld: error: duplicate symbol: __unw_init_local
>>> defined at libunwind.cpp:44 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:44)
>>> libunwind.cpp.o:(__unw_init_local) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_init_local+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: libunwind::LocalAddressSpace::sThisAddressSpace
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(libunwind::LocalAddressSpace::sThisAddressSpace) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.bss._ZN9libunwind17LocalAddressSpace17sThisAddressSpaceE+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_get_reg
>>> defined at libunwind.cpp:99 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:99)
>>> libunwind.cpp.o:(__unw_get_reg) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_get_reg+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_set_reg
>>> defined at libunwind.cpp:114 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:114)
>>> libunwind.cpp.o:(__unw_set_reg) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_set_reg+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_get_fpreg
>>> defined at libunwind.cpp:146 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:146)
>>> libunwind.cpp.o:(__unw_get_fpreg) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_get_fpreg+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_set_fpreg
>>> defined at libunwind.cpp:161 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:161)
>>> libunwind.cpp.o:(__unw_set_fpreg) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_set_fpreg+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_step
>>> defined at libunwind.cpp:197 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:197)
>>> libunwind.cpp.o:(__unw_step) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_step+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_step_stage2
>>> defined at libunwind.cpp:207 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:207)
>>> libunwind.cpp.o:(__unw_step_stage2) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_step_stage2+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_get_proc_info
>>> defined at libunwind.cpp:212 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:212)
>>> libunwind.cpp.o:(__unw_get_proc_info) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_get_proc_info+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_resume
>>> defined at libunwind.cpp:224 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:224)
>>> libunwind.cpp.o:(__unw_resume) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_resume+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_get_proc_name
>>> defined at libunwind.cpp:238 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:238)
>>> libunwind.cpp.o:(__unw_get_proc_name) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_get_proc_name+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_is_fpreg
>>> defined at libunwind.cpp:251 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:251)
>>> libunwind.cpp.o:(__unw_is_fpreg) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_is_fpreg+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_regname
>>> defined at libunwind.cpp:265 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:265)
>>> libunwind.cpp.o:(__unw_regname) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_regname+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_is_signal_frame
>>> defined at libunwind.cpp:270 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:270)
>>> libunwind.cpp.o:(__unw_is_signal_frame) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_is_signal_frame+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_iterate_dwarf_unwind_cache
>>> defined at libunwind.cpp:303 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:303)
>>> libunwind.cpp.o:(__unw_iterate_dwarf_unwind_cache) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_iterate_dwarf_unwind_cache+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_add_dynamic_fde
>>> defined at libunwind.cpp:312 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:312)
>>> libunwind.cpp.o:(__unw_add_dynamic_fde) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_add_dynamic_fde+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_remove_dynamic_fde
>>> defined at libunwind.cpp:331 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:331)
>>> libunwind.cpp.o:(__unw_remove_dynamic_fde) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_remove_dynamic_fde+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_add_dynamic_eh_frame_section
>>> defined at libunwind.cpp:336 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:336)
>>> libunwind.cpp.o:(__unw_add_dynamic_eh_frame_section) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_add_dynamic_eh_frame_section+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: __unw_remove_dynamic_eh_frame_section
>>> defined at libunwind.cpp:358 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:358)
>>> libunwind.cpp.o:(__unw_remove_dynamic_eh_frame_section) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_remove_dynamic_eh_frame_section+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
ld.lld: error: duplicate symbol: unw_local_addr_space
>>> defined at libunwind.cpp:38 (/__w/1/s/src/runtime/src/native/external/llvm-libunwind/src/libunwind.cpp:38)
>>> libunwind.cpp.o:(unw_local_addr_space) in archive ~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.data.unw_local_addr_space+0x0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64/libunwind.a
I hoped that passing -unwindlib=none would make linking work, but unfortunately, it causes the following error:
Android (13989888, +pgo, +bolt, +lto, +mlgo, based on r563880c) clang version 21.0.0 (https://android.googlesource.com/toolchain/llvm-project 5e96669f06077099aa41290cdb4c5e6fa0f59349)
Target: aarch64-unknown-linux-android21
Thread model: posix
InstalledDir: ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin
"~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" -EL
--fix-cortex-a53-843419 -z now -z relro -z max-page-size=16384 --no-rosegment --hash-style=both
--eh-frame-hdr -m aarch64linux -shared -o
bin/Release/net10.0-android/android-arm64/native/NativeAOT.so
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/lib/aarch64-linux-android/21/crtbegin_so.o
-L~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/aarch64
-L~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/lib/aarch64-linux-android/21
-L~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/lib/aarch64-linux-android
-L~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/lib
--compress-debug-sections=zlib obj/Release/net10.0-android/android-arm64/native/NativeAOT.o
--version-script=obj/Release/net10.0-android/android-arm64/native/NativeAOT.exports
--export-dynamic
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libSystem.Native.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libSystem.Globalization.Native.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libSystem.IO.Compression.Native.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libSystem.Security.Cryptography.Native.Android.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libbootstrapperdll.o
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libRuntime.WorkstationGC.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libeventpipe-disabled.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libstandalonegc-disabled.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libaotminipal.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libbrotlienc.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libbrotlidec.a
~/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native/libbrotlicommon.a
--build-id=sha1 --as-needed -e 0x0 -ldl -lz -llog -lm -z relro -z now --eh-frame-hdr -z
max-page-size=16384 -soname libNativeAOT.so --error-unresolved-symbols --no-undefined
~/vc/xamarin/xamarin-android-worktrees/ndk-r29/bin/Debug/lib/packs/Microsoft.Android.Runtime.NativeAOT.36.android-arm64/36.1.99/runtimes/android-arm64/native/libnaot-android.release-static-release.a
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_static.a
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
obj/Release/net10.0-android/android-arm64/android/jni_init_funcs.arm64-v8a.o
obj/Release/net10.0-android/android-arm64/android/environment.arm64-v8a.o --discard-all
--gc-sections -T obj/Release/net10.0-android/android-arm64/native/sections.ld
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/libclang_rt.builtins-aarch64-android.a
-ldl -lc
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/libclang_rt.builtins-aarch64-android.a
-ldl
~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/lib/aarch64-linux-android/21/crtend_so.o
ld.lld: error: undefined symbol: _Unwind_Resume
>>> referenced by stdexcept:0 (out/lib/device-libcxx-aarch64-ndk-cxx/include/c++/v1/stdexcept:0)
>>> hash.cpp.o:(std::__ndk1::__throw_overflow_error[abi:ne210000](char const*)) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_static.a
>>> referenced by thread.cpp:0 (out/llvm-project/libcxx/src/thread.cpp:0)
>>> thread.cpp.o:(std::__ndk1::__thread_local_data()) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_static.a
>>> referenced by call_once.cpp:0 (out/llvm-project/libcxx/src/call_once.cpp:0)
>>> call_once.cpp.o:(std::__ndk1::__call_once(unsigned long volatile&, void*, void (*)(void*))) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_static.a
>>> referenced 198 more times
ld.lld: error: undefined symbol: _Unwind_RaiseException
>>> referenced by cxa_exception.cpp:295 (out/llvm-project/libcxxabi/src/cxa_exception.cpp:295)
>>> cxa_exception.cpp.o:(__cxa_throw) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
ld.lld: error: undefined symbol: _Unwind_SetGR
>>> referenced by cxa_personality.cpp:556 (out/llvm-project/libcxxabi/src/cxa_personality.cpp:556)
>>> cxa_personality.cpp.o:(__gxx_personality_v0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
>>> referenced by cxa_personality.cpp:558 (out/llvm-project/libcxxabi/src/cxa_personality.cpp:558)
>>> cxa_personality.cpp.o:(__gxx_personality_v0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
>>> referenced by cxa_personality.cpp:556 (out/llvm-project/libcxxabi/src/cxa_personality.cpp:556)
>>> cxa_personality.cpp.o:(__gxx_personality_v0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
>>> referenced 1 more times
ld.lld: error: undefined symbol: _Unwind_SetIP
>>> referenced by cxa_personality.cpp:560 (out/llvm-project/libcxxabi/src/cxa_personality.cpp:560)
>>> cxa_personality.cpp.o:(__gxx_personality_v0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
>>> referenced by cxa_personality.cpp:560 (out/llvm-project/libcxxabi/src/cxa_personality.cpp:560)
>>> cxa_personality.cpp.o:(__gxx_personality_v0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
ld.lld: error: undefined symbol: _Unwind_GetLanguageSpecificData
>>> referenced by cxa_personality.cpp:626 (out/llvm-project/libcxxabi/src/cxa_personality.cpp:626)
>>> cxa_personality.cpp.o:(__gxx_personality_v0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
ld.lld: error: undefined symbol: _Unwind_GetIP
>>> referenced by cxa_personality.cpp:641 (out/llvm-project/libcxxabi/src/cxa_personality.cpp:641)
>>> cxa_personality.cpp.o:(__gxx_personality_v0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
ld.lld: error: undefined symbol: _Unwind_GetRegionStart
>>> referenced by cxa_personality.cpp:644 (out/llvm-project/libcxxabi/src/cxa_personality.cpp:644)
>>> cxa_personality.cpp.o:(__gxx_personality_v0) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
ld.lld: error: undefined symbol: _Unwind_DeleteException
>>> referenced by cxa_exception.cpp:586 (out/llvm-project/libcxxabi/src/cxa_exception.cpp:586)
>>> cxa_exception.cpp.o:(__cxa_end_catch) in archive ~/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++abi.a
The problem, I think, stems from the fact that libRuntime.WorkstationGC.a exports libunwind symbols where it should keep them hidden:
microsoft.netcore.app.runtime.nativeaot.android-arm64/10.0.0/runtimes/android-arm64/native$ nm -C libRuntime.WorkstationGC.a | grep __unw
0000000000000000 T __unw_add_dynamic_eh_frame_section
0000000000000000 T __unw_add_dynamic_fde
0000000000000000 T __unw_get_fpreg
0000000000000000 T __unw_get_proc_info
0000000000000000 T __unw_get_proc_name
0000000000000000 T __unw_get_reg
0000000000000000 T __unw_get_save_loc
0000000000000000 T __unw_init_local
0000000000000000 T __unw_is_fpreg
0000000000000000 T __unw_is_signal_frame
0000000000000000 T __unw_iterate_dwarf_unwind_cache
0000000000000000 T __unw_regname
0000000000000000 T __unw_remove_dynamic_eh_frame_section
0000000000000000 T __unw_remove_dynamic_fde
0000000000000000 T __unw_resume
0000000000000000 T __unw_set_fpreg
0000000000000000 T __unw_set_reg
0000000000000000 T __unw_step
0000000000000000 T __unw_step_stage2
0000000000000000 T __unw_getcontextNDK r29 uses LLVM 21
Reproduction Steps
- Check out the https://github.com/dotnet/android/
dev/grendel/ndk-r29branch locally (from this PR) - Go to the checked-out directory and run:
- On Linux/macOS:
make prepare all - On Windows:
build.cmd
- On Linux/macOS:
- After the build completes, go to the
samples/NativeAOTdirectory and run- On Linux/macOS:
../../dotnet-local.sh build -c Release -bl - On Windows:
..\..\dotnet-local.cmd build -c Release -bl
- On Linux/macOS:
Expected behavior
Application should be linked without errors
Actual behavior
Application linking fails with errors
Regression?
No response
Known Workarounds
No known workarounds
Configuration
- .NET version: 10.0.100
- OS: not dependent on the operating system
- Architecture: not dependent on the architecture
- Specific to building a .NET for Android app using NativeAOT with NDK r29
Other information
No response
Reactions are currently unavailable
Metadata
Metadata
Assignees
Type
Projects
- StatusShow more project fieldsNo status
Activity
MichalStrehovsky commentedon Oct 29, 2025
This does look like we should be hiding symbols, but the issue doesn't repro with a simple hello world (I didn't try the sample in the Android repo, just
dotnet new consolefollowed by adotnet publish -r linux-bionic-arm64 -p:DisableUnsupportedError=true -p:PublishAotUsingRuntimePack=true).I wonder if you'd be able to work around by getting these two lines out of the picture:
The native AOT runtime itself doesn't depend on the C++ stdlib. Does dotnet/android bring the dependency, or is the inclusion of this just accidental? The
clanginvocation for the above console app I tried doesn't end up with libc++.dotnet-policy-service commentedon Oct 29, 2025
Tagging subscribers to 'arch-android': @vitek-karas, @simonrozsival, @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.
dotnet-policy-service commentedon Oct 29, 2025
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.
grendello commentedon Oct 29, 2025
@MichalStrehovsky Android runtime needs
libc++, yes, can't remove the dependency alas.grendello commentedon Oct 29, 2025
@MichalStrehovsky note that the build works with NDK r28c which uses an older version of LLVM, so it's a (kind of) regression.
Fix building the repo with Android NDK R29
MichalStrehovsky commentedon Oct 30, 2025
I looked at the duplicate symbols and they are already HIDDEN. I'm not sure if there's a way to solve this besides prefixing all symbols in our copy of libunwind. Looks like all symbols share the same "namespace" and it's not possible to make symbols local to the static library. They're either local to object file, or pollute the global namespace.
As a workaround, linking works with libc++_shared.so.
Looks like NDK r29 newly comes with libunwind.h so we might be able to use that instead of our own copy (NDK 27c doesn't have it) and then we'd avoid the duplicate. I'm not sure how much fragility would that introduce though (if end users build with a different NDK than we did). It probably won't work.
When I replace libc++_static.a in the clang invocation with the libstdc++compat.a shim that comes with the native AOT runtime, I see about 40 undefined symbols, all of them from libnaot-android.release-static-release.a that we control. We should consider applying #76705 treatment to that code. We'd likely get size wins, especially with a statically linked libc++. We even saw a tiny size win with a dynamically linked libc++ and that one was a bit surprising. This would likely work around the problem too since libc++ is the one that depends on libunwind.
3 remaining items
MichalStrehovsky commentedon Oct 30, 2025
We're in the same situation with native AOT runtime (native AOT is a subset of the CoreCLR VM). We share a lot of code with the full runtime. Full runtime uses libc++. Native AOT doesn't.
Ballpark estimate (comparing size with libc++_static vs libc++_shared) is that statically linking libc++ adds 0.5 MB to the Android NAOT sample. This is currently 10% of the sample. But NAOT sample is currently deoptimized when it comes to size due to https://github.com/dotnet/android/blob/ea05d7630612a6fc4d456f3278f3846a806c144c/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets#L113-L114 (I discussed that with the Johnatans on Discord last year). Once that's fixed, I expect NAOT sample to get even smaller (would not be surprised if it's 10s of percent smaller, depending on app). So the question will be "How much work are we willing to do for a 10% saving?".
We'd have to statically link it. For libicu specifically, the NDK only has libicu.so, so I think we're good there.
sbomer commentedon Dec 16, 2025
@grendello are you still able to repro this? I am not hitting the error following your instructions.
sbomer commentedon Jan 5, 2026
I was able to repro this on a fresh vm. I have a workaround that localizes these libunwind symbols, but then I get a similar failure:
which seems to be caused by the compiler emitting some symbol definitions for these into the application object file (and these conflict with the definitions in libRuntime.WorkStationGC.a):
Is that expected @MichalStrehovsky? It looks like a bug to me.
MichalStrehovsky commentedon Jan 7, 2026
Is it possible you're using CoreLib from .NET 10, and libRuntime.WorkStationGC.a from .NET 11?
RhCollectis implemented in managed code in .NET 10 and part of NativeAOT.o, but it's in native code in .NET 11 and part of libRuntime.WorkStationGC.a.(I don't see a definition for the symbol in the object files generated from ILC in main, but do see them for .NET 10. Turns out the reason is #118970.)
sbomer commentedon Jan 7, 2026
Thanks @MichalStrehovsky, that was the issue. After ensuring all bits come from .NET 11, I no longer get that failure. My workaround was using
objcopy --localize-hidden, but that now hits undefined symbols (logDWARF is extern, so --localize-hidden breaks the extern reference at link time). I can work around this by localizing individual symbols with--localize-symbols: https://github.com/dotnet/runtime/compare/main...sbomer:runtime:localizeLibunwind?expand=1The increasingly fragile workarounds reflect the fact that libunwind was not meant to be statically linked multiple times into the same binary. I don't think we should go this route - the fix should be to remove the
libc++dependency from the android nativeaot runtime.sbomer commentedon May 19, 2026
While android is working on removing the libc++ dependency, I now think we should also prevent the conflict on our side. We're not really using libunwind as an unwinder - we're really just using its internals for limited DWARF debug info parsing. Ideally this dependency wouldn't block the final application link from including a libc++ dependency.
I explored a few approaches:
--localize-hiddenon the entirelibRuntime.WorkstationGC.aarchive - this localizes too much (including symbols that need to be global at application link time.--localize-symbolson a specific set of symbols (see earlier comment) - works, but is fragile.--localize-hiddenon the libunwind object before it goes into the runtime archive - initially I hit some problems with thelogDWARFsymbol, but that's not present in release builds. I think this should work to fix the android problem.I think we should do 3) for now. We might also be able to reduce the number of conflicts by removing some dead code that's in the runtime copy of libunwind but not actually used at link time. But I don't think that gets rid of all of the symbols, so we would still need some other workaround.
We also talked about rewriting this dependency in managed code. I intend to keep exploring that in a follow-up but don't want to block on that.
sbomer commentedon May 20, 2026
Nope, still doesn't work - the problem is that some symbols need to be global so they can be referenced from runtime code, but are also provided by the NDK's libunwind. I think the ELF linking model fundamentally doesn't support this (a runtime static archive with cross-object references to symbols that are also provided by a separate library at application link time).
So I believe we can only fix this on our side by introducing a separate namespace for the symbols or avoiding the dependency entirely.
am11 commentedon May 21, 2026
Alternatively, we could align NativeAOT with the coreclr/pal plan in #128422 by adopting HP-libunwind and removing llvm-libunwind. Since @jkotas previously suggested converging these paths, using this issue as a precursor makes it a great time to do so.
Guard unused llvm-libunwind symbols to avoid duplicates on Android (#…