diff --git a/RecodeItLib/Dumper/DumpyILHelper.cs b/RecodeItLib/Dumper/DumpyILHelper.cs new file mode 100644 index 0000000..7f2852b --- /dev/null +++ b/RecodeItLib/Dumper/DumpyILHelper.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Metadata; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using dnlib.DotNet; +using dnlib.DotNet.Emit; +using DumpLib; +using ReCodeIt.Utils; + +namespace ReCodeItLib.Dumper; + +public static class DumpyILHelper +{ + /// + /// Sets up local variables and returns a List of instructions to add. + /// + /// Importer + /// MethodDef + public static List GetBackRequestInstructions(MethodDef method, Importer? gameImporter) + { + return new List + { + Instruction.Create(OpCodes.Ldarg_1), + Instruction.Create(OpCodes.Ldloc_S, method.Body.Variables[6]), + Instruction.Create(OpCodes.Call, gameImporter?.Import(typeof(DumpLib.DumpyTool).GetMethod("LogRequestResponse", new[] { typeof(object), typeof(object) }))) + }; + } + + /// + /// Returns a List of instructions to be added to the method. + /// This is an Async method so there is two parts, this part and a RunValidation method. + /// + /// AssemblyDefinition + /// MethodDefinition + public static List GetRunValidationInstructionsMoveNext(MethodDef method, ModuleDefMD gameModule, ModuleDefMD msModule, Importer? gameImporter) + { + // Add our own local variables + // var1 index0 class1159Type + var sptClassType = gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType); + var sptClass = new Local(sptClassType.ToTypeSig()); + method.Body.Variables.Add(sptClass); + + // var2 index1 ExceptionType + var typer = msModule.GetTypes().First(x => x.Name.ToLower() == "exception"); + var sptExceptionType = gameImporter?.Import(typer); + var sptException = new Local(sptExceptionType.ToTypeSig()); + method.Body.Variables.Add(sptException); + + return new List + { + // most of this is to keep the Async happy + + Instruction.Create(OpCodes.Ldarg_0), + Instruction.Create(OpCodes.Ldfld, gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[2]), + Instruction.Create(OpCodes.Stloc_0), + + // this.Succeed = true; + Instruction.Create(OpCodes.Ldloc_0), + Instruction.Create(OpCodes.Ldc_I4_1), + Instruction.Create(OpCodes.Call, gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).Methods.First(x => x.Name == "set_Succeed")), + + Instruction.Create(OpCodes.Stloc_1), + Instruction.Create(OpCodes.Ldarg_0), + Instruction.Create(OpCodes.Ldc_I4_S, (sbyte)-2), + Instruction.Create(OpCodes.Stfld, gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[0]), + Instruction.Create(OpCodes.Ldarg_0), + Instruction.Create(OpCodes.Ldflda, gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[1]), + Instruction.Create(OpCodes.Ldloc_1), + Instruction.Create(OpCodes.Call, + gameImporter?.Import(gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[1].FieldType.ScopeType.ResolveTypeDef().Methods.First(x => x.Name == "SetException"))), + + Instruction.Create(OpCodes.Ldarg_0), + Instruction.Create(OpCodes.Ldc_I4_S, (sbyte)-2), + Instruction.Create(OpCodes.Stfld, gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[0]), + + Instruction.Create(OpCodes.Ldarg_0), + Instruction.Create(OpCodes.Ldflda, gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[1]), + Instruction.Create(OpCodes.Call, gameImporter?.Import(gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[1].FieldType.ScopeType.ResolveTypeDef().Methods.First(x => x.Name == "SetResult"))), + + Instruction.Create(OpCodes.Ret), + }; + } + + /// + /// Returns a List of instructions to be added to the method. + /// This is an Async method so there is two parts, this part and a RunValidation method. + /// + /// AssemblyDefinition + /// MethodDefinition + /// List + public static List GetEnsureConsistencyInstructions(MethodDef method, ModuleDefMD checkModule, ModuleDefMD msModule, Importer? checkImporter) + { + // init local vars + // var1 index0 TimeSpan type + var sptTimeSpanType = checkImporter?.Import(msModule.GetTypes().First(x => x.Name == "TimeSpan")); + var sptClass = new Local(sptTimeSpanType.ToTypeSig()); + method.Body.Variables.Add(sptClass); + + // Create genericInstance of a method + var type = checkModule.GetTypes().First(DumpyReflectionHelper.GetEnsureConsistencyType).NestedTypes[0].Interfaces[0].Interface; + var typeMethod = checkImporter?.Import(msModule.GetTypes().First(x => x.Name == "Task").Methods.First(x => x.Name == "FromResult")); + var generac = new MethodSpecUser(typeMethod as IMethodDefOrRef, new GenericInstMethodSig(type.ToTypeSig())); + + return new List + { + // return Task.FromResult(ConsistencyController.CheckResult.Succeed(default(TimeSpan))); + Instruction.Create(OpCodes.Ldloca_S, method.Body.Variables[0]), + Instruction.Create(OpCodes.Initobj, sptTimeSpanType), + Instruction.Create(OpCodes.Ldloc_0), + Instruction.Create(OpCodes.Call, checkModule.GetTypes().First(DumpyReflectionHelper.GetEnsureConsistencyType).NestedTypes[0].Methods.First(x => x.Name == "Succeed")), + Instruction.Create(OpCodes.Call, generac), + Instruction.Create(OpCodes.Ret) + }; + } + + /// + /// Returns a List of instructions to be added to the method. + /// This is an Async method so there is two parts, this part and a MoveNext method. + /// + /// AssemblyDefinition + /// MethodDefinition + /// List + public static List GetRunValidationInstructions(MethodDef method, ModuleDefMD gameModule, ModuleDefMD msModule, Importer? gameImporter) + { + // Create genericInstance of a method + var type = gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0]; + var typeMethod = gameImporter?.Import(msModule.GetTypes().First(x => x.Name == "AsyncTaskMethodBuilder").Methods.First(x => x.Name == "Start")); + var generac = new MethodSpecUser(typeMethod as IMethodDefOrRef, new GenericInstMethodSig(type.ToTypeSig())); + + return new List + { + // d__.<>t__builder = AsyncTaskMethodBuilder.Create(); + Instruction.Create(OpCodes.Ldloca_S, method.Body.Variables[0]), + Instruction.Create(OpCodes.Call, gameImporter?.Import(gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[1].FieldType.ScopeType.ResolveTypeDef().Methods.First(x => x.Name == "Create"))), + Instruction.Create(OpCodes.Stfld, gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[1]), + + // d__.<>4__this = this; + Instruction.Create(OpCodes.Ldloca_S, method.Body.Variables[0]), + Instruction.Create(OpCodes.Ldarg_0), + Instruction.Create(OpCodes.Stfld, gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[2]), + + // d__.<>1__state = -1; + Instruction.Create(OpCodes.Ldloca_S, method.Body.Variables[0]), + Instruction.Create(OpCodes.Ldc_I4_M1), + Instruction.Create(OpCodes.Stfld, gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[0]), + + // d__.<>t__builder.Startd__0>(ref d__); + Instruction.Create(OpCodes.Ldloca_S, method.Body.Variables[0]), + Instruction.Create(OpCodes.Ldflda, gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[1]), + Instruction.Create(OpCodes.Ldloca_S, method.Body.Variables[0]), + Instruction.Create(OpCodes.Call, generac), + + // return d__.<>t__builder.Task; + Instruction.Create(OpCodes.Ldloca_S, method.Body.Variables[0]), + Instruction.Create(OpCodes.Ldflda, gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[1]), + Instruction.Create(OpCodes.Call, gameImporter?.Import(gameModule.GetTypes().First(DumpyReflectionHelper.GetRunValidationType).NestedTypes[0].Fields[1].FieldType.ScopeType.ResolveTypeDef().Methods.First(x => x.Name == "get_Task"))), + Instruction.Create(OpCodes.Ret), + }; + } + + public static List GetDumpyTaskInstructions(MethodDef method, ModuleDefMD assembly, Importer? gameImporter) + { + return new List + { + Instruction.Create(OpCodes.Call, gameImporter?.Import(typeof(DumpyTool).GetMethod("StartDumpyTask"))), + Instruction.Create(OpCodes.Pop) + }; + } + + public static ExceptionHandler GetExceptionHandler(MethodDef method, Importer? importer, ModuleDefMD msModule) + { + return new ExceptionHandler() + { + TryStart = method.Body.Instructions[3], + TryEnd = method.Body.Instructions[7], + HandlerStart = method.Body.Instructions[7], + HandlerEnd = method.Body.Instructions[16], + CatchType = importer?.Import(msModule.GetTypes().First(x => x.Name == "Exception")) + }; + } +} \ No newline at end of file