Move non-output to new CppUtils namespace

We prefer to have the Outputs directory contain just one file or
namespace per output module, so we'll move all C++-related stuff to a
new CppUtils namespace instead.
This commit is contained in:
Robert Xiao
2020-06-26 18:03:04 -07:00
committed by Katy
parent de6d9e2230
commit 393d26b2a3
33 changed files with 17 additions and 16 deletions

View File

@@ -0,0 +1,597 @@
/*
Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
Copyright 2020 Robert Xiao - https://robertxiao.ca
All rights reserved.
*/
using Il2CppInspector.CppUtils.UnityHeaders;
using Il2CppInspector.Reflection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Il2CppInspector.CppUtils
{
// Class for generating C header declarations from Reflection objects (TypeInfo, etc.)
public class CppDeclarations
{
private readonly Il2CppModel model;
// Version number and header file to generate structures for
public UnityVersion UnityVersion { get; }
public UnityHeader UnityHeader { get; }
// How inheritance of type structs should be represented.
// Different C++ compilers lay out C++ class structures differently,
// meaning that the compiler must be known in order to generate class type structures
// with the correct layout.
public enum InheritanceStyleEnum
{
C, // Inheritance structs use C syntax, and will automatically choose MSVC or GCC based on inferred compiler.
MSVC, // Inheritance structs are laid out assuming the MSVC compiler, which recursively includes base classes
GCC, // Inheritance structs are laid out assuming the GCC compiler, which packs members from all bases + current class together
}
public InheritanceStyleEnum InheritanceStyle;
public CppDeclarations(Il2CppModel model, UnityVersion version) {
this.model = model;
if (version == null) {
UnityHeader = UnityHeader.GuessHeadersForModel(model)[0];
UnityVersion = UnityHeader.MinVersion;
} else {
UnityVersion = version;
UnityHeader = UnityHeader.GetHeaderForVersion(version);
if (UnityHeader.MetadataVersion != model.Package.BinaryImage.Version) {
/* this can only happen in the CLI frontend with a manually-supplied version number */
Console.WriteLine($"Warning: selected version {UnityVersion} (metadata version {UnityHeader.MetadataVersion})" +
$" does not match metadata version {model.Package.BinaryImage.Version}.");
}
}
InitializeNaming();
InitializeConcreteImplementations();
}
private void GuessInheritanceStyle() {
if (InheritanceStyle == InheritanceStyleEnum.C) {
if (model.Package.BinaryImage is PEReader)
InheritanceStyle = InheritanceStyleEnum.MSVC;
else
InheritanceStyle = InheritanceStyleEnum.GCC;
}
}
// C type declaration used to name variables of the given C# type
public string AsCType(TypeInfo ti) {
// IsArray case handled by TypeNamer.GetName
if (ti.IsByRef || ti.IsPointer) {
return $"{AsCType(ti.ElementType)} *";
} else if (ti.IsValueType) {
if (ti.IsPrimitive) {
switch (ti.Name) {
case "Boolean": return "bool";
case "Byte": return "uint8_t";
case "SByte": return "int8_t";
case "Int16": return "int16_t";
case "UInt16": return "uint16_t";
case "Int32": return "int32_t";
case "UInt32": return "uint32_t";
case "Int64": return "int64_t";
case "UInt64": return "uint64_t";
case "IntPtr": return "void *";
case "UIntPtr": return "void *";
case "Char": return "uint16_t";
case "Double": return "double";
case "Single": return "float";
}
}
return $"struct {TypeNamer.GetName(ti)}";
} else if (ti.IsEnum) {
return $"enum {TypeNamer.GetName(ti)}";
}
return $"struct {TypeNamer.GetName(ti)} *";
}
#region Field Struct Generation
/* Generating field structures (structures for the fields of a given type) occurs in two passes.
* In the first pass (VisitFieldStructs), we walk over a type and all of the types that the resulting structure would depend on.
* In the second pass (GenerateVisitedFieldStructs), we generate all type structures in the necessary order.
* (For example: structures for value types must precede any usage of those value types for layout reasons).
*/
// A cache of field structures that have already been generated, to eliminate duplicate definitions
private readonly HashSet<TypeInfo> VisitedFieldStructs = new HashSet<TypeInfo>();
// A queue of field structures that need to be generated.
private readonly List<TypeInfo> TodoFieldStructs = new List<TypeInfo>();
// Walk over dependencies of the given type, to figure out what field structures it depends on
private void VisitFieldStructs(TypeInfo ti) {
if (VisitedFieldStructs.Contains(ti))
return;
if (ti.IsByRef || ti.IsPointer || ti.ContainsGenericParameters)
return;
VisitedFieldStructs.Add(ti);
if (ti.BaseType != null)
VisitFieldStructs(ti.BaseType);
if (ti.IsArray)
VisitFieldStructs(ti.ElementType);
if (ti.IsEnum)
VisitFieldStructs(ti.GetEnumUnderlyingType());
foreach (var fi in ti.DeclaredFields)
if (!fi.IsStatic && !fi.IsLiteral && (fi.FieldType.IsEnum || fi.FieldType.IsValueType))
VisitFieldStructs(fi.FieldType);
TodoFieldStructs.Add(ti);
}
// Generate the fields for the base class of all objects (Il2CppObject)
// The two fields are inlined so that we can specialize the klass member for each type object
private void GenerateObjectFields(StringBuilder csrc, TypeInfo ti) {
csrc.Append(
$" struct {TypeNamer.GetName(ti)}__Class *klass;\n" +
$" struct MonitorData *monitor;\n");
}
// Generate structure fields for each field of a given type
private void GenerateFieldList(StringBuilder csrc, Namespace ns, TypeInfo ti) {
var namer = ns.MakeNamer<FieldInfo>((field) => field.Name.ToCIdentifier());
foreach (var field in ti.DeclaredFields) {
if (field.IsLiteral || field.IsStatic)
continue;
csrc.Append($" {AsCType(field.FieldType)} {namer.GetName(field)};\n");
}
}
// Generate the C structure for a value type, such as an enum or struct
private void GenerateValueFieldStruct(StringBuilder csrc, TypeInfo ti) {
string name = TypeNamer.GetName(ti);
if (ti.IsEnum) {
// Enums should be represented using enum syntax
// They otherwise behave like value types
var namer = GlobalsNamespace.MakeNamer<FieldInfo>((field) => $"{name}_{field.Name}".ToCIdentifier());
csrc.Append($"enum {name} : {AsCType(ti.GetEnumUnderlyingType())} {{\n");
foreach (var field in ti.DeclaredFields) {
if (field.Name != "value__")
csrc.Append($" {namer.GetName(field)} = {field.DefaultValue},\n");
}
csrc.Append($"}};\n");
// Use System.Enum base type as klass
csrc.Append($"struct {name}__Boxed {{\n");
GenerateObjectFields(csrc, ti.BaseType);
csrc.Append($" {AsCType(ti)} value;\n");
csrc.Append($"}};\n");
} else {
// This structure is passed by value, so it doesn't include Il2CppObject fields.
csrc.Append($"struct {name} {{\n");
GenerateFieldList(csrc, CreateNamespace(), ti);
csrc.Append($"}};\n");
// Also generate the boxed form of the structure which includes the Il2CppObject header.
csrc.Append($"struct {name}__Boxed {{\n");
GenerateObjectFields(csrc, ti);
csrc.Append($" {AsCType(ti)} fields;\n");
csrc.Append($"}};\n");
}
}
// Generate the C structure for a reference type, such as a class or array
private void GenerateRefFieldStruct(StringBuilder csrc, TypeInfo ti) {
var name = TypeNamer.GetName(ti);
if (ti.IsArray || ti.FullName == "System.Array") {
var klassType = ti.IsArray ? ti : ti.BaseType;
var elementType = ti.IsArray ? AsCType(ti.ElementType) : "void *";
csrc.Append($"struct {name} {{\n");
GenerateObjectFields(csrc, klassType);
csrc.Append(
$" struct Il2CppArrayBounds *bounds;\n" +
$" il2cpp_array_size_t max_length;\n" +
$" {elementType} vector[32];\n");
csrc.Append($"}};\n");
return;
}
if (InheritanceStyle == InheritanceStyleEnum.C)
GuessInheritanceStyle();
/* Generate a list of all base classes starting from the root */
List<TypeInfo> baseClasses = new List<TypeInfo>();
for (var bti = ti; bti != null; bti = bti.BaseType)
baseClasses.Add(bti);
baseClasses.Reverse();
var ns = CreateNamespace();
if (InheritanceStyle == InheritanceStyleEnum.MSVC) {
/* MSVC style: classes directly contain their base class as the first member.
* This causes all classes to be aligned to the alignment of their base class. */
TypeInfo firstNonEmpty = null;
foreach (var bti in baseClasses) {
if (bti.DeclaredFields.Where((field) => !field.IsStatic && !field.IsLiteral).Any()) {
firstNonEmpty = bti;
break;
}
}
if (firstNonEmpty == null) {
/* This struct is completely empty. Omit __Fields entirely. */
csrc.Append($"struct {name} {{\n");
GenerateObjectFields(csrc, ti);
csrc.Append($"}};\n");
} else {
if (firstNonEmpty == ti) {
/* All base classes are empty, so this class forms the root of a new hierarchy.
* We have to be a little careful: the rootmost class needs to have its alignment
* set to that of Il2CppObject, but we can't explicitly include Il2CppObject
* in the hierarchy because we want to customize the type of the klass parameter. */
var align = model.Package.BinaryImage.Bits == 32 ? 4 : 8;
csrc.Append($"struct __declspec(align({align})) {name}__Fields {{\n");
GenerateFieldList(csrc, ns, ti);
csrc.Append($"}};\n");
} else {
/* Include the base class fields. Alignment will be dictated by the hierarchy. */
ns.ReserveName("_");
csrc.Append($"struct {name}__Fields {{\n");
csrc.Append($" struct {TypeNamer.GetName(ti.BaseType)}__Fields _;\n");
GenerateFieldList(csrc, ns, ti);
csrc.Append($"}};\n");
}
csrc.Append($"struct {name} {{\n");
GenerateObjectFields(csrc, ti);
csrc.Append($" struct {name}__Fields fields;\n");
csrc.Append($"}};\n");
}
} else if (InheritanceStyle == InheritanceStyleEnum.GCC) {
/* GCC style: after the base class, all fields in the hierarchy are concatenated.
* This saves space (fields are "packed") but requires us to repeat fields from
* base classes. */
ns.ReserveName("klass");
ns.ReserveName("monitor");
csrc.Append($"struct {name} {{\n");
GenerateObjectFields(csrc, ti);
foreach (var bti in baseClasses)
GenerateFieldList(csrc, ns, bti);
csrc.Append($"}};\n");
}
}
// "Flush" the list of visited types, generating C structures for each one
private void GenerateVisitedFieldStructs(StringBuilder csrc) {
foreach (var ti in TodoFieldStructs) {
if (ti.IsEnum || ti.IsValueType)
GenerateValueFieldStruct(csrc, ti);
else
GenerateRefFieldStruct(csrc, ti);
}
TodoFieldStructs.Clear();
}
#endregion
#region Class Struct Generation
// Concrete implementations for abstract classes, for use in looking up VTable signatures and names
private readonly Dictionary<TypeInfo, TypeInfo> ConcreteImplementations = new Dictionary<TypeInfo, TypeInfo>();
/// <summary>
/// VTables for abstract types have "null" in place of abstract functions.
/// This function searches for concrete implementations so that we can properly
/// populate the abstract class VTables.
/// </summary>
private void InitializeConcreteImplementations() {
foreach (var ti in model.Types) {
if (ti.HasElementType || ti.IsAbstract || ti.IsGenericParameter)
continue;
var baseType = ti.BaseType;
while (baseType != null) {
if (baseType.IsAbstract && !ConcreteImplementations.ContainsKey(baseType))
ConcreteImplementations[baseType] = ti;
baseType = baseType.BaseType;
}
}
}
/// <summary>
/// Obtain the vtables for a given type, with implementations of abstract methods filled in.
/// </summary>
/// <param name="ti"></param>
/// <returns></returns>
private MethodBase[] GetFilledVTable(TypeInfo ti) {
MethodBase[] res = ti.GetVTable();
/* An abstract type will have null in the vtable for abstract methods.
* In order to recover the correct method signature for such abstract
* methods, we replace the corresponding vtable slot with an
* implementation from a concrete subclass, as the name and signature
* must match.
* Note that, for the purposes of creating type structures, we don't
* care which concrete implementation we put in this table! The name
* and signature will always match that of the abstract type.
*/
if (ti.IsAbstract && ConcreteImplementations.ContainsKey(ti)) {
res = (MethodBase[])res.Clone();
MethodBase[] impl = ConcreteImplementations[ti].GetVTable();
for (int i = 0; i < res.Length; i++) {
if (res[i] == null)
res[i] = impl[i];
}
}
return res;
}
private readonly HashSet<TypeInfo> VisitedTypes = new HashSet<TypeInfo>();
private readonly List<TypeInfo> TodoTypeStructs = new List<TypeInfo>();
/// <summary>
/// Visit a type and all types it depends on. Must call this before generating type structs.
/// </summary>
/// <param name="ti"></param>
public void VisitType(TypeInfo ti) {
if (VisitedTypes.Contains(ti))
return;
if (ti.ContainsGenericParameters)
return;
VisitedTypes.Add(ti);
if (ti.IsArray) {
VisitFieldStructs(ti);
VisitType(ti.ElementType);
VisitType(ti.BaseType);
return;
} else if (ti.HasElementType) {
VisitType(ti.ElementType);
return;
} else if (ti.IsEnum) {
VisitFieldStructs(ti);
VisitType(ti.GetEnumUnderlyingType());
return;
}
// Visit all fields first, considering only value types,
// so that we can get the layout correct.
VisitFieldStructs(ti);
if (ti.BaseType != null)
VisitType(ti.BaseType);
TypeNamer.GetName(ti);
foreach (var fi in ti.DeclaredFields)
VisitType(fi.FieldType);
foreach (var mi in GetFilledVTable(ti))
if (mi != null && !mi.ContainsGenericParameters)
VisitMethod(mi);
TodoTypeStructs.Add(ti);
}
// Generate the C structure for virtual function calls in a given type (the VTable)
private void GenerateVTableStruct(StringBuilder csrc, TypeInfo ti) {
MethodBase[] vtable;
if (ti.IsInterface) {
/* Interface vtables are just all of the interface methods.
You might have to type a local variable manually as an
interface vtable during an interface call, but the result
should display the correct method name (with a computed
InterfaceOffset added).
*/
vtable = ti.DeclaredMethods.ToArray();
} else {
vtable = ti.GetVTable();
}
var name = TypeNamer.GetName(ti);
var namer = CreateNamespace().MakeNamer<int>((i) => vtable[i]?.Name?.ToCIdentifier() ?? "__unknown");
// Il2Cpp switched to `VirtualInvokeData *vtable` in Unity 5.3.6.
// Previous versions used `MethodInfo **vtable`.
// TODO: Consider adding function types. This considerably increases the script size
// but can significantly help with reverse-engineering certain binaries.
csrc.Append($"struct {name}__VTable {{\n");
if (UnityVersion.CompareTo("5.3.6") < 0) {
for (int i = 0; i < vtable.Length; i++) {
csrc.Append($" MethodInfo *{namer.GetName(i)};\n");
}
} else {
for (int i = 0; i < vtable.Length; i++) {
csrc.Append($" VirtualInvokeData {namer.GetName(i)};\n");
}
}
csrc.Append($"}};\n");
}
// Generate the overall Il2CppClass-shaped structure for the given type
private void GenerateTypeStruct(StringBuilder csrc, TypeInfo ti) {
var name = TypeNamer.GetName(ti);
GenerateVTableStruct(csrc, ti);
csrc.Append($"struct {name}__StaticFields {{\n");
var namer = CreateNamespace().MakeNamer<FieldInfo>((field) => field.Name.ToCIdentifier());
foreach (var field in ti.DeclaredFields) {
if (field.IsLiteral || !field.IsStatic)
continue;
csrc.Append($" {AsCType(field.FieldType)} {namer.GetName(field)};\n");
}
csrc.Append($"}};\n");
/* TODO: type the rgctx_data */
if (UnityVersion.CompareTo("5.5.0") < 0) {
csrc.Append(
$"struct {name}__Class {{\n" +
$" struct Il2CppClass_0 _0;\n" +
$" struct {name}__VTable *vtable;\n" +
$" Il2CppRuntimeInterfaceOffsetPair *interfaceOffsets;\n" +
$" struct {name}__StaticFields *static_fields;\n" +
$" const Il2CppRGCTXData *rgctx_data;\n" +
$" struct Il2CppClass_1 _1;\n" +
$"}};\n");
} else {
csrc.Append(
$"struct {name}__Class {{\n" +
$" struct Il2CppClass_0 _0;\n" +
$" Il2CppRuntimeInterfaceOffsetPair *interfaceOffsets;\n" +
$" struct {name}__StaticFields *static_fields;\n" +
$" const Il2CppRGCTXData *rgctx_data;\n" +
$" struct Il2CppClass_1 _1;\n" +
$" struct {name}__VTable vtable;\n" +
$"}};\n");
}
}
/// <summary>
/// Generate every type that has been visited so far. Types that have previously been generated
/// by this instance will not be generated again.
/// </summary>
/// <returns>A string containing C type declarations</returns>
public string GenerateVisitedTypes() {
var csrc = new StringBuilder();
GenerateVisitedFieldStructs(csrc);
foreach (var ti in TodoTypeStructs)
GenerateTypeStruct(csrc, ti);
TodoTypeStructs.Clear();
return csrc.ToString();
}
#endregion
#region Method Generation
/// <summary>
/// Visit a method and all types it takes/returns. Must call this before generating method declarations.
/// </summary>
/// <param name="mi"></param>
public void VisitMethod(MethodBase method, TypeInfo declaringType = null) {
if (!method.IsStatic)
VisitType(declaringType ?? method.DeclaringType);
if (method is MethodInfo mi)
VisitType(mi.ReturnType);
foreach (var pi in method.DeclaredParameters) {
VisitType(pi.ParameterType);
}
}
// Generate a C declaration for a method
private string GenerateMethodDeclaration(MethodBase method, string name, TypeInfo declaringType) {
string retType;
if (method is MethodInfo mi) {
retType = mi.ReturnType.FullName == "System.Void" ? "void" : AsCType(mi.ReturnType);
} else {
retType = "void";
}
var paramNs = CreateNamespace();
paramNs.ReserveName("method");
var paramNamer = paramNs.MakeNamer<ParameterInfo>((pi) => pi.Name == "" ? "arg" : pi.Name.ToCIdentifier());
var paramList = new List<string>();
// Figure out the "this" param
if (method.IsStatic) {
// In older versions, static methods took a dummy this parameter
if (UnityVersion.CompareTo("2018.3.0") < 0)
paramList.Add("void *this");
} else {
if (declaringType.IsValueType) {
// Methods for structs take the boxed object as the this param
paramList.Add($"struct {TypeNamer.GetName(declaringType)}__Boxed * this");
} else {
paramList.Add($"{AsCType(declaringType)} this");
}
}
foreach (var pi in method.DeclaredParameters) {
paramList.Add($"{AsCType(pi.ParameterType)} {paramNamer.GetName(pi)}");
}
paramList.Add($"struct MethodInfo *method");
return $"{retType} {name}({string.Join(", ", paramList)})";
}
/// <summary>
/// Generate a declaration of the form "retType methName(argTypes argNames...)"
/// You must first visit the method using VisitMethod and then call
/// GenerateVisitedTypes in order to generate any dependent types.
/// </summary>
/// <param name="mi"></param>
/// <returns></returns>
public string GenerateMethodDeclaration(MethodBase method) {
return GenerateMethodDeclaration(method, MethodNamer.GetName(method), method.DeclaringType);
}
/// <summary>
/// Generate a declaration of the form "retType (*name)(argTypes...)"
/// You must first visit the method using VisitMethod and then call
/// GenerateVisitedTypes in order to generate any dependent types.
/// </summary>
/// <param name="mi">Method to generate (only the signature will be used)</param>
/// <param name="name">Name of the function pointer</param>
/// <returns></returns>
public string GenerateFunctionPointer(MethodBase method, string name, TypeInfo declaringType = null) {
return GenerateMethodDeclaration(method, $"(*{name})", declaringType ?? method.DeclaringType);
}
#endregion
#region Naming
// We try decently hard to avoid creating clashing names, and also sanitize any invalid names.
// 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 string[] { "CustomAttributesCache", "CustomAttributeTypeCache", "EventInfo", "FieldInfo", "Hash16", "MemberInfo", "MethodInfo", "MethodVariableKind", "MonitorData", "ParameterInfo", "PInvokeArguments", "PropertyInfo", "SequencePointKind", "StackFrameType", "VirtualInvokeData" }) {
TypeNamespace.ReserveName(typeName);
}
TypeNamer = TypeNamespace.MakeNamer<TypeInfo>((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.
if (ti.IsEnum)
name += "__Enum";
return name;
});
GlobalsNamespace = CreateNamespace();
MethodNamer = TypeNamespace.MakeNamer<MethodBase>((method) => $"{TypeNamer.GetName(method.DeclaringType)}_{method.Name.ToCIdentifier()}");
}
// Reserve C/C++ keywords and built-in names
private static Namespace CreateNamespace() {
var ns = new Namespace();
/* Reserve C/C++ keywords */
foreach (var keyword in new string[] { "_Alignas", "_Alignof", "_Atomic", "_Bool", "_Complex", "_Generic", "_Imaginary", "_Noreturn", "_Static_assert", "_Thread_local", "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "char8_t", "class", "co_await", "co_return", "co_yield", "compl", "concept", "const", "const_cast", "consteval", "constexpr", "constinit", "continue", "decltype", "default", "delete", "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected", "public", "reflexpr", "register", "reinterpret_cast", "requires", "restrict", "return", "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct", "switch", "synchronized", "template", "this", "thread_local", "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq" }) {
ns.ReserveName(keyword);
}
/* Reserve builtin keywords in IDA */
foreach (var keyword in new string[] { "_BYTE", "_DWORD", "_OWORD", "_QWORD", "_UNKNOWN", "_WORD", "__cdecl", "__declspec", "__export", "__far", "__fastcall", "__huge", "__import", "__int128", "__int16", "__int32", "__int64", "__int8", "__interrupt", "__near", "__pascal", "__spoils", "__stdcall", "__thiscall", "__thread", "__unaligned", "__usercall", "__userpurge", "_cs", "_ds", "_es", "_ss", "flat" }) {
ns.ReserveName(keyword);
}
return ns;
}
/// <summary>
/// Namespace for all types and typedefs
/// </summary>
public Namespace TypeNamespace { get; private set; }
public Namespace.Namer<TypeInfo> TypeNamer { get; private set; }
/// <summary>
/// Namespace for global variables and methods
/// </summary>
public Namespace GlobalsNamespace { get; private set; }
public Namespace.Namer<MethodBase> MethodNamer { get; private set; }
#endregion
}
}

