From 20d0ffcdfe7ce609ca052a7bb3e484cfd4bc3dfc Mon Sep 17 00:00:00 2001 From: Katy Coe Date: Mon, 13 Jul 2020 17:55:32 +0200 Subject: [PATCH] AppModel: Move C++ type ordering to model --- .../Cpp/CppDeclarationGenerator.cs | 19 +++++--------- Il2CppInspector.Common/Model/AppModel.cs | 26 +++++++++++++++---- .../Outputs/IDAPythonScript.cs | 6 ++++- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs b/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs index 5625854..10f92ed 100644 --- a/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs +++ b/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs @@ -245,19 +245,16 @@ namespace Il2CppInspector.Cpp } // "Flush" the list of visited types, generating C structures for each one - private List GenerateVisitedFieldStructs() { - var structs = new List(TodoTypeStructs.Count); + private List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType)> GenerateVisitedFieldStructs() { + var structs = new List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType)>(TodoTypeStructs.Count); foreach (var ti in TodoFieldStructs) { if (ti.IsEnum || ti.IsValueType) { var (valueType, boxedType) = GenerateValueFieldStruct(ti); - structs.Add(valueType); - structs.Add(boxedType); + structs.Add((ti, valueType, boxedType, null)); } else { var (objectOrArrayType, fieldsType) = GenerateRefFieldStruct(ti); - if (fieldsType != null) - structs.Add(fieldsType); - structs.Add(objectOrArrayType); + structs.Add((ti, null, objectOrArrayType, fieldsType)); } } TodoFieldStructs.Clear(); @@ -435,14 +432,12 @@ namespace Il2CppInspector.Cpp /// Type declarations that have previously been generated by this instance of CppDeclarationGenerator will not be generated again. /// /// A string containing C type declarations - public List GenerateRemainingTypeDeclarations() { - var decl = GenerateVisitedFieldStructs(); + public List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType, CppType vtableType, CppType staticsType)> GenerateRemainingTypeDeclarations() { + var decl = GenerateVisitedFieldStructs().Select(s => (s.ilType, s.valueType, s.referenceType, s.fieldsType, (CppType) null, (CppType) null)).ToList(); foreach (var ti in TodoTypeStructs) { var (cls, statics, vtable) = GenerateTypeStruct(ti); - decl.Add(vtable); - decl.Add(statics); - decl.Add(cls); + decl.Add((ti, null, cls, null, vtable, statics)); } TodoTypeStructs.Clear(); diff --git a/Il2CppInspector.Common/Model/AppModel.cs b/Il2CppInspector.Common/Model/AppModel.cs index efacd33..803b5ec 100644 --- a/Il2CppInspector.Common/Model/AppModel.cs +++ b/Il2CppInspector.Common/Model/AppModel.cs @@ -49,7 +49,7 @@ namespace Il2CppInspector.Model // All of the C++ types used in the application including Unity internal types // NOTE: This is for querying individual types for static analysis - // To generate code output, use DeclarationOrderedTypes + // To generate code output, use DependencyOrderedTypes public CppTypeCollection TypeCollection { get; set; } // TODO: Change to private set after integrating IDA output // All of the C++ types used in the application (.NET type translations only) @@ -130,7 +130,7 @@ namespace Il2CppInspector.Model foreach (var method in ILModel.MethodsByDefinitionIndex.Where(m => m.VirtualAddress.HasValue)) { declarationGenerator.IncludeMethod(method); - DependencyOrderedTypes.AddRange(declarationGenerator.GenerateRemainingTypeDeclarations()); + AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations()); var fnPtr = declarationGenerator.GenerateMethodDeclaration(method); Methods.Add(method, fnPtr, new AppMethod(method, fnPtr)); @@ -141,7 +141,7 @@ namespace Il2CppInspector.Model foreach (var method in ILModel.GenericMethods.Values.Where(m => m.VirtualAddress.HasValue)) { declarationGenerator.IncludeMethod(method); - DependencyOrderedTypes.AddRange(declarationGenerator.GenerateRemainingTypeDeclarations()); + AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations()); var fnPtr = declarationGenerator.GenerateMethodDeclaration(method); Methods.Add(method, fnPtr, new AppMethod(method, fnPtr)); @@ -160,13 +160,13 @@ namespace Il2CppInspector.Model case MetadataUsageType.TypeInfo: var type = ILModel.GetMetadataUsageType(usage); declarationGenerator.IncludeType(type); - DependencyOrderedTypes.AddRange(declarationGenerator.GenerateRemainingTypeDeclarations()); + AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations()); break; case MetadataUsageType.MethodDef: case MetadataUsageType.MethodRef: var method = ILModel.GetMetadataUsageMethod(usage); declarationGenerator.IncludeMethod(method); - DependencyOrderedTypes.AddRange(declarationGenerator.GenerateRemainingTypeDeclarations()); + AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations()); Methods[method].MethodInfoPtrAddress = address; break; @@ -179,6 +179,22 @@ namespace Il2CppInspector.Model return this; } + private void AddTypes(List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType, CppType vtableType, CppType staticsType)> types) { + foreach (var type in types) { + if (type.vtableType != null) + DependencyOrderedTypes.Add(type.vtableType); + if (type.staticsType != null) + DependencyOrderedTypes.Add(type.staticsType); + + if (type.fieldsType != null) + DependencyOrderedTypes.Add(type.fieldsType); + if (type.valueType != null) + DependencyOrderedTypes.Add(type.valueType); + + DependencyOrderedTypes.Add(type.referenceType); + } + } + // Get all the types for a group public IEnumerable GetTypeGroup(string groupName) => TypeCollection.GetTypeGroup(groupName); public IEnumerable GetDependencyOrderedTypeGroup(string groupName) => DependencyOrderedTypes.Where(t => t.Group == groupName); diff --git a/Il2CppInspector.Common/Outputs/IDAPythonScript.cs b/Il2CppInspector.Common/Outputs/IDAPythonScript.cs index 4b51b97..6aae6f0 100755 --- a/Il2CppInspector.Common/Outputs/IDAPythonScript.cs +++ b/Il2CppInspector.Common/Outputs/IDAPythonScript.cs @@ -226,7 +226,11 @@ typedef __int64 int64_t; } // TODO: Temporary compatibility function, remove when integrated with ApplicationModel - private void writeDecls(List types) => writeDecls(string.Join("\n", types.Select(t => t.ToString()))); + private void writeDecls(List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType, CppType vtableType, CppType staticsType)> types) + => writeDecls(string.Join("\n", + types.SelectMany(t => new List {t.vtableType, t.staticsType, t.fieldsType, t.valueType, t.referenceType}) + .Where(t => t != null) + .Select(t => t.ToString()))); private void writeName(ulong address, string name) { writeLine($"SetName({address.ToAddressString()}, r'{name.ToEscapedString()}')");