处理MethodInfo和RGCTX

This commit is contained in:
Perfare 2020-06-20 22:02:31 +08:00
parent 67837998fb
commit c116200e06
9 changed files with 399 additions and 90 deletions

View file

@ -164,6 +164,11 @@ namespace Il2CppDumper
{
i.SetValue(t, ReadPrimitive(fieldType));
}
else if (fieldType.IsEnum)
{
var e = fieldType.GetField("value__").FieldType;
i.SetValue(t, ReadPrimitive(e));
}
else if (fieldType.IsArray)
{
var arrayLengthAttribute = i.GetCustomAttribute<ArrayLengthAttribute>();

View file

@ -29,6 +29,7 @@ namespace Il2CppDumper
protected long maxMetadataUsages;
private Il2CppCodeGenModule[] codeGenModules;
public ulong[][] codeGenModuleMethodPointers;
public Dictionary<int, Dictionary<uint, Il2CppRGCTXDefinition[]>> rgctxsDictionary = new Dictionary<int, Dictionary<uint, Il2CppRGCTXDefinition[]>>();
public abstract ulong MapVATR(ulong uiAddr);
public abstract bool Search();
@ -138,6 +139,20 @@ namespace Il2CppDumper
{
codeGenModuleMethodPointers[i] = new ulong[codeGenModule.methodPointerCount];
}
var rgctxsDefDictionary = new Dictionary<uint, Il2CppRGCTXDefinition[]>();
rgctxsDictionary.Add(i, rgctxsDefDictionary);
if (codeGenModule.rgctxsCount > 0)
{
var rgctxs = MapVATR<Il2CppRGCTXDefinition>(codeGenModule.rgctxs, codeGenModule.rgctxsCount);
var rgctxRanges = MapVATR<Il2CppTokenRangePair>(codeGenModule.rgctxRanges, codeGenModule.rgctxRangesCount);
foreach (var rgctxRange in rgctxRanges)
{
var rgctxDefs = new Il2CppRGCTXDefinition[rgctxRange.range.length];
Array.Copy(rgctxs, rgctxRange.range.start, rgctxDefs, 0, rgctxRange.range.length);
rgctxsDefDictionary.Add(rgctxRange.token, rgctxDefs);
}
}
}
}
else

View file

@ -231,10 +231,22 @@ namespace Il2CppDumper
public ulong invokerIndices;
public ulong reversePInvokeWrapperCount;
public ulong reversePInvokeWrapperIndices;
public ulong rgctxRangesCount;
public long rgctxRangesCount;
public ulong rgctxRanges;
public ulong rgctxsCount;
public long rgctxsCount;
public ulong rgctxs;
public ulong debuggerMetadata;
}
public class Il2CppRange
{
public int start;
public int length;
}
public class Il2CppTokenRangePair
{
public uint token;
public Il2CppRange range;
}
}

View file

@ -35,6 +35,8 @@ namespace Il2CppDumper
public Il2CppGenericParameter[] genericParameters;
public int[] constraintIndices;
public uint[] vtableMethods;
public Il2CppRGCTXDefinition[] rgctxEntries;
private Dictionary<uint, string> stringCache = new Dictionary<uint, string>();
public Metadata(Stream stream) : base(stream)
@ -113,6 +115,10 @@ namespace Il2CppDumper
}
}
}
if (Version <= 24.1f)
{
rgctxEntries = ReadMetadataClassArray<Il2CppRGCTXDefinition>(metadataHeader.rgctxEntriesOffset, metadataHeader.rgctxEntriesCount);
}
}
private T[] ReadMetadataClassArray<T>(uint addr, int count) where T : new()
@ -213,19 +219,33 @@ namespace Il2CppDumper
if (Version < attr.Min || Version > attr.Max)
continue;
}
switch (i.FieldType.Name)
var fieldType = i.FieldType;
if (fieldType.IsPrimitive)
{
case "Int32":
case "UInt32":
size += 4;
break;
case "Int16":
case "UInt16":
size += 2;
break;
size += GetPrimitiveTypeSize(fieldType.Name);
}
else if (fieldType.IsEnum)
{
var e = fieldType.GetField("value__").FieldType;
size += GetPrimitiveTypeSize(e.Name);
}
}
return size;
int GetPrimitiveTypeSize(string name)
{
switch (name)
{
case "Int32":
case "UInt32":
return 4;
case "Int16":
case "UInt16":
return 2;
default:
return 0;
}
}
}
}
}

