コード例 #1
0
        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());
        }
コード例 #2
0
        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)));
            }
        }
コード例 #3
0
        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));
             */
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        /// <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));
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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)));
            }
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        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));
        }