Пример #1
0
        public void TestGetRuntimeMethodForVirtual()
        {
            Type       type       = typeof(StubHelperTests);
            MethodInfo methodInfo = type.GetMethod("TestGetRuntimeMethodForVirtual");

            Assert.AreEqual(methodInfo, StubHelper.GetRuntimeMethodForVirtual(type, methodInfo));
        }
        public void WhenProductIsValid_CanReturnCubicWeight()
        {
            //Arrange
            var product  = FakeModels.TestProduct;
            var settings = new CubicWeightSettings()
            {
                ConversionFactor = 1
            };

            var stubILogger           = StubHelper.StubILogger <CubicWeightService>();
            var stubIExceptionFactory = StubHelper.StubIExceptionFactory;
            var stubIFetchService     = StubHelper.StubIFetchService;

            var testedService = new CubicWeightService(stubILogger.Object,
                                                       stubIExceptionFactory.Object,
                                                       stubIFetchService.Object,
                                                       Options.Create(settings));

            //Act
            var actual = testedService.WeightCalculator(product);

            //Assert
            var weight = product.Size.CubicMetres * settings.ConversionFactor;

            Assert.Equal(weight, actual);
        }
Пример #3
0
        public static DynamicMethod GenerateStubForMethodPointer(MethodInfo methodInfo)
        {
            List <Type> parameterTypes = new List <Type>();

            parameterTypes.Add(typeof(RuntimeMethodHandle));
            parameterTypes.Add(typeof(RuntimeTypeHandle));

            DynamicMethod stub = new DynamicMethod(
                string.Format("stub_ftn_{0}_{1}", methodInfo.DeclaringType, methodInfo.Name),
                typeof(IntPtr),
                parameterTypes.ToArray(),
                StubHelper.GetOwningModule(),
                true);

            ILGenerator ilGenerator = stub.GetILGenerator();

            ilGenerator.DeclareLocal(typeof(MethodInfo));

            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Ldarg_1);
            ilGenerator.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[] { typeof(RuntimeMethodHandle), typeof(RuntimeTypeHandle) }));
            ilGenerator.Emit(OpCodes.Castclass, typeof(MethodInfo));
            ilGenerator.Emit(OpCodes.Stloc_0);
            ilGenerator.Emit(OpCodes.Ldloc_0);
            ilGenerator.Emit(OpCodes.Call, typeof(MethodRewriter).GetMethod("CreateRewriter", new Type[] { typeof(MethodBase) }));
            ilGenerator.Emit(OpCodes.Call, typeof(MethodRewriter).GetMethod("Rewrite"));
            ilGenerator.Emit(OpCodes.Stloc_0);
            ilGenerator.Emit(OpCodes.Ldloc_0);
            ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetMethodPointer"));
            ilGenerator.Emit(OpCodes.Ret);
            return(stub);
        }
Пример #4
0
        public async Task WhenJsonSourceIsValid_CanReturnAllRegistrations()
        {
            //Arrange
            var registrations = FakeModels.Registrations;
            var testViewData  = FakeModels.CatsViewForRender;
            var renderingData = FakeModels.RenderingData;

            var stubILogger       = StubHelper.StubILogger <RegistrationController>();
            var stubIFetchService = StubHelper.StubIFetchService;

            stubIFetchService.Setup(x => x.GetRegistrations())
            .Returns(Task.FromResult(registrations));
            var stubIVewingService = StubHelper.StubIVewingService;

            stubIVewingService.Setup(x => x.ViewRegistrations(It.IsAny <List <OwnerInfo> >(), ViewType.CatsUnderOnwersGender))
            .Returns(testViewData);
            var stubIRenderService = StubHelper.StubIRenderService;

            stubIRenderService.Setup(x => x.RenderRegistrations(It.IsAny <List <ResultFormat> >()))
            .Returns(renderingData);

            var testedService = new RegistrationController(stubILogger.Object,
                                                           stubIFetchService.Object,
                                                           stubIVewingService.Object,
                                                           stubIRenderService.Object);

            //Act
            var result = await testedService.GetAll();

            var actual = result as ContentResult;

            //Assert
            Assert.Equal((int)HttpStatusCode.OK, actual.StatusCode);
        }
Пример #5
0
        public async Task WhenJsonSourceIsNotValid_HTT500_CanReturnAnEmptyArray()
        {
            //Arrange
            var registrations = new List <OwnerInfo>();

            var stubILogger       = StubHelper.StubILogger <RegistrationController>();
            var stubIFetchService = StubHelper.StubIFetchService;

            stubIFetchService.Setup(x => x.GetRegistrations())
            .Returns(Task.FromResult(registrations));
            var stubIRenderService = StubHelper.StubIRenderService;
            var stubIVewingService = StubHelper.StubIVewingService;

            var testedService = new RegistrationController(stubILogger.Object,
                                                           stubIFetchService.Object,
                                                           stubIVewingService.Object,
                                                           stubIRenderService.Object);

            //Act
            var result = await testedService.GetAll();

            var actual = result as NoContentResult;

            //Assert
            Assert.Equal((int)HttpStatusCode.NoContent, actual.StatusCode);
        }
        public void WhenPrivateValidRegistrations_CanReturnExceptedView()
        {
            //Arrange
            var registrations = FakeModels.Registrations;
            var testViewType  = ViewType.CatsUnderOnwersGender;

            var stubILogger         = StubHelper.StubILogger <ViewsService>();
            var stubViewingServiceA = StubHelper.StubIViewingService;

            stubViewingServiceA.Setup(x => x.ViewSortType)
            .Returns(testViewType);
            stubViewingServiceA.Setup(x => x.SortRegistrations(It.IsAny <List <OwnerInfo> >()))
            .Returns(FakeModels.CatsViewForRender);
            var stubViewingServiceB = StubHelper.StubIViewingService;

            stubViewingServiceB.Setup(x => x.ViewSortType)
            .Returns(ViewType.DogsUnderOnwersGender);
            stubViewingServiceB.Setup(x => x.SortRegistrations(It.IsAny <List <OwnerInfo> >()))
            .Returns(FakeModels.DogsViewForRender);

            var _viewingServices = new List <IViewingService> {
                stubViewingServiceA.Object, stubViewingServiceB.Object
            };

            var testedService = new ViewsService(stubILogger.Object, _viewingServices);

            //Act
            var actual = testedService.ViewRegistrations(registrations, testViewType);

            //Assert
            //the total items of actaul should be equal to the number of cats in the registration
            Assert.Equal(FakeModels.CatsViewForRender.SelectMany(x => x.Items).ToList().Count,
                         actual.SelectMany(x => x.Items).ToList().Count);
        }