View file

@ -47,7 +47,7 @@ namespace Il2CppDumper
public uint typeDefinitionsOffset; // Il2CppTypeDefinition
public int typeDefinitionsCount;
[Version(Max = 24.1f)]
public int rgctxEntriesOffset; // Il2CppRGCTXDefinition
public uint rgctxEntriesOffset; // Il2CppRGCTXDefinition
[Version(Max = 24.1f)]
public int rgctxEntriesCount;
public uint imagesOffset; // Il2CppImageDefinition
@ -320,4 +320,26 @@ namespace Il2CppDumper
public ushort num;
public ushort flags;
}
public enum Il2CppRGCTXDataType
{
IL2CPP_RGCTX_DATA_INVALID,
IL2CPP_RGCTX_DATA_TYPE,
IL2CPP_RGCTX_DATA_CLASS,
IL2CPP_RGCTX_DATA_METHOD,
IL2CPP_RGCTX_DATA_ARRAY,
}
public class Il2CppRGCTXDefinitionData
{
public int rgctxDataDummy;
public int methodIndex => rgctxDataDummy;
public int typeIndex => rgctxDataDummy;
}
public class Il2CppRGCTXDefinition
{
public Il2CppRGCTXDataType type;
public Il2CppRGCTXDefinitionData data;
}
}

View file

@ -23,10 +23,14 @@ typedef unsigned long long uint64_t;
";
public readonly static string GenericHeader =
@"struct VirtualInvokeData
@"typedef void(*Il2CppMethodPointer)();
struct MethodInfo;
struct VirtualInvokeData
{
uintptr_t methodPtr;
void* method;
Il2CppMethodPointer methodPtr;
const MethodInfo* method;
};
struct Il2CppType
@ -43,10 +47,12 @@ struct Il2CppObject
void *monitor;
};
struct Il2CppArrayBounds
union Il2CppRGCTXData
{
uintptr_t length;
int32_t lower_bound;
void* rgctxDataDummy;
const MethodInfo* method;
const Il2CppType* type;
Il2CppClass* klass;
};
";
@ -79,7 +85,6 @@ struct Il2CppArrayBounds
struct Il2CppClass_2
{
void* rgctx_data;
Il2CppClass** typeHierarchy;
void *unity_user_data;
uint32_t initializationExceptionGCHandle;
@ -118,10 +123,45 @@ struct Il2CppClass
{
Il2CppClass_1 _1;
void* static_fields;
Il2CppRGCTXData* rgctx_data;
Il2CppClass_2 _2;
VirtualInvokeData vtable[255];
};
typedef uintptr_t il2cpp_array_size_t;
typedef int32_t il2cpp_array_lower_bound_t;
struct Il2CppArrayBounds
{
il2cpp_array_size_t length;
il2cpp_array_lower_bound_t lower_bound;
};
struct MethodInfo
{
Il2CppMethodPointer methodPointer;
void* invoker_method;
const char* name;
Il2CppClass *klass;
const Il2CppType *return_type;
const void* parameters;
union
{
const Il2CppRGCTXData* rgctx_data;
const void* methodDefinition;
};
union
{
const void* genericMethod;
const void* genericContainer;
};
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint8_t parameters_count;
uint8_t bitflags;
};
";
public readonly static string HeaderV241 =
@ -152,7 +192,6 @@ struct Il2CppClass
struct Il2CppClass_2
{
void* rgctx_data;
Il2CppClass** typeHierarchy;
uint32_t initializationExceptionGCHandle;
uint32_t cctor_started;
@ -190,10 +229,45 @@ struct Il2CppClass
{
Il2CppClass_1 _1;
void* static_fields;
Il2CppRGCTXData* rgctx_data;
Il2CppClass_2 _2;
VirtualInvokeData vtable[255];
};
typedef uintptr_t il2cpp_array_size_t;
typedef int32_t il2cpp_array_lower_bound_t;
struct Il2CppArrayBounds
{
il2cpp_array_size_t length;
il2cpp_array_lower_bound_t lower_bound;
};
struct MethodInfo
{
Il2CppMethodPointer methodPointer;
void* invoker_method;
const char* name;
Il2CppClass *klass;
const Il2CppType *return_type;
const void* parameters;
union
{
const Il2CppRGCTXData* rgctx_data;
const void* methodDefinition;
};
union
{
const void* genericMethod;
const void* genericContainer;
};
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint8_t parameters_count;
uint8_t bitflags;
};
";
public readonly static string HeaderV240 =
@ -223,7 +297,6 @@ struct Il2CppClass
struct Il2CppClass_2
{
void* rgctx_data;
Il2CppClass** typeHierarchy;
uint32_t cctor_started;
uint32_t cctor_finished;
@ -260,10 +333,46 @@ struct Il2CppClass
{
Il2CppClass_1 _1;
void* static_fields;
Il2CppRGCTXData* rgctx_data;
Il2CppClass_2 _2;
VirtualInvokeData vtable[255];
};
typedef int32_t il2cpp_array_size_t;
typedef int32_t il2cpp_array_lower_bound_t;
struct Il2CppArrayBounds
{
il2cpp_array_size_t length;
il2cpp_array_lower_bound_t lower_bound;
};
struct MethodInfo
{
Il2CppMethodPointer methodPointer;
void* invoker_method;
const char* name;
Il2CppClass *declaring_type;
const Il2CppType *return_type;
const void* parameters;
union
{
const Il2CppRGCTXData* rgctx_data;
const void* methodDefinition;
};
union
{
const void* genericMethod;
const void* genericContainer;
};
int32_t customAttributeIndex;
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint8_t parameters_count;
uint8_t bitflags;
};
";
public readonly static string HeaderV22 =
@ -292,7 +401,6 @@ struct Il2CppClass
struct Il2CppClass_2
{
void* rgctx_data;
Il2CppClass** typeHierarchy;
uint32_t cctor_started;
uint32_t cctor_finished;
@ -329,77 +437,44 @@ struct Il2CppClass
{
Il2CppClass_1 _1;
void* static_fields;
Il2CppRGCTXData* rgctx_data;
Il2CppClass_2 _2;
VirtualInvokeData vtable[255];
};
";
public readonly static string HeaderV21 =
@"struct Il2CppClass_1
typedef int32_t il2cpp_array_size_t;
typedef int32_t il2cpp_array_lower_bound_t;
struct Il2CppArrayBounds
{
void* image;
void* gc_desc;
il2cpp_array_size_t length;
il2cpp_array_lower_bound_t lower_bound;
};
struct MethodInfo
{
Il2CppMethodPointer methodPointer;
void* invoker_method;
const char* name;
const char* namespaze;
Il2CppType* byval_arg;
Il2CppType* this_arg;
Il2CppClass* element_class;
Il2CppClass* castClass;
Il2CppClass* declaringType;
Il2CppClass* parent;
void *generic_class;
void* typeDefinition;
void* fields;
void* events;
void* properties;
void* methods;
Il2CppClass** nestedTypes;
Il2CppClass** implementedInterfaces;
VirtualInvokeData* vtable;
void* interfaceOffsets;
};
struct Il2CppClass_2
{
void* rgctx_data;
Il2CppClass** typeHierarchy;
uint32_t cctor_started;
uint32_t cctor_finished;
uint64_t cctor_thread;
int32_t genericContainerIndex;
Il2CppClass *declaring_type;
const Il2CppType *return_type;
const void* parameters;
union
{
const Il2CppRGCTXData* rgctx_data;
const void* methodDefinition;
};
union
{
const void* genericMethod;
const void* genericContainer;
};
int32_t customAttributeIndex;
uint32_t instance_size;
uint32_t actualSize;
uint32_t element_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
int32_t thread_static_fields_offset;
uint32_t flags;
uint32_t token;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint8_t typeHierarchyDepth;
uint8_t rank;
uint8_t minimumAlignment;
uint8_t packingSize;
uint8_t bitflags1;
uint8_t bitflags2;
};
struct Il2CppClass
{
Il2CppClass_1 _1;
void* static_fields;
Il2CppClass_2 _2;
VirtualInvokeData vtable[255];
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint8_t parameters_count;
uint8_t bitflags;
};
";

View file

@ -25,8 +25,9 @@ namespace Il2CppDumper
private List<ulong> genericClassList = new List<ulong>();
private StringBuilder arrayClassPreHeader = new StringBuilder();
private StringBuilder arrayClassHeader = new StringBuilder();
private StringBuilder methodInfoHeader = new StringBuilder();
private static HashSet<string> keyword = new HashSet<string>(StringComparer.Ordinal)
{ "klass", "monitor", "register", "_cs", "auto", "friend", "template", "near", "far", "flat", "default", "_ds", "interrupt" };
{ "klass", "monitor", "register", "_cs", "auto", "friend", "template", "near", "far", "flat", "default", "_ds", "interrupt", "inline", "unsigned", "signed"};
public ScriptGenerator(Il2CppExecutor il2CppExecutor)
{
@ -71,6 +72,9 @@ namespace Il2CppDumper
{
var typeDef = metadata.typeDefs[typeIndex];
AddStruct(typeDef);
var methodInfoName = $"MethodInfo_{typeIndex}";
var structTypeName = structNameDic[typeDef];
GenerateMethodInfo(structTypeName, methodInfoName);
var typeName = executor.GetTypeDefName(typeDef, true, true);
var methodEnd = typeDef.methodStart + typeDef.method_count;
for (var i = typeDef.methodStart; i < methodEnd; ++i)
@ -94,11 +98,15 @@ namespace Il2CppDumper
}
var signature = $"{returnType} {FixName(methodFullName)} (";
var parameterStrs = new List<string>();
if (il2Cpp.Version <= 22f || (methodDef.flags & METHOD_ATTRIBUTE_STATIC) == 0)
if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) == 0)
{
var thisType = ParseType(il2Cpp.types[typeDef.byrefTypeIndex]);
parameterStrs.Add($"{thisType} __this");
}
else if (il2Cpp.Version <= 24f)
{
parameterStrs.Add($"Il2CppObject* __this");
}
for (var j = 0; j < methodDef.parameterCount; j++)
{
var parameterDef = metadata.parameterDefs[methodDef.parameterStart + j];
@ -111,6 +119,7 @@ namespace Il2CppDumper
}
parameterStrs.Add($"{parameterCType} {FixName(parameterName)}");
}
parameterStrs.Add("const MethodInfo* method");
signature += string.Join(", ", parameterStrs);
signature += ");";
scriptMethod.Signature = signature;
@ -139,7 +148,7 @@ namespace Il2CppDumper
}
var signature = $"{returnType} {FixName(methodFullName)} (";
var parameterStrs = new List<string>();
if (il2Cpp.Version <= 22f || (methodDef.flags & METHOD_ATTRIBUTE_STATIC) == 0)
if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) == 0)
{
string thisType;
if (methodSpec.classIndexIndex != -1)
@ -157,6 +166,10 @@ namespace Il2CppDumper
}
parameterStrs.Add($"{thisType} __this");
}
else if (il2Cpp.Version <= 24f)
{
parameterStrs.Add($"Il2CppObject* __this");
}
for (var j = 0; j < methodDef.parameterCount; j++)
{
var parameterDef = metadata.parameterDefs[methodDef.parameterStart + j];
@ -169,6 +182,7 @@ namespace Il2CppDumper
}
parameterStrs.Add($"{parameterCType} {FixName(parameterName)}");
}
parameterStrs.Add($"const {methodInfoName}* method");
signature += string.Join(", ", parameterStrs);
signature += ");";
scriptMethod.Signature = signature;
@ -332,6 +346,25 @@ namespace Il2CppDumper
}
else
{
headerClass.Append($"struct {info.TypeName}_RGCTXs {{\n");
for (int i = 0; i < info.RGCTXs.Count; i++)
{
StructRGCTXInfo rgctx = info.RGCTXs[i];
switch (rgctx.Type)
{
case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_TYPE:
headerClass.Append($"\tIl2CppType* _{i}_{rgctx.TypeName};\n");
break;
case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_CLASS:
headerClass.Append($"\tIl2CppClass* _{i}_{rgctx.ClassName};\n");
break;
case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_METHOD:
headerClass.Append($"\tMethodInfo* _{i}_{rgctx.MethodName};\n");
break;
}
}
headerClass.Append("};\n");
headerClass.Append($"struct {info.TypeName}_StaticFields {{\n");
foreach (var field in info.StaticFields)
{
@ -349,6 +382,7 @@ namespace Il2CppDumper
headerClass.Append($"struct {info.TypeName}_c {{\n" +
$"\tIl2CppClass_1 _1;\n" +
$"\t{info.TypeName}_StaticFields* static_fields;\n" +
$"\t{info.TypeName}_RGCTXs* rgctx_data;\n" +
$"\tIl2CppClass_2 _2;\n" +
$"\t{info.TypeName}_VTable vtable;\n" +
$"}};\n");
@ -395,6 +429,7 @@ namespace Il2CppDumper
sb.Append(headerStruct);
sb.Append(headerClass);
sb.Append(arrayClassHeader);
sb.Append(methodInfoHeader);
File.WriteAllText("il2cpp.h", sb.ToString());
}
@ -554,6 +589,7 @@ namespace Il2CppDumper
structInfo.IsValueType = typeDef.IsValueType;
AddFields(typeDef, structInfo.Fields, structInfo.StaticFields, null, false);
AddVTableMethod(structInfo, typeDef);
AddRGCTX(structInfo, typeDef);
}
private void AddGenericClassStruct(ulong pointer)
@ -655,6 +691,43 @@ namespace Il2CppDumper
}
}
private void AddRGCTX(StructInfo structInfo, Il2CppTypeDefinition typeDef)
{
var imageIndex = typeDefImageIndices[typeDef];
var collection = executor.GetTypeRGCTXDefinition(typeDef, imageIndex);
if (collection != null)
{
foreach (var definitionData in collection)
{
var structRGCTXInfo = new StructRGCTXInfo();
structInfo.RGCTXs.Add(structRGCTXInfo);
structRGCTXInfo.Type = definitionData.type;
switch (definitionData.type)
{
case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_TYPE:
{
var il2CppType = il2Cpp.types[definitionData.data.typeIndex];
structRGCTXInfo.TypeName = FixName(executor.GetTypeName(il2CppType, true, false));
break;
}
case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_CLASS:
{
var il2CppType = il2Cpp.types[definitionData.data.typeIndex];
structRGCTXInfo.ClassName = FixName(executor.GetTypeName(il2CppType, true, false));
break;
}
case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_METHOD:
{
var methodSpec = il2Cpp.methodSpecs[definitionData.data.methodIndex];
(var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec, true);
structRGCTXInfo.MethodName = FixName(methodSpecTypeName + "." + methodSpecMethodName);
break;
}
}
}
}
}
private void ParseArrayClassStruct(Il2CppType il2CppType, Il2CppGenericContext context)
{
var structName = GetIl2CppStructName(il2CppType, context);
@ -662,7 +735,7 @@ namespace Il2CppDumper
arrayClassHeader.Append($"struct {structName}_array {{\n" +
$"\tIl2CppObject obj;\n" +
$"\tIl2CppArrayBounds *bounds;\n" +
$"\tuintptr_t max_length;\n" +
$"\til2cpp_array_size_t max_length;\n" +
$"\t{ParseType(il2CppType, context)} m_Items[65535];\n" +
$"}};\n");
}
@ -730,6 +803,25 @@ namespace Il2CppDumper
}
sb.Append("};\n");
sb.Append($"struct {info.TypeName}_RGCTXs {{\n");
for (int i = 0; i < info.RGCTXs.Count; i++)
{
var rgctx = info.RGCTXs[i];
switch (rgctx.Type)
{
case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_TYPE:
sb.Append($"\tIl2CppType* _{i}_{rgctx.TypeName};\n");
break;
case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_CLASS:
sb.Append($"\tIl2CppClass* _{i}_{rgctx.ClassName};\n");
break;
case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_METHOD:
sb.Append($"\tMethodInfo* _{i}_{rgctx.MethodName};\n");
break;
}
}
sb.Append("};\n");
sb.Append($"struct {info.TypeName}_StaticFields {{\n");
foreach (var field in info.StaticFields)
{
@ -752,6 +844,7 @@ namespace Il2CppDumper
sb.Append($"struct {info.TypeName}_c {{\n" +
$"\tIl2CppClass_1 _1;\n" +
$"\t{info.TypeName}_StaticFields* static_fields;\n" +
$"\t{info.TypeName}_RGCTXs* rgctx_data;\n" +
$"\tIl2CppClass_2 _2;\n" +
$"\t{info.TypeName}_VTable vtable;\n" +
$"}};\n");
@ -900,5 +993,44 @@ namespace Il2CppDumper
return false;
}
}
private void GenerateMethodInfo(string structTypeName, string methodInfoName)
{
methodInfoHeader.Append($"struct {methodInfoName} {{\n");
methodInfoHeader.Append($"\tIl2CppMethodPointer methodPointer;\n");
methodInfoHeader.Append($"\tvoid* invoker_method;\n");
methodInfoHeader.Append($"\tconst char* name;\n");
if (il2Cpp.Version <= 24f)
{
methodInfoHeader.Append($"\t{structTypeName}_c *declaring_type;\n");
}
else
{
methodInfoHeader.Append($"\t{structTypeName}_c *klass;\n");
}
methodInfoHeader.Append($"\tconst Il2CppType *return_type;\n");
methodInfoHeader.Append($"\tconst void* parameters;\n");
methodInfoHeader.Append($"\tunion\n");
methodInfoHeader.Append($"\t{{\n");
methodInfoHeader.Append($"\t\tconst Il2CppRGCTXData* rgctx_data;\n");
methodInfoHeader.Append($"\t\tconst void* methodDefinition;\n");
methodInfoHeader.Append($"\t}};\n");
methodInfoHeader.Append($"\tunion\n");
methodInfoHeader.Append($"\t{{\n");
methodInfoHeader.Append($"\t\tconst void* genericMethod;\n");
methodInfoHeader.Append($"\t\tconst void* genericContainer;\n");
methodInfoHeader.Append($"\t}};\n");
if (il2Cpp.Version <= 24f)
{
methodInfoHeader.Append($"\tint32_t customAttributeIndex;\n");
}
methodInfoHeader.Append($"\tuint32_t token;\n");
methodInfoHeader.Append($"\tuint16_t flags;\n");
methodInfoHeader.Append($"\tuint16_t iflags;\n");
methodInfoHeader.Append($"\tuint16_t slot;\n");
methodInfoHeader.Append($"\tuint8_t parameters_count;\n");
methodInfoHeader.Append($"\tuint8_t bitflags;\n");
methodInfoHeader.Append($"}};\n");
}
}
}

View file

@ -13,6 +13,7 @@ namespace Il2CppDumper
public List<StructFieldInfo> Fields = new List<StructFieldInfo>();
public List<StructFieldInfo> StaticFields = new List<StructFieldInfo>();
public List<StructVTableMethodInfo> VTableMethod = new List<StructVTableMethodInfo>();
public List<StructRGCTXInfo> RGCTXs = new List<StructRGCTXInfo>();
}
public class StructFieldInfo
@ -26,4 +27,12 @@ namespace Il2CppDumper
{
public string MethodName;
}
public class StructRGCTXInfo
{
public Il2CppRGCTXDataType Type;
public string TypeName;
public string ClassName;
public string MethodName;
}
}

View file

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace Il2CppDumper
{
@ -211,5 +212,23 @@ namespace Il2CppDumper
}
return new Il2CppGenericContext { class_inst = classInstPointer, method_inst = methodInstPointer };
}
public Il2CppRGCTXDefinition[] GetTypeRGCTXDefinition(Il2CppTypeDefinition typeDef, int imageIndex)
{
Il2CppRGCTXDefinition[] collection = null;
if (il2Cpp.Version >= 24.2f)
{
il2Cpp.rgctxsDictionary[imageIndex].TryGetValue(typeDef.token, out collection);
}
else
{
if (typeDef.rgctxCount > 0)
{
collection = new Il2CppRGCTXDefinition[typeDef.rgctxCount];
Array.Copy(metadata.rgctxEntries, typeDef.rgctxStartIndex, collection, 0, typeDef.rgctxCount);
}
}
return collection;
}
}
}