public IEnumerable <Record> Collect() { var asm = typeof(ConfMgr).Assembly; foreach (var baseClass in CollectConfBaseClasses()) { var baseTypeName = baseClass.Name.ToString(); var itemTypeName = baseTypeName.Substring(0, baseTypeName.Length - 4) + "Item"; var name = baseTypeName.Substring(4, baseTypeName.Length - 8); var managedBaseType = asm.GetType(baseTypeName); Logger.Assert(managedBaseType != null, $"Type {baseTypeName} must exist in unhollowed assembly"); var managedItemType = asm.GetType(itemTypeName); Logger.Assert(managedItemType != null, $"Type {itemTypeName} must exist in unhollowed assembly"); var itemType = module.Find(itemTypeName, false); Logger.Assert(itemType != null, $"Type {itemTypeName} must exist in dumped assembly"); var ctorInfo = GetProperConstructorInfo(managedItemType); var ctorToken = GetProperConstructorToken(itemType, ctorInfo); var classPtr = IL2CPP.GetIl2CppClass("Assembly-CSharp.dll", "", itemTypeName); IL2CPP.il2cpp_runtime_class_init(classPtr); var ctorVa = IL2CPP.GetIl2CppMethodByToken(classPtr, ctorToken); var fields = GetItemFields(ctorInfo, itemType, managedItemType).ToArray(); // GetIl2CppMethodByToken sometimes points to dynamic generated function, so use RVA in dummy dll directly. var finalInitRva = GetFinalInitRva(baseClass); yield return(new Record { Name = name, BaseType = managedBaseType, ItemType = managedItemType, NativeItemClassPtr = classPtr, ItemCtor = (ctorInfo, ctorVa), FieldsInfo = fields, FinalInitVa = RvaToVa(finalInitRva), });