private void Collect(MethodDefinition meth, MethodReference mref) { GenericInstanceMethod genMeth = null; if (Methods.Contains(meth) || ((genMeth = mref as GenericInstanceMethod) != null && GenericMethods.Contains(genMeth))) { return; } if (genMeth != null) { GenericMethods.Add(genMeth); } else { Methods.Add(meth); } Collect(genMeth?.ReturnType ?? meth.ReturnType); foreach (var param in genMeth?.Parameters ?? meth.Parameters) { Collect(param); } if (meth.HasBody) { Collect(meth.Body); } }
// 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]; } } }