View File

@@ -0,0 +1,88 @@
/*
Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
Copyright 2020 Robert Xiao - https://robertxiao.ca
All rights reserved.
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Il2CppInspector.CppUtils
{
/// <summary>
/// A utility class for managing names in a common namespace.
/// </summary>
public class Namespace
{
// The central data structure that keeps track of which names have been generated
// The value for any given key K is the number of unique objects originally named K, minus 1.
// Each time we see a particular name assigned to a new, different object, we bump its rename count
// and give it a suffix. For example, if we have three different objects all named X,
// we'd name them X, X_1, and X_2, and renameCount["X"] would be 2.
private readonly Dictionary<string, int> renameCount = new Dictionary<string, int>();
// Mark a name as reserved without assigning an object to it (e.g. for keywords and built-in names)
public void ReserveName(string name) {
if (renameCount.ContainsKey(name)) {
throw new Exception($"Can't reserve {name}: already taken!");
}
renameCount[name] = 0;
}
// Create a Namer object which will give names to objects of type T which are unique within this namespace
public Namer<T> MakeNamer<T>(Namer<T>.KeyFunc keyFunc) {
return new Namer<T>(this, keyFunc);
}
/// <summary>
/// A class for managing objects of a common type within a namespace.
/// </summary>
/// <typeparam name="T"></typeparam>
public class Namer<T>
{
// Parent namespace
private Namespace ns;
// Names given out by this Namer.
private readonly Dictionary<T, string> names = new Dictionary<T, string>();
// The function which maps a T object to a suitably mangled name
// That name might be further mangled by the Namer to make the name unique within the namespace
public delegate string KeyFunc(T t);
private readonly KeyFunc keyFunc;
public Namer(Namespace ns, KeyFunc keyFunc) {
this.ns = ns;
this.keyFunc = keyFunc;
}
// Uniquely name an object within the parent namespace
public string GetName(T t) {
// If we've named this particular object before, just return that name
string name;
if (names.TryGetValue(t, out name))
return name;
// Obtain the mangled name for the object
name = keyFunc(t);
// Check if the mangled name has been given to another object - if it has,
// we need to give the object a new suffixed name (e.g. X_1).
// We might need to repeat this process if the new suffixed name also exists.
// Each iteration tacks on another suffix - so we normally expect this to only take
// a single iteration. (It might take multiple iterations in rare cases, e.g.
// another object had the mangled name X_1).
if (ns.renameCount.ContainsKey(name)) {
int v = ns.renameCount[name] + 1;
while (ns.renameCount.ContainsKey(name + "_" + v))
v++;
ns.renameCount[name] = v;
name = name + "_" + v;
}
ns.renameCount[name] = 0;
names[t] = name;
return name;
}
}
}
}

View File

@@ -0,0 +1,818 @@
typedef void (*methodPointerType)();
typedef int32_t il2cpp_array_size_t;
typedef uint32_t Il2CppMethodSlot;
const int ipv6AddressSize = 16;
typedef enum Il2CppTypeEnum
{
IL2CPP_TYPE_END = 0x00,
IL2CPP_TYPE_VOID = 0x01,
IL2CPP_TYPE_BOOLEAN = 0x02,
IL2CPP_TYPE_CHAR = 0x03,
IL2CPP_TYPE_I1 = 0x04,
IL2CPP_TYPE_U1 = 0x05,
IL2CPP_TYPE_I2 = 0x06,
IL2CPP_TYPE_U2 = 0x07,
IL2CPP_TYPE_I4 = 0x08,
IL2CPP_TYPE_U4 = 0x09,
IL2CPP_TYPE_I8 = 0x0a,
IL2CPP_TYPE_U8 = 0x0b,
IL2CPP_TYPE_R4 = 0x0c,
IL2CPP_TYPE_R8 = 0x0d,
IL2CPP_TYPE_STRING = 0x0e,
IL2CPP_TYPE_PTR = 0x0f,
IL2CPP_TYPE_BYREF = 0x10,
IL2CPP_TYPE_VALUETYPE = 0x11,
IL2CPP_TYPE_CLASS = 0x12,
IL2CPP_TYPE_VAR = 0x13,
IL2CPP_TYPE_ARRAY = 0x14,
IL2CPP_TYPE_GENERICINST= 0x15,
IL2CPP_TYPE_TYPEDBYREF = 0x16,
IL2CPP_TYPE_I = 0x18,
IL2CPP_TYPE_U = 0x19,
IL2CPP_TYPE_FNPTR = 0x1b,
IL2CPP_TYPE_OBJECT = 0x1c,
IL2CPP_TYPE_SZARRAY = 0x1d,
IL2CPP_TYPE_MVAR = 0x1e,
IL2CPP_TYPE_CMOD_REQD = 0x1f,
IL2CPP_TYPE_CMOD_OPT = 0x20,
IL2CPP_TYPE_INTERNAL = 0x21,
IL2CPP_TYPE_MODIFIER = 0x40,
IL2CPP_TYPE_SENTINEL = 0x41,
IL2CPP_TYPE_PINNED = 0x45,
IL2CPP_TYPE_ENUM = 0x55
} Il2CppTypeEnum;
typedef int32_t TypeIndex;
typedef int32_t TypeDefinitionIndex;
typedef int32_t FieldIndex;
typedef int32_t DefaultValueIndex;
typedef int32_t DefaultValueDataIndex;
typedef int32_t CustomAttributeIndex;
typedef int32_t ParameterIndex;
typedef int32_t MethodIndex;
typedef int32_t GenericMethodIndex;
typedef int32_t PropertyIndex;
typedef int32_t EventIndex;
typedef int32_t GenericContainerIndex;
typedef int32_t GenericParameterIndex;
typedef int16_t GenericParameterConstraintIndex;
typedef int32_t NestedTypeIndex;
typedef int32_t InterfacesIndex;
typedef int32_t VTableIndex;
typedef int32_t InterfaceOffsetIndex;
typedef int32_t RGCTXIndex;
typedef int32_t StringIndex;
typedef int32_t StringLiteralIndex;
typedef int32_t GenericInstIndex;
typedef int32_t ImageIndex;
typedef int32_t AssemblyIndex;
const TypeIndex kTypeIndexInvalid = -1;
const TypeDefinitionIndex kTypeDefinitionIndexInvalid = -1;
const DefaultValueDataIndex kDefaultValueIndexNull = -1;
const EventIndex kEventIndexInvalid = -1;
const FieldIndex kFieldIndexInvalid = -1;
const MethodIndex kMethodIndexInvalid = -1;
const PropertyIndex kPropertyIndexInvalid = -1;
const GenericContainerIndex kGenericContainerIndexInvalid = -1;
const GenericParameterIndex kGenericParameterIndexInvalid = -1;
const RGCTXIndex kRGCTXIndexInvalid = -1;
const StringLiteralIndex kStringLiteralIndexInvalid = -1;
typedef uint32_t EncodedMethodIndex;
static inline bool IsGenericMethodIndex (EncodedMethodIndex index)
{
return (index & 0x80000000U) != 0;
}
static inline uint32_t GetDecodedMethodIndex (EncodedMethodIndex index)
{
return index & 0x7FFFFFFFU;
}
typedef struct Il2CppImage Il2CppImage;
typedef struct Il2CppType Il2CppType;
typedef struct Il2CppTypeDefinitionMetadata Il2CppTypeDefinitionMetadata;
typedef union Il2CppRGCTXDefinitionData
{
int32_t rgctxDataDummy;
MethodIndex methodIndex;
TypeIndex typeIndex;
} Il2CppRGCTXDefinitionData;
typedef enum Il2CppRGCTXDataType
{
IL2CPP_RGCTX_DATA_INVALID,
IL2CPP_RGCTX_DATA_TYPE,
IL2CPP_RGCTX_DATA_CLASS,
IL2CPP_RGCTX_DATA_METHOD
} Il2CppRGCTXDataType;
typedef struct Il2CppRGCTXDefinition
{
Il2CppRGCTXDataType type;
Il2CppRGCTXDefinitionData data;
} Il2CppRGCTXDefinition;
typedef struct Il2CppInterfaceOffsetPair
{
TypeIndex interfaceTypeIndex;
int32_t offset;
} Il2CppInterfaceOffsetPair;
typedef struct Il2CppTypeDefinition
{
StringIndex nameIndex;
StringIndex namespaceIndex;
CustomAttributeIndex customAttributeIndex;
TypeIndex byvalTypeIndex;
TypeIndex byrefTypeIndex;
TypeIndex declaringTypeIndex;
TypeIndex parentIndex;
TypeIndex elementTypeIndex;
RGCTXIndex rgctxStartIndex;
int32_t rgctxCount;
GenericContainerIndex genericContainerIndex;
MethodIndex delegateWrapperFromManagedToNativeIndex;
int32_t marshalingFunctionsIndex;
uint32_t flags;
FieldIndex fieldStart;
MethodIndex methodStart;
EventIndex eventStart;
PropertyIndex propertyStart;
NestedTypeIndex nestedTypesStart;
InterfacesIndex interfacesStart;
VTableIndex vtableStart;
InterfacesIndex interfaceOffsetsStart;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint32_t bitfield;
} Il2CppTypeDefinition;
typedef struct Il2CppFieldDefinition
{
StringIndex nameIndex;
TypeIndex typeIndex;
CustomAttributeIndex customAttributeIndex;
} Il2CppFieldDefinition;
typedef struct Il2CppFieldDefaultValue
{
FieldIndex fieldIndex;
TypeIndex typeIndex;
DefaultValueDataIndex dataIndex;
} Il2CppFieldDefaultValue;
typedef struct Il2CppFieldMarshaledSize
{
FieldIndex fieldIndex;
TypeIndex typeIndex;
int32_t size;
} Il2CppFieldMarshaledSize;
typedef struct Il2CppParameterDefinition
{
StringIndex nameIndex;
uint32_t token;
CustomAttributeIndex customAttributeIndex;
TypeIndex typeIndex;
} Il2CppParameterDefinition;
typedef struct Il2CppParameterDefaultValue
{
ParameterIndex parameterIndex;
TypeIndex typeIndex;
DefaultValueDataIndex dataIndex;
} Il2CppParameterDefaultValue;
typedef struct Il2CppMethodDefinition
{
StringIndex nameIndex;
TypeDefinitionIndex declaringType;
TypeIndex returnType;
ParameterIndex parameterStart;
CustomAttributeIndex customAttributeIndex;
GenericContainerIndex genericContainerIndex;
MethodIndex methodIndex;
MethodIndex invokerIndex;
MethodIndex delegateWrapperIndex;
RGCTXIndex rgctxStartIndex;
int32_t rgctxCount;
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint16_t parameterCount;
} Il2CppMethodDefinition;
typedef struct Il2CppEventDefinition
{
StringIndex nameIndex;
TypeIndex typeIndex;
MethodIndex add;
MethodIndex remove;
MethodIndex raise;
CustomAttributeIndex customAttributeIndex;
} Il2CppEventDefinition;
typedef struct Il2CppPropertyDefinition
{
StringIndex nameIndex;
MethodIndex get;
MethodIndex set;
uint32_t attrs;
CustomAttributeIndex customAttributeIndex;
} Il2CppPropertyDefinition;
typedef struct Il2CppMethodSpec
{
MethodIndex methodDefinitionIndex;
GenericInstIndex classIndexIndex;
GenericInstIndex methodIndexIndex;
} Il2CppMethodSpec;
typedef struct Il2CppStringLiteral
{
uint32_t length;
StringLiteralIndex dataIndex;
} Il2CppStringLiteral;
typedef struct Il2CppGenericMethodIndices
{
MethodIndex methodIndex;
MethodIndex invokerIndex;
} Il2CppGenericMethodIndices;
typedef struct Il2CppGenericMethodFunctionsDefinitions
{
GenericMethodIndex genericMethodIndex;
Il2CppGenericMethodIndices indices;
} Il2CppGenericMethodFunctionsDefinitions;
const int kPublicKeyByteLength = 8;
typedef struct Il2CppAssemblyName
{
StringIndex nameIndex;
StringIndex cultureIndex;
StringIndex hashValueIndex;
StringIndex publicKeyIndex;
uint32_t hash_alg;
int32_t hash_len;
uint32_t flags;
int32_t major;
int32_t minor;
int32_t build;
int32_t revision;
uint8_t publicKeyToken[8];
} Il2CppAssemblyName;
typedef struct Il2CppImageDefinition
{
StringIndex nameIndex;
AssemblyIndex assemblyIndex;
TypeDefinitionIndex typeStart;
uint32_t typeCount;
MethodIndex entryPointIndex;
} Il2CppImageDefinition;
typedef struct Il2CppAssembly
{
ImageIndex imageIndex;
CustomAttributeIndex customAttributeIndex;
Il2CppAssemblyName aname;
} Il2CppAssembly;
#pragma pack(push, p1,4)
typedef struct Il2CppGlobalMetadataHeader
{
int32_t sanity;
int32_t version;
int32_t stringLiteralOffset;
int32_t stringLiteralCount;
int32_t stringLiteralDataOffset;
int32_t stringLiteralDataCount;
int32_t stringOffset;
int32_t stringCount;
int32_t eventsOffset;
int32_t eventsCount;
int32_t propertiesOffset;
int32_t propertiesCount;
int32_t methodsOffset;
int32_t methodsCount;
int32_t parameterDefaultValuesOffset;
int32_t parameterDefaultValuesCount;
int32_t fieldDefaultValuesOffset;
int32_t fieldDefaultValuesCount;
int32_t fieldAndParameterDefaultValueDataOffset;
int32_t fieldAndParameterDefaultValueDataCount;
int32_t fieldMarshaledSizesOffset;
int32_t fieldMarshaledSizesCount;
int32_t parametersOffset;
int32_t parametersCount;
int32_t fieldsOffset;
int32_t fieldsCount;
int32_t genericParametersOffset;
int32_t genericParametersCount;
int32_t genericParameterConstraintsOffset;
int32_t genericParameterConstraintsCount;
int32_t genericContainersOffset;
int32_t genericContainersCount;
int32_t nestedTypesOffset;
int32_t nestedTypesCount;
int32_t interfacesOffset;
int32_t interfacesCount;
int32_t vtableMethodsOffset;
int32_t vtableMethodsCount;
int32_t interfaceOffsetsOffset;
int32_t interfaceOffsetsCount;
int32_t typeDefinitionsOffset;
int32_t typeDefinitionsCount;
int32_t rgctxEntriesOffset;
int32_t rgctxEntriesCount;
int32_t imagesOffset;
int32_t imagesCount;
int32_t assembliesOffset;
int32_t assembliesCount;
} Il2CppGlobalMetadataHeader;
#pragma pack(pop, p1)
typedef struct Il2CppClass Il2CppClass;
typedef struct MethodInfo MethodInfo;
typedef struct Il2CppType Il2CppType;
typedef struct Il2CppArrayType
{
const Il2CppType* etype;
uint8_t rank;
uint8_t numsizes;
uint8_t numlobounds;
int *sizes;
int *lobounds;
} Il2CppArrayType;
typedef struct Il2CppGenericInst
{
uint32_t type_argc;
const Il2CppType **type_argv;
} Il2CppGenericInst;
typedef struct Il2CppGenericContext
{
const Il2CppGenericInst *class_inst;
const Il2CppGenericInst *method_inst;
} Il2CppGenericContext;
typedef struct Il2CppGenericParameter
{
GenericContainerIndex ownerIndex;
StringIndex nameIndex;
GenericParameterConstraintIndex constraintsStart;
int16_t constraintsCount;
uint16_t num;
uint16_t flags;
} Il2CppGenericParameter;
typedef struct Il2CppGenericContainer
{
int32_t ownerIndex;
int32_t type_argc;
int32_t is_method;
GenericParameterIndex genericParameterStart;
} Il2CppGenericContainer;
typedef struct Il2CppGenericClass
{
TypeDefinitionIndex typeDefinitionIndex;
Il2CppGenericContext context;
Il2CppClass *cached_class;
} Il2CppGenericClass;
typedef struct Il2CppGenericMethod
{
const MethodInfo* methodDefinition;
Il2CppGenericContext context;
} Il2CppGenericMethod;
typedef struct Il2CppType
{
union {
void* dummy;
TypeDefinitionIndex klassIndex;
const Il2CppType *type;
Il2CppArrayType *array;
GenericParameterIndex genericParameterIndex;
Il2CppGenericClass *generic_class;
} data;
unsigned int attrs : 16;
Il2CppTypeEnum type : 8;
unsigned int num_mods : 6;
unsigned int byref : 1;
unsigned int pinned : 1;
} Il2CppType;
typedef enum {
IL2CPP_CALL_DEFAULT,
IL2CPP_CALL_C,
IL2CPP_CALL_STDCALL,
IL2CPP_CALL_THISCALL,
IL2CPP_CALL_FASTCALL,
IL2CPP_CALL_VARARG
} Il2CppCallConvention;
typedef enum Il2CppCharSet
{
CHARSET_ANSI,
CHARSET_UNICODE
} Il2CppCharSet;
typedef struct PInvokeArguments
{
const char* moduleName;
const char* entryPoint;
Il2CppCallConvention callingConvention;
Il2CppCharSet charSet;
int parameterSize;
bool isNoMangle;
} PInvokeArguments;
typedef struct Il2CppClass Il2CppClass;
typedef struct Il2CppImage Il2CppImage;
typedef struct Il2CppAssembly Il2CppAssembly;
typedef struct Il2CppAppDomain Il2CppAppDomain;
typedef struct Il2CppDelegate Il2CppDelegate;
typedef struct Il2CppAppContext Il2CppAppContext;
typedef struct Il2CppNameToTypeDefinitionIndexHashTable Il2CppNameToTypeDefinitionIndexHashTable;
typedef enum Il2CppTypeNameFormat
{
IL2CPP_TYPE_NAME_FORMAT_IL,
IL2CPP_TYPE_NAME_FORMAT_REFLECTION,
IL2CPP_TYPE_NAME_FORMAT_FULL_NAME,
IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
} Il2CppTypeNameFormat;
extern bool g_il2cpp_is_fully_initialized;
typedef struct {
Il2CppImage *corlib;
Il2CppClass *object_class;
Il2CppClass *byte_class;
Il2CppClass *void_class;
Il2CppClass *boolean_class;
Il2CppClass *sbyte_class;
Il2CppClass *int16_class;
Il2CppClass *uint16_class;
Il2CppClass *int32_class;
Il2CppClass *uint32_class;
Il2CppClass *int_class;
Il2CppClass *uint_class;
Il2CppClass *int64_class;
Il2CppClass *uint64_class;
Il2CppClass *single_class;
Il2CppClass *double_class;
Il2CppClass *char_class;
Il2CppClass *string_class;
Il2CppClass *enum_class;
Il2CppClass *array_class;
Il2CppClass *delegate_class;
Il2CppClass *multicastdelegate_class;
Il2CppClass *asyncresult_class;
Il2CppClass *manualresetevent_class;
Il2CppClass *typehandle_class;
Il2CppClass *fieldhandle_class;
Il2CppClass *methodhandle_class;
Il2CppClass *systemtype_class;
Il2CppClass *monotype_class;
Il2CppClass *exception_class;
Il2CppClass *threadabortexception_class;
Il2CppClass *thread_class;
Il2CppClass *appdomain_class;
Il2CppClass *appdomain_setup_class;
Il2CppClass *field_info_class;
Il2CppClass *method_info_class;
Il2CppClass *property_info_class;
Il2CppClass *event_info_class;
Il2CppClass *mono_event_info_class;
Il2CppClass *stringbuilder_class;
Il2CppClass *stack_frame_class;
Il2CppClass *stack_trace_class;
Il2CppClass *marshal_class;
Il2CppClass *typed_reference_class;
Il2CppClass *marshalbyrefobject_class;
Il2CppClass *generic_ilist_class;
Il2CppClass *generic_icollection_class;
Il2CppClass *generic_ienumerable_class;
Il2CppClass *generic_nullable_class;
Il2CppClass *customattribute_data_class;
Il2CppClass *version;
Il2CppClass *culture_info;
Il2CppClass *async_call_class;
Il2CppClass *assembly_class;
Il2CppClass *assembly_name_class;
Il2CppClass *enum_info_class;
Il2CppClass *mono_field_class;
Il2CppClass *mono_method_class;
Il2CppClass *mono_method_info_class;
Il2CppClass *mono_property_info_class;
Il2CppClass *parameter_info_class;
Il2CppClass *module_class;
Il2CppClass *pointer_class;
Il2CppClass *system_exception_class;
Il2CppClass *argument_exception_class;
Il2CppClass *wait_handle_class;
Il2CppClass *safe_handle_class;
Il2CppClass *sort_key_class;
} Il2CppDefaults;
extern Il2CppDefaults il2cpp_defaults;
typedef struct Il2CppClass Il2CppClass;
typedef struct MethodInfo MethodInfo;
typedef struct FieldInfo FieldInfo;
typedef struct Il2CppObject Il2CppObject;
typedef struct CustomAttributesCache
{
int count;
Il2CppObject** attributes;
} CustomAttributesCache;
typedef void (*CustomAttributesCacheGenerator)(CustomAttributesCache*);
const int THREAD_STATIC_FIELD_OFFSET = -1;
typedef struct FieldInfo
{
const char* name;
const Il2CppType* type;
Il2CppClass *parent;
int32_t offset;
CustomAttributeIndex customAttributeIndex;
} FieldInfo;
typedef struct PropertyInfo
{
Il2CppClass *parent;
const char *name;
const MethodInfo *get;
const MethodInfo *set;
uint32_t attrs;
CustomAttributeIndex customAttributeIndex;
} PropertyInfo;
typedef struct EventInfo
{
const char* name;
const Il2CppType* eventType;
Il2CppClass* parent;
const MethodInfo* add;
const MethodInfo* remove;
const MethodInfo* raise;
CustomAttributeIndex customAttributeIndex;
} EventInfo;
typedef struct ParameterInfo
{
const char* name;
int32_t position;
uint32_t token;
CustomAttributeIndex customAttributeIndex;
const Il2CppType* parameter_type;
} ParameterInfo;
typedef void* (*InvokerMethod)(const MethodInfo*, void*, void**);
typedef union Il2CppRGCTXData
{
void* rgctxDataDummy;
const MethodInfo* method;
const Il2CppType* type;
Il2CppClass* klass;
} Il2CppRGCTXData;
typedef struct MethodInfo
{
methodPointerType method;
InvokerMethod invoker_method;
const char* name;
Il2CppClass *declaring_type;
const Il2CppType *return_type;
const ParameterInfo* parameters;
union
{
const Il2CppRGCTXData* rgctx_data;
const Il2CppMethodDefinition* methodDefinition;
};
union
{
const Il2CppGenericMethod* genericMethod;
const Il2CppGenericContainer* genericContainer;
};
CustomAttributeIndex customAttributeIndex;
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint8_t parameters_count;
uint8_t is_generic : 1;
uint8_t is_inflated : 1;
} MethodInfo;
typedef struct Il2CppRuntimeInterfaceOffsetPair
{
Il2CppClass* interfaceType;
int32_t offset;
} Il2CppRuntimeInterfaceOffsetPair;
typedef struct Il2CppClass
{
const Il2CppImage* image;
void* gc_desc;
const char* name;
const char* namespaze;
const Il2CppType* byval_arg;
const Il2CppType* this_arg;
Il2CppClass* element_class;
Il2CppClass* castClass;
Il2CppClass* declaringType;
Il2CppClass* parent;
Il2CppGenericClass *generic_class;
const Il2CppTypeDefinition* typeDefinition;
FieldInfo* fields;
const EventInfo* events;
const PropertyInfo* properties;
const MethodInfo** methods;
Il2CppClass** nestedTypes;
Il2CppClass** implementedInterfaces;
const MethodInfo** vtable;
Il2CppRuntimeInterfaceOffsetPair* interfaceOffsets;
void* static_fields;
const Il2CppRGCTXData* rgctx_data;
Il2CppClass** typeHierarchy;
uint32_t cctor_started;
uint32_t cctor_finished;
__attribute__((aligned(8))) uint64_t cctor_thread;
GenericContainerIndex genericContainerIndex;
CustomAttributeIndex customAttributeIndex;
uint32_t instance_size;
uint32_t actualSize;
uint32_t element_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
int32_t thread_static_fields_offset;
uint32_t flags;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint8_t typeHierarchyDepth;
uint8_t rank;
uint8_t minimumAlignment;
uint8_t packingSize;
uint8_t valuetype : 1;
uint8_t initialized : 1;
uint8_t enumtype : 1;
uint8_t is_generic : 1;
uint8_t has_references : 1;
uint8_t init_pending : 1;
uint8_t size_inited : 1;
uint8_t has_finalize : 1;
uint8_t has_cctor : 1;
uint8_t is_blittable : 1;
} Il2CppClass;
typedef struct Il2CppClass_0 {
const Il2CppImage* image;
void* gc_desc;
const char* name;
const char* namespaze;
const Il2CppType* byval_arg;
const Il2CppType* this_arg;
Il2CppClass* element_class;
Il2CppClass* castClass;
Il2CppClass* declaringType;
Il2CppClass* parent;
Il2CppGenericClass * generic_class;
const Il2CppTypeDefinition* typeDefinition;
FieldInfo* fields;
const EventInfo* events;
const PropertyInfo* properties;
const MethodInfo** methods;
Il2CppClass** nestedTypes;
Il2CppClass** implementedInterfaces;
} Il2CppClass_0;
typedef struct Il2CppClass_1 {
Il2CppClass** typeHierarchy;
uint32_t cctor_started;
uint32_t cctor_finished;
#ifdef IS_32BIT
uint32_t cctor_thread__padding;
uint32_t cctor_thread;
uint32_t cctor_thread__hi;
#else
__attribute__((aligned(8))) uint64_t cctor_thread;
#endif
GenericContainerIndex genericContainerIndex;
CustomAttributeIndex customAttributeIndex;
uint32_t instance_size;
uint32_t actualSize;
uint32_t element_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
int32_t thread_static_fields_offset;
uint32_t flags;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint8_t typeHierarchyDepth;
uint8_t rank;
uint8_t minimumAlignment;
uint8_t packingSize;
uint8_t valuetype : 1;
uint8_t initialized : 1;
uint8_t enumtype : 1;
uint8_t is_generic : 1;
uint8_t has_references : 1;
uint8_t init_pending : 1;
uint8_t size_inited : 1;
uint8_t has_finalize : 1;
uint8_t has_cctor : 1;
uint8_t is_blittable : 1;
} Il2CppClass_1;
typedef struct __attribute__((aligned(8))) Il2CppClass_Merged {
struct Il2CppClass_0 _0;
const MethodInfo** vtable;
Il2CppRuntimeInterfaceOffsetPair* interfaceOffsets;
void* static_fields;
const Il2CppRGCTXData* rgctx_data;
struct Il2CppClass_1 _1;
} Il2CppClass_Merged;
typedef struct Il2CppTypeDefinitionSizes
{
uint32_t instance_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
} Il2CppTypeDefinitionSizes;
typedef struct Il2CppDomain
{
Il2CppAppDomain* domain;
Il2CppObject* setup;
Il2CppAppContext* default_context;
const char* friendly_name;
uint32_t domain_id;
} Il2CppDomain;
typedef struct Il2CppImage
{
const char* name;
AssemblyIndex assemblyIndex;
TypeDefinitionIndex typeStart;
uint32_t typeCount;
MethodIndex entryPointIndex;
Il2CppNameToTypeDefinitionIndexHashTable* nameToClassHashTable;
} Il2CppImage;
typedef struct Il2CppMarshalingFunctions
{
methodPointerType marshal_to_native_func;
methodPointerType marshal_from_native_func;
methodPointerType marshal_cleanup_func;
} Il2CppMarshalingFunctions;
typedef struct Il2CppCodeRegistration
{
uint32_t methodPointersCount;
const methodPointerType* methodPointers;
uint32_t delegateWrappersFromNativeToManagedCount;
const methodPointerType** delegateWrappersFromNativeToManaged;
uint32_t delegateWrappersFromManagedToNativeCount;
const methodPointerType* delegateWrappersFromManagedToNative;
uint32_t marshalingFunctionsCount;
const Il2CppMarshalingFunctions* marshalingFunctions;
uint32_t genericMethodPointersCount;
const methodPointerType* genericMethodPointers;
uint32_t invokerPointersCount;
const InvokerMethod* invokerPointers;
CustomAttributeIndex customAttributeCount;
const CustomAttributesCacheGenerator* customAttributeGenerators;
} Il2CppCodeRegistration;
typedef struct Il2CppMetadataRegistration
{
int32_t genericClassesCount;
Il2CppGenericClass* const * genericClasses;
int32_t genericInstsCount;
const Il2CppGenericInst* const * genericInsts;
int32_t genericMethodTableCount;
const Il2CppGenericMethodFunctionsDefinitions* genericMethodTable;
int32_t typesCount;
const Il2CppType* const * types;
int32_t methodSpecsCount;
const Il2CppMethodSpec* methodSpecs;
int32_t methodReferencesCount;
const EncodedMethodIndex* methodReferences;
FieldIndex fieldOffsetsCount;
const int32_t* fieldOffsets;
TypeDefinitionIndex typeDefinitionsSizesCount;
const Il2CppTypeDefinitionSizes* typeDefinitionsSizes;
} Il2CppMetadataRegistration;
typedef struct Il2CppRuntimeStats
{
uint64_t new_object_count;
uint64_t initialized_class_count;
uint64_t method_count;
uint64_t class_static_data_size;
uint64_t generic_instance_count;
uint64_t generic_class_count;
uint64_t inflated_method_count;
uint64_t inflated_type_count;
bool enabled;
} Il2CppRuntimeStats;
extern Il2CppRuntimeStats il2cpp_runtime_stats;
struct MonitorData;
struct Il2CppObject {
struct Il2CppClass *klass;
struct MonitorData *monitor;
};
typedef int32_t il2cpp_array_lower_bound_t;
struct Il2CppArrayBounds {
il2cpp_array_size_t length;
il2cpp_array_lower_bound_t lower_bound;
};
struct Il2CppArray {
struct Il2CppObject obj;
struct Il2CppArrayBounds *bounds;
il2cpp_array_size_t max_length;
/* vector must be 8-byte aligned.
On 64-bit platforms, this happens naturally.
On 32-bit platforms, sizeof(obj)=8, sizeof(bounds)=4 and sizeof(max_length)=4 so it's also already aligned. */
void *vector[32];
};
struct Il2CppString {
struct Il2CppObject object;
int32_t length;
uint16_t chars[32];
};

