Skip to content

Mono AOT compiler does not prefix exported UnmanagedCallersOnly symbols with underscore when targeting iOS #79491

Closed

Description

@ivanpovazan

Description

If a method is marked with UnmanagedCallersOnlyAttribute and a named export is specified via EntryPoint e.g.,

[UnmanagedCallersOnly(EntryPoint="exposed_managed_method")]
    public static int ManagedMethod() => 42;

Mono AOT compiler exports the symbols as-is without prefixing it with an _ which is required on iOS platforms.
This results in failures when trying to load the symbol dynamically from the native code via:

void *del = dlsym (RTLD_DEFAULT, "exposed_managed_method");

Repro

To reproduce, apply the following patch:

diff --git a/src/mono/sample/iOS/Program.cs b/src/mono/sample/iOS/Program.cs
index 603ff2e4ebc..fbdc8032daa 100644
--- a/src/mono/sample/iOS/Program.cs
+++ b/src/mono/sample/iOS/Program.cs
@@ -24,6 +24,9 @@ private static void OnButtonClick()
         ios_set_text("OnButtonClick! #" + counter++);
     }
 
+    [UnmanagedCallersOnly(EntryPoint="exposed_managed_method")]
+    public static int ManagedMethod() => 42;
+
 #if CI_TEST
     public static async Task<int> Main(string[] args)
 #else
diff --git a/src/mono/sample/iOS/Program.csproj b/src/mono/sample/iOS/Program.csproj
index 0e6aa8777fa..f0187ba8f81 100644
--- a/src/mono/sample/iOS/Program.csproj
+++ b/src/mono/sample/iOS/Program.csproj
@@ -16,6 +16,10 @@
     <TrimMode>Link</TrimMode>
   </PropertyGroup>
 
+  <ItemGroup>
+    <TrimmerRootDescriptor Include="$(MSBuildThisFileDirectory)ILLink.Descriptors.xml" />
+  </ItemGroup>
+
   <PropertyGroup Condition="'$(TargetOS)' == 'MacCatalyst'">
     <DevTeamProvisioning Condition="'$(TargetOS)' == 'MacCatalyst' and '$(DevTeamProvisioning)' == ''">adhoc</DevTeamProvisioning>
     <EnableAppSandbox Condition="'$(EnableAppSandbox)' == ''">false</EnableAppSandbox>
@@ -79,6 +83,7 @@
         TargetOS="$(TargetOS)"
         Arch="$(TargetArchitecture)"
         ProjectName="$(AppName)"
+        NativeMainSource="$(MSBuildThisFileDirectory)/main.m"
         MonoRuntimeHeaders="$(MicrosoftNetCoreAppRuntimePackDir)runtimes\$(TargetOS.ToLower())-$(TargetArchitecture)\native\include\mono-2.0"
         Assemblies="@(BundleAssemblies)"
         MainLibraryFileName="Program.dll"
diff --git a/src/mono/sample/iOS/main.m b/src/mono/sample/iOS/main.m
index 0ab407e8398..e6d8a3f31f4 100644
--- a/src/mono/sample/iOS/main.m
+++ b/src/mono/sample/iOS/main.m
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 #import <UIKit/UIKit.h>
+#import <dlfcn.h>
 #import "runtime.h"
 
 @interface ViewController : UIViewController
@@ -45,6 +46,8 @@ void (*clickHandlerPtr)(void);
     [self.view addSubview:button];
 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        void *del = dlsym (RTLD_DEFAULT, "exposed_managed_method");
+        NSAssert(del != NULL, @"'exposed_managed_method' not found");
         mono_ios_runtime_init ();
     });
 }

And add the ILLink.Descriptors.xml file to the project directory with the following contents:

<linker>
  <!-- this is here to show how to configure the trimming -->
  <assembly fullname="Program">
    <type fullname="Program">
        <method name="ManagedMethod" />
    </type>
  </assembly>
</linker>

Finally, build it with:

cd src/mono/sample/iOS
make build-appbundle MONO_ARCH=arm64 AOT=true DEPLOY_AND_RUN=true

Workaround

Possible workaround is to prefix the EntryPoint name with the underscore, but then such code is not platform independent.

/cc @mdh1418 @steveisok

Activity

  1. added this to the 8.0.0 milestone on Dec 10, 2022
  2. self-assigned this
    on Dec 10, 2022
  3. steveisok commented on Dec 21, 2022

    @steveisok
    Member

    @mdh1418 as this issue mentions, the symbol won't be written w/, for example, an underscore on osx, so

    g_string_append_printf (export_symbols, "%s%s\n", acfg->user_symbol_prefix, export_name);
    will write the incorrect symbol name.

  4. ghost added
    in-prThere is an active PR which will close this issue when it is merged
    on Dec 21, 2022
  5. ghost removed
    in-prThere is an active PR which will close this issue when it is merged
    on Jan 19, 2023
  6. ghost locked as resolved and limited conversation to collaborators on Feb 18, 2023
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

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions