From deeb8daa976f5a716543a86776275b47a1713f35 Mon Sep 17 00:00:00 2001 From: Katy Coe Date: Wed, 22 Jul 2020 19:01:33 +0200 Subject: [PATCH] Unity/C++: Significant re-factoring of Unity header management (see description) Extract resource handling to UnityResource Add API header resource helpers Fix UnityVersion ToString() when Min == Max Replace fixed list of Il2Cpp header reserved names with parsed names from actual selected headers (solves TypeInfo/MemberInfo problems in 5.3.0-5.3.4 (metadata v16-20)) Use CppDeclarationGenerator when initializing CppTypeCollection to ensure all Il2Cpp header symbols are reserved Process API headers in CppTypeCollection.FromUnityHeaders Move #define IS_32BIT handling to UnityHeaders Update tests --- .../Cpp/CppDeclarationGenerator.cs | 13 +- .../Cpp/CppTypeCollection.cs | 36 ++++- .../Cpp/UnityHeaders/UnityHeader.cs | 93 ----------- .../Cpp/UnityHeaders/UnityHeaders.cs | 152 ++++++++++++++++++ .../Cpp/UnityHeaders/UnityVersion.cs | 3 +- Il2CppInspector.Common/Model/AppModel.cs | 25 ++- .../Outputs/CppScaffolding.cs | 9 +- .../Outputs/IDAPythonScript.cs | 4 +- Il2CppInspector.Common/ResourceHelper.cs | 1 - Il2CppInspector.GUI/MainWindow.xaml.cs | 6 +- Il2CppTests/TestCppTypeDeclarations.cs | 12 +- Il2CppTests/TestUnityVersion.cs | 4 +- 12 files changed, 216 insertions(+), 142 deletions(-) delete mode 100644 Il2CppInspector.Common/Cpp/UnityHeaders/UnityHeader.cs create mode 100644 Il2CppInspector.Common/Cpp/UnityHeaders/UnityHeaders.cs diff --git a/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs b/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs index ef77200..e9eb0f7 100644 --- a/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs +++ b/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs @@ -16,13 +16,16 @@ using Il2CppInspector.Reflection; namespace Il2CppInspector.Cpp { // Class for generating C header declarations from Reflection objects (TypeInfo, etc.) - internal class CppDeclarationGenerator + public class CppDeclarationGenerator { private readonly AppModel appModel; private TypeModel model => appModel.ILModel; private CppTypeCollection types => appModel.CppTypeCollection; + // Word size (32/64-bit) for this generator + public int WordSize => appModel.WordSize; + // Version number and header file to generate structures for public UnityVersion UnityVersion => appModel.UnityVersion; @@ -63,7 +66,7 @@ namespace Il2CppInspector.Cpp public CppType AsCType(TypeInfo ti) { // IsArray case handled by TypeNamer.GetName if (ti.IsByRef || ti.IsPointer) { - return AsCType(ti.ElementType).AsPointer(types.WordSize); + return AsCType(ti.ElementType).AsPointer(WordSize); } if (ti.IsValueType) { if (ti.IsPrimitive && primitiveTypeMap.ContainsKey(ti.Name)) { @@ -513,16 +516,10 @@ namespace Il2CppInspector.Cpp // You can customize how naming works by modifying this function. private void InitializeNaming() { TypeNamespace = CreateNamespace(); - // Type names that may appear in the header - foreach (var typeName in new [] { "CustomAttributesCache", "CustomAttributeTypeCache", "EventInfo", "FieldInfo", "Hash16", "MemberInfo", "MethodInfo", "MethodVariableKind", "MonitorData", "ParameterInfo", "PInvokeArguments", "PropertyInfo", "SequencePointKind", "StackFrameType", "VirtualInvokeData" }) { - TypeNamespace.ReserveName(typeName); - } TypeNamer = TypeNamespace.MakeNamer((ti) => { if (ti.IsArray) return TypeNamer.GetName(ti.ElementType) + "__Array"; var name = ti.Name.ToCIdentifier(); - if (name.StartsWith("Il2Cpp")) - name = "_" + name; name = Regex.Replace(name, "__+", "_"); // Work around a dumb IDA bug: enums can't be named the same as certain "built-in" types // like KeyCode, Position, ErrorType. This only applies to enums, not structs. diff --git a/Il2CppInspector.Common/Cpp/CppTypeCollection.cs b/Il2CppInspector.Common/Cpp/CppTypeCollection.cs index 891ee4e..f1fb1c5 100644 --- a/Il2CppInspector.Common/Cpp/CppTypeCollection.cs +++ b/Il2CppInspector.Common/Cpp/CppTypeCollection.cs @@ -535,6 +535,9 @@ namespace Il2CppInspector.Cpp // Get all of the types in a logical group public IEnumerable GetTypeGroup(string groupName) => Types.Values.Where(t => t.Group == groupName); + // Get all of the typedefs in a logical group + public IEnumerable GetTypedefGroup(string groupName) => TypedefAliases.Values.Where(t => t.Group == groupName); + // Add a type private void Add(CppType type) { type.Group = currentGroup; @@ -578,22 +581,45 @@ namespace Il2CppInspector.Cpp public CppEnumType NewDefaultEnum(string name = "") => Enum(Types["int"], name); // Generate a populated CppTypeCollection object from a set of Unity headers - public static CppTypeCollection FromUnityVersion(UnityVersion version, int wordSize = 32) - => FromUnityHeaders(UnityHeader.GetHeaderForVersion(version), wordSize); + // The CppDeclarationGenerator is used to ensure that the Unity header type names are not used again afterwards + // Omit this parameter only when fetching headers for inspection without a model + public static CppTypeCollection FromUnityVersion(UnityVersion version, CppDeclarationGenerator declGen = null) + => FromUnityHeaders(UnityHeaders.UnityHeaders.GetHeadersForVersion(version), declGen); - public static CppTypeCollection FromUnityHeaders(UnityHeader header, int wordSize = 32) { + public static CppTypeCollection FromUnityHeaders(UnityHeaders.UnityHeaders header, CppDeclarationGenerator declGen = null) { + var wordSize = declGen?.WordSize ?? 64; var cppTypes = new CppTypeCollection(wordSize); + // Process Unity headers cppTypes.SetGroup("il2cpp"); // Add junk from config files we haven't included cppTypes.TypedefAliases.Add("Il2CppIManagedObjectHolder", cppTypes["void"].AsPointer(wordSize)); cppTypes.TypedefAliases.Add("Il2CppIUnknown", cppTypes["void"].AsPointer(wordSize)); - // Process Unity headers - var headers = header.GetHeaderText(); + var headers = header.GetTypeHeaderText(wordSize); cppTypes.AddFromDeclarationText(headers); + // Don't allow any of the header type names to be re-used; ignore primitive types + foreach (var type in cppTypes.GetTypeGroup("il2cpp")) + declGen?.TypeNamespace.ReserveName(type.Name); + + foreach (var typedef in cppTypes.GetTypedefGroup("il2cpp")) + declGen?.GlobalsNamespace.ReserveName(typedef.Name); + + cppTypes.SetGroup("il2cpp-api"); + + var apis = header.GetAPIHeaderTypedefText(); + cppTypes.AddFromDeclarationText(apis); + + foreach (var type in cppTypes.GetTypeGroup("il2cpp-api")) + declGen?.TypeNamespace.ReserveName(type.Name); + + foreach (var typedef in cppTypes.GetTypedefGroup("il2cpp-api")) + declGen?.GlobalsNamespace.ReserveName(typedef.Name); + + cppTypes.SetGroup(""); + return cppTypes; } } diff --git a/Il2CppInspector.Common/Cpp/UnityHeaders/UnityHeader.cs b/Il2CppInspector.Common/Cpp/UnityHeaders/UnityHeader.cs deleted file mode 100644 index 0e522f3..0000000 --- a/Il2CppInspector.Common/Cpp/UnityHeaders/UnityHeader.cs +++ /dev/null @@ -1,93 +0,0 @@ -/* - Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty - Copyright 2020 Robert Xiao - https://robertxiao.ca - - All rights reserved. -*/ - -using System.Reflection; -using System.IO; -using System.Linq; -using System.Collections.Generic; -using System.Globalization; - -namespace Il2CppInspector.Cpp.UnityHeaders -{ - // Each instance of UnityHeader represents one header file which potentially covers multiple versions of Unity. - public class UnityHeader - { - // Metadata version of this header. Multiple headers may have the same metadata version - public double MetadataVersion { get; } - - // Minimum and maximum Unity version numbers corresponding to this header. Both endpoints are inclusive - public UnityVersionRange Version { get; } - - // Filename for the embedded .h resource file containing the header - public string HeaderFilename { get; } - - private UnityHeader(string headerFilename) { - HeaderFilename = headerFilename; - Version = UnityVersionRange.FromFilename(HeaderFilename); - MetadataVersion = double.Parse(headerFilename.Split("-")[0], NumberFormatInfo.InvariantInfo); - } - - public override string ToString() => Version.ToString(); - - // Return the contents of this header file as a string - public string GetHeaderText() { - var str = ResourceHelper.GetText(typeof(UnityHeader).Namespace + "." + HeaderFilename); - - // Versions 5.3.6-5.4.6 don't include a definition for VirtualInvokeData - if (Version.Min.CompareTo("5.3.6") >= 0 && Version.Max.CompareTo("5.4.6") <= 0) { - str = str + @"struct VirtualInvokeData -{ - Il2CppMethodPointer methodPtr; - const MethodInfo* method; -} VirtualInvokeData;"; - } - return str; - } - - // List all header files embedded into this build of Il2CppInspector - public static IEnumerable GetAllHeaders() => ResourceHelper.GetNamesForNamespace(typeof(UnityHeader).Namespace) - .Where(s => s.EndsWith(".h")) - .Select(s => new UnityHeader(s.Substring(typeof(UnityHeader).Namespace.Length + 1))); - - // List all API header files and versions embedded into this build of Il2CppInspector - public static Dictionary GetAllAPIs() { - var list = ResourceHelper.GetNamesForNamespace("Il2CppInspector.Cpp.Il2CppAPIHeaders"); - return list.Select(i => new { - Key = i, - Value = UnityVersionRange.FromFilename(i), - }).ToDictionary(kv => kv.Key, kv => kv.Value); - } - - // Get the header file which supports the given version of Unity - public static UnityHeader GetHeaderForVersion(string version) => GetHeaderForVersion(new UnityVersion(version)); - public static UnityHeader GetHeaderForVersion(UnityVersion version) => GetAllHeaders().First(h => h.Version.Contains(version)); - - // Get API file resources - public static string GetAPIResourceNameForVersion(UnityVersion version) => GetAllAPIs().First(h => h.Value.Contains(version)).Key; - public static string GetAPITextForVersion(UnityVersion version) => ResourceHelper.GetText(GetAPIResourceNameForVersion(version)); - - // Guess which header file(s) correspond to the given metadata+binary. - // Note that this may match multiple headers due to structural changes between versions - // that are not reflected in the metadata version. - public static List GuessHeadersForModel(Reflection.TypeModel model) { - List result = new List(); - foreach (var h in GetAllHeaders()) { - if (h.MetadataVersion != model.Package.BinaryImage.Version) - continue; - if (h.MetadataVersion == 21) { - /* Special version logic for metadata version 21 based on the Il2CppMetadataRegistration.fieldOffsets field */ - var headerFieldOffsetsArePointers = h.Version.Min.CompareTo("5.3.7") >= 0 && h.Version.Min.CompareTo("5.4.0") != 0; - var binaryFieldOffsetsArePointers = model.Package.Binary.FieldOffsets == null; - if (headerFieldOffsetsArePointers != binaryFieldOffsetsArePointers) - continue; - } - result.Add(h); - } - return result; - } - } -} diff --git a/Il2CppInspector.Common/Cpp/UnityHeaders/UnityHeaders.cs b/Il2CppInspector.Common/Cpp/UnityHeaders/UnityHeaders.cs new file mode 100644 index 0000000..c68c42d --- /dev/null +++ b/Il2CppInspector.Common/Cpp/UnityHeaders/UnityHeaders.cs @@ -0,0 +1,152 @@ +/* + Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty + Copyright 2020 Robert Xiao - https://robertxiao.ca + + All rights reserved. +*/ + +using System; +using System.Reflection; +using System.IO; +using System.Linq; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Text.RegularExpressions; + +namespace Il2CppInspector.Cpp.UnityHeaders +{ + // Each instance of UnityHeaders represents all of the header files needed to build for a specific range of Unity versions + // Also provides helper functions to fetch various types of resources + public class UnityHeaders + { + // Metadata version for which this group of headers are valid. Multiple headers may have the same metadata version + public double MetadataVersion { get; } + + // Range of Unity versions for which this group of headers are valid + public UnityVersionRange VersionRange { get; } + + // The fully qualified names of the embedded resources + private readonly UnityResource typeHeaderResource; + private readonly UnityResource apiHeaderResource; + + // Initialize from a type header and an API header + private UnityHeaders(UnityResource typeHeaders, UnityResource apiHeaders) { + typeHeaderResource = typeHeaders; + apiHeaderResource = apiHeaders; + + VersionRange = typeHeaders.VersionRange.Intersect(apiHeaders.VersionRange); + MetadataVersion = GetMetadataVersionFromFilename(typeHeaders.Name); + } + + // Return the contents of the type header file as a string + public string GetTypeHeaderText(int WordSize) { + var str = (WordSize == 32 ? "#define IS_32BIT\n" : "") + typeHeaderResource.GetText(); + + // Versions 5.3.6-5.4.6 don't include a definition for VirtualInvokeData + if (VersionRange.Min.CompareTo("5.3.6") >= 0 && VersionRange.Max.CompareTo("5.4.6") <= 0) { + str = str + @"struct VirtualInvokeData +{ + Il2CppMethodPointer methodPtr; + const MethodInfo* method; +} VirtualInvokeData;"; + } + return str; + } + + // Return the contents of the API header file as a string + public string GetAPIHeaderText() => apiHeaderResource.GetText(); + + // Return the contents of the API header file translated to typedefs as a string + public string GetAPIHeaderTypedefText() => GetTypedefsFromAPIHeader(GetAPIHeaderText()); + + public override string ToString() => VersionRange.ToString(); + + // Class which associates an embedded resource with a range of Unity versions + public class UnityResource + { + // The fully qualified name of the embdedded resource + public string Name { get; } + + // Minimum and maximum Unity version numbers corresponding to this resource. Both endpoints are inclusive + public UnityVersionRange VersionRange { get; } + + // Get the text of this resource + public string GetText() => ResourceHelper.GetText(Name); + + public UnityResource(string name) { + Name = name; + VersionRange = UnityVersionRange.FromFilename(name); + } + + public override string ToString() => Name + " for " + VersionRange; + } + + // Static helpers + + // List all type header files embedded into this build of Il2CppInspector + public static IEnumerable GetAllTypeHeaders() => + ResourceHelper.GetNamesForNamespace(typeof(UnityHeaders).Namespace) + .Where(s => s.EndsWith(".h")) + .Select(s => new UnityResource(s)); + + // List all API header files embedded into this build of Il2CppInspector + public static IEnumerable GetAllAPIHeaders() => + ResourceHelper.GetNamesForNamespace("Il2CppInspector.Cpp.Il2CppAPIHeaders") + .Where(s => s.EndsWith(".h")) + .Select(s => new UnityResource(s)); + + // Get the headers which support the given version of Unity + public static UnityHeaders GetHeadersForVersion(UnityVersion version) => + new UnityHeaders(GetTypeHeaderForVersion(version), GetAPIHeaderForVersion(version)); + + public static UnityResource GetTypeHeaderForVersion(UnityVersion version) => GetAllTypeHeaders().First(r => r.VersionRange.Contains(version)); + + // Get the API header file which supports the given version of Unity + public static UnityResource GetAPIHeaderForVersion(UnityVersion version) => GetAllAPIHeaders().First(r => r.VersionRange.Contains(version)); + + // Guess which header file(s) correspond to the given metadata+binary. + // Note that this may match multiple headers due to structural changes between versions + // that are not reflected in the metadata version. + public static List GuessHeadersForBinary(Il2CppBinary binary) { + + List typeHeaders = new List(); + foreach (var r in GetAllTypeHeaders()) { + var metadataVersion = GetMetadataVersionFromFilename(r.Name); + + if (metadataVersion != binary.Image.Version) + continue; + if (metadataVersion == 21) { + /* Special version logic for metadata version 21 based on the Il2CppMetadataRegistration.fieldOffsets field */ + var headerFieldOffsetsArePointers = r.VersionRange.Min.CompareTo("5.3.7") >= 0 && r.VersionRange.Min.CompareTo("5.4.0") != 0; + var binaryFieldOffsetsArePointers = binary.FieldOffsets == null; + if (headerFieldOffsetsArePointers != binaryFieldOffsetsArePointers) + continue; + } + typeHeaders.Add(r); + } + + // TODO: Replace this with an implementation which searches for the correct API header + return typeHeaders.Select(t => new UnityHeaders(t, GetAPIHeaderForVersion(t.VersionRange.Min))).ToList(); + } + + // Convert il2cpp-api-functions.h from "DO_API(r, n, p)" to "typedef r (*n)(p)" + internal static string GetTypedefsFromAPIHeader(string text) { + var rgx = new Regex(@"^DO_API(?:_NO_RETURN)?\((.*?),(.*?),\s*\((.*?)\)\s*\);", RegexOptions.Multiline); + return rgx.Replace(text, "typedef $1 (*$2)($3);"); + } + + // Get a list of function names from il2cpp-api-functions.h, taking #ifs into account + private static IEnumerable GetFunctionNamesFromAPIHeaderText(string text) { + var defText = GetTypedefsFromAPIHeader(text); + var defs = new CppTypeCollection(32); // word size doesn't matter + defs.AddFromDeclarationText(defText); + + return defs.TypedefAliases.Keys; + } + + // Get the metadata version from a type header resource name + private static double GetMetadataVersionFromFilename(string resourceName) + => double.Parse(resourceName.Substring(typeof(UnityHeaders).Namespace.Length + 1).Split('-')[0], NumberFormatInfo.InvariantInfo); + } +} diff --git a/Il2CppInspector.Common/Cpp/UnityHeaders/UnityVersion.cs b/Il2CppInspector.Common/Cpp/UnityHeaders/UnityVersion.cs index 932d5b5..6d22350 100644 --- a/Il2CppInspector.Common/Cpp/UnityHeaders/UnityVersion.cs +++ b/Il2CppInspector.Common/Cpp/UnityHeaders/UnityVersion.cs @@ -6,7 +6,6 @@ */ using System; -using System.Globalization; using System.Linq; using System.Text.RegularExpressions; @@ -181,7 +180,7 @@ namespace Il2CppInspector.Cpp.UnityHeaders var res = $"{Min}"; if (Max == null) res += "+"; - else if (Max != Min) + else if (!Max.Equals(Min)) res += $" - {Max}"; return res; } diff --git a/Il2CppInspector.Common/Model/AppModel.cs b/Il2CppInspector.Common/Model/AppModel.cs index a9bd61e..7267c6b 100644 --- a/Il2CppInspector.Common/Model/AppModel.cs +++ b/Il2CppInspector.Common/Model/AppModel.cs @@ -30,7 +30,7 @@ namespace Il2CppInspector.Model // The Unity IL2CPP C++ headers for the binary // Use this for code output - public UnityHeader UnityHeader { get; private set; } + public UnityHeaders UnityHeaders { get; private set; } // All of the C++ types used in the application including Unity internal types // NOTE: This is for querying individual types for static analysis @@ -58,7 +58,7 @@ namespace Il2CppInspector.Model // The .NET type model for the application public TypeModel ILModel { get; } - // All of the function exports for the binary + // All of the symbol exports (including function exports) for the binary public List Exports { get; } // Delegated C++ types iterator @@ -79,9 +79,6 @@ namespace Il2CppInspector.Model // The compiler used to build the binary public CppCompilerType SourceCompiler => declarationGenerator.InheritanceStyle; - // The Unity header text including word size define - public string UnityHeaderText => (WordSize == 32 ? "#define IS_32BIT\n" : "") + UnityHeader.GetHeaderText(); - // The group that the next added type(s) will be placed in private string group = string.Empty; private string Group { @@ -97,7 +94,7 @@ namespace Il2CppInspector.Model // Save .NET type model ILModel = model; - // Get addresses of IL2CPP API function exports + // Get addresses of all exports Exports = model.Package.Binary.Image.GetExports()?.ToList() ?? new List(); } @@ -116,22 +113,22 @@ namespace Il2CppInspector.Model TargetCompiler = compiler == CppCompilerType.BinaryFormat ? CppCompiler.GuessFromImage(ILModel.Package.BinaryImage) : compiler; // Determine Unity version and get headers - UnityHeader = unityVersion != null ? UnityHeader.GetHeaderForVersion(unityVersion) : UnityHeader.GuessHeadersForModel(ILModel)[0]; - UnityVersion = unityVersion ?? UnityHeader.Version.Min; + UnityHeaders = unityVersion != null ? UnityHeaders.GetHeadersForVersion(unityVersion) : UnityHeaders.GuessHeadersForBinary(ILModel.Package.Binary)[0]; + UnityVersion = unityVersion ?? UnityHeaders.VersionRange.Min; // Check for matching metadata and binary versions - if (UnityHeader.MetadataVersion != ILModel.Package.BinaryImage.Version) { - Console.WriteLine($"Warning: selected version {UnityVersion} (metadata version {UnityHeader.MetadataVersion})" + + if (UnityHeaders.MetadataVersion != ILModel.Package.BinaryImage.Version) { + Console.WriteLine($"Warning: selected version {UnityVersion} (metadata version {UnityHeaders.MetadataVersion})" + $" does not match metadata version {ILModel.Package.BinaryImage.Version}."); } - // Start creation of type model by parsing all of the Unity IL2CPP headers - // Calling declarationGenerator.GenerateRemainingTypeDeclarations() below will automatically add to this collection - CppTypeCollection = CppTypeCollection.FromUnityHeaders(UnityHeader, WordSize); - // Initialize declaration generator to process every type in the binary declarationGenerator = new CppDeclarationGenerator(this); + // Start creation of type model by parsing all of the Unity IL2CPP headers + // Calling declarationGenerator.GenerateRemainingTypeDeclarations() below will automatically add to this collection + CppTypeCollection = CppTypeCollection.FromUnityHeaders(UnityHeaders, declarationGenerator); + // Initialize ordered type list for code output DependencyOrderedCppTypes = new List(); diff --git a/Il2CppInspector.Common/Outputs/CppScaffolding.cs b/Il2CppInspector.Common/Outputs/CppScaffolding.cs index feab3b0..ab806fd 100644 --- a/Il2CppInspector.Common/Outputs/CppScaffolding.cs +++ b/Il2CppInspector.Common/Outputs/CppScaffolding.cs @@ -37,7 +37,7 @@ namespace Il2CppInspector.Outputs writeHeader(); writeSectionHeader("IL2CPP internal types"); - writeCode(model.UnityHeaderText); + writeCode(model.UnityHeaders.GetTypeHeaderText(model.WordSize)); writeCode("namespace app {"); writeLine(""); @@ -133,15 +133,10 @@ namespace Il2CppInspector.Outputs private void writeHeader() { writeLine("// Generated C++ file by Il2CppInspector - http://www.djkaty.com - https://github.com/djkaty"); - writeLine("// Target Unity version: " + model.UnityHeader); + writeLine("// Target Unity version: " + model.UnityHeaders); writeLine(""); } - private void writeUnityHeaders() { - var prefix = (model.Package.BinaryImage.Bits == 32) ? "#define IS_32BIT\n" : ""; - writeCode(prefix + model.UnityHeader.GetHeaderText()); - } - private void writeTypesForGroup(string header, string group) { writeSectionHeader(header); foreach (var cppType in model.GetDependencyOrderedCppTypeGroup(group)) diff --git a/Il2CppInspector.Common/Outputs/IDAPythonScript.cs b/Il2CppInspector.Common/Outputs/IDAPythonScript.cs index 563d099..459d909 100755 --- a/Il2CppInspector.Common/Outputs/IDAPythonScript.cs +++ b/Il2CppInspector.Common/Outputs/IDAPythonScript.cs @@ -27,7 +27,7 @@ namespace Il2CppInspector.Outputs writer = new StreamWriter(fs, Encoding.UTF8); writeLine("# Generated script file by Il2CppInspector - http://www.djkaty.com - https://github.com/djkaty"); - writeLine("# Target Unity version: " + model.UnityHeader); + writeLine("# Target Unity version: " + model.UnityHeaders); writeLine("print('Generated script file by Il2CppInspector - http://www.djkaty.com - https://github.com/djkaty')"); writeSectionHeader("Preamble"); writePreamble(); @@ -84,7 +84,7 @@ typedef __int64 int64_t; private void writeTypes() { writeSectionHeader("IL2CPP internal types"); - writeDecls(model.UnityHeaderText); + writeDecls(model.UnityHeaders.GetTypeHeaderText(model.WordSize)); writeSectionHeader("Application types from method calls"); writeTypes(model.GetDependencyOrderedCppTypeGroup("types_from_methods")); diff --git a/Il2CppInspector.Common/ResourceHelper.cs b/Il2CppInspector.Common/ResourceHelper.cs index 0aee3c6..024763d 100644 --- a/Il2CppInspector.Common/ResourceHelper.cs +++ b/Il2CppInspector.Common/ResourceHelper.cs @@ -9,7 +9,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using Il2CppInspector.Cpp.UnityHeaders; namespace Il2CppInspector { diff --git a/Il2CppInspector.GUI/MainWindow.xaml.cs b/Il2CppInspector.GUI/MainWindow.xaml.cs index 7f319e0..639c53e 100644 --- a/Il2CppInspector.GUI/MainWindow.xaml.cs +++ b/Il2CppInspector.GUI/MainWindow.xaml.cs @@ -205,7 +205,7 @@ namespace Il2CppInspectorGUI var prevCppSelection = cboCppUnityVersion.SelectedItem; cboUnityVersion.Items.Clear(); cboCppUnityVersion.Items.Clear(); - foreach (var version in UnityHeader.GuessHeadersForModel(model.ILModel)) { + foreach (var version in UnityHeaders.GuessHeadersForBinary(model.Package.Binary)) { cboUnityVersion.Items.Add(version); cboCppUnityVersion.Items.Add(version); } @@ -406,7 +406,7 @@ namespace Il2CppInspectorGUI var outFile = scriptSaveFileDialog.FileName; areaBusyIndicator.Visibility = Visibility.Visible; - var selectedVersion = ((UnityHeader) cboUnityVersion.SelectedItem)?.Version.Min; + var selectedVersion = ((UnityHeaders) cboUnityVersion.SelectedItem)?.VersionRange.Min; await Task.Run(() => { OnStatusUpdate(this, "Building C++ application model"); model.Build(selectedVersion, CppCompilerType.GCC); @@ -430,7 +430,7 @@ namespace Il2CppInspectorGUI var cppOutPath = cppSaveFolderDialog.SelectedPath; areaBusyIndicator.Visibility = Visibility.Visible; - var selectedCppUnityVersion = ((UnityHeader) cboCppUnityVersion.SelectedItem)?.Version.Min; + var selectedCppUnityVersion = ((UnityHeaders) cboCppUnityVersion.SelectedItem)?.VersionRange.Min; var cppCompiler = (CppCompilerType) Enum.Parse(typeof(CppCompilerType), cboCppCompiler.SelectionBoxItem.ToString()); await Task.Run(() => { OnStatusUpdate(this, "Building C++ application model"); diff --git a/Il2CppTests/TestCppTypeDeclarations.cs b/Il2CppTests/TestCppTypeDeclarations.cs index ca8678e..3c0458f 100644 --- a/Il2CppTests/TestCppTypeDeclarations.cs +++ b/Il2CppTests/TestCppTypeDeclarations.cs @@ -22,15 +22,17 @@ namespace Il2CppInspector public void TestCppTypeDeclarations() { // NOTE: This test doesn't check for correct results, only that parsing doesn't fail! - var unityAllHeaders = UnityHeader.GetAllHeaders(); + var unityTypeHeaders = UnityHeaders.GetAllTypeHeaders(); // Ensure we have read the embedded assembly resources - Assert.IsTrue(unityAllHeaders.Any()); + Assert.IsTrue(unityTypeHeaders.Any()); // Ensure we can interpret every header from every version of Unity without errors // This will throw InvalidOperationException if there is a problem - foreach (var unityHeader in unityAllHeaders) { - var cppTypes = CppTypeCollection.FromUnityHeaders(unityHeader); + foreach (var unityTypeHeader in unityTypeHeaders) { + var cppTypes = new CppTypeCollection(64); + cppTypes.AddFromDeclarationText(unityTypeHeader.GetText()); + foreach (var cppType in cppTypes.Types) Debug.WriteLine("// " + cppType.Key + "\n" + cppType.Value.ToString("o")); } @@ -38,7 +40,7 @@ namespace Il2CppInspector // Do a few sanity checks taken from real applications // NOTE: Does not provide full code coverage! - var cppTypes2 = CppTypeCollection.FromUnityVersion(new UnityVersion("2019.3.1f1"), 64); + var cppTypes2 = CppTypeCollection.FromUnityVersion(new UnityVersion("2019.3.1f1")); CppComplexType ct; CppField field; diff --git a/Il2CppTests/TestUnityVersion.cs b/Il2CppTests/TestUnityVersion.cs index 61239fc..8fea5d6 100644 --- a/Il2CppTests/TestUnityVersion.cs +++ b/Il2CppTests/TestUnityVersion.cs @@ -17,8 +17,8 @@ namespace Il2CppInspector { [Test] public void TestVersions() { - Assert.That(UnityHeader.GetHeaderForVersion("5.3.1p4").ToString(), Is.EqualTo("5.3.0 - 5.3.1")); - Assert.That(UnityHeader.GetHeaderForVersion("5.6.4").ToString(), Is.EqualTo("5.6.0 - 5.6.7")); + Assert.That(UnityHeaders.GetTypeHeaderForVersion("5.3.1p4").VersionRange.ToString(), Is.EqualTo("5.3.0 - 5.3.1")); + Assert.That(UnityHeaders.GetTypeHeaderForVersion("5.6.4").VersionRange.ToString(), Is.EqualTo("5.6.0 - 5.6.7")); Assert.That(new UnityVersion("2020.1.0b5").ToString(), Is.EqualTo("2020.1.0b5")); Assert.That(new UnityVersion("2020.1").ToString(), Is.EqualTo("2020.1.0")); Assert.That(new UnityVersion("5.3.1").CompareTo("5.3.1p4") == 0);