Skip to content

[release/10.0][Android NativeAOT] NDK r29 duplicate libunwind symbols remain in servicing packages #12138

Description

@simonrozsival

Description

The Android NativeAOT + NDK r29 duplicate-libunwind failure fixed on main by dotnet/runtime#128927 is still present in .NET 10 servicing packages, including 10.0.10.

This is now failing dotnet/android PR validation in:

DotNetInstallAndRunMinorAPILevels(
    True,
    "net10.0-android36.1",
    NativeAOT)

The arm64 application link fails with 20 duplicate symbols between:

Microsoft.NETCore.App.Runtime.NativeAOT.android-arm64/10.0.9/
    runtimes/android-arm64/native/libRuntime.WorkstationGC.a

Android NDK 29.0.14206865/
    .../lib/clang/21/lib/linux/aarch64/libunwind.a

Representative errors:

ld.lld : error : duplicate symbol: __unw_init_local
>>> defined at libunwind.cpp:44
>>> libunwind.cpp.o:(__unw_init_local)
>>>     in libRuntime.WorkstationGC.a
>>> defined at libunwind.cpp
>>> libunwind.cpp.o:(.text.__unw_init_local+0x0)
>>>     in NDK .../aarch64/libunwind.a

ld.lld : error : duplicate symbol: unw_local_addr_space
clang : error : linker command failed with exit code 1
Microsoft.NETCore.Native.targets(389,5): error MSB3073

The complete set of duplicate symbols observed in both failures is:

__unw_add_dynamic_eh_frame_section
__unw_add_dynamic_fde
__unw_get_fpreg
__unw_get_proc_info
__unw_get_proc_name
__unw_get_reg
__unw_init_local
__unw_is_fpreg
__unw_is_signal_frame
__unw_iterate_dwarf_unwind_cache
__unw_regname
__unw_remove_dynamic_eh_frame_section
__unw_remove_dynamic_fde
__unw_resume
__unw_set_fpreg
__unw_set_reg
__unw_step
__unw_step_stage2
libunwind::LocalAddressSpace::sThisAddressSpace
unw_local_addr_space

Recent CI history

I scanned all 76 dotnet/android PR builds from the last three days, including superseded and retried builds. Azure Test results contained this exact failed test in two builds:

Build PR Result
1513118 #12121 Initial run and auto-retry both failed; build failed
1512416 #12130 Initial run and auto-retry both failed; stage retry is running

Both failures have the same configuration:

Component Version
TFM net10.0-android36.1
Runtime NativeAOT, Release
RID android-arm64 (x64 link succeeds)
Microsoft.DotNet.ILCompiler 10.0.9
Microsoft.NETCore.App.Runtime.NativeAOT.android-arm64 10.0.9
Microsoft.Android.Runtime.NativeAOT.36.android-arm64 36.1.69
NDK 29.0.14206865
clang/lld 21.0.0
Android link target aarch64-linux-android21

For comparison, the exact same parameterized test passed in:

The two failures ran on hosted image macos-15/20260715.0340.1; the confirmed passes ran on macos-15/20260629.0276.1. Both images document NDK r29 and ANDROID_NDK_LATEST_HOME pointing to it, so the exact image-level trigger is not yet clear. The product-level conflict is nevertheless the same as dotnet/runtime#121172.

Existing fix and servicing gap

dotnet/runtime#121172 was closed by dotnet/runtime#128927:

d553195ce056de3b309d3f51d558bfe80f6cf911
Privatize NativeAOT libunwind symbols

That commit is on main but is not in release/10.0, and I could not find a release/10.0 backport PR.

Package inspection confirms the gap:

Microsoft.NETCore.App.Runtime.NativeAOT.android-arm64 10.0.9
  nm -g libRuntime.WorkstationGC.a:
    T __unw_get_reg
    T __unw_init_local
    D unw_local_addr_space

Microsoft.NETCore.App.Runtime.NativeAOT.android-arm64 10.0.10
  nm -g libRuntime.WorkstationGC.a:
    T __unw_get_reg
    T __unw_init_local
    D unw_local_addr_space

Microsoft.NETCore.App.Runtime.NativeAOT.android-arm64 11.0.0-preview.7.26360.111
  nm -g: no matches
  nm:
    t __unw_get_reg
    t __unw_init_local
    d unw_local_addr_space

The lowercase symbol types in the .NET 11 package show that dotnet/runtime#128927 correctly made the symbols local. Both current .NET 10 packages still export them globally from the static archive.

Requested action

Please consider backporting dotnet/runtime#128927 (or an equivalent safe fix) to release/10.0 so a future .NET 10 servicing release can link Android NativeAOT apps with NDK r29.

If a servicing backport is not feasible, guidance on the supported workaround would help dotnet/android decide whether to pin the .NET 10 compatibility test to NDK r28.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageIssues that need to be assigned.

    Type

    No type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions