diff --git a/Il2CppDumper/IO/BinaryStream.cs b/Il2CppDumper/IO/BinaryStream.cs index fce3ade..bf8846e 100644 --- a/Il2CppDumper/IO/BinaryStream.cs +++ b/Il2CppDumper/IO/BinaryStream.cs @@ -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(); diff --git a/Il2CppDumper/Il2Cpp/Il2Cpp.cs b/Il2CppDumper/Il2Cpp/Il2Cpp.cs index 2eb9fc1..f8c5378 100644 --- a/Il2CppDumper/Il2Cpp/Il2Cpp.cs +++ b/Il2CppDumper/Il2Cpp/Il2Cpp.cs @@ -29,6 +29,7 @@ namespace Il2CppDumper protected long maxMetadataUsages; private Il2CppCodeGenModule[] codeGenModules; public ulong[][] codeGenModuleMethodPointers; + public Dictionary> rgctxsDictionary = new Dictionary>(); 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(); + rgctxsDictionary.Add(i, rgctxsDefDictionary); + if (codeGenModule.rgctxsCount > 0) + { + var rgctxs = MapVATR(codeGenModule.rgctxs, codeGenModule.rgctxsCount); + var rgctxRanges = MapVATR(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 diff --git a/Il2CppDumper/Il2Cpp/Il2CppClass.cs b/Il2CppDumper/Il2Cpp/Il2CppClass.cs index ff712c7..20f1ea3 100644 --- a/Il2CppDumper/Il2Cpp/Il2CppClass.cs +++ b/Il2CppDumper/Il2Cpp/Il2CppClass.cs @@ -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; + } } diff --git a/Il2CppDumper/Il2Cpp/Metadata.cs b/Il2CppDumper/Il2Cpp/Metadata.cs index cecf2b1..cae00a8 100644 --- a/Il2CppDumper/Il2Cpp/Metadata.cs +++ b/Il2CppDumper/Il2Cpp/Metadata.cs @@ -35,6 +35,8 @@ namespace Il2CppDumper public Il2CppGenericParameter[] genericParameters; public int[] constraintIndices; public uint[] vtableMethods; + public Il2CppRGCTXDefinition[] rgctxEntries; + private Dictionary stringCache = new Dictionary(); public Metadata(Stream stream) : base(stream) @@ -113,6 +115,10 @@ namespace Il2CppDumper } } } + if (Version <= 24.1f) + { + rgctxEntries = ReadMetadataClassArray(metadataHeader.rgctxEntriesOffset, metadataHeader.rgctxEntriesCount); + } } private T[] ReadMetadataClassArray(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; + } + } } } } diff --git a/Il2CppDumper/Il2Cpp/MetadataClass.cs b/Il2CppDumper/Il2Cpp/MetadataClass.cs index bbdd65b..cba2e94 100644 --- a/Il2CppDumper/Il2Cpp/MetadataClass.cs +++ b/Il2CppDumper/Il2Cpp/MetadataClass.cs @@ -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; + } } diff --git a/Il2CppDumper/Outputs/HeaderConstants.cs b/Il2CppDumper/Outputs/HeaderConstants.cs index 24c5e5e..5abd685 100644 --- a/Il2CppDumper/Outputs/HeaderConstants.cs +++ b/Il2CppDumper/Outputs/HeaderConstants.cs @@ -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; }; "; diff --git a/Il2CppDumper/Outputs/ScriptGenerator.cs b/Il2CppDumper/Outputs/ScriptGenerator.cs index a4e2288..f5c2737 100644 --- a/Il2CppDumper/Outputs/ScriptGenerator.cs +++ b/Il2CppDumper/Outputs/ScriptGenerator.cs @@ -25,8 +25,9 @@ namespace Il2CppDumper private List genericClassList = new List(); private StringBuilder arrayClassPreHeader = new StringBuilder(); private StringBuilder arrayClassHeader = new StringBuilder(); + private StringBuilder methodInfoHeader = new StringBuilder(); private static HashSet keyword = new HashSet(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(); - 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(); - 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"); + } } } diff --git a/Il2CppDumper/Outputs/StructInfo.cs b/Il2CppDumper/Outputs/StructInfo.cs index 0ea0930..bc05f55 100644 --- a/Il2CppDumper/Outputs/StructInfo.cs +++ b/Il2CppDumper/Outputs/StructInfo.cs @@ -13,6 +13,7 @@ namespace Il2CppDumper public List Fields = new List(); public List StaticFields = new List(); public List VTableMethod = new List(); + public List RGCTXs = new List(); } 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; + } } diff --git a/Il2CppDumper/Utils/Il2CppExecutor.cs b/Il2CppDumper/Utils/Il2CppExecutor.cs index 5fba503..6486341 100644 --- a/Il2CppDumper/Utils/Il2CppExecutor.cs +++ b/Il2CppDumper/Utils/Il2CppExecutor.cs @@ -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; + } } }