private static void AddParameters(MethodDef method) { if (method.Parameters.Count == 0) { method.Body.Instructions.Add(OpCodes.Ldnull.ToInstruction()); return; } method.Body.Instructions.Add(OpCodes.Ldc_I4.ToInstruction(method.Parameters.Count)); method.Body.Instructions.Add(OpCodes.Newarr.ToInstruction(method.Module.CorLibTypes.Object)); method.Body.Instructions.Add(OpCodes.Dup.ToInstruction()); for (var i = 0; i < method.Parameters.Count; i++) { method.Body.Instructions.Add(OpCodes.Ldc_I4.ToInstruction(i)); method.Body.Instructions.Add(OpCodes.Ldarg.ToInstruction(method.Parameters[i])); var cor = method.Module.CorLibTypes; var param = method.Parameters[i]; if (!param.IsHiddenThisParameter) { if (param.Type != cor.String && param.Type != cor.Object && param.Type != cor.TypedReference) { var spec = new TypeSpecUser(param.Type); method.Body.Instructions.Add(new Instruction(OpCodes.Box, spec)); } } method.Body.Instructions.Add(OpCodes.Stelem_Ref.ToInstruction()); method.Body.Instructions.Add(OpCodes.Dup.ToInstruction()); } method.Body.Instructions.Remove(method.Body.Instructions.Last()); }
internal override void ProcessOperand(TypeService service, MethodDef method, IList <Instruction> body, ref int index, MemberRef operand) { Debug.Assert(service != null, $"{nameof(service)} != null"); Debug.Assert(method != null, $"{nameof(method)} != null"); Debug.Assert(body != null, $"{nameof(body)} != null"); Debug.Assert(operand != null, $"{nameof(operand)} != null"); Debug.Assert(index >= 0, $"{nameof(index)} >= 0"); Debug.Assert(index < body.Count, $"{nameof(index)} < {nameof(body)}.Count"); var current = service.GetItem(method); if (operand.MethodSig == null) { return; } if (operand.MethodSig.Params.Count > 0 || body[index].OpCode != OpCodes.Newobj) { return; } ModuleDef mod = method.Module; var corlibType = mod.CorLibTypes.GetTypeRef("System", "Type").ResolveThrow(); var gettype = corlibType.FindMethod("GetTypeFromHandle"); var createInstance = mod.CorLibTypes.GetTypeRef("System", "Activator").ResolveThrow() .FindMethod("CreateInstance", MethodSig.CreateStatic(mod.CorLibTypes.Object, corlibType.ToTypeSig())); TypeSig sig = null; if (operand.Class is TypeRef typeRef) { sig = typeRef.ToTypeSig(); } if (operand.Class is TypeSpec typeSpec) { sig = typeSpec.ToTypeSig(); } if (sig != null) { body[index].OpCode = OpCodes.Ldtoken; var gen = current?.GetGeneric(sig); TypeSpecUser newTypeSpec = null; if (gen != null) { newTypeSpec = new TypeSpecUser(new GenericMVar(gen.Number)); } else { newTypeSpec = new TypeSpecUser(sig); } body[index].Operand = newTypeSpec; body.Insert(++index, Instruction.Create(OpCodes.Call, mod.Import(gettype))); body.Insert(++index, Instruction.Create(OpCodes.Call, mod.Import(createInstance))); } }
public static void CreateMethodRestore(MethodDef target, MethodDef newMethod, ModuleDefMD module) { AssemblyRef dnlib = module.GetAssemblyRef(new UTF8String("dnlib")); TypeRefUser Instruction = new TypeRefUser(module, new UTF8String("dnlib"), new UTF8String("Instruction"), dnlib); TypeSig instructionSig = Instruction.ToTypeSig(); var assemblyRef = module.CorLibTypes.AssemblyRef; var listRef = new TypeRefUser(module, @"System.Collections.Generic", "List`1", assemblyRef); var listGenericInstSig = new GenericInstSig(new ClassSig(listRef), instructionSig); var listTypeSpec = new TypeSpecUser(listGenericInstSig); var listCtor = new MemberRefUser(module, ".ctor", MethodSig.CreateInstance(module.CorLibTypes.Void), listTypeSpec); var instruictionCtor = new MemberRefUser(module, ".ctor", MethodSig.CreateInstance(module.CorLibTypes.Void), instructionSig.TryGetTypeSpec()); var listAdd = new MemberRefUser(module, "Add", MethodSig.CreateInstance(module.CorLibTypes.Void, new GenericVar(0)), listTypeSpec); // sdsd newMethod.Body.Instructions.Add(OpCodes.Newobj.ToInstruction(listCtor)); newMethod.Body.Instructions.Add(OpCodes.Stloc_0.ToInstruction()); // Store list to local[0] /* * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Dup)); * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Ldsfld, OpCodes.Add)); * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Ldc_I4_S, 0x37)); * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Box, module.CorLibTypes.Int32)); * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Newobj, instruictionCtor)); * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Callvirt, listAdd)); */ }
private MethodDef CreateFactoryMethodNoParameters(ITypeService service, ModuleDef module) { var instancevar = new GenericParamUser(0, GenericParamAttributes.NoSpecialConstraint, "t"); var mvar = new GenericMVar(0); var typeSpec = new TypeSpecUser(mvar); var local = new Local(mvar); var rtHandle = new Local(module.Import(typeof(RuntimeTypeHandle)).ToTypeSig()); var method = new MethodDefUser("create", new MethodSig(CallingConvention.Default, 1, mvar), MethodAttributes.Static); method.GenericParameters.Add(instancevar); var gettype = typeof(Type).GetMethod("GetTypeFromHandle"); var comparetypes = typeof(Type).GetMethod("op_Equality"); var i = new List <Instruction>(); i.Add(Instruction.Create(OpCodes.Ldtoken, typeSpec)); i.Add(Instruction.Create(OpCodes.Call, module.Import(gettype))); i.Add(Instruction.Create(OpCodes.Stloc, rtHandle)); foreach (var mr in ObjectCreationRef) { Instruction endjump = Instruction.Create(OpCodes.Nop); i.Add(Instruction.Create(OpCodes.Ldloc, rtHandle)); i.Add(Instruction.Create(OpCodes.Ldtoken, mr.DeclaringType)); i.Add(Instruction.Create(OpCodes.Call, module.Import(gettype))); i.Add(Instruction.Create(OpCodes.Call, module.Import(comparetypes))); i.Add(Instruction.Create(OpCodes.Brfalse_S, endjump)); i.Add(Instruction.Create(OpCodes.Newobj, mr)); i.Add(Instruction.Create(OpCodes.Ret)); i.Add(endjump); } i.Add(Instruction.Create(OpCodes.Ldloca_S, local)); i.Add(Instruction.Create(OpCodes.Initobj, typeSpec)); i.Add(Instruction.Create(OpCodes.Ldloc, local)); i.Add(Instruction.Create(OpCodes.Ret)); method.Body = new CilBody(true, i, new ExceptionHandler[0], new Local[] { local, rtHandle }); return(method); }
/// <summary> /// Converts WinMD member reference <paramref name="mr"/> to a CLR member reference. Returns /// <c>null</c> if it's not a CLR compatible WinMD member reference. /// </summary> /// <param name="module">Owner module or <c>null</c></param> /// <param name="mr">Member reference</param> /// <returns></returns> public static MemberRef ToCLR(ModuleDef module, MemberRef mr) { // See WinMDAdapter::CheckIfMethodImplImplementsARedirectedInterface // in coreclr: md/winmd/adapter.cpp if (mr == null) { return(null); } if (mr.Name != CloseName) { return(null); } var msig = mr.MethodSig; if (msig == null) { return(null); } var cl = mr.Class; IMemberRefParent newCl; TypeSpec ts; if (cl is TypeRef tr) { var newTr = ToCLR(module, tr); if (newTr == null || !IsIDisposable(newTr)) { return(null); } newCl = newTr; } else if ((ts = cl as TypeSpec) != null) { var gis = ts.TypeSig as GenericInstSig; if (gis == null || !(gis.GenericType is ClassSig)) { return(null); } tr = gis.GenericType.TypeRef; if (tr == null) { return(null); } var newTr = ToCLR(module, tr, out bool isClrValueType); if (newTr == null || !IsIDisposable(newTr)) { return(null); } newCl = new TypeSpecUser(new GenericInstSig(isClrValueType ? (ClassOrValueTypeSig) new ValueTypeSig(newTr) : new ClassSig(newTr), gis.GenericArguments)); } else { return(null); } return(new MemberRefUser(mr.Module, DisposeName, msig, newCl)); }
public static void Run() { // This is the file that will be created string newFileName = @"GenericExample1.exe"; // Create the module var mod = new ModuleDefUser("GenericExample1", Guid.NewGuid(), new AssemblyRefUser(new AssemblyNameInfo(typeof(int).Assembly.GetName().FullName))); // It's a console app mod.Kind = ModuleKind.Console; // Create the assembly and add the created module to it new AssemblyDefUser("GenericExample1", new Version(1, 2, 3, 4)).Modules.Add(mod); // Add the startup type. It derives from System.Object. TypeDef startUpType = new TypeDefUser("My.Namespace", "Startup", mod.CorLibTypes.Object.TypeDefOrRef); startUpType.Attributes = TypeAttributes.NotPublic | TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.AnsiClass; // Add the type to the module mod.Types.Add(startUpType); // Create the entry point method MethodDef entryPoint = new MethodDefUser("Main", MethodSig.CreateStatic(mod.CorLibTypes.Int32, new SZArraySig(mod.CorLibTypes.String))); entryPoint.Attributes = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot; entryPoint.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed; // Name the 1st argument (argument 0 is the return type) entryPoint.ParamDefs.Add(new ParamDefUser("args", 1)); // Add the method to the startup type startUpType.Methods.Add(entryPoint); // Set module entry point mod.EntryPoint = entryPoint; // Create System.Console type reference var systemConsole = mod.CorLibTypes.GetTypeRef("System", "Console"); // Create 'void System.Console.WriteLine(string,object)' method reference var writeLine2 = new MemberRefUser(mod, "WriteLine", MethodSig.CreateStatic(mod.CorLibTypes.Void, mod.CorLibTypes.String, mod.CorLibTypes.Object), systemConsole); // // Method 1: Create List<String> inst signature by importing (easy way) // -------------------------------------------------------------------- //Importer importer = new Importer(mod); //var listGenericInstSig = importer.ImportAsTypeSig(typeof(System.Collections.Generic.List<String>)); // // Method 2: Create List<String> inst signature manually (harder way) // ------------------------------------------------------------------ var assemblyRef = mod.CorLibTypes.AssemblyRef; var listRef = new TypeRefUser(mod, @"System.Collections.Generic", "List`1", assemblyRef); // Create the GenericInstSig from a ClassSig with <String> generic arg var listGenericInstSig = new GenericInstSig(new ClassSig(listRef), mod.CorLibTypes.String); // Create TypeSpec from GenericInstSig var listTypeSpec = new TypeSpecUser(listGenericInstSig); // Create System.Collections.Generic.List<String>::.ctor method reference var listCtor = new MemberRefUser(mod, ".ctor", MethodSig.CreateInstance(mod.CorLibTypes.Void), listTypeSpec); // Create Add(!0) method reference, !0 signifying first generic argument of declaring type // In this case, would be Add(String item) // (GenericMVar would be used for method generic argument, such as Add<!!0>(!!0)) var listAdd = new MemberRefUser(mod, "Add", MethodSig.CreateInstance(mod.CorLibTypes.Void, new GenericVar(0)), listTypeSpec); var listGetCount = new MemberRefUser(mod, "get_Count", MethodSig.CreateInstance(mod.CorLibTypes.Int32), listTypeSpec); IList <Local> locals = new List <Local>(); locals.Add(new Local(listGenericInstSig)); // local[0]: class [mscorlib]System.Collections.Generic.List`1<string> var body = new CilBody(true, new List <Instruction>(), new List <ExceptionHandler>(), locals); // Call the list .ctor body.Instructions.Add(OpCodes.Newobj.ToInstruction(listCtor)); body.Instructions.Add(OpCodes.Stloc_0.ToInstruction()); // Store list to local[0] // list.Add("Item 1") body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); body.Instructions.Add(OpCodes.Ldstr.ToInstruction("Item 1")); body.Instructions.Add(OpCodes.Callvirt.ToInstruction(listAdd)); // WriteLine("Array: {0}", list.ToArray()); //body.Instructions.Add(OpCodes.Ldstr.ToInstruction("Array: {0}")); //body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); // Load list from local[0] //body.Instructions.Add(OpCodes.Callvirt.ToInstruction(listToArray)); //body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2)); // WriteLine("Count: {0}", list.Count) body.Instructions.Add(OpCodes.Ldstr.ToInstruction("Count: {0}")); body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); // Load list from local[0] body.Instructions.Add(OpCodes.Callvirt.ToInstruction(listGetCount)); body.Instructions.Add(OpCodes.Box.ToInstruction(mod.CorLibTypes.Int32)); body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2)); // return 0; body.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction()); body.Instructions.Add(OpCodes.Ret.ToInstruction()); entryPoint.Body = body; // Save the assembly mod.Write(newFileName); }
public override void ProcessOperand(TypeService service, MethodDef method, IList <Instruction> body, ref int index, MemberRef operand) { ScannedMethod current = service.GetItem(method.MDToken) as ScannedMethod; if (operand.MethodSig.Params.Count > 0 || current == null || body[index].OpCode != OpCodes.Newobj) { return; } ModuleDef mod = method.Module; var gettype = typeof(Type).GetMethod("GetTypeFromHandle"); var createInstance = typeof(Activator).GetMethod("CreateInstance", new Type[] { typeof(Type) }); var createInstanceArgs = typeof(Activator).GetMethod("CreateInstance", new Type[] { typeof(Type), typeof(object[]) }); TypeSig sig = null; if (operand.Class is TypeRef) { sig = (operand.Class as TypeRef)?.ToTypeSig(); } if (operand.Class is TypeSpec) { sig = (operand.Class as TypeSpec)?.ToTypeSig(); } if (sig != null) { //ScannedItem t = service.GetItem(operand.MDToken); //if (t != null) { // sig = t.CreateGenericTypeSig(service.GetItem(method.DeclaringType.MDToken)); // } var paramCount = operand.MethodSig.Params.Count; var gen = current.GetGeneric(sig); body[index].OpCode = OpCodes.Ldtoken; TypeSpecUser newTypeSpec = null; if (gen != null) { newTypeSpec = new TypeSpecUser(new GenericMVar(gen.Number)); } else { newTypeSpec = new TypeSpecUser(sig); } body[index].Operand = newTypeSpec; /* * var genericCallSig = new GenericInstMethodSig( new TypeSig[] { current.ConvertToGenericIfAvalible(sig) }); * foreach(var param in operand.MethodSig.Params.Select(x => current.ConvertToGenericIfAvalible(x))) { * genericCallSig.GenericArguments.Add(param); * } * * // tgtMethod.GenericInstMethodSig = genericCallSig; * var spec = new MethodSpecUser(tgtMethod, genericCallSig); * * body[index].OpCode = OpCodes.Call; * body[index].Operand = tgtMethod; */ body.Insert(++index, Instruction.Create(OpCodes.Call, mod.Import(gettype))); body.Insert(++index, Instruction.Create(OpCodes.Call, mod.Import(createInstance))); } }
public static void Run() { // This is the file that will be created string newFileName = @"GenericExample2.exe"; // Create the module var mod = new ModuleDefUser("GenericExample2", Guid.NewGuid(), new AssemblyRefUser(new AssemblyNameInfo(typeof(int).Assembly.GetName().FullName))); // It's a console app mod.Kind = ModuleKind.Console; // Create the assembly and add the created module to it new AssemblyDefUser("GenericExample2", new Version(1, 2, 3, 4)).Modules.Add(mod); // Add the startup type. It derives from System.Object. TypeDef startUpType = new TypeDefUser("My.Namespace", "Startup", mod.CorLibTypes.Object.TypeDefOrRef); startUpType.Attributes = TypeAttributes.NotPublic | TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.AnsiClass; // Add the type to the module mod.Types.Add(startUpType); // Create the entry point method MethodDef entryPoint = new MethodDefUser("Main", MethodSig.CreateStatic(mod.CorLibTypes.Int32, new SZArraySig(mod.CorLibTypes.String))); entryPoint.Attributes = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot; entryPoint.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed; // Name the 1st argument (argument 0 is the return type) entryPoint.ParamDefs.Add(new ParamDefUser("args", 1)); // Add the method to the startup type startUpType.Methods.Add(entryPoint); // Set module entry point mod.EntryPoint = entryPoint; // Create System.Console type reference var systemConsole = mod.CorLibTypes.GetTypeRef("System", "Console"); // Create 'void System.Console.WriteLine(string,object)' method reference var writeLine2 = new MemberRefUser(mod, "WriteLine", MethodSig.CreateStatic(mod.CorLibTypes.Void, mod.CorLibTypes.String, mod.CorLibTypes.Object), systemConsole); var assemblyRef = mod.CorLibTypes.AssemblyRef; // Create 'System.Collections.ObjectModel.ReadOnlyCollection`1' type ref var roCollectionRef = new TypeRefUser(mod, "System.Collections.ObjectModel", "ReadOnlyCollection`1", assemblyRef); // Create 'ReadOnlyCollection<!!0>' signature for return type var roCollectionSig = new GenericInstSig(new ClassSig(roCollectionRef), new GenericMVar(0)); // Return type // Create 'ReadOnlyCollection<Int32>' type spec var roCollectionTypeSpec = new TypeSpecUser(new GenericInstSig(new ClassSig(roCollectionRef), mod.CorLibTypes.Int32)); // Create 'ReadOnlyCollection<Int32>.get_Count()' method reference var roCollectionGetCount = new MemberRefUser(mod, "get_Count", MethodSig.CreateInstance(mod.CorLibTypes.Int32), roCollectionTypeSpec); // Create 'System.Array' type ref var arrayRef = new TypeRefUser(mod, "System", "Array", assemblyRef); // Create 'ReadOnlyCollection<T> Array.AsReadOnly<T>(T[] array)' method reference // Apparently CreateStaticGeneric should be used only if at least one GenericMVar is used? Not 100% certain. var asReadOnly = new MemberRefUser(mod, "AsReadOnly", MethodSig.CreateStaticGeneric(1, roCollectionSig, new SZArraySig(new GenericMVar(0))), arrayRef); // Create 'Array.AsReadOnly<Int32>' method spec var asReadOnlySpec = new MethodSpecUser(asReadOnly, new GenericInstMethodSig(mod.CorLibTypes.Int32)); // Create 'ReadOnlyCollection<Int32>' signature for local var roCollectionInt32 = roCollectionTypeSpec.TryGetGenericInstSig(); // Method body locals IList <Local> locals = new List <Local>(); locals.Add(new Local(new SZArraySig(mod.CorLibTypes.Int32))); // local[0]: Int32[] locals.Add(new Local(roCollectionInt32)); // local[1]: class [mscorlib]System.Collections.ObjectModel.ReadOnlyCollection`1<Int32> var body = new CilBody(true, new List <Instruction>(), new List <ExceptionHandler>(), locals); // array = new Int32[2]; body.Instructions.Add(OpCodes.Ldc_I4_2.ToInstruction()); body.Instructions.Add(OpCodes.Newarr.ToInstruction(mod.CorLibTypes.Int32)); body.Instructions.Add(OpCodes.Stloc_0.ToInstruction()); // Store array to local[0] // array[0] = 5; body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); body.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction()); body.Instructions.Add(OpCodes.Ldc_I4_5.ToInstruction()); body.Instructions.Add(OpCodes.Stelem_I4.ToInstruction()); // array[1] = 111; body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); body.Instructions.Add(OpCodes.Ldc_I4_1.ToInstruction()); body.Instructions.Add(OpCodes.Ldc_I4.ToInstruction(111)); body.Instructions.Add(OpCodes.Stelem_I4.ToInstruction()); // collection = Array.AsReadOnly<Int32>(array) body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); body.Instructions.Add(OpCodes.Call.ToInstruction(asReadOnlySpec)); body.Instructions.Add(OpCodes.Stloc_1.ToInstruction()); // Console.WriteLine("Count: {0}", collection.Count) body.Instructions.Add(OpCodes.Ldstr.ToInstruction("Count: {0}")); body.Instructions.Add(OpCodes.Ldloc_1.ToInstruction()); body.Instructions.Add(OpCodes.Callvirt.ToInstruction(roCollectionGetCount)); body.Instructions.Add(OpCodes.Box.ToInstruction(mod.CorLibTypes.Int32)); body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2)); // return 0; body.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction()); body.Instructions.Add(OpCodes.Ret.ToInstruction()); entryPoint.Body = body; // Save the assembly mod.Write(newFileName); }
private MethodDef CreateFactory(ITypeService service, ModuleDef module, int paramNumber, IList <IMethodDefOrRef> methods) { var declaringTypeGeneric = new GenericParamUser(0, GenericParamAttributes.NoSpecialConstraint, "t"); var declaringTypeGenericMVar = new GenericMVar(0); var pGenericTypeSpecs = Enumerable.Range(1, paramNumber).Select((x) => new TypeSpecUser(new GenericMVar(x))).ToArray(); var returnGeneric = new GenericMVar(paramNumber + 1);//last generic is return type var typeSpec = new TypeSpecUser(declaringTypeGenericMVar); var local = new Local(declaringTypeGenericMVar); var rtHandle = new Local(module.Import(typeof(RuntimeTypeHandle)).ToTypeSig()); var methodSig = new MethodSig(CallingConvention.Default, 1, returnGeneric, //Method index Enumerable.Range(1, paramNumber) .Select(x => new GenericMVar(x)) .Concat(new TypeSig[] { module.CorLibTypes.UInt32 }) //Index .ToArray()); var method = new MethodDefUser("call", methodSig, MethodAttributes.Static); method.GenericParameters.Add(declaringTypeGeneric); for (ushort genericNum = 1; genericNum < paramNumber + 2 /*declare type / return type */; genericNum++) { method.GenericParameters.Add(new GenericParamUser(genericNum, GenericParamAttributes.NoSpecialConstraint, "p" + genericNum.ToString())); } var gettype = typeof(Type).GetMethod("GetTypeFromHandle"); var comparetypes = typeof(Type).GetMethod("op_Equality"); var i = new List <Instruction>(); i.Add(Instruction.Create(OpCodes.Ldtoken, typeSpec)); i.Add(Instruction.Create(OpCodes.Call, module.Import(gettype))); i.Add(Instruction.Create(OpCodes.Stloc, rtHandle)); var retDef = new Instruction[] { Instruction.Create(OpCodes.Ldloca_S, local), Instruction.Create(OpCodes.Initobj, new TypeSpecUser(returnGeneric)), Instruction.Create(OpCodes.Ldloc, local), Instruction.Create(OpCodes.Ret), }; foreach (var mr in methods) { Instruction endjump = Instruction.Create(OpCodes.Nop); //Calling type i.Add(Instruction.Create(OpCodes.Ldloc, rtHandle)); i.Add(Instruction.Create(OpCodes.Ldtoken, mr.DeclaringType)); i.Add(Instruction.Create(OpCodes.Call, module.Import(gettype))); i.Add(Instruction.Create(OpCodes.Call, module.Import(comparetypes))); i.Add(Instruction.Create(OpCodes.Brfalse_S, endjump)); //method index i.Add(Instruction.Create(OpCodes.Ldarg, new Parameter(paramNumber))); i.Add(Instruction.Create(OpCodes.Ldc_I4, GetIndexOfMethodInDeclaringType(mr))); i.Add(Instruction.Create(OpCodes.Ceq)); i.Add(Instruction.Create(OpCodes.Brfalse_S, endjump)); //params for (int index = 0; index < mr.MethodSig.Params.Count; index++) { i.Add(Instruction.Create(OpCodes.Ldtoken, pGenericTypeSpecs[index])); i.Add(Instruction.Create(OpCodes.Call, module.Import(gettype))); i.Add(Instruction.Create(OpCodes.Ldtoken, new TypeSpecUser(mr.MethodSig.Params[index]))); i.Add(Instruction.Create(OpCodes.Call, module.Import(gettype))); i.Add(Instruction.Create(OpCodes.Call, module.Import(comparetypes))); i.Add(Instruction.Create(OpCodes.Brfalse_S, endjump)); } for (int index = 0; index < paramNumber; index++) { i.Add(Instruction.Create(OpCodes.Ldarg, new Parameter(index))); } i.Add(Instruction.Create(OpCodes.Call, mr)); if (mr.MethodSig.RetType != module.CorLibTypes.Void) { i.Add(Instruction.Create(OpCodes.Ret)); } else { // i.AddRange(retDef); } i.Add(endjump); } i.AddRange(retDef); method.Body = new CilBody(true, i, new ExceptionHandler[0], new Local[] { local, rtHandle }); // method.Body.KeepOldMaxStack = true; return(method); }
internal static async Task <int> Execute(ModuleDefMD targetModule) { /* * * Insert the following IL code into GameManager.AllButOnePlayersDied(): * * {IL_00FE: call TrainerOptions Singleton`1<TrainerOptions>::get_Instance()} * {IL_0103: ldfld System.Boolean TrainerOptions::NoWinners} * {IL_0108: brtrue.s IL_012E} * {IL_010A: ldarg.0} * {IL_010B: ldfld System.Collections.Generic.List`1<Controller> GameManager::playersAlive} * {IL_0110: ldc.i4.0} * {IL_0111: callvirt Controller System.Collections.Generic.List`1<Controller>::get_Item(System.Int32)} * {IL_0116: ldfld Fighting Controller::fighting} * {IL_011B: ldfld CharacterStats Fighting::stats} * {IL_0120: dup} * {IL_0121: ldfld System.Int32 CharacterStats::wins} * {IL_0126: ldc.i4.1} * {IL_0127: add} * {IL_0128: stfld System.Int32 CharacterStats::wins} * {IL_012D: br.s ldarg.0} * {IL_012E: call TrainerOptions Singleton`1<TrainerOptions>::get_Instance()} * {IL_0133: ldc.i4.0} * {IL_0134: stfld System.Boolean TrainerOptions::NoWinners} * */ var gameManagerTypeDef = targetModule.Find("GameManager", true); var targetTrainerOptionsTypeDef = targetModule.Find("TrainerOptions", true); var controllerTypeDef = targetModule.Find("Controller", true); var fightingTypeDef = targetModule.Find("Fighting", true); var characterStatsTypeDef = targetModule.Find("CharacterStats", true); if (targetTrainerOptionsTypeDef == null) { return(await Task.FromResult(1)); } var gameManagerAllButOnePlayersDiedMethodDef = gameManagerTypeDef.FindMethod("AllButOnePlayersDied"); if (gameManagerAllButOnePlayersDiedMethodDef == null) { return(await Task.FromResult(2)); } var singletonTypeDef = targetModule.Find("TrainerManager", true); var checkCheatsEnabledMethodDef = singletonTypeDef.FindMethod("CheckCheatsEnabled"); var targetSingletonTrainerOptionsInstantiationInstruction = checkCheatsEnabledMethodDef.Body.Instructions.FirstOrDefault(); var targetAssemblyRef = targetModule.CorLibTypes.AssemblyRef; var gameManagerPlayersAliveFieldDef = gameManagerTypeDef.FindField("playersAlive"); var trainerOptionsNoWinnersFieldDef = targetTrainerOptionsTypeDef.FindField("NoWinners"); var genericListTypeRef = new TypeRefUser(targetModule, @"System.Collections.Generic", "List`1", targetAssemblyRef); var genericListControllerGenericInstSig = new GenericInstSig(new ClassSig(genericListTypeRef), controllerTypeDef.ToTypeSig()); // Create TypeSpec from GenericInstSig var genericListControllerTypeSpec = new TypeSpecUser(genericListControllerGenericInstSig); var genericListControllerGetItemMemberRefUser = new MemberRefUser(targetModule, "get_Item", MethodSig.CreateInstance(new GenericVar(0), targetModule.CorLibTypes.Int32), genericListControllerTypeSpec); var fightingFieldDef = controllerTypeDef.FindField("fighting"); var characterStatsFieldDef = fightingTypeDef.FindField("stats"); var winsFieldDef = characterStatsTypeDef.FindField("wins"); var firstExistingInstruction = gameManagerAllButOnePlayersDiedMethodDef.Body.Instructions.FirstOrDefault(); // Construct the new instructions that are going to be injected var logicInstructions = new List <Instruction> { targetSingletonTrainerOptionsInstantiationInstruction, new Instruction(OpCodes.Ldfld, trainerOptionsNoWinnersFieldDef), new Instruction(OpCodes.Brtrue_S, targetSingletonTrainerOptionsInstantiationInstruction), new Instruction(OpCodes.Ldarg_0), new Instruction(OpCodes.Ldfld, gameManagerPlayersAliveFieldDef), new Instruction(OpCodes.Ldc_I4_0), new Instruction(OpCodes.Callvirt, genericListControllerGetItemMemberRefUser), new Instruction(OpCodes.Ldfld, fightingFieldDef), new Instruction(OpCodes.Ldfld, characterStatsFieldDef), new Instruction(OpCodes.Dup), new Instruction(OpCodes.Ldfld, winsFieldDef), new Instruction(OpCodes.Ldc_I4_1), new Instruction(OpCodes.Add), new Instruction(OpCodes.Stfld, winsFieldDef), new Instruction(OpCodes.Br_S, firstExistingInstruction), targetSingletonTrainerOptionsInstantiationInstruction, new Instruction(OpCodes.Ldc_I4_0), new Instruction(OpCodes.Stfld, trainerOptionsNoWinnersFieldDef) }; // Add new instructions to the top of the method for (var i = 0; i < logicInstructions.Count; i++) { gameManagerAllButOnePlayersDiedMethodDef.Body.Instructions.Insert(i, logicInstructions[i]); } gameManagerAllButOnePlayersDiedMethodDef.Body.UpdateInstructionOffsets(); return(await Task.FromResult(0)); }