View File

@@ -0,0 +1,866 @@
typedef void (*methodPointerType)();
typedef int32_t il2cpp_array_size_t;
typedef uint32_t Il2CppMethodSlot;
const int ipv6AddressSize = 16;
typedef enum Il2CppTypeEnum
{
IL2CPP_TYPE_END = 0x00,
IL2CPP_TYPE_VOID = 0x01,
IL2CPP_TYPE_BOOLEAN = 0x02,
IL2CPP_TYPE_CHAR = 0x03,
IL2CPP_TYPE_I1 = 0x04,
IL2CPP_TYPE_U1 = 0x05,
IL2CPP_TYPE_I2 = 0x06,
IL2CPP_TYPE_U2 = 0x07,
IL2CPP_TYPE_I4 = 0x08,
IL2CPP_TYPE_U4 = 0x09,
IL2CPP_TYPE_I8 = 0x0a,
IL2CPP_TYPE_U8 = 0x0b,
IL2CPP_TYPE_R4 = 0x0c,
IL2CPP_TYPE_R8 = 0x0d,
IL2CPP_TYPE_STRING = 0x0e,
IL2CPP_TYPE_PTR = 0x0f,
IL2CPP_TYPE_BYREF = 0x10,
IL2CPP_TYPE_VALUETYPE = 0x11,
IL2CPP_TYPE_CLASS = 0x12,
IL2CPP_TYPE_VAR = 0x13,
IL2CPP_TYPE_ARRAY = 0x14,
IL2CPP_TYPE_GENERICINST= 0x15,
IL2CPP_TYPE_TYPEDBYREF = 0x16,
IL2CPP_TYPE_I = 0x18,
IL2CPP_TYPE_U = 0x19,
IL2CPP_TYPE_FNPTR = 0x1b,
IL2CPP_TYPE_OBJECT = 0x1c,
IL2CPP_TYPE_SZARRAY = 0x1d,
IL2CPP_TYPE_MVAR = 0x1e,
IL2CPP_TYPE_CMOD_REQD = 0x1f,
IL2CPP_TYPE_CMOD_OPT = 0x20,
IL2CPP_TYPE_INTERNAL = 0x21,
IL2CPP_TYPE_MODIFIER = 0x40,
IL2CPP_TYPE_SENTINEL = 0x41,
IL2CPP_TYPE_PINNED = 0x45,
IL2CPP_TYPE_ENUM = 0x55
} Il2CppTypeEnum;
typedef int32_t TypeIndex;
typedef int32_t TypeDefinitionIndex;
typedef int32_t FieldIndex;
typedef int32_t DefaultValueIndex;
typedef int32_t DefaultValueDataIndex;
typedef int32_t CustomAttributeIndex;
typedef int32_t ParameterIndex;
typedef int32_t MethodIndex;
typedef int32_t GenericMethodIndex;
typedef int32_t PropertyIndex;
typedef int32_t EventIndex;
typedef int32_t GenericContainerIndex;
typedef int32_t GenericParameterIndex;
typedef int16_t GenericParameterConstraintIndex;
typedef int32_t NestedTypeIndex;
typedef int32_t InterfacesIndex;
typedef int32_t VTableIndex;
typedef int32_t InterfaceOffsetIndex;
typedef int32_t RGCTXIndex;
typedef int32_t StringIndex;
typedef int32_t StringLiteralIndex;
typedef int32_t GenericInstIndex;
typedef int32_t ImageIndex;
typedef int32_t AssemblyIndex;
const TypeIndex kTypeIndexInvalid = -1;
const TypeDefinitionIndex kTypeDefinitionIndexInvalid = -1;
const DefaultValueDataIndex kDefaultValueIndexNull = -1;
const EventIndex kEventIndexInvalid = -1;
const FieldIndex kFieldIndexInvalid = -1;
const MethodIndex kMethodIndexInvalid = -1;
const PropertyIndex kPropertyIndexInvalid = -1;
const GenericContainerIndex kGenericContainerIndexInvalid = -1;
const GenericParameterIndex kGenericParameterIndexInvalid = -1;
const RGCTXIndex kRGCTXIndexInvalid = -1;
const StringLiteralIndex kStringLiteralIndexInvalid = -1;
typedef uint32_t EncodedMethodIndex;
typedef enum Il2CppMetadataUsage
{
kIl2CppMetadataUsageInvalid,
kIl2CppMetadataUsageTypeInfo,
kIl2CppMetadataUsageIl2CppType,
kIl2CppMetadataUsageMethodDef,
kIl2CppMetadataUsageFieldInfo,
kIl2CppMetadataUsageStringLiteral,
kIl2CppMetadataUsageMethodRef,
} Il2CppMetadataUsage;
static inline Il2CppMetadataUsage GetEncodedIndexType (EncodedMethodIndex index)
{
return (Il2CppMetadataUsage)((index & 0xE0000000) >> 29);
}
static inline uint32_t GetDecodedMethodIndex (EncodedMethodIndex index)
{
return index & 0x1FFFFFFFU;
}
typedef struct Il2CppImage Il2CppImage;
typedef struct Il2CppType Il2CppType;
typedef struct Il2CppTypeDefinitionMetadata Il2CppTypeDefinitionMetadata;
typedef union Il2CppRGCTXDefinitionData
{
int32_t rgctxDataDummy;
MethodIndex methodIndex;
TypeIndex typeIndex;
} Il2CppRGCTXDefinitionData;
typedef enum Il2CppRGCTXDataType
{
IL2CPP_RGCTX_DATA_INVALID,
IL2CPP_RGCTX_DATA_TYPE,
IL2CPP_RGCTX_DATA_CLASS,
IL2CPP_RGCTX_DATA_METHOD
} Il2CppRGCTXDataType;
typedef struct Il2CppRGCTXDefinition
{
Il2CppRGCTXDataType type;
Il2CppRGCTXDefinitionData data;
} Il2CppRGCTXDefinition;
typedef struct Il2CppInterfaceOffsetPair
{
TypeIndex interfaceTypeIndex;
int32_t offset;
} Il2CppInterfaceOffsetPair;
typedef struct Il2CppTypeDefinition
{
StringIndex nameIndex;
StringIndex namespaceIndex;
CustomAttributeIndex customAttributeIndex;
TypeIndex byvalTypeIndex;
TypeIndex byrefTypeIndex;
TypeIndex declaringTypeIndex;
TypeIndex parentIndex;
TypeIndex elementTypeIndex;
RGCTXIndex rgctxStartIndex;
int32_t rgctxCount;
GenericContainerIndex genericContainerIndex;
MethodIndex delegateWrapperFromManagedToNativeIndex;
int32_t marshalingFunctionsIndex;
uint32_t flags;
FieldIndex fieldStart;
MethodIndex methodStart;
EventIndex eventStart;
PropertyIndex propertyStart;
NestedTypeIndex nestedTypesStart;
InterfacesIndex interfacesStart;
VTableIndex vtableStart;
InterfacesIndex interfaceOffsetsStart;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint32_t bitfield;
uint32_t token;
} Il2CppTypeDefinition;
typedef struct Il2CppFieldDefinition
{
StringIndex nameIndex;
TypeIndex typeIndex;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} Il2CppFieldDefinition;
typedef struct Il2CppFieldDefaultValue
{
FieldIndex fieldIndex;
TypeIndex typeIndex;
DefaultValueDataIndex dataIndex;
} Il2CppFieldDefaultValue;
typedef struct Il2CppFieldMarshaledSize
{
FieldIndex fieldIndex;
TypeIndex typeIndex;
int32_t size;
} Il2CppFieldMarshaledSize;
typedef struct Il2CppFieldRef
{
TypeIndex typeIndex;
FieldIndex fieldIndex;
} Il2CppFieldRef;
typedef struct Il2CppParameterDefinition
{
StringIndex nameIndex;
uint32_t token;
CustomAttributeIndex customAttributeIndex;
TypeIndex typeIndex;
} Il2CppParameterDefinition;
typedef struct Il2CppParameterDefaultValue
{
ParameterIndex parameterIndex;
TypeIndex typeIndex;
DefaultValueDataIndex dataIndex;
} Il2CppParameterDefaultValue;
typedef struct Il2CppMethodDefinition
{
StringIndex nameIndex;
TypeDefinitionIndex declaringType;
TypeIndex returnType;
ParameterIndex parameterStart;
CustomAttributeIndex customAttributeIndex;
GenericContainerIndex genericContainerIndex;
MethodIndex methodIndex;
MethodIndex invokerIndex;
MethodIndex delegateWrapperIndex;
RGCTXIndex rgctxStartIndex;
int32_t rgctxCount;
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint16_t parameterCount;
} Il2CppMethodDefinition;
typedef struct Il2CppEventDefinition
{
StringIndex nameIndex;
TypeIndex typeIndex;
MethodIndex add;
MethodIndex remove;
MethodIndex raise;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} Il2CppEventDefinition;
typedef struct Il2CppPropertyDefinition
{
StringIndex nameIndex;
MethodIndex get;
MethodIndex set;
uint32_t attrs;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} Il2CppPropertyDefinition;
typedef struct Il2CppMethodSpec
{
MethodIndex methodDefinitionIndex;
GenericInstIndex classIndexIndex;
GenericInstIndex methodIndexIndex;
} Il2CppMethodSpec;
typedef struct Il2CppStringLiteral
{
uint32_t length;
StringLiteralIndex dataIndex;
} Il2CppStringLiteral;
typedef struct Il2CppGenericMethodIndices
{
MethodIndex methodIndex;
MethodIndex invokerIndex;
} Il2CppGenericMethodIndices;
typedef struct Il2CppGenericMethodFunctionsDefinitions
{
GenericMethodIndex genericMethodIndex;
Il2CppGenericMethodIndices indices;
} Il2CppGenericMethodFunctionsDefinitions;
const int kPublicKeyByteLength = 8;
typedef struct Il2CppAssemblyName
{
StringIndex nameIndex;
StringIndex cultureIndex;
StringIndex hashValueIndex;
StringIndex publicKeyIndex;
uint32_t hash_alg;
int32_t hash_len;
uint32_t flags;
int32_t major;
int32_t minor;
int32_t build;
int32_t revision;
uint8_t publicKeyToken[8];
} Il2CppAssemblyName;
typedef struct Il2CppImageDefinition
{
StringIndex nameIndex;
AssemblyIndex assemblyIndex;
TypeDefinitionIndex typeStart;
uint32_t typeCount;
MethodIndex entryPointIndex;
uint32_t token;
} Il2CppImageDefinition;
typedef struct Il2CppAssembly
{
ImageIndex imageIndex;
CustomAttributeIndex customAttributeIndex;
Il2CppAssemblyName aname;
} Il2CppAssembly;
typedef struct Il2CppMetadataUsageList
{
uint32_t start;
uint32_t count;
} Il2CppMetadataUsageList;
typedef struct Il2CppMetadataUsagePair
{
uint32_t destinationIndex;
uint32_t encodedSourceIndex;
} Il2CppMetadataUsagePair;
#pragma pack(push, p1,4)
typedef struct Il2CppGlobalMetadataHeader
{
int32_t sanity;
int32_t version;
int32_t stringLiteralOffset;
int32_t stringLiteralCount;
int32_t stringLiteralDataOffset;
int32_t stringLiteralDataCount;
int32_t stringOffset;
int32_t stringCount;
int32_t eventsOffset;
int32_t eventsCount;
int32_t propertiesOffset;
int32_t propertiesCount;
int32_t methodsOffset;
int32_t methodsCount;
int32_t parameterDefaultValuesOffset;
int32_t parameterDefaultValuesCount;
int32_t fieldDefaultValuesOffset;
int32_t fieldDefaultValuesCount;
int32_t fieldAndParameterDefaultValueDataOffset;
int32_t fieldAndParameterDefaultValueDataCount;
int32_t fieldMarshaledSizesOffset;
int32_t fieldMarshaledSizesCount;
int32_t parametersOffset;
int32_t parametersCount;
int32_t fieldsOffset;
int32_t fieldsCount;
int32_t genericParametersOffset;
int32_t genericParametersCount;
int32_t genericParameterConstraintsOffset;
int32_t genericParameterConstraintsCount;
int32_t genericContainersOffset;
int32_t genericContainersCount;
int32_t nestedTypesOffset;
int32_t nestedTypesCount;
int32_t interfacesOffset;
int32_t interfacesCount;
int32_t vtableMethodsOffset;
int32_t vtableMethodsCount;
int32_t interfaceOffsetsOffset;
int32_t interfaceOffsetsCount;
int32_t typeDefinitionsOffset;
int32_t typeDefinitionsCount;
int32_t rgctxEntriesOffset;
int32_t rgctxEntriesCount;
int32_t imagesOffset;
int32_t imagesCount;
int32_t assembliesOffset;
int32_t assembliesCount;
int32_t metadataUsageListsOffset;
int32_t metadataUsageListsCount;
int32_t metadataUsagePairsOffset;
int32_t metadataUsagePairsCount;
int32_t fieldRefsOffset;
int32_t fieldRefsCount;
} Il2CppGlobalMetadataHeader;
#pragma pack(pop, p1)
typedef struct Il2CppClass Il2CppClass;
typedef struct MethodInfo MethodInfo;
typedef struct Il2CppType Il2CppType;
typedef struct Il2CppArrayType
{
const Il2CppType* etype;
uint8_t rank;
uint8_t numsizes;
uint8_t numlobounds;
int *sizes;
int *lobounds;
} Il2CppArrayType;
typedef struct Il2CppGenericInst
{
uint32_t type_argc;
const Il2CppType **type_argv;
} Il2CppGenericInst;
typedef struct Il2CppGenericContext
{
const Il2CppGenericInst *class_inst;
const Il2CppGenericInst *method_inst;
} Il2CppGenericContext;
typedef struct Il2CppGenericParameter
{
GenericContainerIndex ownerIndex;
StringIndex nameIndex;
GenericParameterConstraintIndex constraintsStart;
int16_t constraintsCount;
uint16_t num;
uint16_t flags;
} Il2CppGenericParameter;
typedef struct Il2CppGenericContainer
{
int32_t ownerIndex;
int32_t type_argc;
int32_t is_method;
GenericParameterIndex genericParameterStart;
} Il2CppGenericContainer;
typedef struct Il2CppGenericClass
{
TypeDefinitionIndex typeDefinitionIndex;
Il2CppGenericContext context;
Il2CppClass *cached_class;
} Il2CppGenericClass;
typedef struct Il2CppGenericMethod
{
const MethodInfo* methodDefinition;
Il2CppGenericContext context;
} Il2CppGenericMethod;
typedef struct Il2CppType
{
union {
void* dummy;
TypeDefinitionIndex klassIndex;
const Il2CppType *type;
Il2CppArrayType *array;
GenericParameterIndex genericParameterIndex;
Il2CppGenericClass *generic_class;
} data;
unsigned int attrs : 16;
Il2CppTypeEnum type : 8;
unsigned int num_mods : 6;
unsigned int byref : 1;
unsigned int pinned : 1;
} Il2CppType;
typedef enum {
IL2CPP_CALL_DEFAULT,
IL2CPP_CALL_C,
IL2CPP_CALL_STDCALL,
IL2CPP_CALL_THISCALL,
IL2CPP_CALL_FASTCALL,
IL2CPP_CALL_VARARG
} Il2CppCallConvention;
typedef enum Il2CppCharSet
{
CHARSET_ANSI,
CHARSET_UNICODE
} Il2CppCharSet;
typedef struct PInvokeArguments
{
const char* moduleName;
const char* entryPoint;
Il2CppCallConvention callingConvention;
Il2CppCharSet charSet;
int parameterSize;
bool isNoMangle;
} PInvokeArguments;
typedef struct Il2CppClass Il2CppClass;
typedef struct Il2CppImage Il2CppImage;
typedef struct Il2CppAssembly Il2CppAssembly;
typedef struct Il2CppAppDomain Il2CppAppDomain;
typedef struct Il2CppDelegate Il2CppDelegate;
typedef struct Il2CppAppContext Il2CppAppContext;
typedef struct Il2CppNameToTypeDefinitionIndexHashTable Il2CppNameToTypeDefinitionIndexHashTable;
typedef enum Il2CppTypeNameFormat
{
IL2CPP_TYPE_NAME_FORMAT_IL,
IL2CPP_TYPE_NAME_FORMAT_REFLECTION,
IL2CPP_TYPE_NAME_FORMAT_FULL_NAME,
IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
} Il2CppTypeNameFormat;
extern bool g_il2cpp_is_fully_initialized;
typedef struct {
Il2CppImage *corlib;
Il2CppClass *object_class;
Il2CppClass *byte_class;
Il2CppClass *void_class;
Il2CppClass *boolean_class;
Il2CppClass *sbyte_class;
Il2CppClass *int16_class;
Il2CppClass *uint16_class;
Il2CppClass *int32_class;
Il2CppClass *uint32_class;
Il2CppClass *int_class;
Il2CppClass *uint_class;
Il2CppClass *int64_class;
Il2CppClass *uint64_class;
Il2CppClass *single_class;
Il2CppClass *double_class;
Il2CppClass *char_class;
Il2CppClass *string_class;
Il2CppClass *enum_class;
Il2CppClass *array_class;
Il2CppClass *delegate_class;
Il2CppClass *multicastdelegate_class;
Il2CppClass *asyncresult_class;
Il2CppClass *manualresetevent_class;
Il2CppClass *typehandle_class;
Il2CppClass *fieldhandle_class;
Il2CppClass *methodhandle_class;
Il2CppClass *systemtype_class;
Il2CppClass *monotype_class;
Il2CppClass *exception_class;
Il2CppClass *threadabortexception_class;
Il2CppClass *thread_class;
Il2CppClass *appdomain_class;
Il2CppClass *appdomain_setup_class;
Il2CppClass *field_info_class;
Il2CppClass *method_info_class;
Il2CppClass *property_info_class;
Il2CppClass *event_info_class;
Il2CppClass *mono_event_info_class;
Il2CppClass *stringbuilder_class;
Il2CppClass *stack_frame_class;
Il2CppClass *stack_trace_class;
Il2CppClass *marshal_class;
Il2CppClass *typed_reference_class;
Il2CppClass *marshalbyrefobject_class;
Il2CppClass *generic_ilist_class;
Il2CppClass *generic_icollection_class;
Il2CppClass *generic_ienumerable_class;
Il2CppClass *generic_nullable_class;
Il2CppClass *customattribute_data_class;
Il2CppClass *version;
Il2CppClass *culture_info;
Il2CppClass *async_call_class;
Il2CppClass *assembly_class;
Il2CppClass *assembly_name_class;
Il2CppClass *enum_info_class;
Il2CppClass *mono_field_class;
Il2CppClass *mono_method_class;
Il2CppClass *mono_method_info_class;
Il2CppClass *mono_property_info_class;
Il2CppClass *parameter_info_class;
Il2CppClass *module_class;
Il2CppClass *pointer_class;
Il2CppClass *system_exception_class;
Il2CppClass *argument_exception_class;
Il2CppClass *wait_handle_class;
Il2CppClass *safe_handle_class;
Il2CppClass *sort_key_class;
} Il2CppDefaults;
extern Il2CppDefaults il2cpp_defaults;
typedef struct Il2CppClass Il2CppClass;
typedef struct MethodInfo MethodInfo;
typedef struct FieldInfo FieldInfo;
typedef struct Il2CppObject Il2CppObject;
typedef struct MemberInfo MemberInfo;
typedef struct CustomAttributesCache
{
int count;
Il2CppObject** attributes;
} CustomAttributesCache;
typedef struct CustomAttributeTypeCache
{
int count;
Il2CppClass** attributeTypes;
} CustomAttributeTypeCache;
typedef void (*CustomAttributesCacheGenerator)(CustomAttributesCache*, CustomAttributeTypeCache*);
const int THREAD_STATIC_FIELD_OFFSET = -1;
typedef struct FieldInfo
{
const char* name;
const Il2CppType* type;
Il2CppClass *parent;
int32_t offset;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} FieldInfo;
typedef struct PropertyInfo
{
Il2CppClass *parent;
const char *name;
const MethodInfo *get;
const MethodInfo *set;
uint32_t attrs;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} PropertyInfo;
typedef struct EventInfo
{
const char* name;
const Il2CppType* eventType;
Il2CppClass* parent;
const MethodInfo* add;
const MethodInfo* remove;
const MethodInfo* raise;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} EventInfo;
typedef struct ParameterInfo
{
const char* name;
int32_t position;
uint32_t token;
CustomAttributeIndex customAttributeIndex;
const Il2CppType* parameter_type;
} ParameterInfo;
typedef void* (*InvokerMethod)(const MethodInfo*, void*, void**);
typedef union Il2CppRGCTXData
{
void* rgctxDataDummy;
const MethodInfo* method;
const Il2CppType* type;
Il2CppClass* klass;
} Il2CppRGCTXData;
typedef struct MethodInfo
{
methodPointerType method;
InvokerMethod invoker_method;
const char* name;
Il2CppClass *declaring_type;
const Il2CppType *return_type;
const ParameterInfo* parameters;
union
{
const Il2CppRGCTXData* rgctx_data;
const Il2CppMethodDefinition* methodDefinition;
};
union
{
const Il2CppGenericMethod* genericMethod;
const Il2CppGenericContainer* genericContainer;
};
CustomAttributeIndex customAttributeIndex;
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint8_t parameters_count;
uint8_t is_generic : 1;
uint8_t is_inflated : 1;
} MethodInfo;
typedef struct Il2CppRuntimeInterfaceOffsetPair
{
Il2CppClass* interfaceType;
int32_t offset;
} Il2CppRuntimeInterfaceOffsetPair;
typedef struct Il2CppClass
{
const Il2CppImage* image;
void* gc_desc;
const char* name;
const char* namespaze;
const Il2CppType* byval_arg;
const Il2CppType* this_arg;
Il2CppClass* element_class;
Il2CppClass* castClass;
Il2CppClass* declaringType;
Il2CppClass* parent;
Il2CppGenericClass *generic_class;
const Il2CppTypeDefinition* typeDefinition;
FieldInfo* fields;
const EventInfo* events;
const PropertyInfo* properties;
const MethodInfo** methods;
Il2CppClass** nestedTypes;
Il2CppClass** implementedInterfaces;
const MethodInfo** vtable;
Il2CppRuntimeInterfaceOffsetPair* interfaceOffsets;
void* static_fields;
const Il2CppRGCTXData* rgctx_data;
Il2CppClass** typeHierarchy;
uint32_t cctor_started;
uint32_t cctor_finished;
__attribute__((aligned(8))) uint64_t cctor_thread;
GenericContainerIndex genericContainerIndex;
CustomAttributeIndex customAttributeIndex;
uint32_t instance_size;
uint32_t actualSize;
uint32_t element_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
int32_t thread_static_fields_offset;
uint32_t flags;
uint32_t token;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint8_t typeHierarchyDepth;
uint8_t rank;
uint8_t minimumAlignment;
uint8_t packingSize;
uint8_t valuetype : 1;
uint8_t initialized : 1;
uint8_t enumtype : 1;
uint8_t is_generic : 1;
uint8_t has_references : 1;
uint8_t init_pending : 1;
uint8_t size_inited : 1;
uint8_t has_finalize : 1;
uint8_t has_cctor : 1;
uint8_t is_blittable : 1;
} Il2CppClass;
typedef struct Il2CppClass_0 {
const Il2CppImage* image;
void* gc_desc;
const char* name;
const char* namespaze;
const Il2CppType* byval_arg;
const Il2CppType* this_arg;
Il2CppClass* element_class;
Il2CppClass* castClass;
Il2CppClass* declaringType;
Il2CppClass* parent;
Il2CppGenericClass * generic_class;
const Il2CppTypeDefinition* typeDefinition;
FieldInfo* fields;
const EventInfo* events;
const PropertyInfo* properties;
const MethodInfo** methods;
Il2CppClass** nestedTypes;
Il2CppClass** implementedInterfaces;
} Il2CppClass_0;
typedef struct Il2CppClass_1 {
Il2CppClass** typeHierarchy;
uint32_t cctor_started;
uint32_t cctor_finished;
#ifdef IS_32BIT
uint32_t cctor_thread__padding;
uint32_t cctor_thread;
uint32_t cctor_thread__hi;
#else
__attribute__((aligned(8))) uint64_t cctor_thread;
#endif
GenericContainerIndex genericContainerIndex;
CustomAttributeIndex customAttributeIndex;
uint32_t instance_size;
uint32_t actualSize;
uint32_t element_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
int32_t thread_static_fields_offset;
uint32_t flags;
uint32_t token;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint8_t typeHierarchyDepth;
uint8_t rank;
uint8_t minimumAlignment;
uint8_t packingSize;
uint8_t valuetype : 1;
uint8_t initialized : 1;
uint8_t enumtype : 1;
uint8_t is_generic : 1;
uint8_t has_references : 1;
uint8_t init_pending : 1;
uint8_t size_inited : 1;
uint8_t has_finalize : 1;
uint8_t has_cctor : 1;
uint8_t is_blittable : 1;
} Il2CppClass_1;
typedef struct __attribute__((aligned(8))) Il2CppClass_Merged {
struct Il2CppClass_0 _0;
const MethodInfo** vtable;
Il2CppRuntimeInterfaceOffsetPair* interfaceOffsets;
void* static_fields;
const Il2CppRGCTXData* rgctx_data;
struct Il2CppClass_1 _1;
} Il2CppClass_Merged;
typedef struct Il2CppTypeDefinitionSizes
{
uint32_t instance_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
} Il2CppTypeDefinitionSizes;
typedef struct Il2CppDomain
{
Il2CppAppDomain* domain;
Il2CppObject* setup;
Il2CppAppContext* default_context;
const char* friendly_name;
uint32_t domain_id;
} Il2CppDomain;
typedef struct Il2CppImage
{
const char* name;
AssemblyIndex assemblyIndex;
TypeDefinitionIndex typeStart;
uint32_t typeCount;
MethodIndex entryPointIndex;
Il2CppNameToTypeDefinitionIndexHashTable* nameToClassHashTable;
uint32_t token;
} Il2CppImage;
typedef struct Il2CppMarshalingFunctions
{
methodPointerType marshal_to_native_func;
methodPointerType marshal_from_native_func;
methodPointerType marshal_cleanup_func;
} Il2CppMarshalingFunctions;
typedef struct Il2CppCodeRegistration
{
uint32_t methodPointersCount;
const methodPointerType* methodPointers;
uint32_t delegateWrappersFromNativeToManagedCount;
const methodPointerType** delegateWrappersFromNativeToManaged;
uint32_t delegateWrappersFromManagedToNativeCount;
const methodPointerType* delegateWrappersFromManagedToNative;
uint32_t marshalingFunctionsCount;
const Il2CppMarshalingFunctions* marshalingFunctions;
uint32_t genericMethodPointersCount;
const methodPointerType* genericMethodPointers;
uint32_t invokerPointersCount;
const InvokerMethod* invokerPointers;
CustomAttributeIndex customAttributeCount;
const CustomAttributesCacheGenerator* customAttributeGenerators;
} Il2CppCodeRegistration;
typedef struct Il2CppMetadataRegistration
{
int32_t genericClassesCount;
Il2CppGenericClass* const * genericClasses;
int32_t genericInstsCount;
const Il2CppGenericInst* const * genericInsts;
int32_t genericMethodTableCount;
const Il2CppGenericMethodFunctionsDefinitions* genericMethodTable;
int32_t typesCount;
const Il2CppType* const * types;
int32_t methodSpecsCount;
const Il2CppMethodSpec* methodSpecs;
FieldIndex fieldOffsetsCount;
const int32_t* fieldOffsets;
TypeDefinitionIndex typeDefinitionsSizesCount;
const Il2CppTypeDefinitionSizes* typeDefinitionsSizes;
const size_t metadataUsagesCount;
void** const* metadataUsages;
} Il2CppMetadataRegistration;
typedef struct Il2CppRuntimeStats
{
uint64_t new_object_count;
uint64_t initialized_class_count;
uint64_t method_count;
uint64_t class_static_data_size;
uint64_t generic_instance_count;
uint64_t generic_class_count;
uint64_t inflated_method_count;
uint64_t inflated_type_count;
bool enabled;
} Il2CppRuntimeStats;
extern Il2CppRuntimeStats il2cpp_runtime_stats;
struct MonitorData;
struct Il2CppObject {
struct Il2CppClass *klass;
struct MonitorData *monitor;
};
typedef int32_t il2cpp_array_lower_bound_t;
struct Il2CppArrayBounds {
il2cpp_array_size_t length;
il2cpp_array_lower_bound_t lower_bound;
};
struct Il2CppArray {
struct Il2CppObject obj;
struct Il2CppArrayBounds *bounds;
il2cpp_array_size_t max_length;
/* vector must be 8-byte aligned.
On 64-bit platforms, this happens naturally.
On 32-bit platforms, sizeof(obj)=8, sizeof(bounds)=4 and sizeof(max_length)=4 so it's also already aligned. */
void *vector[32];
};
struct Il2CppString {
struct Il2CppObject object;
int32_t length;
uint16_t chars[32];
};

