dotnet / dotnet/macios

net7/8-ios: EntryPointNotFoundException on remapped DllImports, even when

Open
#19,624 8 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
C#
Stars
2.9k
Forks
576
Avg merge
2d 13h
Merged PRs (30d)
96

Description

This is a followup to https://github.com/xamarin/xamarin-macios/issues/19599. We've migrated to using NativeLibrary.SetDllImportResolver; however, this results in "EntryPointNotFound" unless the function is statically referenced elsewhere.

In legacy Xamarin, using the "Do not strip native debugging symbols." and -force_load flags would preserve all the entry points but it appears that no longer works as expected.

### Steps to Reproduce

1. Link with a static library in net8.0-ios.
2. Make sure to check "Do not strip native debugging symbols."
3. Add force_load to the builder flags, --cxx --gcc_flags "-L$(MSBuildProjectDirectory) -force_load $(MSBuildProjectDirectory)/libSDL2.a"
4. Create a DllImport which is rewritten, example:

[DllImport("RemapMe", EntryPoint = "SDL_SetHint", CallingConvention = CallingConvention.Cdecl)]
private static extern unsafe SDL_bool Internal_SDL_SetHint(
byte* name,
byte* value
);

NativeLibrary.SetDllImportResolver(assembly, MapAndLoad);

private static IntPtr MapAndLoad(
string libraryName,
Assembly assembly,
DllImportSearchPath? dllImportSearchPath
) {
return NativeLibrary.GetMainProgramHandle();
}

(A sample .cs and library are attached.)

### Expected Behavior
Native function can be invoked.

### Actual Behavior
Native function fails with "EntryPointNotFound" exception.

In the associated test file, we see:
Hello world!
Assembly is TestProj, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Attempting to call SDL_SetHint using DllImportResolver with __Internal...
Received request to map UseInternal TestProj, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null AssemblyDirectory...
Rewriting to __Internal
Received request to map UseInternal TestProj, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null AssemblyDirectory...
Rewriting to __Internal
System.DllNotFoundException: UseInternal
at Program.Main(String[] args) in /Users/miles/Projects/TestProj/Main.cs:line 40
Attempting to call SDL_SetHint using DllImportResolver with GetProgramHandle...
Received request to map UseProgramHandle TestProj, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null AssemblyDirectory...
Rewriting using MainProgramHandle
System.EntryPointNotFoundException: SDL_SetHint
at Program.Main(String[] args) in /Users/miles/Projects/TestProj/Main.cs:line 52
Test complete.

### Workaround
If the entry point is directly referenced elsewhere in the project, i.e.,

[DllImport("__Internal", EntryPoint = "SDL_SetHint", CallingConvention = CallingConvention.Cdecl)]
private static extern void DoNotUse();

then the remapped calls will function correctly, but any remapped calls to other entry points will still fail.

### Environment
net8.0-ios. This worked fine with .dll.config files in legacy Xamarin.

[sample.zip](https://github.com/xamarin/xamarin-macios/files/13643938/sample.zip)

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.