/// <summary> /// Creates all the Assemblies defined in the provided metadata, along with (stub) definitions of all the types contained therein, and registers them with the resolver. /// </summary> /// <param name="metadata">The Il2Cpp metadata to extract assemblies from</param> /// <param name="resolver">The Assembly Resolver that assemblies are registered with, used to ensure assemblies can cross reference.</param> /// <param name="moduleParams">Configuration for the module creation.</param> /// <returns>A list of Mono.Cecil Assemblies, containing empty type definitions for each defined type.</returns> internal static List <AssemblyDefinition> CreateAssemblies(Il2CppMetadata metadata, RegistryAssemblyResolver resolver, ModuleParameters moduleParams) { var assemblies = new List <AssemblyDefinition>(); foreach (var assemblyDefinition in metadata.assemblyDefinitions) { //Get the name of the assembly (= the name of the DLL without the file extension) var assemblyNameString = metadata.GetStringFromIndex(assemblyDefinition.nameIndex).Replace(".dll", ""); //Build a Mono.Cecil assembly name from this name var asmName = new AssemblyNameDefinition(assemblyNameString, new Version("0.0.0.0")); Console.Write($"\t\t{assemblyNameString}..."); //Create an empty assembly and register it var assembly = AssemblyDefinition.CreateAssembly(asmName, metadata.GetStringFromIndex(assemblyDefinition.nameIndex), moduleParams); resolver.Register(assembly); assemblies.Add(assembly); //Ensure it really _is_ empty var mainModule = assembly.MainModule; mainModule.Types.Clear(); //Find the end index of the types belonging to this assembly (as they're all in one huge list in the metadata) var end = assemblyDefinition.firstTypeIndex + assemblyDefinition.typeCount; for (var defNumber = assemblyDefinition.firstTypeIndex; defNumber < end; defNumber++) { //Get the metadata type info, its namespace, and name. var type = metadata.typeDefs[defNumber]; var ns = metadata.GetStringFromIndex(type.namespaceIndex); var name = metadata.GetStringFromIndex(type.nameIndex); TypeDefinition definition; if (type.declaringTypeIndex != -1) { //This is a type declared within another (inner class/type) definition = SharedState.TypeDefsByIndex[defNumber]; } else { //This is a new type so ensure it's registered definition = new TypeDefinition(ns, name, (TypeAttributes)type.flags); mainModule.Types.Add(definition); SharedState.TypeDefsByIndex.Add(defNumber, definition); } //Ensure we include all inner types within this type. for (var nestedNumber = 0; nestedNumber < type.nested_type_count; nestedNumber++) { //These are stored in a separate field in the metadata. var nestedIndex = metadata.nestedTypeIndices[type.nestedTypesStart + nestedNumber]; var nested = metadata.typeDefs[nestedIndex]; //Create it and register. var nestedDef = new TypeDefinition(metadata.GetStringFromIndex(nested.namespaceIndex), metadata.GetStringFromIndex(nested.nameIndex), (TypeAttributes)nested.flags); definition.NestedTypes.Add(nestedDef); SharedState.TypeDefsByIndex.Add(nestedIndex, nestedDef); } } Console.WriteLine("OK"); } return(assemblies); }
/// <summary> /// Creates all the Assemblies defined in the provided metadata, along with (stub) definitions of all the types contained therein, and registers them with the resolver. /// </summary> /// <param name="metadata">The Il2Cpp metadata to extract assemblies from</param> /// <param name="resolver">The Assembly Resolver that assemblies are registered with, used to ensure assemblies can cross reference.</param> /// <param name="moduleParams">Configuration for the module creation.</param> /// <returns>A list of Mono.Cecil Assemblies, containing empty type definitions for each defined type.</returns> internal static List <AssemblyDefinition> CreateAssemblies(Il2CppMetadata metadata, RegistryAssemblyResolver resolver, ModuleParameters moduleParams) { var assemblies = new List <AssemblyDefinition>(); foreach (var assemblyDefinition in metadata.imageDefinitions) { //Get the name of the assembly (= the name of the DLL without the file extension) var assemblyNameString = metadata.GetStringFromIndex(assemblyDefinition.nameIndex).Replace(".dll", ""); //Build a Mono.Cecil assembly name from this name var asmName = new AssemblyNameDefinition(assemblyNameString, new Version("0.0.0.0")); Console.Write($"\t\t{assemblyNameString}..."); //Create an empty assembly and register it var assembly = AssemblyDefinition.CreateAssembly(asmName, metadata.GetStringFromIndex(assemblyDefinition.nameIndex), moduleParams); resolver.Register(assembly); assemblies.Add(assembly); //Ensure it really _is_ empty var mainModule = assembly.MainModule; mainModule.Types.Clear(); //Find the end index of the types belonging to this assembly (as they're all in one huge list in the metadata) var end = assemblyDefinition.firstTypeIndex + assemblyDefinition.typeCount; for (var defNumber = assemblyDefinition.firstTypeIndex; defNumber < end; defNumber++) { //Get the metadata type info, its namespace, and name. var type = metadata.typeDefs[defNumber]; var ns = metadata.GetStringFromIndex(type.namespaceIndex); var name = metadata.GetStringFromIndex(type.nameIndex); TypeDefinition?definition = null; if (type.declaringTypeIndex != -1) { //This is a type declared within another (inner class/type) //Have we already declared this type due to handling its parent? SharedState.TypeDefsByIndex.TryGetValue(defNumber, out definition); } if (definition == null) { //This is a new type (including nested type with parent not defined yet) so ensure it's registered definition = new TypeDefinition(ns, name, (TypeAttributes)type.flags); if (ns == "System" && name == "String") { typeof(TypeReference).GetField("etype", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(definition, (byte)0x0e); //mark as string } mainModule.Types.Add(definition); SharedState.AllTypeDefinitions.Add(definition); SharedState.TypeDefsByIndex.Add(defNumber, definition); } //Ensure we include all inner types within this type. for (var nestedNumber = 0; nestedNumber < type.nested_type_count; nestedNumber++) { //These are stored in a separate field in the metadata. var nestedIndex = metadata.nestedTypeIndices[type.nestedTypesStart + nestedNumber]; var nested = metadata.typeDefs[nestedIndex]; if (SharedState.TypeDefsByIndex.TryGetValue(nestedIndex, out var alreadyMadeNestedType)) { //Type has already been defined (can be out-of-order in v27+) so we just add it. definition.NestedTypes.Add(alreadyMadeNestedType); } else { //Create it and register. var nestedDef = new TypeDefinition(metadata.GetStringFromIndex(nested.namespaceIndex), metadata.GetStringFromIndex(nested.nameIndex), (TypeAttributes)nested.flags); definition.NestedTypes.Add(nestedDef); SharedState.AllTypeDefinitions.Add(nestedDef); SharedState.TypeDefsByIndex.Add(nestedIndex, nestedDef); } } } Console.WriteLine("OK"); } return(assemblies); }