Пример #7
0
        public static DynamicMethod GenerateStubForDirectLoad(MethodBase method)
        {
            DynamicMethod stub = new DynamicMethod(
                StubHelper.CreateStubNameFromMethod("stub_ldftn", method),
                typeof(IntPtr),
                Array.Empty <Type>(),
                StubHelper.GetOwningModule(),
                true);

            ILGenerator ilGenerator = stub.GetILGenerator();

            if (method.GetMethodBody() == null || StubHelper.IsIntrinsic(method))
            {
                // Method has no body or is a compiler intrinsic,
                // simply forward arguments to original or shim
                if (method.IsConstructor)
                {
                    ilGenerator.Emit(OpCodes.Ldftn, (ConstructorInfo)method);
                }
                else
                {
                    ilGenerator.Emit(OpCodes.Ldftn, (MethodInfo)method);
                }

                ilGenerator.Emit(OpCodes.Ret);
                return(stub);
            }

            Label rewriteLabel = ilGenerator.DefineLabel();
            Label returnLabel  = ilGenerator.DefineLabel();

            // Inject method info into instruction stream
            if (method.IsConstructor)
            {
                ilGenerator.Emit(OpCodes.Ldtoken, (ConstructorInfo)method);
            }
            else
            {
                ilGenerator.Emit(OpCodes.Ldtoken, (MethodInfo)method);
            }

            ilGenerator.Emit(OpCodes.Ldtoken, method.DeclaringType);
            ilGenerator.Emit(OpCodes.Call, s_getMethodFromHandleMethod);

            // Rewrite method
            ilGenerator.MarkLabel(rewriteLabel);
            ilGenerator.Emit(OpCodes.Ldc_I4_0);
            ilGenerator.Emit(OpCodes.Call, s_createRewriterMethod);
            ilGenerator.Emit(OpCodes.Call, s_rewriteMethod);

            // Retrieve pointer to rewritten method
            ilGenerator.Emit(OpCodes.Call, s_getMethodPointerMethod);

            ilGenerator.MarkLabel(returnLabel);
            ilGenerator.Emit(OpCodes.Ret);

            return(stub);
        }
Пример #8
0
        public void TestStaticMethodRewrite()
        {
            MethodInfo     methodInfo     = typeof(StubHelper).GetMethod("GetMethodPointer");
            MethodRewriter methodRewriter = MethodRewriter.CreateRewriter(methodInfo);
            DynamicMethod  dynamicMethod  = methodRewriter.Rewrite() as DynamicMethod;

            Delegate func = dynamicMethod.CreateDelegate(typeof(Func <MethodBase, IntPtr>));

            Assert.AreEqual(StubHelper.GetMethodPointer(methodInfo), func.DynamicInvoke(methodInfo));
        }
Пример #9
0
        public void TestGetShimDelegateTarget()
        {
            Action action = new Action(() => Console.Clear());
            Shim   shim   = Shim.Replace(() => Console.Clear()).With(action);

            PoseContext.Isolate(() => { }, shim);

            Assert.AreEqual(action.Target, StubHelper.GetShimDelegateTarget(0));
            Assert.AreSame(action.Target, StubHelper.GetShimDelegateTarget(0));
        }
Пример #10
0
        public void TestGetShimReplacementMethod()
        {
            Action action = new Action(() => Console.Clear());
            Shim   shim   = Shim.Replace(() => Console.Clear()).With(action);

            PoseContext.Isolate(() => { }, shim);

            Assert.AreEqual(action.Method, StubHelper.GetShimReplacementMethod(0));
            Assert.AreSame(action.Method, StubHelper.GetShimReplacementMethod(0));
        }
Пример #11
0
        public void TestGetMethodPointer()
        {
            MethodInfo    methodInfo = typeof(Console).GetMethod("Clear");
            DynamicMethod dynamicMethod
                = new DynamicMethod("Method", typeof(void), Type.EmptyTypes);
            ILGenerator ilGenerator = dynamicMethod.GetILGenerator();

            ilGenerator.Emit(OpCodes.Ret);

            Assert.AreNotEqual(IntPtr.Zero, StubHelper.GetMethodPointer(methodInfo));
            Assert.AreNotEqual(IntPtr.Zero, StubHelper.GetMethodPointer(dynamicMethod));
        }
Пример #12
0
        public static DynamicMethod GenerateStubForVirtualLoad(MethodInfo method)
        {
            DynamicMethod stub = new DynamicMethod(
                StubHelper.CreateStubNameFromMethod("stub_ldvirtftn", method),
                typeof(IntPtr),
                new Type[] { method.DeclaringType.IsInterface ? typeof(object) : method.DeclaringType },
                StubHelper.GetOwningModule(),
                true);

            ILGenerator ilGenerator = stub.GetILGenerator();

            if ((method.GetMethodBody() == null && !method.IsAbstract) || StubHelper.IsIntrinsic(method))
            {
                // Method has no body or is a compiler intrinsic,
                // simply forward arguments to original or shim
                ilGenerator.Emit(OpCodes.Ldarg, 0);
                ilGenerator.Emit(OpCodes.Ldvirtftn, method);
                ilGenerator.Emit(OpCodes.Ret);
                return(stub);
            }

            ilGenerator.DeclareLocal(typeof(MethodInfo));

            Label rewriteLabel = ilGenerator.DefineLabel();
            Label returnLabel  = ilGenerator.DefineLabel();

            // Inject method info into instruction stream
            ilGenerator.Emit(OpCodes.Ldtoken, method);
            ilGenerator.Emit(OpCodes.Ldtoken, method.DeclaringType);
            ilGenerator.Emit(OpCodes.Call, s_getMethodFromHandleMethod);
            ilGenerator.Emit(OpCodes.Castclass, typeof(MethodInfo));
            ilGenerator.Emit(OpCodes.Stloc_0);

            // Resolve virtual method to object type
            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Ldloc_0);
            ilGenerator.Emit(OpCodes.Call, s_devirtualizeMethodMethod);

            // Rewrite resolved method
            ilGenerator.MarkLabel(rewriteLabel);
            ilGenerator.Emit(method.DeclaringType.IsInterface ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
            ilGenerator.Emit(OpCodes.Call, s_createRewriterMethod);
            ilGenerator.Emit(OpCodes.Call, s_rewriteMethod);

            // Retrieve pointer to rewritten method
            ilGenerator.Emit(OpCodes.Call, s_getMethodPointerMethod);

            ilGenerator.MarkLabel(returnLabel);
            ilGenerator.Emit(OpCodes.Ret);

            return(stub);
        }
Пример #13
0
        public void Rewrite(RuntimeMethodHandle handle, RuntimeTypeHandle declaringType)
        {
            MethodInfo mi;
            int        i;
            IntPtr     ip;
            Type       type;

            mi = MethodBase.GetMethodFromHandle(handle, declaringType) as MethodInfo;

            type = mi.GetType();

            mi = StubHelper.GetRuntimeMethodForVirtual(type, mi);
        }
        public void WhenPrivateValidResults_CanRenderToExpectedFormat()
        {
            //Arrange
            var testViewData = FakeModels.CatsViewForRender;

            var stubILogger = StubHelper.StubILogger <RenderService>();

            var testedService = new RenderService(stubILogger.Object);

            //Act
            var actual = testedService.RenderRegistrations(testViewData);

            //Assert
            Assert.Contains("Female", actual);
        }
