Skip to content
This repository has been archived by the owner on Jul 1, 2024. It is now read-only.

Commit

Permalink
Fixed compatibility with U2021.2.0+
Browse files Browse the repository at this point in the history
  • Loading branch information
knah committed Feb 22, 2022
1 parent f1adce3 commit c10c999
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 35 deletions.
2 changes: 1 addition & 1 deletion AssemblyUnhollower/AssemblyUnhollower.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFrameworks>net4.7.2;net5.0;netstandard2.1</TargetFrameworks>
<Nullable>enable</Nullable>
<Version>0.4.17.1</Version>
<Version>0.4.18.0</Version>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
Expand Down
6 changes: 2 additions & 4 deletions ReleaseChangelog.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
This is a small feature update. Generated assemblies should be fully compatible with those generated by 0.4.16.x.
This is a small bugfix update. Generated assemblies should be fully compatible with those generated by 0.4.17.x.

New features:
* PDB generator project (not bundled in release zip) - see README
* New CLI option `--add-prefix-to` to add Il2Cpp prefix to additional assemblies and namespaces to prevent conflicts with managed libs.
* 0.4.17.1 - strip Optional attribute off unstripped ICall delegates as Mono crashed on those
* Fixed compatibility with Unity versions 2021.2.0 and above

10 changes: 7 additions & 3 deletions UnhollowerBaseLib/ClassInjector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ public static void RegisterTypeInIl2CppImpl(Type type, bool logSuccess, params I
{
var vTableMethod = UnityVersionHandler.Wrap(interfaces[i].Methods[j]);
var methodName = Marshal.PtrToStringAnsi(vTableMethod.Name);
if (!infos.TryGetValue((methodName, vTableMethod.ParametersCount, (vTableMethod.ExtraFlags & MethodInfoExtraFlags.is_generic) != 0), out var methodIndex))
if (!infos.TryGetValue((methodName, vTableMethod.ParametersCount, vTableMethod.IsGeneric), out var methodIndex))
{
++index;
continue;
Expand Down Expand Up @@ -378,9 +378,9 @@ private static bool IsMethodEligible(MethodInfo method)
if (monoMethod.IsGenericMethod)
{
if (monoMethod.ContainsGenericParameters)
converted.ExtraFlags |= MethodInfoExtraFlags.is_generic;
converted.IsGeneric = true;
else
converted.ExtraFlags |= MethodInfoExtraFlags.is_inflated;
converted.IsInflated = true;
}

if (!monoMethod.ContainsGenericParameters)
Expand Down Expand Up @@ -646,6 +646,10 @@ private static void HookGenericMethodGetMethod()
if (targetMethod == IntPtr.Zero)
return;

var targetTargets = XrefScannerLowLevel.JumpTargets(targetMethod).Take(2).ToList();
if (targetTargets.Count == 1) // U2021.2.0+, there's additional shim that takes 3 parameters
targetMethod = targetTargets[0];

ourOriginalGenericGetMethod = Detour.Detour(targetMethod, new GenericGetMethodDelegate(GenericGetMethodPatch));
LogSupport.Trace("il2cpp_class_from_il2cpp_type patched");
}
Expand Down
36 changes: 25 additions & 11 deletions UnhollowerBaseLib/DelegateSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,21 +248,35 @@ public static TIl2Cpp ConvertDelegate<TIl2Cpp>(Delegate @delegate) where TIl2Cpp
var managedTrampoline =
GetOrCreateNativeToManagedTrampoline(signature, nativeDelegateInvokeMethod, managedInvokeMethod);

var nativeDelegatePtr = IL2CPP.il2cpp_object_new(classTypePtr);
var converted = new Il2CppSystem.Delegate(nativeDelegatePtr);

converted.method_ptr = Marshal.GetFunctionPointerForDelegate(managedTrampoline);
converted.method_info = nativeDelegateInvokeMethod; // todo: is this truly a good hack?
var methodInfo = UnityVersionHandler.NewMethod();
converted.method = methodInfo.Pointer;

methodInfo.MethodPointer = converted.method_ptr;
methodInfo.InvokerMethod = IntPtr.Zero;
methodInfo.MethodPointer = Marshal.GetFunctionPointerForDelegate(managedTrampoline);
methodInfo.ParametersCount = (byte) parameterInfos.Length;
methodInfo.Slot = ushort.MaxValue;
methodInfo.ExtraFlags = MethodInfoExtraFlags.is_marshalled_from_native;
methodInfo.IsMarshalledFromNative = true;

converted.m_target = new Il2CppToMonoDelegateReference(@delegate, methodInfo.Pointer);
var delegateReference = new Il2CppToMonoDelegateReference(@delegate, methodInfo.Pointer);

Il2CppSystem.Delegate converted;
if (UnityVersionHandler.MustUseDelegateConstructor)
{
converted = ((TIl2Cpp) Activator.CreateInstance(typeof(TIl2Cpp), delegateReference.Cast<Object>(), methodInfo.Pointer)).Cast<Il2CppSystem.Delegate>();
}
else
{
var nativeDelegatePtr = IL2CPP.il2cpp_object_new(classTypePtr);
converted = new Il2CppSystem.Delegate(nativeDelegatePtr);
}

converted.method_ptr = methodInfo.MethodPointer;
converted.method_info = nativeDelegateInvokeMethod; // todo: is this truly a good hack?
converted.method = methodInfo.Pointer;
converted.m_target = delegateReference;

if (UnityVersionHandler.MustUseDelegateConstructor)
{ // U2021.2.0+ hack in case the constructor did the wrong thing anyway
converted.invoke_impl = converted.method_ptr;
converted.method_code = converted.m_target.Pointer;
}

return converted.Cast<TIl2Cpp>();
}
Expand Down
6 changes: 6 additions & 0 deletions UnhollowerBaseLib/Runtime/UnityVersionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public static class UnityVersionHandler
private static readonly Dictionary<Type, object> Handlers = new();

private static Version UnityVersion = new(2018, 4, 20);
// Version since which extra_arg is set to invoke_multicast, necessitating constructor calls
private static readonly Version DelegatesGotComplexVersion = new Version(2021, 2, 0);

internal static INativeAssemblyStructHandler assemblyStructHandler;
internal static INativeClassStructHandler classStructHandler;
Expand Down Expand Up @@ -68,6 +70,8 @@ static UnityVersionHandler()
RecalculateHandlers();
}

