Repository navigation
IL Linker Intrinsics + Marshal Methods, oh my! #8155
Description
Activity
- addedArea: App RuntimeIssues in `libmonodroid.so`.Issues in `libmonodroid.so`.needs-triageIssues that need to be assigned.Issues that need to be assigned.
on Jun 28, 2023 If I update
android.csprojto contain:<RuntimeIdentifiers>android-x64;android-arm64</RuntimeIdentifiers>
i.e. only 64-bit platforms, then
ikdasm obj/Release/net8.0-android/android-arm64/linked/shrunk/androidlib.dllshows thatIntPtr.Sizewas inlined to 8, as expected.If I remove use of marshal methods from
androidlibby removingMyRunner.javaand updatingClass1.csto just useIntPtr.Size(while keeping trimming enabled):namespace androidlib; public class Class1 { public static readonly bool Is64Bit = IntPtr.Size >= 8; }
Then the resulting app IL is as expected:
% find obj -iname androidlib.dll | xargs shasum 289d3b268c35fc56fe28ee1658845e66666332f4 obj/Release/net8.0-android/android-arm/linked/shrunk/androidlib.dll 289d3b268c35fc56fe28ee1658845e66666332f4 obj/Release/net8.0-android/android-arm/linked/androidlib.dll 289d3b268c35fc56fe28ee1658845e66666332f4 obj/Release/net8.0-android/android-x86/linked/shrunk/androidlib.dll 289d3b268c35fc56fe28ee1658845e66666332f4 obj/Release/net8.0-android/android-x86/linked/androidlib.dll a1da91d2d5e9ca6b38d8a5670bb16e9f06a86a9a obj/Release/net8.0-android/android-arm64/linked/shrunk/androidlib.dll a1da91d2d5e9ca6b38d8a5670bb16e9f06a86a9a obj/Release/net8.0-android/android-arm64/linked/androidlib.dll a1da91d2d5e9ca6b38d8a5670bb16e9f06a86a9a obj/Release/net8.0-android/android-x64/linked/shrunk/androidlib.dll a1da91d2d5e9ca6b38d8a5670bb16e9f06a86a9a obj/Release/net8.0-android/android-x64/linked/androidlib.dll32-bit assemblies differ from 64-bit assemblies, and:
.field public static initonly bool Is64Bit .method private hidebysig specialname rtspecialname static void .cctor() cil managed { // Code size 17 (0x11) .maxstack 8 IL_0000: ldc.i4 0x8 IL_0005: ldc.i4.8 IL_0006: clt IL_0008: ldc.i4.0 IL_0009: ceq IL_000b: stsfld bool androidlib.Class1::Is64Bit IL_0010: ret } // end of method Class1::.cctoron the 64-bit
androidlib.dll,IntPtr.Sizeis inlined to 8.Disabling LLVM marshal methods by setting
$(AndroidEnableMarshalMethods)=False is another workaround, and will result in per-arch assemblies.Associated Discord conversation: https://discord.com/channels/732297728826277939/732297837953679412/1123700509585440810
- added a commit that references this issue
on Jun 28, 2023 - added a commit that references this issue
on Jul 13, 2023 - removedneeds-triageIssues that need to be assigned.Issues that need to be assigned.
on Jan 9, 2024 - added a commit that references this issue
on Jan 18, 2024 - added a commit that references this issue
on Mar 15, 2024 I believe this was fixed by #8253.
- locked and limited conversation to collaborators
on Oct 27, 2024
Android application type
.NET Android (net7.0-android, etc.)
Affected platform version
.NET 8 in main (ff6eb66)
Description
The .NET Linker will apply optimizations that can result in per-ABI assemblies, see e.g. https://github.com/dotnet/runtime/blob/318c0e6708ced35180fd5218170f82246e2f2bac/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.64bit.xml
LLVM Marshal Methods (8bc7a3e) updates assemblies.
What happens if we mix these together?
Steps to Reproduce
See
intrinsics+mm.zip, which is:Create an Android Class Library project:
dotnet new androidlib -n androidlibTo (1), add
MyRunner.java, which contains avirtual/abstract/etc. method. (There needs to bevirtualmethods so that the assembly contains marshal methods.)To (1), update
Class1.csto inherit from theMyRunnertype and override the method. Additionally,Class1.cs(or some other type in the same project/assembly) should useIntPtr.Size:Enable trimming for
androidlib.csproj:Create an Android App project:
dotnet new androidlib -n androidUpdate
android.csprojto referenceandrodilib.csproj:Update
MainActivity.csto use the types from (2), (3):Build & run the resulting app in Release configuration.
The app builds successfully:
The app runs successfully:
However, the app is "wrong". Because we set
$(IsTrimmable)=True onandroidlib.dll, the linker will "inline"IntPtr.Sizeto a constant value based on the architecture,8for 64-bit platforms,4for 32-bit platforms. But…We can see that
IntPtr.Sizewas inlined to 4 for arm64, where it should be 8!Additionally, all of the
androidlib.dllassemblies are identical!When running the app on a Pixel 6 (64-bit device!), we see the same erroneous behavior:
😱
Did you find any workaround?
Don't enable trimming; either don't set
$(IsTrimmable)at all, or set$(IsTrimmable)=False.Relevant log output
No response