From 5ab028807c3fd483a3862561d3f8b743ca487a08 Mon Sep 17 00:00:00 2001 From: Perfare Date: Fri, 19 Jun 2020 12:04:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=B3=9B=E5=9E=8B=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Il2CppDumper/Il2Cpp/Il2Cpp.cs | 16 +++-- Il2CppDumper/Outputs/Il2CppDecompiler.cs | 8 ++- Il2CppDumper/Outputs/ScriptGenerator.cs | 85 ++++++++++++++++++------ Il2CppDumper/Utils/Il2CppExecutor.cs | 23 +++++-- 4 files changed, 97 insertions(+), 35 deletions(-) diff --git a/Il2CppDumper/Il2Cpp/Il2Cpp.cs b/Il2CppDumper/Il2Cpp/Il2Cpp.cs index 3d147f6..2eb9fc1 100644 --- a/Il2CppDumper/Il2Cpp/Il2Cpp.cs +++ b/Il2CppDumper/Il2Cpp/Il2Cpp.cs @@ -20,9 +20,11 @@ namespace Il2CppDumper private Dictionary typeDic = new Dictionary(); public ulong[] metadataUsages; private Il2CppGenericMethodFunctionsDefinitions[] genericMethodTable; + public ulong[] genericInstPointers; public Il2CppGenericInst[] genericInsts; public Il2CppMethodSpec[] methodSpecs; - public Dictionary> genericMethoddDictionary = new Dictionary>(); + public Dictionary> methodDefinitionMethodSpecs = new Dictionary>(); + public Dictionary methodSpecGenericMethodPointers = new Dictionary(); private bool fieldOffsetsArePointers; protected long maxMetadataUsages; private Il2CppCodeGenModule[] codeGenModules; @@ -94,7 +96,8 @@ namespace Il2CppDumper if (pCodeRegistration.unresolvedVirtualCallCount != 0) unresolvedVirtualCallPointers = MapVATR(pCodeRegistration.unresolvedVirtualCallPointers, pCodeRegistration.unresolvedVirtualCallCount); } - genericInsts = Array.ConvertAll(MapVATR(pMetadataRegistration.genericInsts, pMetadataRegistration.genericInstsCount), x => MapVATR(x)); + genericInstPointers = MapVATR(pMetadataRegistration.genericInsts, pMetadataRegistration.genericInstsCount); + genericInsts = Array.ConvertAll(genericInstPointers, MapVATR); fieldOffsetsArePointers = Version > 21; if (Version == 21) { @@ -147,12 +150,13 @@ namespace Il2CppDumper { var methodSpec = methodSpecs[table.genericMethodIndex]; var methodDefinitionIndex = methodSpec.methodDefinitionIndex; - if (!genericMethoddDictionary.TryGetValue(methodDefinitionIndex, out var tuple)) + if (!methodDefinitionMethodSpecs.TryGetValue(methodDefinitionIndex, out var list)) { - tuple = new List<(Il2CppMethodSpec, ulong)>(); - genericMethoddDictionary.Add(methodDefinitionIndex, tuple); + list = new List(); + methodDefinitionMethodSpecs.Add(methodDefinitionIndex, list); } - tuple.Add((methodSpec, genericMethodPointers[table.indices.methodIndex])); + list.Add(methodSpec); + methodSpecGenericMethodPointers.Add(methodSpec, genericMethodPointers[table.indices.methodIndex]); } } diff --git a/Il2CppDumper/Outputs/Il2CppDecompiler.cs b/Il2CppDumper/Outputs/Il2CppDecompiler.cs index 278e8be..0d75d4c 100644 --- a/Il2CppDumper/Outputs/Il2CppDecompiler.cs +++ b/Il2CppDumper/Outputs/Il2CppDecompiler.cs @@ -335,12 +335,13 @@ namespace Il2CppDumper writer.Write(string.Join(", ", parameterStrs)); writer.Write(") { }\n"); - if (il2Cpp.genericMethoddDictionary.TryGetValue(i, out var genericMethods)) + if (il2Cpp.methodDefinitionMethodSpecs.TryGetValue(i, out var methodSpecs)) { writer.Write("\t/* GenericInstMethod :\n"); - foreach ((var methodSpec, var genericMethodPointer) in genericMethods) + foreach (var methodSpec in methodSpecs) { writer.Write("\t|\n"); + var genericMethodPointer = il2Cpp.methodSpecGenericMethodPointers[methodSpec]; if (genericMethodPointer > 0) { var fixedPointer = il2Cpp.GetRVA(genericMethodPointer); @@ -350,7 +351,8 @@ namespace Il2CppDumper { writer.Write("\t|-RVA: -1 Offset: -1\n"); } - writer.Write($"\t|-{executor.GetMethodSpecMethodName(methodSpec)}\n"); + (var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec); + writer.Write($"\t|-{methodSpecTypeName}.{methodSpecMethodName}\n"); } writer.Write("\t*/\n"); } diff --git a/Il2CppDumper/Outputs/ScriptGenerator.cs b/Il2CppDumper/Outputs/ScriptGenerator.cs index 9bff1c9..039bf33 100644 --- a/Il2CppDumper/Outputs/ScriptGenerator.cs +++ b/Il2CppDumper/Outputs/ScriptGenerator.cs @@ -37,6 +37,7 @@ namespace Il2CppDumper public void WriteScript(Config config) { var json = new ScriptJson(); + // 生成唯一名称 for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++) { var imageDef = metadata.imageDefs[imageIndex]; @@ -44,9 +45,21 @@ namespace Il2CppDumper for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++) { var typeDef = metadata.typeDefs[typeIndex]; + typeDefImageIndices.Add(typeDef, imageIndex); CreateStructNameDic(typeDef); } } + // 处理类定义 + foreach (var typeDef in metadata.typeDefs) + { + AddStruct(typeDef); + } + // 处理泛型实例类 + foreach (var genericClass in il2Cpp.types.Where(x => x.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST)) + { + ParseType(genericClass); + } + // 处理函数 for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++) { var imageDef = metadata.imageDefs[imageIndex]; @@ -54,9 +67,7 @@ namespace Il2CppDumper for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++) { var typeDef = metadata.typeDefs[typeIndex]; - AddStruct(typeDef); var typeName = executor.GetTypeDefName(typeDef, true, true); - typeDefImageIndices.Add(typeDef, imageIndex); var methodEnd = typeDef.methodStart + typeDef.method_count; for (var i = typeDef.methodStart; i < methodEnd; ++i) { @@ -91,9 +102,54 @@ namespace Il2CppDumper signature += ");"; scriptMethod.Signature = signature; } + //泛型实例函数 + if (il2Cpp.methodDefinitionMethodSpecs.TryGetValue(i, out var methodSpecs)) + { + foreach (var methodSpec in methodSpecs) + { + var genericMethodPointer = il2Cpp.methodSpecGenericMethodPointers[methodSpec]; + if (genericMethodPointer > 0) + { + var scriptMethod = new ScriptMethod(); + json.ScriptMethod.Add(scriptMethod); + scriptMethod.Address = il2Cpp.GetRVA(genericMethodPointer); + (var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec, true); + var methodFullName = methodSpecTypeName + "$$" + methodSpecMethodName; + scriptMethod.Name = methodFullName; + + var genericContext = executor.GetMethodSpecGenericContext(methodSpec); + var methodReturnType = il2Cpp.types[methodDef.returnType]; + var returnType = ParseType(methodReturnType, genericContext); + var signature = $"{returnType} {FixName(methodFullName)} ("; + var parameterStrs = new List(); + if (il2Cpp.Version <= 22f || (methodDef.flags & METHOD_ATTRIBUTE_STATIC) == 0) + { + var thisType = ParseType(il2Cpp.types[typeDef.byrefTypeIndex]); + if (methodSpec.classIndexIndex != -1) + { + var typeToReplaceName = FixName(typeName); + var typeReplaceName = FixName(methodSpecTypeName); + thisType = thisType.Replace(typeToReplaceName, typeReplaceName); + } + parameterStrs.Add($"{thisType} __this"); + } + for (var j = 0; j < methodDef.parameterCount; j++) + { + var parameterDef = metadata.parameterDefs[methodDef.parameterStart + j]; + var parameterName = metadata.GetStringFromIndex(parameterDef.nameIndex); + var parameterType = il2Cpp.types[parameterDef.typeIndex]; + parameterStrs.Add($"{ParseType(parameterType, genericContext)} {FixName(parameterName)}"); + } + signature += string.Join(", ", parameterStrs); + signature += ");"; + scriptMethod.Signature = signature; + } + } + } } } } + // 处理MetadataUsage if (il2Cpp.Version > 16) { foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo @@ -177,30 +233,15 @@ namespace Il2CppDumper foreach (var i in metadata.metadataUsageDic[6]) //kIl2CppMetadataUsageMethodRef { var methodSpec = il2Cpp.methodSpecs[i.Value]; - var methodDef = metadata.methodDefs[methodSpec.methodDefinitionIndex]; - var typeDef = metadata.typeDefs[methodDef.declaringType]; - var typeName = executor.GetTypeDefName(typeDef, true, false); - if (methodSpec.classIndexIndex != -1) - { - var classInst = il2Cpp.genericInsts[methodSpec.classIndexIndex]; - typeName += executor.GetGenericInstParams(classInst); - } - var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex); - if (methodSpec.methodIndexIndex != -1) - { - var methodInst = il2Cpp.genericInsts[methodSpec.methodIndexIndex]; - methodName += executor.GetGenericInstParams(methodInst); - } - methodName += "()"; var scriptMetadataMethod = new ScriptMetadataMethod(); json.ScriptMetadataMethod.Add(scriptMetadataMethod); scriptMetadataMethod.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]); - scriptMetadataMethod.Name = "Method$" + methodName; - var imageIndex = typeDefImageIndices[typeDef]; - var methodPointer = il2Cpp.GetMethodPointer(methodDef, imageIndex); - if (methodPointer > 0) + (var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec, true); + scriptMetadataMethod.Name = "Method$" + methodSpecTypeName + "." + methodSpecMethodName + "()"; + var genericMethodPointer = il2Cpp.methodSpecGenericMethodPointers[methodSpec]; + if (genericMethodPointer > 0) { - scriptMetadataMethod.MethodAddress = il2Cpp.GetRVA(methodPointer); + scriptMetadataMethod.MethodAddress = il2Cpp.GetRVA(genericMethodPointer); } } } diff --git a/Il2CppDumper/Utils/Il2CppExecutor.cs b/Il2CppDumper/Utils/Il2CppExecutor.cs index 77a90c7..5fba503 100644 --- a/Il2CppDumper/Utils/Il2CppExecutor.cs +++ b/Il2CppDumper/Utils/Il2CppExecutor.cs @@ -178,23 +178,38 @@ namespace Il2CppDumper return $"<{string.Join(", ", genericParameterNames)}>"; } - public string GetMethodSpecMethodName(Il2CppMethodSpec methodSpec) + public (string, string) GetMethodSpecName(Il2CppMethodSpec methodSpec, bool addNamespace = false) { var methodDef = metadata.methodDefs[methodSpec.methodDefinitionIndex]; var typeDef = metadata.typeDefs[methodDef.declaringType]; - var typeName = GetTypeDefName(typeDef, false, false); + var typeName = GetTypeDefName(typeDef, addNamespace, false); if (methodSpec.classIndexIndex != -1) { var classInst = il2Cpp.genericInsts[methodSpec.classIndexIndex]; typeName += GetGenericInstParams(classInst); } - var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex); + var methodName = metadata.GetStringFromIndex(methodDef.nameIndex); if (methodSpec.methodIndexIndex != -1) { var methodInst = il2Cpp.genericInsts[methodSpec.methodIndexIndex]; methodName += GetGenericInstParams(methodInst); } - return methodName; + return (typeName, methodName); + } + + public Il2CppGenericContext GetMethodSpecGenericContext(Il2CppMethodSpec methodSpec) + { + var classInstPointer = 0ul; + var methodInstPointer = 0ul; + if (methodSpec.classIndexIndex != -1) + { + classInstPointer = il2Cpp.genericInstPointers[methodSpec.classIndexIndex]; + } + if (methodSpec.methodIndexIndex != -1) + { + methodInstPointer = il2Cpp.genericInstPointers[methodSpec.methodIndexIndex]; + } + return new Il2CppGenericContext { class_inst = classInstPointer, method_inst = methodInstPointer }; } } }