// Create type model public TypeModel(Il2CppInspector package) { Package = package; TypesByDefinitionIndex = new TypeInfo[package.TypeDefinitions.Length]; TypesByReferenceIndex = new TypeInfo[package.TypeReferences.Count]; GenericParameterTypes = new TypeInfo[package.GenericParameters.Length]; MethodsByDefinitionIndex = new MethodBase[package.Methods.Length]; MethodInvokers = new MethodInvoker[package.MethodInvokePointers.Length]; // Recursively create hierarchy of assemblies and types from TypeDefs // No code that executes here can access any type through a TypeRef (ie. via TypesByReferenceIndex) for (var image = 0; image < package.Images.Length; image++) { Assemblies.Add(new Assembly(this, image)); } // Create and reference types from TypeRefs // Note that you can't resolve any TypeRefs until all the TypeDefs have been processed for (int typeRefIndex = 0; typeRefIndex < package.TypeReferences.Count; typeRefIndex++) { if (TypesByReferenceIndex[typeRefIndex] != null) { /* type already generated - probably by forward reference through GetTypeFromVirtualAddress */ continue; } var typeRef = Package.TypeReferences[typeRefIndex]; var referencedType = resolveTypeReference(typeRef); TypesByReferenceIndex[typeRefIndex] = referencedType; } // Create types and methods from MethodSpec (which incorporates TypeSpec in IL2CPP) foreach (var spec in Package.MethodSpecs) { var methodDefinition = MethodsByDefinitionIndex[spec.methodDefinitionIndex]; var declaringType = methodDefinition.DeclaringType; // Concrete instance of a generic class // If the class index is not specified, we will later create a generic method in a non-generic class if (spec.classIndexIndex != -1) { var genericInstance = Package.GenericInstances[spec.classIndexIndex]; var genericArguments = ResolveGenericArguments(genericInstance); declaringType = declaringType.MakeGenericType(genericArguments); } MethodBase method; if (methodDefinition is ConstructorInfo) { method = declaringType.GetConstructorByDefinition((ConstructorInfo)methodDefinition); } else { method = declaringType.GetMethodByDefinition((MethodInfo)methodDefinition); } if (spec.methodIndexIndex != -1) { var genericInstance = Package.GenericInstances[spec.methodIndexIndex]; var genericArguments = ResolveGenericArguments(genericInstance); method = method.MakeGenericMethod(genericArguments); } method.VirtualAddress = Package.GetGenericMethodPointer(spec); GenericMethods[spec] = method; } // Generate a list of all namespaces used Namespaces = Assemblies.SelectMany(x => x.DefinedTypes).GroupBy(t => t.Namespace).Select(n => n.Key).Distinct().ToList(); // Find all custom attribute generators (populate AttributesByIndices) (use ToList() to force evaluation) var allAssemblyAttributes = Assemblies.Select(a => a.CustomAttributes).ToList(); var allTypeAttributes = TypesByDefinitionIndex.Select(t => t.CustomAttributes).ToList(); var allEventAttributes = TypesByDefinitionIndex.SelectMany(t => t.DeclaredEvents).Select(e => e.CustomAttributes).ToList(); var allFieldAttributes = TypesByDefinitionIndex.SelectMany(t => t.DeclaredFields).Select(f => f.CustomAttributes).ToList(); var allPropertyAttributes = TypesByDefinitionIndex.SelectMany(t => t.DeclaredProperties).Select(p => p.CustomAttributes).ToList(); var allMethodAttributes = MethodsByDefinitionIndex.Select(m => m.CustomAttributes).ToList(); var allParameterAttributes = MethodsByDefinitionIndex.SelectMany(m => m.DeclaredParameters).Select(p => p.CustomAttributes).ToList(); // Create method invokers (one per signature, in invoker index order) foreach (var method in MethodsByDefinitionIndex) { var index = package.GetInvokerIndex(method.DeclaringType.Assembly.ModuleDefinition, method.Definition); if (index != -1) { if (MethodInvokers[index] == null) { MethodInvokers[index] = new MethodInvoker(method, index); } method.Invoker = MethodInvokers[index]; } } // TODO: Some invokers are not initialized or missing, need to find out why // Create method invokers sourced from generic method invoker indices foreach (var spec in GenericMethods.Keys) { if (package.GenericMethodInvokerIndices.TryGetValue(spec, out var index)) { if (MethodInvokers[index] == null) { MethodInvokers[index] = new MethodInvoker(GenericMethods[spec], index); } GenericMethods[spec].Invoker = MethodInvokers[index]; } } }
// Create type model public Il2CppModel(Il2CppInspector package) { Package = package; TypesByDefinitionIndex = new TypeInfo[package.TypeDefinitions.Length]; TypesByReferenceIndex = new TypeInfo[package.TypeReferences.Count]; MethodsByDefinitionIndex = new MethodBase[package.Methods.Length]; MethodInvokers = new MethodInvoker[package.MethodInvokePointers.Length]; // Recursively create hierarchy of assemblies and types from TypeDefs // No code that executes here can access any type through a TypeRef (ie. via TypesByReferenceIndex) for (var image = 0; image < package.Images.Length; image++) { Assemblies.Add(new Assembly(this, image)); } // Create and reference types from TypeRefs // Note that you can't resolve any TypeRefs until all the TypeDefs have been processed for (int typeRefIndex = 0; typeRefIndex < package.TypeReferences.Count; typeRefIndex++) { var typeRef = Package.TypeReferences[typeRefIndex]; var referencedType = resolveTypeReference(typeRef); TypesByReferenceIndex[typeRefIndex] = referencedType; } // Create types and methods from MethodSpec (which incorporates TypeSpec in IL2CPP) foreach (var spec in Package.MethodSpecs) { TypeInfo declaringType; // Concrete instance of a generic class // If the class index is not specified, we will later create a generic method in a non-generic class if (spec.classIndexIndex != -1) { if (!TypesByMethodSpecClassIndex.ContainsKey(spec.classIndexIndex)) { TypesByMethodSpecClassIndex.Add(spec.classIndexIndex, new TypeInfo(this, spec)); } declaringType = TypesByMethodSpecClassIndex[spec.classIndexIndex]; } else { declaringType = MethodsByDefinitionIndex[spec.methodDefinitionIndex].DeclaringType; } // Concrete instance of a generic method if (spec.methodIndexIndex != -1) { // Method or constructor var concreteMethod = new MethodInfo(this, spec, declaringType); if (concreteMethod.Name == ConstructorInfo.ConstructorName || concreteMethod.Name == ConstructorInfo.TypeConstructorName) { GenericMethods.Add(spec, new ConstructorInfo(this, spec, declaringType)); } else { GenericMethods.Add(spec, concreteMethod); } } } // Create method invokers (one per signature, in invoker index order) foreach (var method in MethodsByDefinitionIndex) { var index = package.GetInvokerIndex(method.DeclaringType.Assembly.ModuleDefinition, method.Definition); if (index != -1) { if (MethodInvokers[index] == null) { MethodInvokers[index] = new MethodInvoker(method, index); } method.Invoker = MethodInvokers[index]; } } // TODO: Some invokers are not initialized or missing, need to find out why // Create method invokers sourced from generic method invoker indices foreach (var spec in GenericMethods.Keys) { if (package.GenericMethodInvokerIndices.TryGetValue(spec, out var index)) { if (MethodInvokers[index] == null) { MethodInvokers[index] = new MethodInvoker(GenericMethods[spec], index); } GenericMethods[spec].Invoker = MethodInvokers[index]; } } }