[iOS] .NET 9.0.13 broke NativeAOT builds with classic linker when AesGcm is used
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
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::classicOrdinalForProxy(ld::Atom const*) (.cold.3) + 0
2 0x100cbbdb0 ld::tool::SymbolTableAtom::classicOrdinalForProxy(ld::Atom const*) + 172
3 0x100cbcc24 ld::tool::SymbolTableAtom::addImport(ld::Atom const*, ld::tool::StringPoolAtom*) + 140
4 0x100cbe508 ld::tool::SymbolTableAtom::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](https://github.com/user-attachments/files/25424151/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:
```csharp
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 `15.0`. Raising it to `18.0` also makes the problem go away because the OS deployed Swift version is new enough.
Finally, `<_UseClassicLinker>true` (dotnet/macios workload) switch is used to force the usage of the old linker.
Contributor guide
Assessment
This issue has not been assessed yet.