Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -354,3 +354,5 @@ MigrationBackup/
.ionide/

launchsettings.json

.DS_Store
83 changes: 79 additions & 4 deletions Il2CppInterop.Common/XrefScans/XrefScanMethodDb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,64 @@ static XrefScanMethodDb()
GeneratedDatabasesUtil.GetDatabasePath(MethodAddressToTokenMap.FileName));
XrefScanCache = new MethodXrefScanCache(GeneratedDatabasesUtil.GetDatabasePath(MethodXrefScanCache.FileName));

foreach (ProcessModule module in Process.GetCurrentProcess().Modules)
if (module.ModuleName == "GameAssembly.dll")
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
var errorPtr = IntPtr.Zero;
var libHandle = dlopen("GameAssembly.dylib", 2);

if (libHandle == IntPtr.Zero)
{
var procPath = Process.GetCurrentProcess().MainModule.FileName;
var appContentsPath = Directory.GetParent(procPath).Parent.FullName;
var gameAssemblyPath = Path.Combine(appContentsPath, "Frameworks", "GameAssembly.dylib");

if (File.Exists(gameAssemblyPath))
{
libHandle = dlopen(gameAssemblyPath, 2);
}
}

if (libHandle == IntPtr.Zero)
{
errorPtr = dlerror();

var errorMessage = errorPtr != IntPtr.Zero
? Marshal.PtrToStringAnsi(errorPtr)
: "Unknown dlopen failure";

throw new DllNotFoundException(
$"Failed to load \"GameAssembly.dylib\" with error message: {errorMessage}");
}

// Clear any previous error state.
dlerror();

var symbolAddress = dlsym(libHandle, "il2cpp_init");
errorPtr = dlerror();

if (errorPtr != IntPtr.Zero)
{
GameAssemblyBase = (long)module.BaseAddress;
break;
var errorMessage = Marshal.PtrToStringAnsi(errorPtr);

throw new EntryPointNotFoundException(
$"Failed to find symbol \"il2cpp_init\" with error message: {errorMessage}");
}

if (dladdr(symbolAddress, out var info) == 0)
{
throw new InvalidOperationException();
}

var baseAddress = info.dli_fbase;
GameAssemblyBase = (long)baseAddress;
}
else
{
GameAssemblyBase = (long)Process.GetCurrentProcess()
.Modules.OfType<ProcessModule>()
.Single(x => x.ModuleName is "GameAssembly.dll" or "GameAssembly.so" or "UserAssembly.dll" || string.Equals(x.ModuleName, "GameAssembly.dll", StringComparison.OrdinalIgnoreCase))
.BaseAddress;
}
}

public static MethodBase TryResolvePointer(IntPtr methodStart)
Expand Down Expand Up @@ -64,4 +116,27 @@ internal static void CallMetadataInitForMethod(CachedScanResultsAttribute attrib

Marshal.WriteByte((IntPtr)(GameAssemblyBase + attribute.MetadataInitFlagRva), 1);
}

[StructLayout(LayoutKind.Sequential)]
private struct DlInfo
{
public IntPtr dli_fname;
public IntPtr dli_fbase;
public IntPtr dli_sname;
public IntPtr dli_saddr;
}

[DllImport("libSystem.dylib", EntryPoint = "dlopen", CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi)]
private static extern IntPtr dlopen(string filename, int flags);

[DllImport("libSystem.dylib", EntryPoint = "dlerror", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr dlerror();

[DllImport("libSystem.dylib", EntryPoint = "dlsym", CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi)]
private static extern IntPtr dlsym(IntPtr handle, string symbol);

[DllImport("libSystem.dylib", EntryPoint = "dladdr", CallingConvention = CallingConvention.Cdecl)]
private static extern int dladdr(IntPtr addr, out DlInfo info);
Comment on lines +120 to +141

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Annotate these with [SupportedOSPlatform("osx")]

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using Il2CppInterop.Common;
Expand Down Expand Up @@ -141,7 +141,7 @@ public override IntPtr FindTargetMethod()
// inlined but we'll treat it the same even though it doesn't receive the type parameter the RDX register
// doesn't get cleared so we still get the same parameters
var classGetDefaultFieldValue = s_Signatures
.Select(s => MemoryUtils.FindSignatureInModule(InjectorHelpers.Il2CppModule, s))
.Select(s => MemoryUtils.FindSignatureInBlock(InjectorHelpers.Il2CppModuleBaseAddress, InjectorHelpers.Il2CppModuleMemorySize, s))
.FirstOrDefault(p => p != 0);

if (classGetDefaultFieldValue == 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ internal unsafe class GenericMethod_GetMethod_Hook : Hook<GenericMethod_GetMetho
public override IntPtr FindTargetMethod()
{
var genericMethodGetMethod = s_Signatures
.Select(s => MemoryUtils.FindSignatureInModule(InjectorHelpers.Il2CppModule, s))
.Select(s => MemoryUtils.FindSignatureInBlock(InjectorHelpers.Il2CppModuleBaseAddress, InjectorHelpers.Il2CppModuleMemorySize, s))
.FirstOrDefault(p => p != 0);

if (genericMethodGetMethod == 0)
Expand Down
Loading
Loading