AppModel: Generate composite type mappings
This commit is contained in:
@@ -21,7 +21,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
private readonly AppModel appModel;
|
private readonly AppModel appModel;
|
||||||
|
|
||||||
private TypeModel model => appModel.ILModel;
|
private TypeModel model => appModel.ILModel;
|
||||||
private CppTypeCollection types => appModel.TypeCollection;
|
private CppTypeCollection types => appModel.CppTypeCollection;
|
||||||
|
|
||||||
// Version number and header file to generate structures for
|
// Version number and header file to generate structures for
|
||||||
public UnityVersion UnityVersion => appModel.UnityVersion;
|
public UnityVersion UnityVersion => appModel.UnityVersion;
|
||||||
@@ -245,8 +245,8 @@ namespace Il2CppInspector.Cpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "Flush" the list of visited types, generating C structures for each one
|
// "Flush" the list of visited types, generating C structures for each one
|
||||||
private List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType)> GenerateVisitedFieldStructs() {
|
private List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType, CppComplexType fieldsType)> GenerateVisitedFieldStructs() {
|
||||||
var structs = new List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType)>(TodoTypeStructs.Count);
|
var structs = new List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType, CppComplexType fieldsType)>(TodoTypeStructs.Count);
|
||||||
foreach (var ti in TodoFieldStructs) {
|
foreach (var ti in TodoFieldStructs) {
|
||||||
if (ti.IsEnum || ti.IsValueType) {
|
if (ti.IsEnum || ti.IsValueType) {
|
||||||
var (valueType, boxedType) = GenerateValueFieldStruct(ti);
|
var (valueType, boxedType) = GenerateValueFieldStruct(ti);
|
||||||
@@ -432,8 +432,10 @@ namespace Il2CppInspector.Cpp
|
|||||||
/// Type declarations that have previously been generated by this instance of CppDeclarationGenerator will not be generated again.
|
/// Type declarations that have previously been generated by this instance of CppDeclarationGenerator will not be generated again.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A string containing C type declarations</returns>
|
/// <returns>A string containing C type declarations</returns>
|
||||||
public List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType, CppType vtableType, CppType staticsType)> GenerateRemainingTypeDeclarations() {
|
public List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType, CppComplexType fieldsType,
|
||||||
var decl = GenerateVisitedFieldStructs().Select(s => (s.ilType, s.valueType, s.referenceType, s.fieldsType, (CppType) null, (CppType) null)).ToList();
|
CppComplexType vtableType, CppComplexType staticsType)> GenerateRemainingTypeDeclarations() {
|
||||||
|
var decl = GenerateVisitedFieldStructs().Select(s =>
|
||||||
|
(s.ilType, s.valueType, s.referenceType, s.fieldsType, (CppComplexType) null, (CppComplexType) null)).ToList();
|
||||||
|
|
||||||
foreach (var ti in TodoTypeStructs) {
|
foreach (var ti in TodoTypeStructs) {
|
||||||
var (cls, statics, vtable) = GenerateTypeStruct(ti);
|
var (cls, statics, vtable) = GenerateTypeStruct(ti);
|
||||||
|
|||||||
@@ -16,22 +16,6 @@ using Il2CppInspector.Reflection;
|
|||||||
namespace Il2CppInspector.Model
|
namespace Il2CppInspector.Model
|
||||||
{
|
{
|
||||||
// Class that represents a composite IL/C++ type
|
// Class that represents a composite IL/C++ type
|
||||||
public class AppType
|
|
||||||
{
|
|
||||||
// The corresponding C++ type definition which represents an instance of the object
|
|
||||||
// If a .NET type, this is derived from Il2CppObject, otherwise it can be any type
|
|
||||||
// If the underlying .NET type is a struct (value type), this will return the boxed version
|
|
||||||
public CppType CppType { get; internal set; }
|
|
||||||
|
|
||||||
// For an underlying .NET type which is a struct (value type), the unboxed type, otherwise null
|
|
||||||
public CppType CppValueType { get; internal set; }
|
|
||||||
|
|
||||||
// The type in the model this object represents (for .NET types, otherwise null)
|
|
||||||
public TypeInfo ILType { get; internal set; }
|
|
||||||
|
|
||||||
// The VA of the Il2CppClass object which defines this type (for .NET types, otherwise zero)
|
|
||||||
public ulong VirtualAddress { get; internal set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Class that represents the entire structure of the IL2CPP binary realized as C++ types and code,
|
// Class that represents the entire structure of the IL2CPP binary realized as C++ types and code,
|
||||||
// correlated with .NET types where applicable. Primarily designed to enable automated static analysis of disassembly code.
|
// correlated with .NET types where applicable. Primarily designed to enable automated static analysis of disassembly code.
|
||||||
@@ -49,16 +33,19 @@ namespace Il2CppInspector.Model
|
|||||||
|
|
||||||
// All of the C++ types used in the application including Unity internal types
|
// All of the C++ types used in the application including Unity internal types
|
||||||
// NOTE: This is for querying individual types for static analysis
|
// NOTE: This is for querying individual types for static analysis
|
||||||
// To generate code output, use DependencyOrderedTypes
|
// To generate code output, use DependencyOrderedCppTypes
|
||||||
public CppTypeCollection TypeCollection { get; set; } // TODO: Change to private set after integrating IDA output
|
public CppTypeCollection CppTypeCollection { get; set; } // TODO: Change to private set after integrating IDA output
|
||||||
|
|
||||||
// All of the C++ types used in the application (.NET type translations only)
|
// All of the C++ types used in the application (.NET type translations only)
|
||||||
// The types are ordered to enable the production of code output without forward dependencies
|
// The types are ordered to enable the production of code output without forward dependencies
|
||||||
public List<CppType> DependencyOrderedTypes { get; private set; }
|
public List<CppType> DependencyOrderedCppTypes { get; private set; }
|
||||||
|
|
||||||
// Composite mapping of all the .NET methods in the IL2CPP binary
|
// Composite mapping of all the .NET methods in the IL2CPP binary
|
||||||
public MultiKeyDictionary<MethodBase, CppFnPtrType, AppMethod> Methods = new MultiKeyDictionary<MethodBase, CppFnPtrType, AppMethod>();
|
public MultiKeyDictionary<MethodBase, CppFnPtrType, AppMethod> Methods = new MultiKeyDictionary<MethodBase, CppFnPtrType, AppMethod>();
|
||||||
|
|
||||||
|
// Composite mapping of all the .NET types in the IL2CPP binary
|
||||||
|
public MultiKeyDictionary<TypeInfo, CppComplexType, AppType> Types = new MultiKeyDictionary<TypeInfo, CppComplexType, AppType>();
|
||||||
|
|
||||||
// The .NET type model for the application
|
// The .NET type model for the application
|
||||||
public TypeModel ILModel { get; }
|
public TypeModel ILModel { get; }
|
||||||
|
|
||||||
@@ -66,8 +53,8 @@ namespace Il2CppInspector.Model
|
|||||||
public List<Export> Exports { get; }
|
public List<Export> Exports { get; }
|
||||||
|
|
||||||
// Delegated C++ types iterator
|
// Delegated C++ types iterator
|
||||||
public IEnumerator<CppType> GetEnumerator() => TypeCollection.GetEnumerator();
|
public IEnumerator<CppType> GetEnumerator() => CppTypeCollection.GetEnumerator();
|
||||||
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable) TypeCollection).GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable) CppTypeCollection).GetEnumerator();
|
||||||
|
|
||||||
// The C++ declaration generator for this binary
|
// The C++ declaration generator for this binary
|
||||||
// TODO: Make this private once IDA output integration is completed
|
// TODO: Make this private once IDA output integration is completed
|
||||||
@@ -117,16 +104,16 @@ namespace Il2CppInspector.Model
|
|||||||
|
|
||||||
// Start creation of type model by parsing all of the Unity IL2CPP headers
|
// Start creation of type model by parsing all of the Unity IL2CPP headers
|
||||||
// Calling declarationGenerator.GenerateRemainingTypeDeclarations() below will automatically add to this collection
|
// Calling declarationGenerator.GenerateRemainingTypeDeclarations() below will automatically add to this collection
|
||||||
TypeCollection = CppTypeCollection.FromUnityHeaders(UnityHeader, WordSize);
|
CppTypeCollection = CppTypeCollection.FromUnityHeaders(UnityHeader, WordSize);
|
||||||
|
|
||||||
// Initialize declaration generator to process every type in the binary
|
// Initialize declaration generator to process every type in the binary
|
||||||
declarationGenerator = new CppDeclarationGenerator(this);
|
declarationGenerator = new CppDeclarationGenerator(this);
|
||||||
|
|
||||||
// Initialize ordered type list for code output
|
// Initialize ordered type list for code output
|
||||||
DependencyOrderedTypes = new List<CppType>();
|
DependencyOrderedCppTypes = new List<CppType>();
|
||||||
|
|
||||||
// Add method definitions to C++ type model
|
// Add method definitions to C++ type model
|
||||||
TypeCollection.SetGroup("type_definitions");
|
CppTypeCollection.SetGroup("type_definitions");
|
||||||
|
|
||||||
foreach (var method in ILModel.MethodsByDefinitionIndex.Where(m => m.VirtualAddress.HasValue)) {
|
foreach (var method in ILModel.MethodsByDefinitionIndex.Where(m => m.VirtualAddress.HasValue)) {
|
||||||
declarationGenerator.IncludeMethod(method);
|
declarationGenerator.IncludeMethod(method);
|
||||||
@@ -137,7 +124,7 @@ namespace Il2CppInspector.Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add generic methods to C++ type model
|
// Add generic methods to C++ type model
|
||||||
TypeCollection.SetGroup("types_from_generics");
|
CppTypeCollection.SetGroup("types_from_generics");
|
||||||
|
|
||||||
foreach (var method in ILModel.GenericMethods.Values.Where(m => m.VirtualAddress.HasValue)) {
|
foreach (var method in ILModel.GenericMethods.Values.Where(m => m.VirtualAddress.HasValue)) {
|
||||||
declarationGenerator.IncludeMethod(method);
|
declarationGenerator.IncludeMethod(method);
|
||||||
@@ -149,7 +136,7 @@ namespace Il2CppInspector.Model
|
|||||||
|
|
||||||
// Add metadata usage types to C++ type model
|
// Add metadata usage types to C++ type model
|
||||||
// Not supported in il2cpp <19
|
// Not supported in il2cpp <19
|
||||||
TypeCollection.SetGroup("types_from_usages");
|
CppTypeCollection.SetGroup("types_from_usages");
|
||||||
|
|
||||||
if (Package.MetadataUsages != null)
|
if (Package.MetadataUsages != null)
|
||||||
foreach (var usage in Package.MetadataUsages) {
|
foreach (var usage in Package.MetadataUsages) {
|
||||||
@@ -161,6 +148,15 @@ namespace Il2CppInspector.Model
|
|||||||
var type = ILModel.GetMetadataUsageType(usage);
|
var type = ILModel.GetMetadataUsageType(usage);
|
||||||
declarationGenerator.IncludeType(type);
|
declarationGenerator.IncludeType(type);
|
||||||
AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations());
|
AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations());
|
||||||
|
|
||||||
|
if (usage.Type == MetadataUsageType.TypeInfo)
|
||||||
|
Types[type].TypeClassAddress = address;
|
||||||
|
else if (!Types.ContainsKey(type))
|
||||||
|
// Generic type definition has no associated C++ type, therefore no dictionary subkey
|
||||||
|
Types.Add(type, new AppType(type, null, cppTypeRefPtr: address));
|
||||||
|
else
|
||||||
|
// Regular type reference
|
||||||
|
Types[type].TypeRefPtrAddress = address;
|
||||||
break;
|
break;
|
||||||
case MetadataUsageType.MethodDef:
|
case MetadataUsageType.MethodDef:
|
||||||
case MetadataUsageType.MethodRef:
|
case MetadataUsageType.MethodRef:
|
||||||
@@ -179,24 +175,32 @@ namespace Il2CppInspector.Model
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddTypes(List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType, CppType vtableType, CppType staticsType)> types) {
|
private void AddTypes(List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType,
|
||||||
|
CppComplexType fieldsType, CppComplexType vtableType, CppComplexType staticsType)> types) {
|
||||||
|
|
||||||
|
// Add types to dependency-ordered list
|
||||||
foreach (var type in types) {
|
foreach (var type in types) {
|
||||||
if (type.vtableType != null)
|
if (type.vtableType != null)
|
||||||
DependencyOrderedTypes.Add(type.vtableType);
|
DependencyOrderedCppTypes.Add(type.vtableType);
|
||||||
if (type.staticsType != null)
|
if (type.staticsType != null)
|
||||||
DependencyOrderedTypes.Add(type.staticsType);
|
DependencyOrderedCppTypes.Add(type.staticsType);
|
||||||
|
|
||||||
if (type.fieldsType != null)
|
if (type.fieldsType != null)
|
||||||
DependencyOrderedTypes.Add(type.fieldsType);
|
DependencyOrderedCppTypes.Add(type.fieldsType);
|
||||||
if (type.valueType != null)
|
if (type.valueType != null)
|
||||||
DependencyOrderedTypes.Add(type.valueType);
|
DependencyOrderedCppTypes.Add(type.valueType);
|
||||||
|
|
||||||
DependencyOrderedTypes.Add(type.referenceType);
|
DependencyOrderedCppTypes.Add(type.referenceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create composite types
|
||||||
|
foreach (var type in types)
|
||||||
|
if (!Types.ContainsKey(type.ilType))
|
||||||
|
Types.Add(type.ilType, type.referenceType, new AppType(type.ilType, type.referenceType, type.valueType));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all the types for a group
|
// Get all the types for a group
|
||||||
public IEnumerable<CppType> GetTypeGroup(string groupName) => TypeCollection.GetTypeGroup(groupName);
|
public IEnumerable<CppType> GetTypeGroup(string groupName) => CppTypeCollection.GetTypeGroup(groupName);
|
||||||
public IEnumerable<CppType> GetDependencyOrderedTypeGroup(string groupName) => DependencyOrderedTypes.Where(t => t.Group == groupName);
|
public IEnumerable<CppType> GetDependencyOrderedTypeGroup(string groupName) => DependencyOrderedCppTypes.Where(t => t.Group == groupName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
42
Il2CppInspector.Common/Model/AppType.cs
Normal file
42
Il2CppInspector.Common/Model/AppType.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Il2CppInspector.Cpp;
|
||||||
|
using Il2CppInspector.Reflection;
|
||||||
|
|
||||||
|
namespace Il2CppInspector.Model
|
||||||
|
{
|
||||||
|
public class AppType
|
||||||
|
{
|
||||||
|
// The corresponding C++ type definition which represents an instance of the object
|
||||||
|
// This is derived from Il2CppObject
|
||||||
|
// If the underlying .NET type is a struct (value type), this will return the boxed version
|
||||||
|
public CppComplexType CppType { get; internal set; }
|
||||||
|
|
||||||
|
// For an underlying .NET type which is a struct (value type), the unboxed type, otherwise null
|
||||||
|
public CppComplexType CppValueType { get; internal set; }
|
||||||
|
|
||||||
|
// The type in the .NET type model this object maps to
|
||||||
|
public TypeInfo ILType { get; internal set; }
|
||||||
|
|
||||||
|
// The VA of the Il2CppClass object which defines this type (ClassName__TypeInfo)
|
||||||
|
public ulong TypeClassAddress { get; internal set; }
|
||||||
|
|
||||||
|
// The VA of the Il2CppType* (VA of the pointer to the Il2CppType) object which references this type
|
||||||
|
public ulong TypeRefPtrAddress { get; internal set; }
|
||||||
|
|
||||||
|
public AppType(TypeInfo ilType, CppComplexType cppType, CppComplexType valueType = null,
|
||||||
|
ulong cppClassPtr = 0xffffffff_ffffffff, ulong cppTypeRefPtr = 0xffffffff_ffffffff) {
|
||||||
|
CppType = cppType;
|
||||||
|
ILType = ilType;
|
||||||
|
CppValueType = valueType;
|
||||||
|
TypeClassAddress = cppClassPtr;
|
||||||
|
TypeRefPtrAddress = cppTypeRefPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => ILType.FullName + " -> " + CppType.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ namespace Il2CppInspector.Outputs
|
|||||||
var internalModel = new AppModel(model.ILModel);
|
var internalModel = new AppModel(model.ILModel);
|
||||||
internalModel.UnityVersion = model.UnityVersion;
|
internalModel.UnityVersion = model.UnityVersion;
|
||||||
internalModel.UnityHeader = model.UnityHeader;
|
internalModel.UnityHeader = model.UnityHeader;
|
||||||
internalModel.TypeCollection = CppTypeCollection.FromUnityHeaders(model.UnityHeader, model.WordSize);
|
internalModel.CppTypeCollection = CppTypeCollection.FromUnityHeaders(model.UnityHeader, model.WordSize);
|
||||||
model = internalModel;
|
model = internalModel;
|
||||||
declGenerator = new CppDeclarationGenerator(model);
|
declGenerator = new CppDeclarationGenerator(model);
|
||||||
|
|
||||||
@@ -226,7 +226,8 @@ typedef __int64 int64_t;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Temporary compatibility function, remove when integrated with ApplicationModel
|
// TODO: Temporary compatibility function, remove when integrated with ApplicationModel
|
||||||
private void writeDecls(List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType, CppType vtableType, CppType staticsType)> types)
|
private void writeDecls(List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType,
|
||||||
|
CppComplexType fieldsType, CppComplexType vtableType, CppComplexType staticsType)> types)
|
||||||
=> writeDecls(string.Join("\n",
|
=> writeDecls(string.Join("\n",
|
||||||
types.SelectMany(t => new List<CppType> {t.vtableType, t.staticsType, t.fieldsType, t.valueType, t.referenceType})
|
types.SelectMany(t => new List<CppType> {t.vtableType, t.staticsType, t.fieldsType, t.valueType, t.referenceType})
|
||||||
.Where(t => t != null)
|
.Where(t => t != null)
|
||||||
|
|||||||
Reference in New Issue
Block a user