View File

@@ -0,0 +1,873 @@
typedef void (*methodPointerType)();
typedef int32_t il2cpp_array_size_t;
typedef uint32_t Il2CppMethodSlot;
const int ipv6AddressSize = 16;
typedef int32_t il2cpp_hresult_t;
typedef enum Il2CppTypeEnum
{
IL2CPP_TYPE_END = 0x00,
IL2CPP_TYPE_VOID = 0x01,
IL2CPP_TYPE_BOOLEAN = 0x02,
IL2CPP_TYPE_CHAR = 0x03,
IL2CPP_TYPE_I1 = 0x04,
IL2CPP_TYPE_U1 = 0x05,
IL2CPP_TYPE_I2 = 0x06,
IL2CPP_TYPE_U2 = 0x07,
IL2CPP_TYPE_I4 = 0x08,
IL2CPP_TYPE_U4 = 0x09,
IL2CPP_TYPE_I8 = 0x0a,
IL2CPP_TYPE_U8 = 0x0b,
IL2CPP_TYPE_R4 = 0x0c,
IL2CPP_TYPE_R8 = 0x0d,
IL2CPP_TYPE_STRING = 0x0e,
IL2CPP_TYPE_PTR = 0x0f,
IL2CPP_TYPE_BYREF = 0x10,
IL2CPP_TYPE_VALUETYPE = 0x11,
IL2CPP_TYPE_CLASS = 0x12,
IL2CPP_TYPE_VAR = 0x13,
IL2CPP_TYPE_ARRAY = 0x14,
IL2CPP_TYPE_GENERICINST= 0x15,
IL2CPP_TYPE_TYPEDBYREF = 0x16,
IL2CPP_TYPE_I = 0x18,
IL2CPP_TYPE_U = 0x19,
IL2CPP_TYPE_FNPTR = 0x1b,
IL2CPP_TYPE_OBJECT = 0x1c,
IL2CPP_TYPE_SZARRAY = 0x1d,
IL2CPP_TYPE_MVAR = 0x1e,
IL2CPP_TYPE_CMOD_REQD = 0x1f,
IL2CPP_TYPE_CMOD_OPT = 0x20,
IL2CPP_TYPE_INTERNAL = 0x21,
IL2CPP_TYPE_MODIFIER = 0x40,
IL2CPP_TYPE_SENTINEL = 0x41,
IL2CPP_TYPE_PINNED = 0x45,
IL2CPP_TYPE_ENUM = 0x55
} Il2CppTypeEnum;
typedef int32_t TypeIndex;
typedef int32_t TypeDefinitionIndex;
typedef int32_t FieldIndex;
typedef int32_t DefaultValueIndex;
typedef int32_t DefaultValueDataIndex;
typedef int32_t CustomAttributeIndex;
typedef int32_t ParameterIndex;
typedef int32_t MethodIndex;
typedef int32_t GenericMethodIndex;
typedef int32_t PropertyIndex;
typedef int32_t EventIndex;
typedef int32_t GenericContainerIndex;
typedef int32_t GenericParameterIndex;
typedef int16_t GenericParameterConstraintIndex;
typedef int32_t NestedTypeIndex;
typedef int32_t InterfacesIndex;
typedef int32_t VTableIndex;
typedef int32_t InterfaceOffsetIndex;
typedef int32_t RGCTXIndex;
typedef int32_t StringIndex;
typedef int32_t StringLiteralIndex;
typedef int32_t GenericInstIndex;
typedef int32_t ImageIndex;
typedef int32_t AssemblyIndex;
const TypeIndex kTypeIndexInvalid = -1;
const TypeDefinitionIndex kTypeDefinitionIndexInvalid = -1;
const DefaultValueDataIndex kDefaultValueIndexNull = -1;
const EventIndex kEventIndexInvalid = -1;
const FieldIndex kFieldIndexInvalid = -1;
const MethodIndex kMethodIndexInvalid = -1;
const PropertyIndex kPropertyIndexInvalid = -1;
const GenericContainerIndex kGenericContainerIndexInvalid = -1;
const GenericParameterIndex kGenericParameterIndexInvalid = -1;
const RGCTXIndex kRGCTXIndexInvalid = -1;
const StringLiteralIndex kStringLiteralIndexInvalid = -1;
typedef uint32_t EncodedMethodIndex;
typedef enum Il2CppMetadataUsage
{
kIl2CppMetadataUsageInvalid,
kIl2CppMetadataUsageTypeInfo,
kIl2CppMetadataUsageIl2CppType,
kIl2CppMetadataUsageMethodDef,
kIl2CppMetadataUsageFieldInfo,
kIl2CppMetadataUsageStringLiteral,
kIl2CppMetadataUsageMethodRef,
} Il2CppMetadataUsage;
static inline Il2CppMetadataUsage GetEncodedIndexType (EncodedMethodIndex index)
{
return (Il2CppMetadataUsage)((index & 0xE0000000) >> 29);
}
static inline uint32_t GetDecodedMethodIndex (EncodedMethodIndex index)
{
return index & 0x1FFFFFFFU;
}
typedef struct Il2CppImage Il2CppImage;
typedef struct Il2CppType Il2CppType;
typedef struct Il2CppTypeDefinitionMetadata Il2CppTypeDefinitionMetadata;
typedef union Il2CppRGCTXDefinitionData
{
int32_t rgctxDataDummy;
MethodIndex methodIndex;
TypeIndex typeIndex;
} Il2CppRGCTXDefinitionData;
typedef enum Il2CppRGCTXDataType
{
IL2CPP_RGCTX_DATA_INVALID,
IL2CPP_RGCTX_DATA_TYPE,
IL2CPP_RGCTX_DATA_CLASS,
IL2CPP_RGCTX_DATA_METHOD
} Il2CppRGCTXDataType;
typedef struct Il2CppRGCTXDefinition
{
Il2CppRGCTXDataType type;
Il2CppRGCTXDefinitionData data;
} Il2CppRGCTXDefinition;
typedef struct Il2CppInterfaceOffsetPair
{
TypeIndex interfaceTypeIndex;
int32_t offset;
} Il2CppInterfaceOffsetPair;
typedef struct Il2CppTypeDefinition
{
StringIndex nameIndex;
StringIndex namespaceIndex;
CustomAttributeIndex customAttributeIndex;
TypeIndex byvalTypeIndex;
TypeIndex byrefTypeIndex;
TypeIndex declaringTypeIndex;
TypeIndex parentIndex;
TypeIndex elementTypeIndex;
RGCTXIndex rgctxStartIndex;
int32_t rgctxCount;
GenericContainerIndex genericContainerIndex;
MethodIndex delegateWrapperFromManagedToNativeIndex;
int32_t marshalingFunctionsIndex;
uint32_t flags;
FieldIndex fieldStart;
MethodIndex methodStart;
EventIndex eventStart;
PropertyIndex propertyStart;
NestedTypeIndex nestedTypesStart;
InterfacesIndex interfacesStart;
VTableIndex vtableStart;
InterfacesIndex interfaceOffsetsStart;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint32_t bitfield;
uint32_t token;
} Il2CppTypeDefinition;
typedef struct Il2CppFieldDefinition
{
StringIndex nameIndex;
TypeIndex typeIndex;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} Il2CppFieldDefinition;
typedef struct Il2CppFieldDefaultValue
{
FieldIndex fieldIndex;
TypeIndex typeIndex;
DefaultValueDataIndex dataIndex;
} Il2CppFieldDefaultValue;
typedef struct Il2CppFieldMarshaledSize
{
FieldIndex fieldIndex;
TypeIndex typeIndex;
int32_t size;
} Il2CppFieldMarshaledSize;
typedef struct Il2CppFieldRef
{
TypeIndex typeIndex;
FieldIndex fieldIndex;
} Il2CppFieldRef;
typedef struct Il2CppParameterDefinition
{
StringIndex nameIndex;
uint32_t token;
CustomAttributeIndex customAttributeIndex;
TypeIndex typeIndex;
} Il2CppParameterDefinition;
typedef struct Il2CppParameterDefaultValue
{
ParameterIndex parameterIndex;
TypeIndex typeIndex;
DefaultValueDataIndex dataIndex;
} Il2CppParameterDefaultValue;
typedef struct Il2CppMethodDefinition
{
StringIndex nameIndex;
TypeDefinitionIndex declaringType;
TypeIndex returnType;
ParameterIndex parameterStart;
CustomAttributeIndex customAttributeIndex;
GenericContainerIndex genericContainerIndex;
MethodIndex methodIndex;
MethodIndex invokerIndex;
MethodIndex delegateWrapperIndex;
RGCTXIndex rgctxStartIndex;
int32_t rgctxCount;
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint16_t parameterCount;
} Il2CppMethodDefinition;
typedef struct Il2CppEventDefinition
{
StringIndex nameIndex;
TypeIndex typeIndex;
MethodIndex add;
MethodIndex remove;
MethodIndex raise;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} Il2CppEventDefinition;
typedef struct Il2CppPropertyDefinition
{
StringIndex nameIndex;
MethodIndex get;
MethodIndex set;
uint32_t attrs;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} Il2CppPropertyDefinition;
typedef struct Il2CppMethodSpec
{
MethodIndex methodDefinitionIndex;
GenericInstIndex classIndexIndex;
GenericInstIndex methodIndexIndex;
} Il2CppMethodSpec;
typedef struct Il2CppStringLiteral
{
uint32_t length;
StringLiteralIndex dataIndex;
} Il2CppStringLiteral;
typedef struct Il2CppGenericMethodIndices
{
MethodIndex methodIndex;
MethodIndex invokerIndex;
} Il2CppGenericMethodIndices;
typedef struct Il2CppGenericMethodFunctionsDefinitions
{
GenericMethodIndex genericMethodIndex;
Il2CppGenericMethodIndices indices;
} Il2CppGenericMethodFunctionsDefinitions;
const int kPublicKeyByteLength = 8;
typedef struct Il2CppAssemblyName
{
StringIndex nameIndex;
StringIndex cultureIndex;
StringIndex hashValueIndex;
StringIndex publicKeyIndex;
uint32_t hash_alg;
int32_t hash_len;
uint32_t flags;
int32_t major;
int32_t minor;
int32_t build;
int32_t revision;
uint8_t publicKeyToken[8];
} Il2CppAssemblyName;
typedef struct Il2CppImageDefinition
{
StringIndex nameIndex;
AssemblyIndex assemblyIndex;
TypeDefinitionIndex typeStart;
uint32_t typeCount;
MethodIndex entryPointIndex;
uint32_t token;
} Il2CppImageDefinition;
typedef struct Il2CppAssembly
{
ImageIndex imageIndex;
CustomAttributeIndex customAttributeIndex;
int32_t referencedAssemblyStart;
int32_t referencedAssemblyCount;
Il2CppAssemblyName aname;
} Il2CppAssembly;
typedef struct Il2CppMetadataUsageList
{
uint32_t start;
uint32_t count;
} Il2CppMetadataUsageList;
typedef struct Il2CppMetadataUsagePair
{
uint32_t destinationIndex;
uint32_t encodedSourceIndex;
} Il2CppMetadataUsagePair;
#pragma pack(push, p1,4)
typedef struct Il2CppGlobalMetadataHeader
{
int32_t sanity;
int32_t version;
int32_t stringLiteralOffset;
int32_t stringLiteralCount;
int32_t stringLiteralDataOffset;
int32_t stringLiteralDataCount;
int32_t stringOffset;
int32_t stringCount;
int32_t eventsOffset;
int32_t eventsCount;
int32_t propertiesOffset;
int32_t propertiesCount;
int32_t methodsOffset;
int32_t methodsCount;
int32_t parameterDefaultValuesOffset;
int32_t parameterDefaultValuesCount;
int32_t fieldDefaultValuesOffset;
int32_t fieldDefaultValuesCount;
int32_t fieldAndParameterDefaultValueDataOffset;
int32_t fieldAndParameterDefaultValueDataCount;
int32_t fieldMarshaledSizesOffset;
int32_t fieldMarshaledSizesCount;
int32_t parametersOffset;
int32_t parametersCount;
int32_t fieldsOffset;
int32_t fieldsCount;
int32_t genericParametersOffset;
int32_t genericParametersCount;
int32_t genericParameterConstraintsOffset;
int32_t genericParameterConstraintsCount;
int32_t genericContainersOffset;
int32_t genericContainersCount;
int32_t nestedTypesOffset;
int32_t nestedTypesCount;
int32_t interfacesOffset;
int32_t interfacesCount;
int32_t vtableMethodsOffset;
int32_t vtableMethodsCount;
int32_t interfaceOffsetsOffset;
int32_t interfaceOffsetsCount;
int32_t typeDefinitionsOffset;
int32_t typeDefinitionsCount;
int32_t rgctxEntriesOffset;
int32_t rgctxEntriesCount;
int32_t imagesOffset;
int32_t imagesCount;
int32_t assembliesOffset;
int32_t assembliesCount;
int32_t metadataUsageListsOffset;
int32_t metadataUsageListsCount;
int32_t metadataUsagePairsOffset;
int32_t metadataUsagePairsCount;
int32_t fieldRefsOffset;
int32_t fieldRefsCount;
int32_t referencedAssembliesOffset;
int32_t referencedAssembliesCount;
} Il2CppGlobalMetadataHeader;
#pragma pack(pop, p1)
typedef struct Il2CppClass Il2CppClass;
typedef struct MethodInfo MethodInfo;
typedef struct Il2CppType Il2CppType;
typedef struct Il2CppArrayType
{
const Il2CppType* etype;
uint8_t rank;
uint8_t numsizes;
uint8_t numlobounds;
int *sizes;
int *lobounds;
} Il2CppArrayType;
typedef struct Il2CppGenericInst
{
uint32_t type_argc;
const Il2CppType **type_argv;
} Il2CppGenericInst;
typedef struct Il2CppGenericContext
{
const Il2CppGenericInst *class_inst;
const Il2CppGenericInst *method_inst;
} Il2CppGenericContext;
typedef struct Il2CppGenericParameter
{
GenericContainerIndex ownerIndex;
StringIndex nameIndex;
GenericParameterConstraintIndex constraintsStart;
int16_t constraintsCount;
uint16_t num;
uint16_t flags;
} Il2CppGenericParameter;
typedef struct Il2CppGenericContainer
{
int32_t ownerIndex;
int32_t type_argc;
int32_t is_method;
GenericParameterIndex genericParameterStart;
} Il2CppGenericContainer;
typedef struct Il2CppGenericClass
{
TypeDefinitionIndex typeDefinitionIndex;
Il2CppGenericContext context;
Il2CppClass *cached_class;
} Il2CppGenericClass;
typedef struct Il2CppGenericMethod
{
const MethodInfo* methodDefinition;
Il2CppGenericContext context;
} Il2CppGenericMethod;
typedef struct Il2CppType
{
union {
void* dummy;
TypeDefinitionIndex klassIndex;
const Il2CppType *type;
Il2CppArrayType *array;
GenericParameterIndex genericParameterIndex;
Il2CppGenericClass *generic_class;
} data;
unsigned int attrs : 16;
Il2CppTypeEnum type : 8;
unsigned int num_mods : 6;
unsigned int byref : 1;
unsigned int pinned : 1;
} Il2CppType;
typedef enum {
IL2CPP_CALL_DEFAULT,
IL2CPP_CALL_C,
IL2CPP_CALL_STDCALL,
IL2CPP_CALL_THISCALL,
IL2CPP_CALL_FASTCALL,
IL2CPP_CALL_VARARG
} Il2CppCallConvention;
typedef enum Il2CppCharSet
{
CHARSET_ANSI,
CHARSET_UNICODE
} Il2CppCharSet;
typedef struct PInvokeArguments
{
const char* moduleName;
const char* entryPoint;
Il2CppCallConvention callingConvention;
Il2CppCharSet charSet;
int parameterSize;
bool isNoMangle;
} PInvokeArguments;
typedef struct Il2CppClass Il2CppClass;
typedef struct Il2CppImage Il2CppImage;
typedef struct Il2CppAssembly Il2CppAssembly;
typedef struct Il2CppAppDomain Il2CppAppDomain;
typedef struct Il2CppDelegate Il2CppDelegate;
typedef struct Il2CppAppContext Il2CppAppContext;
typedef struct Il2CppNameToTypeDefinitionIndexHashTable Il2CppNameToTypeDefinitionIndexHashTable;
typedef enum Il2CppTypeNameFormat
{
IL2CPP_TYPE_NAME_FORMAT_IL,
IL2CPP_TYPE_NAME_FORMAT_REFLECTION,
IL2CPP_TYPE_NAME_FORMAT_FULL_NAME,
IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
} Il2CppTypeNameFormat;
extern bool g_il2cpp_is_fully_initialized;
typedef struct {
Il2CppImage *corlib;
Il2CppClass *object_class;
Il2CppClass *byte_class;
Il2CppClass *void_class;
Il2CppClass *boolean_class;
Il2CppClass *sbyte_class;
Il2CppClass *int16_class;
Il2CppClass *uint16_class;
Il2CppClass *int32_class;
Il2CppClass *uint32_class;
Il2CppClass *int_class;
Il2CppClass *uint_class;
Il2CppClass *int64_class;
Il2CppClass *uint64_class;
Il2CppClass *single_class;
Il2CppClass *double_class;
Il2CppClass *char_class;
Il2CppClass *string_class;
Il2CppClass *enum_class;
Il2CppClass *array_class;
Il2CppClass *delegate_class;
Il2CppClass *multicastdelegate_class;
Il2CppClass *asyncresult_class;
Il2CppClass *manualresetevent_class;
Il2CppClass *typehandle_class;
Il2CppClass *fieldhandle_class;
Il2CppClass *methodhandle_class;
Il2CppClass *systemtype_class;
Il2CppClass *monotype_class;
Il2CppClass *exception_class;
Il2CppClass *threadabortexception_class;
Il2CppClass *thread_class;
Il2CppClass *appdomain_class;
Il2CppClass *appdomain_setup_class;
Il2CppClass *field_info_class;
Il2CppClass *method_info_class;
Il2CppClass *property_info_class;
Il2CppClass *event_info_class;
Il2CppClass *mono_event_info_class;
Il2CppClass *stringbuilder_class;
Il2CppClass *stack_frame_class;
Il2CppClass *stack_trace_class;
Il2CppClass *marshal_class;
Il2CppClass *typed_reference_class;
Il2CppClass *marshalbyrefobject_class;
Il2CppClass *generic_ilist_class;
Il2CppClass *generic_icollection_class;
Il2CppClass *generic_ienumerable_class;
Il2CppClass *generic_nullable_class;
Il2CppClass *customattribute_data_class;
Il2CppClass *version;
Il2CppClass *culture_info;
Il2CppClass *async_call_class;
Il2CppClass *assembly_class;
Il2CppClass *assembly_name_class;
Il2CppClass *enum_info_class;
Il2CppClass *mono_field_class;
Il2CppClass *mono_method_class;
Il2CppClass *mono_method_info_class;
Il2CppClass *mono_property_info_class;
Il2CppClass *parameter_info_class;
Il2CppClass *module_class;
Il2CppClass *pointer_class;
Il2CppClass *system_exception_class;
Il2CppClass *argument_exception_class;
Il2CppClass *wait_handle_class;
Il2CppClass *safe_handle_class;
Il2CppClass *sort_key_class;
} Il2CppDefaults;
extern Il2CppDefaults il2cpp_defaults;
typedef struct Il2CppClass Il2CppClass;
typedef struct MethodInfo MethodInfo;
typedef struct FieldInfo FieldInfo;
typedef struct Il2CppObject Il2CppObject;
typedef struct MemberInfo MemberInfo;
typedef struct CustomAttributesCache
{
int count;
Il2CppObject** attributes;
} CustomAttributesCache;
typedef struct CustomAttributeTypeCache
{
int count;
Il2CppClass** attributeTypes;
} CustomAttributeTypeCache;
typedef void (*CustomAttributesCacheGenerator)(CustomAttributesCache*, CustomAttributeTypeCache*);
const int THREAD_STATIC_FIELD_OFFSET = -1;
typedef struct FieldInfo
{
const char* name;
const Il2CppType* type;
Il2CppClass *parent;
int32_t offset;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} FieldInfo;
typedef struct PropertyInfo
{
Il2CppClass *parent;
const char *name;
const MethodInfo *get;
const MethodInfo *set;
uint32_t attrs;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} PropertyInfo;
typedef struct EventInfo
{
const char* name;
const Il2CppType* eventType;
Il2CppClass* parent;
const MethodInfo* add;
const MethodInfo* remove;
const MethodInfo* raise;
CustomAttributeIndex customAttributeIndex;
uint32_t token;
} EventInfo;
typedef struct ParameterInfo
{
const char* name;
int32_t position;
uint32_t token;
CustomAttributeIndex customAttributeIndex;
const Il2CppType* parameter_type;
} ParameterInfo;
typedef void* (*InvokerMethod)(const MethodInfo*, void*, void**);
typedef union Il2CppRGCTXData
{
void* rgctxDataDummy;
const MethodInfo* method;
const Il2CppType* type;
Il2CppClass* klass;
} Il2CppRGCTXData;
typedef struct MethodInfo
{
methodPointerType method;
InvokerMethod invoker_method;
const char* name;
Il2CppClass *declaring_type;
const Il2CppType *return_type;
const ParameterInfo* parameters;
union
{
const Il2CppRGCTXData* rgctx_data;
const Il2CppMethodDefinition* methodDefinition;
};
union
{
const Il2CppGenericMethod* genericMethod;
const Il2CppGenericContainer* genericContainer;
};
CustomAttributeIndex customAttributeIndex;
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint8_t parameters_count;
uint8_t is_generic : 1;
uint8_t is_inflated : 1;
} MethodInfo;
typedef struct Il2CppRuntimeInterfaceOffsetPair
{
Il2CppClass* interfaceType;
int32_t offset;
} Il2CppRuntimeInterfaceOffsetPair;
typedef struct Il2CppClass
{
const Il2CppImage* image;
void* gc_desc;
const char* name;
const char* namespaze;
const Il2CppType* byval_arg;
const Il2CppType* this_arg;
Il2CppClass* element_class;
Il2CppClass* castClass;
Il2CppClass* declaringType;
Il2CppClass* parent;
Il2CppGenericClass *generic_class;
const Il2CppTypeDefinition* typeDefinition;
FieldInfo* fields;
const EventInfo* events;
const PropertyInfo* properties;
const MethodInfo** methods;
Il2CppClass** nestedTypes;
Il2CppClass** implementedInterfaces;
const MethodInfo** vtable;
Il2CppRuntimeInterfaceOffsetPair* interfaceOffsets;
void* static_fields;
const Il2CppRGCTXData* rgctx_data;
Il2CppClass** typeHierarchy;
uint32_t cctor_started;
uint32_t cctor_finished;
__attribute__((aligned(8))) uint64_t cctor_thread;
GenericContainerIndex genericContainerIndex;
CustomAttributeIndex customAttributeIndex;
uint32_t instance_size;
uint32_t actualSize;
uint32_t element_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
int32_t thread_static_fields_offset;
uint32_t flags;
uint32_t token;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint8_t typeHierarchyDepth;
uint8_t rank;
uint8_t minimumAlignment;
uint8_t packingSize;
uint8_t valuetype : 1;
uint8_t initialized : 1;
uint8_t enumtype : 1;
uint8_t is_generic : 1;
uint8_t has_references : 1;
uint8_t init_pending : 1;
uint8_t size_inited : 1;
uint8_t has_finalize : 1;
uint8_t has_cctor : 1;
uint8_t is_blittable : 1;
uint8_t is_import : 1;
} Il2CppClass;
typedef struct Il2CppClass_0 {
const Il2CppImage* image;
void* gc_desc;
const char* name;
const char* namespaze;
const Il2CppType* byval_arg;
const Il2CppType* this_arg;
Il2CppClass* element_class;
Il2CppClass* castClass;
Il2CppClass* declaringType;
Il2CppClass* parent;
Il2CppGenericClass * generic_class;
const Il2CppTypeDefinition* typeDefinition;
FieldInfo* fields;
const EventInfo* events;
const PropertyInfo* properties;
const MethodInfo** methods;
Il2CppClass** nestedTypes;
Il2CppClass** implementedInterfaces;
} Il2CppClass_0;
typedef struct Il2CppClass_1 {
Il2CppClass** typeHierarchy;
uint32_t cctor_started;
uint32_t cctor_finished;
#ifdef IS_32BIT
uint32_t cctor_thread__padding;
uint32_t cctor_thread;
uint32_t cctor_thread__hi;
#else
__attribute__((aligned(8))) uint64_t cctor_thread;
#endif
GenericContainerIndex genericContainerIndex;
CustomAttributeIndex customAttributeIndex;
uint32_t instance_size;
uint32_t actualSize;
uint32_t element_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
int32_t thread_static_fields_offset;
uint32_t flags;
uint32_t token;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint8_t typeHierarchyDepth;
uint8_t rank;
uint8_t minimumAlignment;
uint8_t packingSize;
uint8_t valuetype : 1;
uint8_t initialized : 1;
uint8_t enumtype : 1;
uint8_t is_generic : 1;
uint8_t has_references : 1;
uint8_t init_pending : 1;
uint8_t size_inited : 1;
uint8_t has_finalize : 1;
uint8_t has_cctor : 1;
uint8_t is_blittable : 1;
uint8_t is_import : 1;
} Il2CppClass_1;
typedef struct __attribute__((aligned(8))) Il2CppClass_Merged {
struct Il2CppClass_0 _0;
const MethodInfo** vtable;
Il2CppRuntimeInterfaceOffsetPair* interfaceOffsets;
void* static_fields;
const Il2CppRGCTXData* rgctx_data;
struct Il2CppClass_1 _1;
} Il2CppClass_Merged;
typedef struct Il2CppTypeDefinitionSizes
{
uint32_t instance_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
} Il2CppTypeDefinitionSizes;
typedef struct Il2CppDomain
{
Il2CppAppDomain* domain;
Il2CppObject* setup;
Il2CppAppContext* default_context;
const char* friendly_name;
uint32_t domain_id;
} Il2CppDomain;
typedef struct Il2CppImage
{
const char* name;
AssemblyIndex assemblyIndex;
TypeDefinitionIndex typeStart;
uint32_t typeCount;
MethodIndex entryPointIndex;
Il2CppNameToTypeDefinitionIndexHashTable* nameToClassHashTable;
uint32_t token;
} Il2CppImage;
typedef struct Il2CppMarshalingFunctions
{
methodPointerType marshal_to_native_func;
methodPointerType marshal_from_native_func;
methodPointerType marshal_cleanup_func;
} Il2CppMarshalingFunctions;
typedef struct Il2CppCodeRegistration
{
uint32_t methodPointersCount;
const methodPointerType* methodPointers;
uint32_t delegateWrappersFromNativeToManagedCount;
const methodPointerType** delegateWrappersFromNativeToManaged;
uint32_t delegateWrappersFromManagedToNativeCount;
const methodPointerType* delegateWrappersFromManagedToNative;
uint32_t marshalingFunctionsCount;
const Il2CppMarshalingFunctions* marshalingFunctions;
uint32_t genericMethodPointersCount;
const methodPointerType* genericMethodPointers;
uint32_t invokerPointersCount;
const InvokerMethod* invokerPointers;
CustomAttributeIndex customAttributeCount;
const CustomAttributesCacheGenerator* customAttributeGenerators;
} Il2CppCodeRegistration;
typedef struct Il2CppMetadataRegistration
{
int32_t genericClassesCount;
Il2CppGenericClass* const * genericClasses;
int32_t genericInstsCount;
const Il2CppGenericInst* const * genericInsts;
int32_t genericMethodTableCount;
const Il2CppGenericMethodFunctionsDefinitions* genericMethodTable;
int32_t typesCount;
const Il2CppType* const * types;
int32_t methodSpecsCount;
const Il2CppMethodSpec* methodSpecs;
FieldIndex fieldOffsetsCount;
const int32_t* fieldOffsets;
TypeDefinitionIndex typeDefinitionsSizesCount;
const Il2CppTypeDefinitionSizes* typeDefinitionsSizes;
const size_t metadataUsagesCount;
void** const* metadataUsages;
} Il2CppMetadataRegistration;
typedef struct Il2CppRuntimeStats
{
uint64_t new_object_count;
uint64_t initialized_class_count;
uint64_t method_count;
uint64_t class_static_data_size;
uint64_t generic_instance_count;
uint64_t generic_class_count;
uint64_t inflated_method_count;
uint64_t inflated_type_count;
bool enabled;
} Il2CppRuntimeStats;
extern Il2CppRuntimeStats il2cpp_runtime_stats;
struct MonitorData;
struct Il2CppObject {
struct Il2CppClass *klass;
struct MonitorData *monitor;
};
typedef int32_t il2cpp_array_lower_bound_t;
struct Il2CppArrayBounds {
il2cpp_array_size_t length;
il2cpp_array_lower_bound_t lower_bound;
};
struct Il2CppArray {
struct Il2CppObject obj;
struct Il2CppArrayBounds *bounds;
il2cpp_array_size_t max_length;
/* vector must be 8-byte aligned.
On 64-bit platforms, this happens naturally.
On 32-bit platforms, sizeof(obj)=8, sizeof(bounds)=4 and sizeof(max_length)=4 so it's also already aligned. */
void *vector[32];
};
struct Il2CppString {
struct Il2CppObject object;
int32_t length;
uint16_t chars[32];
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,97 @@
/*
Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
Copyright 2020 Robert Xiao - https://robertxiao.ca
All rights reserved.
*/
using System.Reflection;
using System.IO;
using System.Linq;
using System.Collections.Generic;
namespace Il2CppInspector.CppUtils.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 UnityVersion MinVersion { get; }
public UnityVersion MaxVersion { get; }
// Filename for the embedded .h resource file containing the header
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;
}
// Determine if this header supports the given version of Unity
public bool Contains(UnityVersion version) => version.CompareTo(MinVersion) >= 0 && (MaxVersion == null || version.CompareTo(MaxVersion) <= 0);
// Return the contents of this header file as a string
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;
}
// List all header files embedded into this build of Il2Cpp
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)));
}
// 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().Where(v => v.Contains(version)).First();
// 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<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;
}
}
}

