Skip to content

[iOS] .NET 9.0.13 broke NativeAOT builds with classic linker when AesGcm is used #124609

Open

Description

@filipnavara

There's a Swift shim in libSystem.Security.Cryptography.Native.Apple.a. The build tools were likely upgraded between .NET 9.0.12 an .NET 9.0.13 which resulted in additional dependencies inside the Swift shim:

                 U __swift_FORCE_LOAD_$_swiftXPC
00000000000022d0 S __swift_FORCE_LOAD_$_swiftXPC_$_pal_swiftbindings
                 U __swift_FORCE_LOAD_$_swift_Builtin_float
00000000000022a8 S __swift_FORCE_LOAD_$_swift_Builtin_float_$_pal_swiftbindings
                 U __swift_FORCE_LOAD_$_swift_errno
0000000000002270 S __swift_FORCE_LOAD_$_swift_errno_$_pal_swiftbindings
                 U __swift_FORCE_LOAD_$_swift_math
00000000000022a0 S __swift_FORCE_LOAD_$_swift_math_$_pal_swiftbindings
                 U __swift_FORCE_LOAD_$_swift_signal
0000000000002278 S __swift_FORCE_LOAD_$_swift_signal_$_pal_swiftbindings
                 U __swift_FORCE_LOAD_$_swift_stdio
0000000000002298 S __swift_FORCE_LOAD_$_swift_stdio_$_pal_swiftbindings
                 U __swift_FORCE_LOAD_$_swift_time
0000000000002288 S __swift_FORCE_LOAD_$_swift_time_$_pal_swiftbindings
                 U __swift_FORCE_LOAD_$_swiftsys_time
0000000000002280 S __swift_FORCE_LOAD_$_swiftsys_time_$_pal_swiftbindings
                 U __swift_FORCE_LOAD_$_swiftunistd
0000000000002290 S __swift_FORCE_LOAD_$_swiftunistd_$_pal_swiftbindings

The new Apple linker has some logic to handle some backwards compatibility but that doesn't work with classic linker. The classic linker fails to compile the project now:

 /usr/local/share/dotnet/packs/Microsoft.iOS.Sdk.net9.0_26.0/26.0.9785/targets/Xamarin.Shared.Sdk.targets(1835,3): error : 
      clang++ exited with code 1:
      0  0x100d81788  __assert_rtn + 160
      1  0x100d84570  ld::tool::SymbolTableAtom<x86_64>::classicOrdinalForProxy(ld::Atom const*) (.cold.3) + 0
      2  0x100cbbdb0  ld::tool::SymbolTableAtom<x86_64>::classicOrdinalForProxy(ld::Atom const*) + 172
      3  0x100cbcc24  ld::tool::SymbolTableAtom<arm64>::addImport(ld::Atom const*, ld::tool::StringPoolAtom*) + 140
      4  0x100cbe508  ld::tool::SymbolTableAtom<arm64>::encode() + 396
      5  0x100cb03b0  ___ZN2ld4tool10OutputFile20buildLINKEDITContentERNS_8InternalE_block_invoke.413 + 36
      6  0x18814ca28  _dispatch_call_block_and_release + 32
      7  0x1881664b0  _dispatch_client_callout + 16
      8  0x188183d9c  _dispatch_channel_invoke.cold.9 + 76
      9  0x18815eadc  _dispatch_root_queue_drain + 708
      10  0x18815f120  _dispatch_worker_thread2 + 184
      11  0x188303e84  _pthread_wqthread + 232
      A linker snapshot was created at:
      	/tmp/AesGcmAppleNAOT-2026-02-19-191403.ld-snapshot
      ld: Assertion failed: (it != _dylibToOrdinal.end()), function dylibToOrdinal, file OutputFile.cpp, line 5196.

We cannot use the new linker due to #119380.

Minimal repro:
AesGcmAppleNAOT.zip - Run dotnet publish

The repro simply uses the AesGcm class which depends on the Swift shim. For simplicity, any code like this is sufficient to reference the class and the related shims:

using (var aes = new AesGcm(new byte[32], 16))
    aes.Encrypt([], [], [], [], []);

The project includes global.json which pins the SDK version to 9.0.311. Downgrading to 9.0.310 (9.0.12 runtime) makes the error go away.

