Add header files for every known Unity version.

We want to get types into the IDA output, and to do that we need
accurate types for the Il2Cpp structures. Unfortunately, some crucial
types like Il2CppClass change between versions without any corresponding
metadata changes, meaning that we have to manually identify the version
outside of the Inspector somehow (e.g. by looking at the version number
embedded in Unity asset files). This patch adds header files for *every*
known Unity version from 5.3.0 to 2019.3.8, merging them into version
ranges where header files don't change.

It also adds front-end support for supplying the version number in both
the CLI and GUI. The GUI is given the ability to guess the version
number approximately to reduce the number of choices presented to the
user.
This commit is contained in:
Robert Xiao
2020-04-14 02:09:39 -07:00
committed by Katy
parent b87d82fd11
commit 34f0d4ceef
32 changed files with 27176 additions and 9 deletions

View File

@@ -0,0 +1,81 @@
using System.Reflection;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System;
namespace Il2CppInspector.Outputs.UnityHeaders
{
public class UnityHeader
{
public double MetadataVersion { get; }
public UnityVersion MinVersion { get; }
public UnityVersion MaxVersion { get; }
public string HeaderFilename { get; }
private UnityHeader(string headerFilename) {
HeaderFilename = headerFilename;
var bits = headerFilename.Replace(".h", "").Split("-");
MetadataVersion = double.Parse(bits[0]);
MinVersion = new UnityVersion(bits[1]);
if (bits.Length == 2)
MaxVersion = MinVersion;
else if (bits[2] != "")
MaxVersion = new UnityVersion(bits[2]);
}
public override string ToString() {
var res = $"{MinVersion}";
if (MaxVersion == null)
res += "+";
else if (MaxVersion != MinVersion)
res += $" - {MaxVersion}";
return res;
}
public bool Contains(UnityVersion version) {
return version.CompareTo(MinVersion) >= 0 && (MaxVersion == null || version.CompareTo(MaxVersion) <= 0);
}
public string GetHeaderText() {
string resourceName = typeof(UnityHeader).Namespace + "." + HeaderFilename;
Assembly assembly = Assembly.GetCallingAssembly();
using Stream stream = assembly.GetManifestResourceStream(resourceName);
if (stream == null) {
throw new FileNotFoundException(resourceName);
}
using StreamReader reader = new StreamReader(stream);
string result = reader.ReadToEnd();
return result;
}
public static IEnumerable<UnityHeader> GetAllHeaders() {
string prefix = typeof(UnityHeader).Namespace + ".";
Assembly assembly = Assembly.GetCallingAssembly();
return assembly.GetManifestResourceNames()
.Where(s => s.StartsWith(prefix) && s.EndsWith(".h"))
.Select(s => new UnityHeader(s.Substring(prefix.Length)));
}
public static UnityHeader GetHeaderForVersion(string version) => GetHeaderForVersion(new UnityVersion(version));
public static UnityHeader GetHeaderForVersion(UnityVersion version) {
return GetAllHeaders().Where(v => v.Contains(version)).First();
}
public static List<UnityHeader> GuessHeadersForModel(Reflection.Il2CppModel model) {
List<UnityHeader> result = new List<UnityHeader>();
foreach (var v in GetAllHeaders()) {
if (v.MetadataVersion != model.Package.BinaryImage.Version)
continue;
if (v.MetadataVersion == 21) {
/* Special version logic for metadata version 21 based on the Il2CppMetadataRegistration.fieldOffsets field */
var headerFieldOffsetsArePointers = (v.MinVersion.CompareTo("5.3.7") >= 0 && v.MinVersion.CompareTo("5.4.0") != 0);
var binaryFieldOffsetsArePointers = (model.Package.Binary.FieldOffsets == null);
if (headerFieldOffsetsArePointers != binaryFieldOffsetsArePointers)
continue;
}
result.Add(v);
}
return result;
}
}
}