public static bool MustUseDelegateConstructor { get; private set; }

private static void RecalculateHandlers()
{
Handlers.Clear();
Expand All @@ -91,6 +95,8 @@ private static void RecalculateHandlers()
parameterInfoStructHandler = GetHandler<INativeParameterInfoStructHandler>();
propertyInfoStructHandler = GetHandler<INativePropertyInfoStructHandler>();
typeStructHandler = GetHandler<INativeTypeStructHandler>();

MustUseDelegateConstructor = UnityVersion >= DelegatesGotComplexVersion;
}

private static T GetHandler<T>()
Expand Down
12 changes: 6 additions & 6 deletions UnhollowerBaseLib/Runtime/VersionSpecific/Class/Class_27_3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,20 +225,20 @@ public bool IsGeneric

public bool SizeInited
{
get => this.CheckBit(bitfield1offset, 7);
set => this.SetBit(bitfield1offset, 7, value);
get => this.CheckBit(bitfield2offset, 0);
set => this.SetBit(bitfield2offset, 0, value);
}

public bool HasFinalize
{
get => this.CheckBit(bitfield2offset, 0);
set => this.SetBit(bitfield2offset, 0, value);
get => this.CheckBit(bitfield2offset, 1);
set => this.SetBit(bitfield2offset, 1, value);
}

public bool IsVtableInitialized
{
get => this.CheckBit(bitfield2offset, 4);
set => this.SetBit(bitfield2offset, 4, value);
get => this.CheckBit(bitfield2offset, 5);
set => this.SetBit(bitfield2offset, 5, value);
}

public ref IntPtr Name => ref NativeClass->name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public interface INativeMethodInfoStruct : INativeStruct
ref Il2CppMethodFlags Flags { get; }
ref byte ParametersCount { get; }
unsafe ref Il2CppParameterInfo* Parameters { get; }
ref MethodInfoExtraFlags ExtraFlags { get; }
bool IsGeneric { get; set; }
bool IsInflated { get; set; }
bool IsMarshalledFromNative { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,35 @@ public NativeMethodInfoStructWrapper(IntPtr pointer)

public ref Il2CppParameterInfo* Parameters => ref NativeMethod->parameters;

public ref MethodInfoExtraFlags ExtraFlags => ref NativeMethod->extra_flags;
public bool IsGeneric
{
get => (NativeMethod->extra_flags & MethodInfoExtraFlags.is_generic) != 0;
set
{
if (value) NativeMethod->extra_flags |= MethodInfoExtraFlags.is_generic;
else NativeMethod->extra_flags &= ~MethodInfoExtraFlags.is_generic;
}
}

public bool IsInflated
{
get => (NativeMethod->extra_flags & MethodInfoExtraFlags.is_inflated) != 0;
set
{
if (value) NativeMethod->extra_flags |= MethodInfoExtraFlags.is_inflated;
else NativeMethod->extra_flags &= ~MethodInfoExtraFlags.is_inflated;
}
}

public bool IsMarshalledFromNative
{
get => (NativeMethod->extra_flags & MethodInfoExtraFlags.is_marshalled_from_native) != 0;
set
{
if (value) NativeMethod->extra_flags |= MethodInfoExtraFlags.is_marshalled_from_native;
else NativeMethod->extra_flags &= ~MethodInfoExtraFlags.is_marshalled_from_native;
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,35 @@ public NativeMethodInfoStructWrapper(IntPtr pointer)

public ref Il2CppParameterInfo* Parameters => ref NativeMethod->parameters;

public ref MethodInfoExtraFlags ExtraFlags => ref NativeMethod->extra_flags;
public bool IsGeneric
{
get => (NativeMethod->extra_flags & MethodInfoExtraFlags.is_generic) != 0;
set
{
if (value) NativeMethod->extra_flags |= MethodInfoExtraFlags.is_generic;
else NativeMethod->extra_flags &= ~MethodInfoExtraFlags.is_generic;
}
}

public bool IsInflated
{
get => (NativeMethod->extra_flags & MethodInfoExtraFlags.is_inflated) != 0;
set
{
if (value) NativeMethod->extra_flags |= MethodInfoExtraFlags.is_inflated;
else NativeMethod->extra_flags &= ~MethodInfoExtraFlags.is_inflated;
}
}

public bool IsMarshalledFromNative
{
get => (NativeMethod->extra_flags & MethodInfoExtraFlags.is_marshalled_from_native) != 0;
set
{
if (value) NativeMethod->extra_flags |= MethodInfoExtraFlags.is_marshalled_from_native;
else NativeMethod->extra_flags &= ~MethodInfoExtraFlags.is_marshalled_from_native;
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,17 @@ internal struct Il2CppMethodInfo_27_3
public ushort slot;
public byte parameters_count;

public MethodInfoExtraFlags extra_flags;
/*uint8_t is_generic : 1; /* true if method is a generic method definition #1#
uint8_t is_inflated : 1; /* true if declaring_type is a generic instance or if method is a generic instance#1#
uint8_t wrapper_type : 1; /* always zero (MONO_WRAPPER_NONE) needed for the debugger #1#
uint8_t is_marshaled_from_native : 1*/
public MethodInfoExtraFlags_27_3 extra_flags;
}

[Flags]
public enum MethodInfoExtraFlags_27_3 : byte
{
is_generic = 0x1,
is_inflated = 0x2,
wrapper_type = 0x4,
has_full_generic_sharing_signature = 0x8,
indirect_call_via_invokers = 0x10
}


Expand Down Expand Up @@ -125,7 +131,31 @@ public NativeMethodInfoStructWrapper(IntPtr pointer)

public ref Il2CppParameterInfo* Parameters => ref NativeMethod->parameters;

public ref MethodInfoExtraFlags ExtraFlags => ref NativeMethod->extra_flags;
public bool IsGeneric
{
get => (NativeMethod->extra_flags & MethodInfoExtraFlags_27_3.is_generic) != 0;
set
{
if (value) NativeMethod->extra_flags |= MethodInfoExtraFlags_27_3.is_generic;
else NativeMethod->extra_flags &= ~MethodInfoExtraFlags_27_3.is_generic;
}
}

public bool IsInflated
{
get => (NativeMethod->extra_flags & MethodInfoExtraFlags_27_3.is_inflated) != 0;
set
{
if (value) NativeMethod->extra_flags |= MethodInfoExtraFlags_27_3.is_inflated;
else NativeMethod->extra_flags &= ~MethodInfoExtraFlags_27_3.is_inflated;
}
}

public bool IsMarshalledFromNative
{
get => false;
set { /* no-op */ }
}
}
}
}
2 changes: 1 addition & 1 deletion UnhollowerBaseLib/UnhollowerBaseLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>net4.7.2;netstandard2.1</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<Version>0.4.17.0</Version>
<Version>0.4.18.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down

0 comments on commit c10c999

Please sign in to comment.