From 270ac529a2645c66481a073ba67b0c3271aacf98 Mon Sep 17 00:00:00 2001 From: Perfare Date: Thu, 27 Feb 2020 16:23:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=A7=E5=B9=85=E5=BA=A6=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E5=A4=84=E7=90=86=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Il2CppDumper/ExecutableFormats/Il2Cpp.cs | 7 ++- Il2CppDumper/ExecutableFormats/Metadata.cs | 48 ++++++++++++++------ Il2CppDumper/Il2CppDumper.csproj | 1 + Il2CppDumper/Outputs/Il2CppDecompiler.cs | 34 ++++---------- Il2CppDumper/Utils/DummyAssemblyGenerator.cs | 6 +-- Il2CppDumper/Utils/Il2CppExecutor.cs | 18 +++++--- Il2CppDumper/Utils/ReadCache.cs | 31 +++++++++++++ 7 files changed, 93 insertions(+), 52 deletions(-) create mode 100644 Il2CppDumper/Utils/ReadCache.cs diff --git a/Il2CppDumper/ExecutableFormats/Il2Cpp.cs b/Il2CppDumper/ExecutableFormats/Il2Cpp.cs index ab70dd5..66abb22 100644 --- a/Il2CppDumper/ExecutableFormats/Il2Cpp.cs +++ b/Il2CppDumper/ExecutableFormats/Il2Cpp.cs @@ -129,7 +129,12 @@ namespace Il2CppDumper public T MapVATR(ulong addr) where T : new() { - return ReadClass(MapVATR(addr)); + if (!ReadClassCache.TryGetValue(addr, out var value)) + { + value = ReadClass(MapVATR(addr)); + ReadClassCache.Add(addr, value); + } + return value; } public T[] MapVATR(ulong addr, long count) where T : new() diff --git a/Il2CppDumper/ExecutableFormats/Metadata.cs b/Il2CppDumper/ExecutableFormats/Metadata.cs index fd82c4c..cecf2b1 100644 --- a/Il2CppDumper/ExecutableFormats/Metadata.cs +++ b/Il2CppDumper/ExecutableFormats/Metadata.cs @@ -14,10 +14,13 @@ namespace Il2CppDumper public Il2CppMethodDefinition[] methodDefs; public Il2CppParameterDefinition[] parameterDefs; public Il2CppFieldDefinition[] fieldDefs; - private Il2CppFieldDefaultValue[] fieldDefaultValues; - private Il2CppParameterDefaultValue[] parameterDefaultValues; + //private Il2CppFieldDefaultValue[] fieldDefaultValues; + //private Il2CppParameterDefaultValue[] parameterDefaultValues; + private Dictionary fieldDefaultValuesDic; + private Dictionary parameterDefaultValuesDic; public Il2CppPropertyDefinition[] propertyDefs; public Il2CppCustomAttributeTypeRange[] attributeTypeRanges; + private Dictionary> attributeTypeRangesDic; private Il2CppStringLiteral[] stringLiterals; private Il2CppMetadataUsageList[] metadataUsageLists; private Il2CppMetadataUsagePair[] metadataUsagePairs; @@ -69,8 +72,10 @@ namespace Il2CppDumper methodDefs = ReadMetadataClassArray(metadataHeader.methodsOffset, metadataHeader.methodsCount); parameterDefs = ReadMetadataClassArray(metadataHeader.parametersOffset, metadataHeader.parametersCount); fieldDefs = ReadMetadataClassArray(metadataHeader.fieldsOffset, metadataHeader.fieldsCount); - fieldDefaultValues = ReadMetadataClassArray(metadataHeader.fieldDefaultValuesOffset, metadataHeader.fieldDefaultValuesCount); - parameterDefaultValues = ReadMetadataClassArray(metadataHeader.parameterDefaultValuesOffset, metadataHeader.parameterDefaultValuesCount); + var fieldDefaultValues = ReadMetadataClassArray(metadataHeader.fieldDefaultValuesOffset, metadataHeader.fieldDefaultValuesCount); + var parameterDefaultValues = ReadMetadataClassArray(metadataHeader.parameterDefaultValuesOffset, metadataHeader.parameterDefaultValuesCount); + fieldDefaultValuesDic = fieldDefaultValues.ToDictionary(x => x.fieldIndex); + parameterDefaultValuesDic = parameterDefaultValues.ToDictionary(x => x.parameterIndex); propertyDefs = ReadMetadataClassArray(metadataHeader.propertiesOffset, metadataHeader.propertiesCount); interfaceIndices = ReadClassArray(metadataHeader.interfacesOffset, metadataHeader.interfacesCount / 4); nestedTypeIndices = ReadClassArray(metadataHeader.nestedTypesOffset, metadataHeader.nestedTypesCount / 4); @@ -94,6 +99,20 @@ namespace Il2CppDumper attributeTypeRanges = ReadMetadataClassArray(metadataHeader.attributesInfoOffset, metadataHeader.attributesInfoCount); attributeTypes = ReadClassArray(metadataHeader.attributeTypesOffset, metadataHeader.attributeTypesCount / 4); } + if (Version > 24) + { + attributeTypeRangesDic = new Dictionary>(); + foreach (var imageDef in imageDefs) + { + var dic = new Dictionary(); + attributeTypeRangesDic[imageDef] = dic; + var end = imageDef.customAttributeStart + imageDef.customAttributeCount; + for (int i = imageDef.customAttributeStart; i < end; i++) + { + dic.Add(attributeTypeRanges[i].token, i); + } + } + } } private T[] ReadMetadataClassArray(uint addr, int count) where T : new() @@ -101,14 +120,14 @@ namespace Il2CppDumper return ReadClassArray(addr, count / MySizeOf(typeof(T))); } - public Il2CppFieldDefaultValue GetFieldDefaultValueFromIndex(int index) + public bool GetFieldDefaultValueFromIndex(int index, out Il2CppFieldDefaultValue value) { - return fieldDefaultValues.FirstOrDefault(x => x.fieldIndex == index); + return fieldDefaultValuesDic.TryGetValue(index, out value); } - public Il2CppParameterDefaultValue GetParameterDefaultValueFromIndex(int index) + public bool GetParameterDefaultValueFromIndex(int index, out Il2CppParameterDefaultValue value) { - return parameterDefaultValues.FirstOrDefault(x => x.parameterIndex == index); + return parameterDefaultValuesDic.TryGetValue(index, out value); } public uint GetDefaultValueFromIndex(int index) @@ -130,15 +149,14 @@ namespace Il2CppDumper { if (Version > 24) { - var end = imageDef.customAttributeStart + imageDef.customAttributeCount; - for (int i = imageDef.customAttributeStart; i < end; i++) + if (attributeTypeRangesDic[imageDef].TryGetValue(token, out var index)) { - if (attributeTypeRanges[i].token == token) - { - return i; - } + return index; + } + else + { + return -1; } - return -1; } else { diff --git a/Il2CppDumper/Il2CppDumper.csproj b/Il2CppDumper/Il2CppDumper.csproj index dbb5b18..ae9148c 100644 --- a/Il2CppDumper/Il2CppDumper.csproj +++ b/Il2CppDumper/Il2CppDumper.csproj @@ -66,6 +66,7 @@ + diff --git a/Il2CppDumper/Outputs/Il2CppDecompiler.cs b/Il2CppDumper/Outputs/Il2CppDecompiler.cs index 0cf507d..bbba040 100644 --- a/Il2CppDumper/Outputs/Il2CppDecompiler.cs +++ b/Il2CppDumper/Outputs/Il2CppDecompiler.cs @@ -39,29 +39,13 @@ namespace Il2CppDumper for (int typeDefIndex = imageDef.typeStart; typeDefIndex < typeEnd; typeDefIndex++) { var typeDef = metadata.typeDefs[typeDefIndex]; - var isValueType = false; - var isEnum = false; var extends = new List(); if (typeDef.parentIndex >= 0) { var parent = il2Cpp.types[typeDef.parentIndex]; - var parentFullName = executor.GetTypeName(parent, true, false); - if (parentFullName == "System.ValueType") + var parentName = executor.GetTypeName(parent, false, false); + if (!typeDef.IsValueType && !typeDef.IsEnum && parentName != "object") { - var typeFullName = executor.GetTypeDefName(typeDef, true, true); - if (typeFullName != "System.Enum") - { - isValueType = true; - } - } - else if (parentFullName == "System.Enum") - { - isValueType = true; - isEnum = true; - } - else if (parentFullName != "object") - { - var parentName = executor.GetTypeName(parent, false, false); extends.Add(parentName); } } @@ -106,13 +90,13 @@ namespace Il2CppDumper writer.Write("static "); else if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) == 0 && (typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0) writer.Write("abstract "); - else if (!isValueType && !isEnum && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0) + else if (!typeDef.IsValueType && !typeDef.IsEnum && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0) writer.Write("sealed "); if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0) writer.Write("interface "); - else if (isEnum) + else if (typeDef.IsEnum) writer.Write("enum "); - else if (isValueType) + else if (typeDef.IsValueType) writer.Write("struct "); else writer.Write("class "); @@ -133,7 +117,6 @@ namespace Il2CppDumper { var fieldDef = metadata.fieldDefs[i]; var fieldType = il2Cpp.types[fieldDef.typeIndex]; - var fieldDefaultValue = metadata.GetFieldDefaultValueFromIndex(i); if (config.DumpAttribute) { writer.Write(GetCustomAttribute(imageDef, fieldDef.customAttributeIndex, fieldDef.token, "\t")); @@ -171,7 +154,7 @@ namespace Il2CppDumper writer.Write("readonly "); } writer.Write($"{executor.GetTypeName(fieldType, false, false)} {metadata.GetStringFromIndex(fieldDef.nameIndex)}"); - if (fieldDefaultValue != null && fieldDefaultValue.dataIndex != -1) + if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefaultValue) && fieldDefaultValue.dataIndex != -1) { if (TryGetDefaultValue(fieldDefaultValue.typeIndex, fieldDefaultValue.dataIndex, out var value)) { @@ -196,7 +179,7 @@ namespace Il2CppDumper } } if (config.DumpFieldOffset) - writer.Write("; // 0x{0:X}\n", il2Cpp.GetFieldOffsetFromIndex(typeDefIndex, i - typeDef.fieldStart, i, isValueType)); + writer.Write("; // 0x{0:X}\n", il2Cpp.GetFieldOffsetFromIndex(typeDefIndex, i - typeDef.fieldStart, i, typeDef.IsValueType)); else writer.Write(";\n"); } @@ -315,8 +298,7 @@ namespace Il2CppDumper } } parameterStr += $"{parameterTypeName} {parameterName}"; - var parameterDefault = metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j); - if (parameterDefault != null && parameterDefault.dataIndex != -1) + if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1) { if (TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value)) { diff --git a/Il2CppDumper/Utils/DummyAssemblyGenerator.cs b/Il2CppDumper/Utils/DummyAssemblyGenerator.cs index 48da96a..7ac9303 100644 --- a/Il2CppDumper/Utils/DummyAssemblyGenerator.cs +++ b/Il2CppDumper/Utils/DummyAssemblyGenerator.cs @@ -128,8 +128,7 @@ namespace Il2CppDumper typeDefinition.Fields.Add(fieldDefinition); fieldDefinitionDic.Add(i, fieldDefinition); //fieldDefault - var fieldDefault = metadata.GetFieldDefaultValueFromIndex(i); - if (fieldDefault != null && fieldDefault.dataIndex != -1) + if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefault) && fieldDefault.dataIndex != -1) { if (TryGetDefaultValue(fieldDefault.typeIndex, fieldDefault.dataIndex, out var value)) { @@ -199,8 +198,7 @@ namespace Il2CppDumper methodDefinition.Parameters.Add(parameterDefinition); parameterDefinitionDic.Add(methodDef.parameterStart + j, parameterDefinition); //ParameterDefault - var parameterDefault = metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j); - if (parameterDefault != null && parameterDefault.dataIndex != -1) + if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1) { if (TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value)) { diff --git a/Il2CppDumper/Utils/Il2CppExecutor.cs b/Il2CppDumper/Utils/Il2CppExecutor.cs index e9036cc..38cd1d8 100644 --- a/Il2CppDumper/Utils/Il2CppExecutor.cs +++ b/Il2CppDumper/Utils/Il2CppExecutor.cs @@ -6,6 +6,7 @@ namespace Il2CppDumper { public Metadata metadata; public Il2Cpp il2Cpp; + private Dictionary GenericInstParamsCache = new Dictionary(); private static readonly Dictionary TypeString = new Dictionary { {1,"void"}, @@ -170,14 +171,19 @@ namespace Il2CppDumper public string GetGenericInstParams(Il2CppGenericInst genericInst) { - var typeNames = new List(); - var pointers = il2Cpp.MapVATR(genericInst.type_argv, genericInst.type_argc); - for (uint i = 0; i < genericInst.type_argc; ++i) + if (!GenericInstParamsCache.TryGetValue(genericInst, out var value)) { - var oriType = il2Cpp.GetIl2CppType(pointers[i]); - typeNames.Add(GetTypeName(oriType, false, false)); + var typeNames = new List(); + var pointers = il2Cpp.MapVATR(genericInst.type_argv, genericInst.type_argc); + for (uint i = 0; i < genericInst.type_argc; ++i) + { + var oriType = il2Cpp.GetIl2CppType(pointers[i]); + typeNames.Add(GetTypeName(oriType, false, false)); + } + value = $"<{string.Join(", ", typeNames)}>"; + GenericInstParamsCache.Add(genericInst, value); } - return $"<{string.Join(", ", typeNames)}>"; + return value; } } } diff --git a/Il2CppDumper/Utils/ReadCache.cs b/Il2CppDumper/Utils/ReadCache.cs new file mode 100644 index 0000000..db3a2c1 --- /dev/null +++ b/Il2CppDumper/Utils/ReadCache.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Il2CppDumper +{ + internal static class ReadClassCache + { + private static Dictionary CacheInstance; + + public static void Add(ulong key, T value) + { + if (CacheInstance == null) + { + CacheInstance = new Dictionary(); + } + CacheInstance.Add(key, value); + } + + public static bool TryGetValue(ulong key, out T value) + { + if (CacheInstance == null) + { + CacheInstance = new Dictionary(); + } + return CacheInstance.TryGetValue(key, out value); + } + } +}