diff --git a/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs b/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs
index 10f92ed..dc694c3 100644
--- a/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs
+++ b/Il2CppInspector.Common/Cpp/CppDeclarationGenerator.cs
@@ -21,7 +21,7 @@ namespace Il2CppInspector.Cpp
private readonly AppModel appModel;
private TypeModel model => appModel.ILModel;
- private CppTypeCollection types => appModel.TypeCollection;
+ private CppTypeCollection types => appModel.CppTypeCollection;
// Version number and header file to generate structures for
public UnityVersion UnityVersion => appModel.UnityVersion;
@@ -245,8 +245,8 @@ namespace Il2CppInspector.Cpp
}
// "Flush" the list of visited types, generating C structures for each one
- private List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType)> GenerateVisitedFieldStructs() {
- var structs = new List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType)>(TodoTypeStructs.Count);
+ private List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType, CppComplexType fieldsType)> GenerateVisitedFieldStructs() {
+ var structs = new List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType, CppComplexType fieldsType)>(TodoTypeStructs.Count);
foreach (var ti in TodoFieldStructs) {
if (ti.IsEnum || ti.IsValueType) {
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.
///
/// A string containing C type declarations
- public List<(TypeInfo ilType, CppType valueType, CppType referenceType, CppType fieldsType, CppType vtableType, CppType staticsType)> GenerateRemainingTypeDeclarations() {
- var decl = GenerateVisitedFieldStructs().Select(s => (s.ilType, s.valueType, s.referenceType, s.fieldsType, (CppType) null, (CppType) null)).ToList();
+ public List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType, CppComplexType fieldsType,
+ 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) {
var (cls, statics, vtable) = GenerateTypeStruct(ti);
diff --git a/Il2CppInspector.Common/Model/AppModel.cs b/Il2CppInspector.Common/Model/AppModel.cs
index 803b5ec..c0b933c 100644
--- a/Il2CppInspector.Common/Model/AppModel.cs
+++ b/Il2CppInspector.Common/Model/AppModel.cs
@@ -16,22 +16,6 @@ using Il2CppInspector.Reflection;
namespace Il2CppInspector.Model
{
// 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,
// 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
// NOTE: This is for querying individual types for static analysis
- // To generate code output, use DependencyOrderedTypes
- public CppTypeCollection TypeCollection { get; set; } // TODO: Change to private set after integrating IDA output
+ // To generate code output, use DependencyOrderedCppTypes
+ 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)
// The types are ordered to enable the production of code output without forward dependencies
- public List DependencyOrderedTypes { get; private set; }
+ public List DependencyOrderedCppTypes { get; private set; }
// Composite mapping of all the .NET methods in the IL2CPP binary
public MultiKeyDictionary Methods = new MultiKeyDictionary();
+ // Composite mapping of all the .NET types in the IL2CPP binary
+ public MultiKeyDictionary Types = new MultiKeyDictionary();
+
// The .NET type model for the application
public TypeModel ILModel { get; }
@@ -66,8 +53,8 @@ namespace Il2CppInspector.Model
public List Exports { get; }
// Delegated C++ types iterator
- public IEnumerator GetEnumerator() => TypeCollection.GetEnumerator();
- IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable) TypeCollection).GetEnumerator();
+ public IEnumerator GetEnumerator() => CppTypeCollection.GetEnumerator();
+ IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable) CppTypeCollection).GetEnumerator();
// The C++ declaration generator for this binary
// 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
// 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
declarationGenerator = new CppDeclarationGenerator(this);
// Initialize ordered type list for code output
- DependencyOrderedTypes = new List();
+ DependencyOrderedCppTypes = new List();
// 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)) {
declarationGenerator.IncludeMethod(method);
@@ -137,7 +124,7 @@ namespace Il2CppInspector.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)) {
declarationGenerator.IncludeMethod(method);
@@ -149,7 +136,7 @@ namespace Il2CppInspector.Model
// Add metadata usage types to C++ type model
// Not supported in il2cpp <19
- TypeCollection.SetGroup("types_from_usages");
+ CppTypeCollection.SetGroup("types_from_usages");
if (Package.MetadataUsages != null)
foreach (var usage in Package.MetadataUsages) {
@@ -161,6 +148,15 @@ namespace Il2CppInspector.Model
var type = ILModel.GetMetadataUsageType(usage);
declarationGenerator.IncludeType(type);
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;
case MetadataUsageType.MethodDef:
case MetadataUsageType.MethodRef:
@@ -179,24 +175,32 @@ namespace Il2CppInspector.Model
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) {
if (type.vtableType != null)
- DependencyOrderedTypes.Add(type.vtableType);
+ DependencyOrderedCppTypes.Add(type.vtableType);
if (type.staticsType != null)
- DependencyOrderedTypes.Add(type.staticsType);
+ DependencyOrderedCppTypes.Add(type.staticsType);
if (type.fieldsType != null)
- DependencyOrderedTypes.Add(type.fieldsType);
+ DependencyOrderedCppTypes.Add(type.fieldsType);
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
- public IEnumerable GetTypeGroup(string groupName) => TypeCollection.GetTypeGroup(groupName);
- public IEnumerable GetDependencyOrderedTypeGroup(string groupName) => DependencyOrderedTypes.Where(t => t.Group == groupName);
+ public IEnumerable GetTypeGroup(string groupName) => CppTypeCollection.GetTypeGroup(groupName);
+ public IEnumerable GetDependencyOrderedTypeGroup(string groupName) => DependencyOrderedCppTypes.Where(t => t.Group == groupName);
}
}
diff --git a/Il2CppInspector.Common/Model/AppType.cs b/Il2CppInspector.Common/Model/AppType.cs
new file mode 100644
index 0000000..da6f520
--- /dev/null
+++ b/Il2CppInspector.Common/Model/AppType.cs
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/Il2CppInspector.Common/Outputs/IDAPythonScript.cs b/Il2CppInspector.Common/Outputs/IDAPythonScript.cs
index 6aae6f0..232bec7 100755
--- a/Il2CppInspector.Common/Outputs/IDAPythonScript.cs
+++ b/Il2CppInspector.Common/Outputs/IDAPythonScript.cs
@@ -29,7 +29,7 @@ namespace Il2CppInspector.Outputs
var internalModel = new AppModel(model.ILModel);
internalModel.UnityVersion = model.UnityVersion;
internalModel.UnityHeader = model.UnityHeader;
- internalModel.TypeCollection = CppTypeCollection.FromUnityHeaders(model.UnityHeader, model.WordSize);
+ internalModel.CppTypeCollection = CppTypeCollection.FromUnityHeaders(model.UnityHeader, model.WordSize);
model = internalModel;
declGenerator = new CppDeclarationGenerator(model);
@@ -226,7 +226,8 @@ typedef __int64 int64_t;
}
// 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",
types.SelectMany(t => new List {t.vtableType, t.staticsType, t.fieldsType, t.valueType, t.referenceType})
.Where(t => t != null)