Пример #15
0
        public void WhenPrivateValidRegistrations_CanReturnExceptedCatsView()
        {
            //Arrange
            var registrations = FakeModels.Registrations;

            var stubILogger = StubHelper.StubILogger <CatsUnderOnwersGenderView>();

            var testedService = new CatsUnderOnwersGenderView(stubILogger.Object);

            //Act
            var actual = testedService.SortRegistrations(registrations);

            //Assert
            //the total items of actaul should be equal to the number of cats in the registration
            Assert.Equal(registrations.SelectMany(x => x.Pets).ToList().Count(x => x.Type == PetType.Cat),
                         actual.SelectMany(x => x.Items).ToList().Count);
        }
Пример #16
0
        public void TestGetIndexOfMatchingShim()
        {
            StubHelperTests          stubHelperTests = new StubHelperTests();
            Action                   staticAction    = new Action(() => { });
            Action <StubHelperTests> instanceAction  = new Action <StubHelperTests>((@this) => { });

            Shim shim  = Shim.Replace(() => Console.Clear()).With(staticAction);
            Shim shim1 = Shim.Replace(() => Is.A <StubHelperTests>().TestGetIndexOfMatchingShim()).With(instanceAction);
            Shim shim2 = Shim.Replace(() => stubHelperTests.TestGetIndexOfMatchingShim()).With(instanceAction);

            PoseContext.Isolate(() => { }, shim, shim1, shim2);

            MethodInfo consoleMethodInfo = typeof(Console).GetMethod("Clear");
            MethodInfo stubMethodInfo    = typeof(StubHelperTests).GetMethod("TestGetIndexOfMatchingShim");

            Assert.AreEqual(0, StubHelper.GetIndexOfMatchingShim(consoleMethodInfo, null));
            Assert.AreEqual(1, StubHelper.GetIndexOfMatchingShim(stubMethodInfo, new StubHelperTests()));
            Assert.AreEqual(2, StubHelper.GetIndexOfMatchingShim(stubMethodInfo, stubHelperTests));
        }
        public void WhenSizeIsNull_CanReturnZero()
        {
            //Arrange
            var emptyProduct = new Product();
            var settings     = new CubicWeightSettings()
            {
                ConversionFactor = 250
            };

            var stubILogger           = StubHelper.StubILogger <CubicWeightService>();
            var stubIExceptionFactory = StubHelper.StubIExceptionFactory;
            var stubIFetchService     = StubHelper.StubIFetchService;

            var testedService = new CubicWeightService(stubILogger.Object,
                                                       stubIExceptionFactory.Object,
                                                       stubIFetchService.Object,
                                                       Options.Create(settings));

            //Act
            var actual = testedService.WeightCalculator(emptyProduct);

            //Assert
            Assert.Equal(0, actual);
        }
        public async Task WhenJsonSourceIsNotValid_CanReturnAnEmptyList()
        {
            //Arrange
            List <OwnerInfo> registrations = null;
            var settings = new JsonConsumerSettings();

            var stubILogger           = StubHelper.StubILogger <FetchService>();
            var stubIExceptionFactory = StubHelper.StubIExceptionFactory;
            var stubIRestApiService   = StubHelper.StubIRestApiService;

            stubIRestApiService.Setup(x => x.GetRequestAsync <List <OwnerInfo> >(It.IsAny <string>()))
            .Returns(Task.FromResult(registrations));

            var testedService = new FetchService(stubILogger.Object,
                                                 stubIExceptionFactory.Object,
                                                 stubIRestApiService.Object,
                                                 Options.Create(settings));

            //Act
            var actual = await testedService.GetRegistrations();

            //Assert
            Assert.False(actual.Any());
        }