View File

@@ -0,0 +1,113 @@
/*
Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
Copyright 2020 Robert Xiao - https://robertxiao.ca
All rights reserved.
*/
using System;
using System.Text.RegularExpressions;
namespace Il2CppInspector.CppUtils.UnityHeaders
{
// Parsed representation of a Unity version number, such as 5.3.0f1 or 2019.3.7.
public class UnityVersion : IComparable<UnityVersion>, IEquatable<UnityVersion>
{
// A sorted enumeration of build types, in order of maturity
public enum BuildTypeEnum
{
Unspecified,
Alpha,
Beta,
ReleaseCandidate,
Final,
Patch,
}
public static string BuildTypeToString(BuildTypeEnum buildType) => buildType switch
{
BuildTypeEnum.Unspecified => "",
BuildTypeEnum.Alpha => "a",
BuildTypeEnum.Beta => "b",
BuildTypeEnum.ReleaseCandidate => "rc",
BuildTypeEnum.Final => "f",
BuildTypeEnum.Patch => "p",
_ => throw new ArgumentException(),
};
public static BuildTypeEnum StringToBuildType(string s) => s switch
{
"" => BuildTypeEnum.Unspecified,
"a" => BuildTypeEnum.Alpha,
"b" => BuildTypeEnum.Beta,
"rc" => BuildTypeEnum.ReleaseCandidate,
"f" => BuildTypeEnum.Final,
"p" => BuildTypeEnum.Patch,
_ => throw new ArgumentException("Unknown build type " + s),
};
// Unity version number is of the form <Major>.<Minor>.<Update>[<BuildType><BuildNumber>]
public int Major { get; }
public int Minor { get; }
public int Update { get; }
public BuildTypeEnum BuildType { get; }
public int BuildNumber { get; }
public UnityVersion(string versionString) {
var match = Regex.Match(versionString, @"^(\d+)\.(\d+)(?:\.(\d+))?(?:([a-zA-Z]+)(\d+))?$");
if (!match.Success)
throw new ArgumentException($"'${versionString}' is not a valid Unity version number.");
Major = int.Parse(match.Groups[1].Value);
Minor = int.Parse(match.Groups[2].Value);
Update = match.Groups[3].Success ? int.Parse(match.Groups[3].Value) : 0;
BuildType = match.Groups[4].Success ? StringToBuildType(match.Groups[4].Value) : BuildTypeEnum.Unspecified;
BuildNumber = match.Groups[5].Success ? int.Parse(match.Groups[5].Value) : 0;
}
public static implicit operator UnityVersion(string versionString) => new UnityVersion(versionString);
public override string ToString() {
var res = $"{Major}.{Minor}.{Update}";
if (BuildType != BuildTypeEnum.Unspecified)
res += $"{BuildTypeToString(BuildType)}{BuildNumber}";
return res;
}
// Compare two version numbers, intransitively (due to the Unspecified build type)
public int CompareTo(UnityVersion other) {
int res;
if (0 != (res = Major.CompareTo(other.Major)))
return res;
if (0 != (res = Minor.CompareTo(other.Minor)))
return res;
if (0 != (res = Update.CompareTo(other.Update)))
return res;
// same major.minor.update - if one of these is suffix-less, they compare equal
// yes, this makes the compare function non-transitive; don't use it to sort things
if (BuildType == BuildTypeEnum.Unspecified || other.BuildType == BuildTypeEnum.Unspecified)
return 0;
if (0 != (res = BuildType.CompareTo(other.BuildType)))
return res;
if (0 != (res = BuildNumber.CompareTo(other.BuildNumber)))
return res;
return 0;
}
public override bool Equals(object obj) {
return Equals(obj as UnityVersion);
}
public bool Equals(UnityVersion other) {
return other != null &&
Major == other.Major &&
Minor == other.Minor &&
Update == other.Update &&
BuildType == other.BuildType &&
BuildNumber == other.BuildNumber;
}
public override int GetHashCode() {
return HashCode.Combine(Major, Minor, Update, BuildType, BuildNumber);
}
}
}