diff --git a/Il2CppDumper/Outputs/HeaderConstants.cs b/Il2CppDumper/Outputs/HeaderConstants.cs index 94368ce..24c5e5e 100644 --- a/Il2CppDumper/Outputs/HeaderConstants.cs +++ b/Il2CppDumper/Outputs/HeaderConstants.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Il2CppDumper +namespace Il2CppDumper { public static class HeaderConstants { @@ -55,13 +49,6 @@ struct Il2CppArrayBounds int32_t lower_bound; }; -struct Il2CppArray -{ - Il2CppObject obj; - Il2CppArrayBounds *bounds; - uintptr_t max_length; -}; - "; public readonly static string HeaderV242 = diff --git a/Il2CppDumper/Outputs/ScriptGenerator.cs b/Il2CppDumper/Outputs/ScriptGenerator.cs index 2358c36..a9948f1 100644 --- a/Il2CppDumper/Outputs/ScriptGenerator.cs +++ b/Il2CppDumper/Outputs/ScriptGenerator.cs @@ -15,13 +15,15 @@ namespace Il2CppDumper private Metadata metadata; private Il2Cpp il2Cpp; private Dictionary typeDefImageIndices = new Dictionary(); - private List structInfo = new List(); + private List structInfoList = new List(); private Dictionary structInfoWithStructName = new Dictionary(); private HashSet structCache = new HashSet(); private HashSet structNameHashSet = new HashSet(StringComparer.Ordinal); private Dictionary structNameDic = new Dictionary(); private Dictionary genericClassStructNameDic = new Dictionary(); private List genericClassList = new List(); + private StringBuilder arrayClassPreHeader = new StringBuilder(); + private StringBuilder arrayClassHeader = new StringBuilder(); public ScriptGenerator(Il2CppExecutor il2CppExecutor) { @@ -101,9 +103,9 @@ namespace Il2CppDumper scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]); scriptMetadata.Name = "Class$" + typeName; var signature = GetIl2CppStructName(type); - if (signature == "Il2CppArray*") + if (signature.EndsWith("_array")) { - scriptMetadata.Signature = signature; + scriptMetadata.Signature = signature + "*"; } else { @@ -119,9 +121,9 @@ namespace Il2CppDumper scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]); scriptMetadata.Name = "Object$" + typeName; var signature = GetIl2CppStructName(type); - if (signature == "Il2CppArray*") + if (signature.EndsWith("_array")) { - scriptMetadata.Signature = signature; + scriptMetadata.Signature = signature + "*"; } else { @@ -233,21 +235,20 @@ namespace Il2CppDumper json.Addresses = orderedPointers; } File.WriteAllText("script.json", JsonConvert.SerializeObject(json, Formatting.Indented)); - //.h + //il2cpp.h for (int i = 0; i < genericClassList.Count; i++) { var pointer = genericClassList[i]; AddGenericClassStruct(pointer); } - //TODO 处理数组类型 var preHeader = new StringBuilder(); var headerStruct = new StringBuilder(); var headerClass = new StringBuilder(); - foreach (var info in structInfo) + foreach (var info in structInfoList) { structInfoWithStructName.Add(info.TypeName + "_o", info); } - foreach (var info in structInfo) + foreach (var info in structInfoList) { preHeader.Append($"struct {info.TypeName}_o;\n"); @@ -317,8 +318,10 @@ namespace Il2CppDumper return; } sb.Append(preHeader); + sb.Append(arrayClassPreHeader); sb.Append(headerStruct); sb.Append(headerClass); + sb.Append(arrayClassHeader); File.WriteAllText("il2cpp.h", sb.ToString()); } @@ -418,8 +421,18 @@ namespace Il2CppDumper } return "Il2CppObject*"; } - case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY: //TODO - return "Il2CppArray*"; + case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY: + { + var arrayType = il2Cpp.MapVATR(il2CppType.data.array); + var elementType = il2Cpp.GetIl2CppType(arrayType.etype); + var elementStructName = GetIl2CppStructName(elementType, context); + var typeStructName = elementStructName + "_array"; + if (structNameHashSet.Add(typeStructName)) + { + ParseArrayClassStruct(elementType, context); + } + return typeStructName + "*"; + } case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST: { var genericClass = il2Cpp.MapVATR(il2CppType.data.generic_class); @@ -448,10 +461,19 @@ namespace Il2CppDumper return "intptr_t"; case Il2CppTypeEnum.IL2CPP_TYPE_U: return "uintptr_t"; - case Il2CppTypeEnum.IL2CPP_TYPE_OBJECT: //TODO + case Il2CppTypeEnum.IL2CPP_TYPE_OBJECT: return "Il2CppObject*"; - case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY: //TODO - return "Il2CppArray*"; + case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY: + { + var elementType = il2Cpp.GetIl2CppType(il2CppType.data.type); + var elementStructName = GetIl2CppStructName(elementType, context); + var typeStructName = elementStructName + "_array"; + if (structNameHashSet.Add(typeStructName)) + { + ParseArrayClassStruct(elementType, context); + } + return typeStructName + "*"; + } case Il2CppTypeEnum.IL2CPP_TYPE_MVAR: { if (context != null) @@ -473,7 +495,7 @@ namespace Il2CppDumper private void AddStruct(Il2CppTypeDefinition typeDef) { var structInfo = new StructInfo(); - this.structInfo.Add(structInfo); + structInfoList.Add(structInfo); structInfo.TypeName = structNameDic[typeDef]; structInfo.IsValueType = typeDef.IsValueType; AddFields(typeDef, structInfo.Fields, structInfo.StaticFields, null, false); @@ -485,7 +507,7 @@ namespace Il2CppDumper var genericClass = il2Cpp.MapVATR(pointer); var typeDef = metadata.typeDefs[genericClass.typeDefinitionIndex]; var structInfo = new StructInfo(); - this.structInfo.Add(structInfo); + structInfoList.Add(structInfo); structInfo.TypeName = genericClassStructNameDic[pointer]; structInfo.IsValueType = typeDef.IsValueType; AddFields(typeDef, structInfo.Fields, structInfo.StaticFields, genericClass.context, false); @@ -579,6 +601,18 @@ namespace Il2CppDumper } } + private void ParseArrayClassStruct(Il2CppType il2CppType, Il2CppGenericContext context) + { + var structName = GetIl2CppStructName(il2CppType, context); + arrayClassPreHeader.Append($"struct {structName}_array;\n"); + arrayClassHeader.Append($"struct {structName}_array {{\n" + + $"\tIl2CppObject obj;\n" + + $"\tIl2CppArrayBounds *bounds;\n" + + $"\tuintptr_t max_length;\n" + + $"\t{ParseType(il2CppType, context)} m_Items[65535];\n" + + $"}};\n"); + } + private void TypeDefinitionFromIl2CppType(Il2CppType il2CppType, out Il2CppTypeDefinition typeDef, out Il2CppGenericContext context) { context = null; @@ -671,7 +705,7 @@ namespace Il2CppDumper return pre.Append(sb).ToString(); } - private string GetIl2CppStructName(Il2CppType il2CppType) + private string GetIl2CppStructName(Il2CppType il2CppType, Il2CppGenericContext context = null) { switch (il2CppType.type) { @@ -704,9 +738,29 @@ namespace Il2CppDumper var oriType = il2Cpp.GetIl2CppType(il2CppType.data.type); return GetIl2CppStructName(oriType); } - case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY: //TODO - case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY: //TODO - return "Il2CppArray*"; + case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY: + { + var arrayType = il2Cpp.MapVATR(il2CppType.data.array); + var elementType = il2Cpp.GetIl2CppType(arrayType.etype); + var elementStructName = GetIl2CppStructName(elementType, context); + var typeStructName = elementStructName + "_array"; + if (structNameHashSet.Add(typeStructName)) + { + ParseArrayClassStruct(elementType, context); + } + return typeStructName; + } + case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY: + { + var elementType = il2Cpp.GetIl2CppType(il2CppType.data.type); + var elementStructName = GetIl2CppStructName(elementType, context); + var typeStructName = elementStructName + "_array"; + if (structNameHashSet.Add(typeStructName)) + { + ParseArrayClassStruct(elementType, context); + } + return typeStructName; + } case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST: { if (!genericClassStructNameDic.TryGetValue(il2CppType.data.generic_class, out var typeStructName)) @@ -725,6 +779,32 @@ namespace Il2CppDumper } return typeStructName; } + case Il2CppTypeEnum.IL2CPP_TYPE_VAR: + { + if (context != null) + { + var genericParameter = metadata.genericParameters[il2CppType.data.genericParameterIndex]; + var genericInst = il2Cpp.MapVATR(context.class_inst); + var pointers = il2Cpp.MapVATR(genericInst.type_argv, genericInst.type_argc); + var pointer = pointers[genericParameter.num]; + var type = il2Cpp.GetIl2CppType(pointer); + return GetIl2CppStructName(type); + } + return "System_Object"; + } + case Il2CppTypeEnum.IL2CPP_TYPE_MVAR: + { + if (context != null) + { + var genericParameter = metadata.genericParameters[il2CppType.data.genericParameterIndex]; + var genericInst = il2Cpp.MapVATR(context.method_inst); + var pointers = il2Cpp.MapVATR(genericInst.type_argv, genericInst.type_argc); + var pointer = pointers[genericParameter.num]; + var type = il2Cpp.GetIl2CppType(pointer); + return GetIl2CppStructName(type); + } + return "System_Object"; + } default: throw new NotSupportedException(); }