Пример #19
0
        public MethodBase Rewrite()
        {
            List <Type> parameterTypes = new List <Type>();

            if (!_method.IsStatic)
            {
                if (_method.IsForValueType())
                {
                    parameterTypes.Add(_method.DeclaringType.MakeByRefType());
                }
                else
                {
                    parameterTypes.Add(_method.DeclaringType);
                }
            }

            parameterTypes.AddRange(_method.GetParameters().Select(p => p.ParameterType));
            Type returnType = _method.IsConstructor ? typeof(void) : (_method as MethodInfo).ReturnType;

            DynamicMethod dynamicMethod = new DynamicMethod(
                string.Format("dynamic_{0}_{1}", _method.DeclaringType, _method.Name),
                returnType,
                parameterTypes.ToArray(),
                StubHelper.GetOwningModule(),
                true);

            MethodDisassembler disassembler = new MethodDisassembler(_method);
            MethodBody         methodBody   = _method.GetMethodBody();

            IList <LocalVariableInfo> locals             = methodBody.LocalVariables;
            Dictionary <int, Label>   targetInstructions = new Dictionary <int, Label>();
            List <ExceptionHandler>   handlers           = new List <ExceptionHandler>();

            ILGenerator ilGenerator  = dynamicMethod.GetILGenerator();
            var         instructions = disassembler.GetILInstructions();

            foreach (var clause in methodBody.ExceptionHandlingClauses)
            {
                ExceptionHandler handler = new ExceptionHandler();
                handler.Flag         = clause.Flags.ToString();
                handler.CatchType    = handler.Flag == "Clause" ? clause.CatchType : null;
                handler.TryStart     = clause.TryOffset;
                handler.TryEnd       = (clause.TryOffset + clause.TryLength);
                handler.HandlerStart = clause.HandlerOffset;
                handler.HandlerEnd   = (clause.HandlerOffset + clause.HandlerLength);
                handlers.Add(handler);
            }

            foreach (var local in locals)
            {
                ilGenerator.DeclareLocal(local.LocalType, local.IsPinned);
            }

            var ifTargets = instructions
                            .Where(i => (i.Operand as Instruction) != null)
                            .Where(i => !s_IgnoredOpCodes.Contains(i.OpCode))
                            .Select(i => (i.Operand as Instruction));

            foreach (Instruction instruction in ifTargets)
            {
                targetInstructions.TryAdd(instruction.Offset, ilGenerator.DefineLabel());
            }

            var switchTargets = instructions
                                .Where(i => (i.Operand as Instruction[]) != null)
                                .Select(i => (i.Operand as Instruction[]));

            foreach (Instruction[] _instructions in switchTargets)
            {
                foreach (Instruction _instruction in _instructions)
                {
                    targetInstructions.TryAdd(_instruction.Offset, ilGenerator.DefineLabel());
                }
            }

            foreach (var instruction in instructions)
            {
                EmitILForExceptionHandlers(ilGenerator, instruction, handlers);

                if (s_IgnoredOpCodes.Contains(instruction.OpCode))
                {
                    continue;
                }

                if (targetInstructions.TryGetValue(instruction.Offset, out Label label))
                {
                    ilGenerator.MarkLabel(label);
                }

                switch (instruction.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    EmitILForInlineNone(ilGenerator, instruction);
                    break;

                case OperandType.InlineI:
                    EmitILForInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineI8:
                    EmitILForInlineI8(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineI:
                    EmitILForShortInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineR:
                    EmitILForInlineR(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineR:
                    EmitILForShortInlineR(ilGenerator, instruction);
                    break;

                case OperandType.InlineString:
                    EmitILForInlineString(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    EmitILForInlineBrTarget(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.InlineSwitch:
                    EmitILForInlineSwitch(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    EmitILForInlineVar(ilGenerator, instruction);
                    break;

                case OperandType.InlineTok:
                case OperandType.InlineType:
                case OperandType.InlineField:
                case OperandType.InlineMethod:
                    EmitILForInlineMember(ilGenerator, instruction);
                    break;

                default:
                    throw new NotSupportedException();
                }
            }

            return(dynamicMethod);
        }
Пример #20
0
        public static DynamicMethod GenerateStubForMethod(MethodInfo methodInfo)
        {
            ParameterInfo[] parameters = methodInfo.GetParameters();

            List <Type> signatureParamTypes = new List <Type>();
            List <Type> parameterTypes      = new List <Type>();

            if (!methodInfo.IsStatic)
            {
                if (methodInfo.IsForValueType())
                {
                    signatureParamTypes.Add(methodInfo.DeclaringType.MakeByRefType());
                }
                else
                {
                    signatureParamTypes.Add(methodInfo.DeclaringType);
                }
            }

            signatureParamTypes.AddRange(parameters.Select(p => p.ParameterType));
            parameterTypes.AddRange(signatureParamTypes);
            parameterTypes.Add(typeof(RuntimeMethodHandle));
            parameterTypes.Add(typeof(RuntimeTypeHandle));

            DynamicMethod stub = new DynamicMethod(
                string.Format("stub_{0}_{1}", methodInfo.DeclaringType, methodInfo.Name),
                methodInfo.ReturnType,
                parameterTypes.ToArray(),
                StubHelper.GetOwningModule(),
                true);

            ILGenerator ilGenerator = stub.GetILGenerator();

            ilGenerator.DeclareLocal(typeof(MethodInfo));
            ilGenerator.DeclareLocal(typeof(int));
            ilGenerator.DeclareLocal(typeof(IntPtr));

            Label rewriteLabel = ilGenerator.DefineLabel();
            Label returnLabel  = ilGenerator.DefineLabel();

            ilGenerator.Emit(OpCodes.Ldarg, parameterTypes.Count - 2);
            ilGenerator.Emit(OpCodes.Ldarg, parameterTypes.Count - 1);
            ilGenerator.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[] { typeof(RuntimeMethodHandle), typeof(RuntimeTypeHandle) }));
            ilGenerator.Emit(OpCodes.Castclass, typeof(MethodInfo));
            ilGenerator.Emit(OpCodes.Stloc_0);

            ilGenerator.Emit(OpCodes.Ldloc_0);
            ilGenerator.Emit(methodInfo.IsStatic || methodInfo.IsForValueType() ? OpCodes.Ldnull : OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetIndexOfMatchingShim", new Type[] { typeof(MethodBase), typeof(Object) }));
            ilGenerator.Emit(OpCodes.Stloc_1);
            ilGenerator.Emit(OpCodes.Ldloc_1);
            ilGenerator.Emit(OpCodes.Ldc_I4_M1);
            ilGenerator.Emit(OpCodes.Ceq);
            ilGenerator.Emit(OpCodes.Brtrue_S, rewriteLabel);

            var methodBase = StubHelper.GetShimReplacementMethod(StubHelper.GetIndexOfMatchingShim(methodInfo as MethodBase, null));

            if (StubHelper.MethodBaseIsShimmyDynamic(methodBase))
            {
                var dynamicMethod = StubHelper.GetDynamicMethodFromDynamicMethodBase(methodBase);

                EmitArguments(ilGenerator, signatureParamTypes);
                ilGenerator.EmitCall(OpCodes.Call, dynamicMethod, null);
            }
            else
            {
                // do things the classic Pose way
                ilGenerator.Emit(OpCodes.Ldloc_1);
                ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetShimReplacementMethod"));
                ilGenerator.Emit(OpCodes.Stloc_0);
                ilGenerator.Emit(OpCodes.Ldloc_0);
                ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetMethodPointer"));
                ilGenerator.Emit(OpCodes.Stloc_2);
                ilGenerator.Emit(OpCodes.Ldloc_1);
                ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetShimDelegateTarget"));

                EmitArguments(ilGenerator, signatureParamTypes);

                ilGenerator.Emit(OpCodes.Ldloc_2);
                ilGenerator.EmitCalli(OpCodes.Calli, CallingConventions.HasThis, methodInfo.ReturnType, signatureParamTypes.ToArray(), null);
            }

            ilGenerator.Emit(OpCodes.Br_S, returnLabel);

            ilGenerator.MarkLabel(rewriteLabel);
            ilGenerator.Emit(OpCodes.Ldloc_0);
            ilGenerator.Emit(OpCodes.Call, typeof(MethodRewriter).GetMethod("CreateRewriter", new Type[] { typeof(MethodBase) }));
            ilGenerator.Emit(OpCodes.Call, typeof(MethodRewriter).GetMethod("Rewrite"));
            ilGenerator.Emit(OpCodes.Castclass, typeof(MethodInfo));
            ilGenerator.Emit(OpCodes.Stloc_0);
            for (int i = 0; i < signatureParamTypes.Count; i++)
            {
                ilGenerator.Emit(OpCodes.Ldarg, i);
            }
            ilGenerator.Emit(OpCodes.Ldloc_0);
            ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetMethodPointer"));
            ilGenerator.EmitCalli(OpCodes.Calli, CallingConventions.Standard, methodInfo.ReturnType, signatureParamTypes.ToArray(), null);
            ilGenerator.MarkLabel(returnLabel);
            ilGenerator.Emit(OpCodes.Ret);
            return(stub);
        }
Пример #21
0
        public MethodBase Rewrite()
        {
            List <Type> parameterTypes = new List <Type>();

            if (!_method.IsStatic)
            {
                if (_method.IsForValueType())
                {
                    parameterTypes.Add(_method.DeclaringType.MakeByRefType());
                }
                else
                {
                    parameterTypes.Add(_method.DeclaringType);
                }
            }

            parameterTypes.AddRange(_method.GetParameters().Select(p => p.ParameterType));
            Type returnType = _method.IsConstructor ? typeof(void) : (_method as MethodInfo).ReturnType;

            DynamicMethod dynamicMethod = new DynamicMethod(string.Format("dynamic_{0}_{1}", _method.DeclaringType, _method.Name), returnType, parameterTypes.ToArray(), StubHelper.GetOwningModule(), true);


            MethodDisassembler disassembler = new MethodDisassembler(_method);
            MethodBody         methodBody   = _method.GetMethodBody();

            IList <LocalVariableInfo> locals             = methodBody.LocalVariables;
            Dictionary <int, Label>   targetInstructions = new Dictionary <int, Label>();
            List <ExceptionHandler>   handlers           = new List <ExceptionHandler>();

            ILGenerator ilGenerator  = dynamicMethod.GetILGenerator();
            var         instructions = disassembler.GetILInstructions();
            var         code         = _method.GetMethodBody();

            foreach (var clause in methodBody.ExceptionHandlingClauses)
            {
                ExceptionHandler handler = new ExceptionHandler();
                handler.Flag         = clause.Flags.ToString();
                handler.CatchType    = handler.Flag == "Clause" ? clause.CatchType : null;
                handler.TryStart     = clause.TryOffset;
                handler.TryEnd       = (clause.TryOffset + clause.TryLength);
                handler.HandlerStart = clause.HandlerOffset;
                handler.HandlerEnd   = (clause.HandlerOffset + clause.HandlerLength);
                handlers.Add(handler);
            }

            foreach (var local in locals)
            {
                ilGenerator.DeclareLocal(local.LocalType, local.IsPinned);
            }

            var ifTargets = instructions
                            .Where(i => (i.Operand as Instruction) != null)
                            .Where(i => !s_IgnoredOpCodes.Contains(i.OpCode))
                            .Select(i => (i.Operand as Instruction));

            foreach (Instruction instruction in ifTargets)
            {
                targetInstructions.TryAdd(instruction.Offset, ilGenerator.DefineLabel());
            }

            var switchTargets = instructions
                                .Where(i => (i.Operand as Instruction[]) != null)
                                .Select(i => (i.Operand as Instruction[]));

            foreach (Instruction[] _instructions in switchTargets)
            {
                foreach (Instruction _instruction in _instructions)
                {
                    targetInstructions.TryAdd(_instruction.Offset, ilGenerator.DefineLabel());
                }
            }

            foreach (var instruction in instructions)
            {
                EmitILForExceptionHandlers(ilGenerator, instruction, handlers);

                if (s_IgnoredOpCodes.Contains(instruction.OpCode))
                {
                    continue;
                }

                if (targetInstructions.TryGetValue(instruction.Offset, out Label label))
                {
                    ilGenerator.MarkLabel(label);
                }

                // If a constrained instruction is a prefix for an interface, we know any value types
                // must have implemented the interface explicitly, and thus both the constrained and
                // callvirt instructions can be replaced by a simple call instruction.
                // This is necessary as Invoking methods by reflection doesn't seem to work the same way as the CLR which
                // replaces constrained/callvirt pairs to simple calls on the type itself, and the fact that it doesn't do this
                // seems to break Pose and the calls to Method.Invoke
                if (instruction.OpCode == OpCodes.Constrained)
                {
                    _lastInstruction = instruction;
                    _wasLastInstructionConstrained = true;
                    _lastType = instruction.Operand as TypeInfo;

                    continue;
                }
                if (_wasLastInstructionConstrained)
                {
                    _wasLastInstructionConstrained = false;
                    if (instruction.OpCode == OpCodes.Callvirt && ((instruction.Operand as MethodInfo)?.DeclaringType?.IsInterface ?? false))
                    {
                        // emit Nops for constrained call (size is 6)
                        // TODO: Get size from actual offset difference and emit that number of nops... though constrained is always 6 and very unlikely to change
                        EmitILNop(ilGenerator);
                        EmitILNop(ilGenerator);
                        EmitILNop(ilGenerator);
                        EmitILNop(ilGenerator);
                        EmitILNop(ilGenerator);
                        EmitILNop(ilGenerator);

                        // change operand and continue
                        var currentMethodInfo     = instruction.Operand as MethodInfo;
                        var replacementMethodInfo = _lastType.GetMethod(currentMethodInfo.Name);

                        EmitILForMethod(ilGenerator, instruction, replacementMethodInfo, true);

                        continue;
                    }

                    EmitILForInlineMember(ilGenerator, _lastInstruction);

                    _lastInstruction = null;
                    _lastType        = null;
                }
                else
                {
                    _wasLastInstructionConstrained = false;
                }

                switch (instruction.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    EmitILForInlineNone(ilGenerator, instruction);
                    break;

                case OperandType.InlineI:
                    EmitILForInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineI8:
                    EmitILForInlineI8(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineI:
                    EmitILForShortInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineR:
                    EmitILForInlineR(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineR:
                    EmitILForShortInlineR(ilGenerator, instruction);
                    break;

                case OperandType.InlineString:
                    EmitILForInlineString(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    EmitILForInlineBrTarget(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.InlineSwitch:
                    EmitILForInlineSwitch(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    EmitILForInlineVar(ilGenerator, instruction);
                    break;

                case OperandType.InlineTok:
                case OperandType.InlineType:
                case OperandType.InlineField:
                case OperandType.InlineMethod:
                    EmitILForInlineMember(ilGenerator, instruction);
                    break;

                default:
                    throw new NotSupportedException();
                }
            }

            return(dynamicMethod);
        }
Пример #22
0
        public static DynamicMethod GenerateStubForConstructor(ConstructorInfo constructorInfo, OpCode opCode, bool forValueType)
        {
            ParameterInfo[] parameters = constructorInfo.GetParameters();

            List <Type> signatureParamTypes = new List <Type>();
            List <Type> parameterTypes      = new List <Type>();

            if (forValueType)
            {
                signatureParamTypes.Add(constructorInfo.DeclaringType.MakeByRefType());
            }
            else
            {
                signatureParamTypes.Add(constructorInfo.DeclaringType);
            }

            signatureParamTypes.AddRange(parameters.Select(p => p.ParameterType));

            if (opCode == OpCodes.Newobj)
            {
                parameterTypes.AddRange(parameters.Select(p => p.ParameterType));
            }
            else
            {
                parameterTypes.AddRange(signatureParamTypes);
            }
            parameterTypes.Add(typeof(RuntimeMethodHandle));
            parameterTypes.Add(typeof(RuntimeTypeHandle));

            DynamicMethod stub = new DynamicMethod(
                string.Format("stub_ctor_{0}_{1}", constructorInfo.DeclaringType, constructorInfo.Name),
                opCode == OpCodes.Newobj ? constructorInfo.DeclaringType : typeof(void),
                parameterTypes.ToArray(),
                StubHelper.GetOwningModule(),
                true);

            ILGenerator ilGenerator = stub.GetILGenerator();

            ilGenerator.DeclareLocal(constructorInfo.DeclaringType);
            ilGenerator.DeclareLocal(typeof(ConstructorInfo));
            ilGenerator.DeclareLocal(typeof(MethodInfo));
            ilGenerator.DeclareLocal(typeof(int));
            ilGenerator.DeclareLocal(typeof(IntPtr));

            Label rewriteLabel = ilGenerator.DefineLabel();
            Label returnLabel  = ilGenerator.DefineLabel();

            ilGenerator.Emit(OpCodes.Ldarg, parameterTypes.Count - 2);
            ilGenerator.Emit(OpCodes.Ldarg, parameterTypes.Count - 1);
            ilGenerator.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[] { typeof(RuntimeMethodHandle), typeof(RuntimeTypeHandle) }));
            ilGenerator.Emit(OpCodes.Castclass, typeof(ConstructorInfo));
            ilGenerator.Emit(OpCodes.Stloc_1);

            ilGenerator.Emit(OpCodes.Ldloc_1);
            ilGenerator.Emit(OpCodes.Ldnull);
            ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetIndexOfMatchingShim", new Type[] { typeof(MethodBase), typeof(Object) }));
            ilGenerator.Emit(OpCodes.Stloc_3);
            ilGenerator.Emit(OpCodes.Ldloc_3);
            ilGenerator.Emit(OpCodes.Ldc_I4_M1);
            ilGenerator.Emit(OpCodes.Ceq);
            ilGenerator.Emit(OpCodes.Brtrue_S, rewriteLabel);
            ilGenerator.Emit(OpCodes.Ldloc_3);
            ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetShimReplacementMethod"));
            ilGenerator.Emit(OpCodes.Stloc_2);
            ilGenerator.Emit(OpCodes.Ldloc_2);
            ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetMethodPointer"));
            ilGenerator.Emit(OpCodes.Stloc, 4);
            ilGenerator.Emit(OpCodes.Ldloc_3);
            ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetShimDelegateTarget"));
            for (int i = 0; i < signatureParamTypes.Count - 1; i++)
            {
                ilGenerator.Emit(OpCodes.Ldarg, i);
            }
            ilGenerator.Emit(OpCodes.Ldloc, 4);
            ilGenerator.EmitCalli(OpCodes.Calli, CallingConventions.HasThis, constructorInfo.DeclaringType, signatureParamTypes.Skip(1).ToArray(), null);
            ilGenerator.Emit(OpCodes.Stloc_0);
            if (opCode == OpCodes.Call)
            {
                if (forValueType)
                {
                    ilGenerator.Emit(OpCodes.Ldarg_0);
                    ilGenerator.Emit(OpCodes.Ldloc_0);
                    ilGenerator.Emit(OpCodes.Stobj, constructorInfo.DeclaringType);
                }
                else
                {
                    ilGenerator.Emit(OpCodes.Ldloc_0);
                    ilGenerator.Emit(OpCodes.Starg, 0);
                }
            }
            ilGenerator.Emit(OpCodes.Br_S, returnLabel);

            ilGenerator.MarkLabel(rewriteLabel);
            if (opCode == OpCodes.Newobj)
            {
                if (forValueType)
                {
                    ilGenerator.Emit(OpCodes.Ldloca, 0);
                    ilGenerator.Emit(OpCodes.Initobj, constructorInfo.DeclaringType);
                }
                else
                {
                    ilGenerator.Emit(OpCodes.Ldarg, parameterTypes.Count - 1);
                    ilGenerator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));
                    ilGenerator.Emit(OpCodes.Call, typeof(FormatterServices).GetMethod("GetUninitializedObject"));
                    ilGenerator.Emit(OpCodes.Stloc_0);
                }
            }

            ilGenerator.Emit(OpCodes.Ldloc_1);
            ilGenerator.Emit(OpCodes.Call, typeof(MethodRewriter).GetMethod("CreateRewriter", new Type[] { typeof(MethodBase) }));
            ilGenerator.Emit(OpCodes.Call, typeof(MethodRewriter).GetMethod("Rewrite"));
            ilGenerator.Emit(OpCodes.Castclass, typeof(MethodInfo));
            ilGenerator.Emit(OpCodes.Stloc_2);
            int count = signatureParamTypes.Count;

            if (opCode == OpCodes.Newobj)
            {
                if (forValueType)
                {
                    ilGenerator.Emit(OpCodes.Ldloca, 0);
                }
                else
                {
                    ilGenerator.Emit(OpCodes.Ldloc_0);
                }
                count = count - 1;
            }
            for (int i = 0; i < count; i++)
            {
                ilGenerator.Emit(OpCodes.Ldarg, i);
            }
            ilGenerator.Emit(OpCodes.Ldloc_2);
            ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetMethodPointer"));
            ilGenerator.EmitCalli(OpCodes.Calli, CallingConventions.Standard, typeof(void), signatureParamTypes.ToArray(), null);
            ilGenerator.MarkLabel(returnLabel);
            if (opCode == OpCodes.Newobj)
            {
                ilGenerator.Emit(OpCodes.Ldloc_0);
            }
            ilGenerator.Emit(OpCodes.Ret);
            return(stub);
        }
Пример #23
0
        public static DynamicMethod GenerateStubForVirtualCall(MethodInfo method)
        {
            Type thisType = method.DeclaringType.IsInterface ? typeof(object) : method.DeclaringType;

            List <Type> signatureParamTypes = new List <Type>();

            signatureParamTypes.Add(thisType);
            signatureParamTypes.AddRange(method.GetParameters().Select(p => p.ParameterType));

            DynamicMethod stub = new DynamicMethod(
                StubHelper.CreateStubNameFromMethod("stub_callvirt", method),
                method.ReturnType,
                signatureParamTypes.ToArray(),
                StubHelper.GetOwningModule(),
                true);

            ILGenerator ilGenerator = stub.GetILGenerator();

            if ((method.GetMethodBody() == null && !method.IsAbstract) || StubHelper.IsIntrinsic(method))
            {
                // Method has no body or is a compiler intrinsic,
                // simply forward arguments to original or shim
                for (int i = 0; i < signatureParamTypes.Count; i++)
                {
                    ilGenerator.Emit(OpCodes.Ldarg, i);
                }

                ilGenerator.Emit(OpCodes.Callvirt, method);
                ilGenerator.Emit(OpCodes.Ret);
                return(stub);
            }

            ilGenerator.DeclareLocal(typeof(MethodInfo));
            ilGenerator.DeclareLocal(typeof(IntPtr));

            Label rewriteLabel = ilGenerator.DefineLabel();
            Label returnLabel  = ilGenerator.DefineLabel();

            // Inject method info into instruction stream
            ilGenerator.Emit(OpCodes.Ldtoken, method);
            ilGenerator.Emit(OpCodes.Ldtoken, method.DeclaringType);
            ilGenerator.Emit(OpCodes.Call, s_getMethodFromHandleMethod);
            ilGenerator.Emit(OpCodes.Castclass, typeof(MethodInfo));
            ilGenerator.Emit(OpCodes.Stloc_0);

            // Resolve virtual method to object type
            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Ldloc_0);
            ilGenerator.Emit(OpCodes.Call, s_devirtualizeMethodMethod);

            // Rewrite resolved method
            ilGenerator.MarkLabel(rewriteLabel);
            ilGenerator.Emit(method.DeclaringType.IsInterface ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
            ilGenerator.Emit(OpCodes.Call, s_createRewriterMethod);
            ilGenerator.Emit(OpCodes.Call, s_rewriteMethod);
            ilGenerator.Emit(OpCodes.Castclass, typeof(MethodInfo));

            // Retrieve pointer to rewritten method
            ilGenerator.Emit(OpCodes.Call, s_getMethodPointerMethod);
            ilGenerator.Emit(OpCodes.Stloc_1);

            // Setup stack and make indirect call
            for (int i = 0; i < signatureParamTypes.Count; i++)
            {
                ilGenerator.Emit(OpCodes.Ldarg, i);
            }
            ilGenerator.Emit(OpCodes.Ldloc_1);
            ilGenerator.EmitCalli(OpCodes.Calli, CallingConventions.Standard, method.ReturnType, signatureParamTypes.ToArray(), null);

            ilGenerator.MarkLabel(returnLabel);
            ilGenerator.Emit(OpCodes.Ret);

            return(stub);
        }
Пример #24
0
        public MethodBase Rewrite()
        {
            List <Type> parameterTypes = new List <Type>();

            if (!m_method.IsStatic)
            {
                Type thisType = m_isInterfaceDispatch ? typeof(object) : m_owningType;
                if (!m_isInterfaceDispatch && m_owningType.IsValueType)
                {
                    thisType = thisType.MakeByRefType();
                }

                parameterTypes.Add(thisType);
            }

            parameterTypes.AddRange(m_method.GetParameters().Select(p => p.ParameterType));
            Type returnType = m_method.IsConstructor ? typeof(void) : (m_method as MethodInfo).ReturnType;

            DynamicMethod dynamicMethod = new DynamicMethod(
                StubHelper.CreateStubNameFromMethod("impl", m_method),
                returnType,
                parameterTypes.ToArray(),
                StubHelper.GetOwningModule(),
                true);

            var methodBody         = m_method.GetMethodBody();
            var locals             = methodBody.LocalVariables;
            var targetInstructions = new Dictionary <int, Label>();
            var handlers           = new List <ExceptionHandler>();

            var ilGenerator  = dynamicMethod.GetILGenerator();
            var instructions = m_method.GetInstructions();

            foreach (var clause in methodBody.ExceptionHandlingClauses)
            {
                ExceptionHandler handler = new ExceptionHandler();
                handler.Flags        = clause.Flags;
                handler.CatchType    = clause.Flags == ExceptionHandlingClauseOptions.Clause ? clause.CatchType : null;
                handler.TryStart     = clause.TryOffset;
                handler.TryEnd       = clause.TryOffset + clause.TryLength;
                handler.FilterStart  = clause.Flags == ExceptionHandlingClauseOptions.Filter ? clause.FilterOffset : -1;
                handler.HandlerStart = clause.HandlerOffset;
                handler.HandlerEnd   = clause.HandlerOffset + clause.HandlerLength;
                handlers.Add(handler);
            }

            foreach (var local in locals)
            {
                ilGenerator.DeclareLocal(local.LocalType, local.IsPinned);
            }

            var ifTargets = instructions
                            .Where(i => (i.Operand as Instruction) != null)
                            .Select(i => (i.Operand as Instruction));

            foreach (Instruction instruction in ifTargets)
            {
                targetInstructions.TryAdd(instruction.Offset, ilGenerator.DefineLabel());
            }

            var switchTargets = instructions
                                .Where(i => (i.Operand as Instruction[]) != null)
                                .Select(i => (i.Operand as Instruction[]));

            foreach (Instruction[] _instructions in switchTargets)
            {
                foreach (Instruction _instruction in _instructions)
                {
                    targetInstructions.TryAdd(_instruction.Offset, ilGenerator.DefineLabel());
                }
            }

#if DEBUG
            Debug.WriteLine("\n" + m_method);
#endif

            foreach (var instruction in instructions)
            {
#if DEBUG
                Debug.WriteLine(instruction);
#endif

                EmitILForExceptionHandlers(ilGenerator, instruction, handlers);

                if (targetInstructions.TryGetValue(instruction.Offset, out Label label))
                {
                    ilGenerator.MarkLabel(label);
                }

                if (s_IngoredOpCodes.Contains(instruction.OpCode))
                {
                    continue;
                }

                switch (instruction.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    EmitILForInlineNone(ilGenerator, instruction);
                    break;

                case OperandType.InlineI:
                    EmitILForInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineI8:
                    EmitILForInlineI8(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineI:
                    EmitILForShortInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineR:
                    EmitILForInlineR(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineR:
                    EmitILForShortInlineR(ilGenerator, instruction);
                    break;

                case OperandType.InlineString:
                    EmitILForInlineString(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    EmitILForInlineBrTarget(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.InlineSwitch:
                    EmitILForInlineSwitch(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    EmitILForInlineVar(ilGenerator, instruction);
                    break;

                case OperandType.InlineTok:
                case OperandType.InlineType:
                case OperandType.InlineField:
                case OperandType.InlineMethod:
                    EmitILForInlineMember(ilGenerator, instruction);
                    break;

                default:
                    throw new NotSupportedException(instruction.OpCode.OperandType.ToString());
                }
            }

#if DEBUG
            var ilBytes = ilGenerator.GetILBytes();
            var browsableDynamicMethod = new BrowsableDynamicMethod(dynamicMethod, new DynamicMethodBody(ilBytes, locals));
            Debug.WriteLine("\n" + dynamicMethod);

            foreach (var instruction in browsableDynamicMethod.GetInstructions())
            {
                Debug.WriteLine(instruction);
            }
#endif
            return(dynamicMethod);
        }
Пример #25
0
 public void TestGetOwningModule()
 {
     Assert.AreEqual(typeof(StubHelper).Module, StubHelper.GetOwningModule());
     Assert.AreNotEqual(typeof(StubHelperTests).Module, StubHelper.GetOwningModule());
 }
Пример #26
0
        public static DynamicMethod GenerateStubForObjectInitialization(ConstructorInfo constructor)
        {
            Type thisType = constructor.DeclaringType;

            if (thisType.IsValueType)
            {
                thisType = thisType.MakeByRefType();
            }

            List <Type> signatureParamTypes = new List <Type>();

            signatureParamTypes.Add(thisType);
            signatureParamTypes.AddRange(constructor.GetParameters().Select(p => p.ParameterType));

            DynamicMethod stub = new DynamicMethod(
                StubHelper.CreateStubNameFromMethod("stub_newobj", constructor),
                constructor.DeclaringType,
                signatureParamTypes.Skip(1).ToArray(),
                StubHelper.GetOwningModule(),
                true);

            ILGenerator ilGenerator = stub.GetILGenerator();

            if (constructor.GetMethodBody() == null || StubHelper.IsIntrinsic(constructor))
            {
                // Constructor has no body or is a compiler intrinsic,
                // simply forward arguments to original or shim
                for (int i = 0; i < signatureParamTypes.Count - 1; i++)
                {
                    ilGenerator.Emit(OpCodes.Ldarg, i);
                }

                ilGenerator.Emit(OpCodes.Newobj, constructor);
                ilGenerator.Emit(OpCodes.Ret);
                return(stub);
            }

            ilGenerator.DeclareLocal(typeof(IntPtr));
            ilGenerator.DeclareLocal(constructor.DeclaringType);

            Label rewriteLabel = ilGenerator.DefineLabel();
            Label returnLabel  = ilGenerator.DefineLabel();

            // Inject method info into instruction stream
            ilGenerator.Emit(OpCodes.Ldtoken, constructor);
            ilGenerator.Emit(OpCodes.Ldtoken, constructor.DeclaringType);
            ilGenerator.Emit(OpCodes.Call, s_getMethodFromHandleMethod);

            // Rewrite method
            ilGenerator.MarkLabel(rewriteLabel);
            ilGenerator.Emit(OpCodes.Ldc_I4_0);
            ilGenerator.Emit(OpCodes.Call, s_createRewriterMethod);
            ilGenerator.Emit(OpCodes.Call, s_rewriteMethod);

            // Retrieve pointer to rewritten method
            ilGenerator.Emit(OpCodes.Call, s_getMethodPointerMethod);
            ilGenerator.Emit(OpCodes.Stloc_0);

            if (constructor.DeclaringType.IsValueType)
            {
                ilGenerator.Emit(OpCodes.Ldloca_S, (byte)1);
                ilGenerator.Emit(OpCodes.Dup);
                ilGenerator.Emit(OpCodes.Initobj, constructor.DeclaringType);
            }
            else
            {
                ilGenerator.Emit(OpCodes.Ldtoken, constructor.DeclaringType);
                ilGenerator.Emit(OpCodes.Call, s_getTypeFromHandleMethod);
                ilGenerator.Emit(OpCodes.Call, s_getUninitializedObjectMethod);
                ilGenerator.Emit(OpCodes.Dup);
                ilGenerator.Emit(OpCodes.Stloc_1);
            }

            // Setup stack and make indirect call
            for (int i = 0; i < signatureParamTypes.Count - 1; i++)
            {
                ilGenerator.Emit(OpCodes.Ldarg, i);
            }
            ilGenerator.Emit(OpCodes.Ldloc_0);
            ilGenerator.EmitCalli(OpCodes.Calli, CallingConventions.Standard, typeof(void), signatureParamTypes.ToArray(), null);

            ilGenerator.MarkLabel(returnLabel);
            ilGenerator.Emit(OpCodes.Ldloc_1);
            ilGenerator.Emit(OpCodes.Ret);

            return(stub);
        }
Пример #27
0
        public static DynamicMethod GenerateStubForDirectCall(MethodBase method)
        {
            Type        returnType          = method.IsConstructor ? typeof(void) : (method as MethodInfo).ReturnType;
            List <Type> signatureParamTypes = new List <Type>();

            if (!method.IsStatic)
            {
                Type thisType = method.DeclaringType;
                if (thisType.IsValueType)
                {
                    thisType = thisType.MakeByRefType();
                }

                signatureParamTypes.Add(thisType);
            }

            signatureParamTypes.AddRange(method.GetParameters().Select(p => p.ParameterType));

            DynamicMethod stub = new DynamicMethod(
                StubHelper.CreateStubNameFromMethod("stub_call", method),
                returnType,
                signatureParamTypes.ToArray(),
                StubHelper.GetOwningModule(),
                true);

            ILGenerator ilGenerator = stub.GetILGenerator();

            if (method.GetMethodBody() == null || StubHelper.IsIntrinsic(method))
            {
                // Method has no body or is a compiler intrinsic,
                // simply forward arguments to original or shim
                for (int i = 0; i < signatureParamTypes.Count; i++)
                {
                    ilGenerator.Emit(OpCodes.Ldarg, i);
                }

                if (method.IsConstructor)
                {
                    ilGenerator.Emit(OpCodes.Call, (ConstructorInfo)method);
                }
                else
                {
                    ilGenerator.Emit(OpCodes.Call, (MethodInfo)method);
                }

                ilGenerator.Emit(OpCodes.Ret);
                return(stub);
            }

            ilGenerator.DeclareLocal(typeof(IntPtr));

            Label rewriteLabel = ilGenerator.DefineLabel();
            Label returnLabel  = ilGenerator.DefineLabel();

            // Inject method info into instruction stream
            if (method.IsConstructor)
            {
                ilGenerator.Emit(OpCodes.Ldtoken, (ConstructorInfo)method);
            }
            else
            {
                ilGenerator.Emit(OpCodes.Ldtoken, (MethodInfo)method);
            }

            ilGenerator.Emit(OpCodes.Ldtoken, method.DeclaringType);
            ilGenerator.Emit(OpCodes.Call, s_getMethodFromHandleMethod);

            // Rewrite method
            ilGenerator.MarkLabel(rewriteLabel);
            ilGenerator.Emit(OpCodes.Ldc_I4_0);
            ilGenerator.Emit(OpCodes.Call, s_createRewriterMethod);
            ilGenerator.Emit(OpCodes.Call, s_rewriteMethod);

            // Retrieve pointer to rewritten method
            ilGenerator.Emit(OpCodes.Call, s_getMethodPointerMethod);
            ilGenerator.Emit(OpCodes.Stloc_0);

            // Setup stack and make indirect call
            for (int i = 0; i < signatureParamTypes.Count; i++)
            {
                ilGenerator.Emit(OpCodes.Ldarg, i);
            }
            ilGenerator.Emit(OpCodes.Ldloc_0);
            ilGenerator.EmitCalli(OpCodes.Calli, CallingConventions.Standard, returnType, signatureParamTypes.ToArray(), null);

            ilGenerator.MarkLabel(returnLabel);
            ilGenerator.Emit(OpCodes.Ret);

            return(stub);
        }