Minimal supported platform version is set with <SupportedOSPlatformVersion>15.0</SupportedOSPlatformVersion>. Raising it to 18.0 also makes the problem go away because the OS deployed Swift version is new enough.

Finally, <_UseClassicLinker>true</_UseClassicLinker> (dotnet/macios workload) switch is used to force the usage of the old linker.

Activity

  1. dotnet-policy-service commented on Feb 19, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to 'os-ios': @vitek-karas, @kotlarmilos, @steveisok, @akoeplinger
    See info in area-owners.md if you want to be subscribed.

  2. dotnet-policy-service commented on Feb 19, 2026

    @dotnet-policy-service
    Contributor

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

  3. filipnavara commented on Feb 19, 2026

    @filipnavara
    MemberAuthor

    Presumably we may need to tweak something like the -runtime-compatibility-version none option if the build tools are updated between patch releases:

    COMMAND xcrun swiftc -emit-object -static -parse-as-library -enable-library-evolution ${SWIFT_COMPILER_ERRORS_FLAG} -gline-tables-only ${SWIFT_OPTIMIZATION_FLAG} -runtime-compatibility-version none ${SWIFT_SDK_FLAG} -target ${SWIFT_COMPILER_TARGET} ${CMAKE_CURRENT_SOURCE_DIR}/pal_swiftbindings.swift -o pal_swiftbindings.o

    I tried using -runtime-compatibility-version 5.0 -disable-autolinking-runtime-compatibility -disable-autolinking-runtime-compatibility-concurrency -disable-autolinking-runtime-compatibility-dynamic-replacements which builds. However, I cannot quite reproduce the same build output as in the precompiled runtime artifacts in the first place so I cannot easily verify whether it did the right thing or not.

    (Managed to reproduce the broken build output with Xcode 16.4 and the suggestion above doesn't help)

  4. dotnet-policy-service commented on Feb 19, 2026

    @dotnet-policy-service
    Contributor

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

  5. akoeplinger commented on Feb 20, 2026

    @akoeplinger
    Member

    Yes we noticed this in #120589 (comment), but we have no choice but to move forward on the macOS image we use.

    Just to confirm, you're using a newer Xcode but just the old linker?

  6. akoeplinger commented on Feb 20, 2026

    @akoeplinger
    Member

    I tried a lot of similar things like you mentioned to workaround back then but I couldn't get the swift shims to stop being injected, it'd be awesome if you find something :)

  7. filipnavara commented on Feb 20, 2026

    @filipnavara
    MemberAuthor

    Just to confirm, you're using a newer Xcode but just the old linker?

    Yep, Xcode 26.2.

  8. akoeplinger commented on Feb 20, 2026

    @akoeplinger
    Member

    Hmm ok, that's another angle that wasn't apparent in #120589

    but we have no choice but to move forward on the macOS image we use

    that's not completely true, for 8.0/9.0 we could theoretically move back to the macos-14 image which is still available for a couple more months (assuming whatever Xcode is there doesn't inject the new shims). not sure how viable that is though

  9. 8 remaining items

  10. dotnet-policy-service commented on Apr 13, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @dotnet/runtime-infrastructure
    See info in area-owners.md if you want to be subscribed.

  11. added this to the 11.0.0 milestone on Apr 14, 2026
  12. removed
    untriagedNew issue has not been triaged by the area owner
    on Apr 14, 2026
  13. agocke commented on Apr 18, 2026

    @agocke
    Member

    So if we had Xcode 26 on our build machines, would that work?

  14. filipnavara commented on Apr 18, 2026

    @filipnavara
    MemberAuthor

    So if we had Xcode 26 on our build machines, would that work?

    If it was used for the build then yes. (Xcode 26.something is available on the image)

    I suppose the issue is partly to do some targeted small change vs. switching the whole build to use newer Xcode.

  15. JulieLeeMSFT commented on Jul 10, 2026

    @JulieLeeMSFT
    Member

    @akoeplinger, assigning this issue to you. Please triage further if it needs to be pushed out.

  16. akoeplinger commented on Jul 14, 2026

    @akoeplinger
    Member

    Moving to 12.0

  17. modified the milestones: 11.0.0, 12.0.0 on Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions