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

Implemented: Generic Support for Methods in UnhollowerUtils #89

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
44 changes: 40 additions & 4 deletions UnhollowerBaseLib/UnhollowerUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ namespace UnhollowerBaseLib
{
public class UnhollowerUtils
{
private static FieldInfo GetFieldInfoFromMethod(MethodBase method, string prefix)
private const string GenericDeclaringTypeName = "MethodInfoStoreGeneric_";
private const string GenericFieldName = "Pointer";

private static FieldInfo GetFieldInfoFromMethod(MethodBase method, string prefix, FieldType type = FieldType.None)
{
var body = method.GetMethodBody();
if (body == null) throw new ArgumentException("Target method may not be abstract");
Expand All @@ -16,20 +19,53 @@ private static FieldInfo GetFieldInfoFromMethod(MethodBase method, string prefix
{
if (opCode != OpCodes.Ldsfld) continue;
var fieldInfo = methodModule.ResolveField((int) opArg);
if (fieldInfo?.FieldType != typeof(IntPtr) || !fieldInfo.Name.StartsWith(prefix)) continue;
return fieldInfo;
if (fieldInfo?.FieldType != typeof(IntPtr))
continue;

switch (type)
{
case FieldType.None:
if (fieldInfo.Name.StartsWith(prefix))
return fieldInfo;

break;

case FieldType.GenericMethod:

if (fieldInfo.Name.Equals(GenericFieldName) &&
fieldInfo.DeclaringType.Name.StartsWith(GenericDeclaringTypeName))
{
var genericType = fieldInfo.DeclaringType.GetGenericTypeDefinition().MakeGenericType(method.GetGenericArguments());
return genericType.GetField(GenericFieldName, BindingFlags.NonPublic | BindingFlags.Static);
}

break;

default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
}
return null;
}

public static FieldInfo GetIl2CppMethodInfoPointerFieldForGeneratedMethod(MethodBase method)
{
return GetFieldInfoFromMethod(method, "NativeMethodInfoPtr_");
const string prefix = "NativeMethodInfoPtr_";
if (method.IsGenericMethod)
return GetFieldInfoFromMethod(method, prefix, FieldType.GenericMethod);

return GetFieldInfoFromMethod(method, prefix);
}

public static FieldInfo GetIl2CppFieldInfoPointerFieldForGeneratedFieldAccessor(MethodBase method)
{
return GetFieldInfoFromMethod(method, "NativeFieldInfoPtr_");
}

private enum FieldType
{
None,
GenericMethod
}
}
}