/// <summary>
        /// Initializes a new instance of the <see cref="MethodBodyRewriterParameters"/> class.
        /// </summary>
        /// <param name="IL">The CilWorker that is responsible for the current method body.</param>
        /// <param name="oldInstructions">The value indicating the list of old instructions in the current method body.</param>
        /// <param name="interceptionDisabled">The value that determines whether or not interception is disabled.</param>
        /// <param name="invocationInfo">The local variable that will store the <see cref="IInvocationInfo"/> instance.</param>
        /// <param name="returnValue">The value indicating the local variable that will store the return value.</param>
        /// <param name="methodReplacementProvider">The <see cref="IMethodReplacementProvider"/> instance.</param>
        /// <param name="aroundInvokeProvider">The <see cref="IAroundInvokeProvider"/> instance.</param>
        /// <param name="classMethodReplacementProvider">The class-level<see cref="IMethodReplacementProvider"/> instance.</param>
        /// <param name="getMethodReplacementProviderMethod">The functor that resolves the GetMethodReplacementProvider method.</param>
        /// <param name="registryType">The interception registry type that will be responsible for handling class-level interception events.</param>
        public MethodBodyRewriterParameters(CilWorker IL, IEnumerable<Instruction> oldInstructions,
                                            VariableDefinition interceptionDisabled,
                                            VariableDefinition invocationInfo,
                                            VariableDefinition returnValue,
                                            VariableDefinition methodReplacementProvider,
                                            VariableDefinition aroundInvokeProvider,
                                            VariableDefinition classMethodReplacementProvider,
                                            Func<ModuleDefinition, MethodReference> getMethodReplacementProviderMethod,
                                            Type registryType)
        {
            if (methodReplacementProvider.VariableType.FullName != typeof(IMethodReplacementProvider).FullName)
                throw new ArgumentException("methodReplacementProvider");

            if (aroundInvokeProvider.VariableType.FullName != typeof(IAroundInvokeProvider).FullName)
                throw new ArgumentException("aroundInvokeProvider");

            _cilWorker = IL;
            _oldInstructions = oldInstructions;
            _interceptionDisabled = interceptionDisabled;
            _invocationInfo = invocationInfo;
            _returnValue = returnValue;
            _methodReplacementProvider = methodReplacementProvider;
            _aroundInvokeProvider = aroundInvokeProvider;
            _classMethodReplacementProvider = classMethodReplacementProvider;
            _getMethodReplacementProviderMethod = getMethodReplacementProviderMethod;
            _registryType = registryType;
        }
Ejemplo n.º 2
0
        public void Emit(CilWorker IL)
        {
            var module = IL.GetModule();
            var modifiableType = module.ImportType<IModifiableType>();
            var getInterceptionDisabledMethod = module.ImportMethod<IModifiableType>("get_IsInterceptionDisabled");
            if (!_hostMethod.HasThis)
            {
                IL.Emit(OpCodes.Ldc_I4_0);
                IL.Emit(OpCodes.Stloc, _interceptionDisabled);
                return;
            }

            var skipLabel = IL.Create(OpCodes.Nop);

            // var interceptionDisabled = this.IsInterceptionDisabled;
            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Isinst, modifiableType);
            IL.Emit(OpCodes.Brfalse, skipLabel);

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Isinst, modifiableType);
            IL.Emit(OpCodes.Callvirt, getInterceptionDisabledMethod);
            IL.Emit(OpCodes.Stloc, _interceptionDisabled);

            IL.Append(skipLabel);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Rewrites a target method using the given CilWorker.
        /// </summary>
        /// <param name="method">The target method.</param>
        /// <param name="IL">The CilWorker that will be used to rewrite the target method.</param>
        /// <param name="oldInstructions">The original instructions from the target method body.</param>
        public void Rewrite(MethodDefinition method, CilWorker IL, IEnumerable<Instruction> oldInstructions)
        {
            var declaringType = method.DeclaringType;
            var module = declaringType.Module;

            // Interfaces and Enums cannot be modified
            if (declaringType.IsInterface || declaringType.IsEnum)
                return;

            ImportReferences(module);

            AddLocals(method);

            if (!_modifiedTypes.Contains(declaringType))
            {
                AddAdditionalMembers(declaringType);
                _modifiedTypes.Add(declaringType);
            }

            var newInstructions = new Queue<Instruction>();
            foreach (var instruction in oldInstructions)
            {
                // Intercept only the load field and the load static field instruction
                if (!ShouldReplace(instruction, method))
                {
                    IL.Append(instruction);
                    continue;
                }

                Replace(instruction, method, IL);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Rewrites a target method using the given CilWorker.
        /// </summary>
        /// <param name="method">The target method.</param>
        /// <param name="IL">The CilWorker that will be used to rewrite the target method.</param>
        /// <param name="oldInstructions">The original instructions from the target method body.</param>
        public void Rewrite(MethodDefinition method, CilWorker IL, IEnumerable<Instruction> oldInstructions)
        {
            if (!ShouldRewrite(method))
                return;

            var declaringType = method.DeclaringType;

            var body = IL.GetBody();
            body.InitLocals = true;

            var module = declaringType.Module;

            // Interfaces and Enums cannot be modified
            if (declaringType.IsInterface || declaringType.IsEnum)
                return;

            ImportReferences(module);

            AddLocals(method);

            if (!_modifiedTypes.Contains(declaringType))
            {
                AddAdditionalMembers(declaringType);
                _modifiedTypes.Add(declaringType);
            }

            RewriteMethodBody(method, IL, oldInstructions);
        }
        /// <summary>
        /// Adds the original instructions to a given method body.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> responsible for the target method body.</param>
        public void Emit(CilWorker IL)
        {
            var originalInstructions = new List<Instruction>(_oldInstructions);
            Instruction lastInstruction = originalInstructions.LastOrDefault();

            if (lastInstruction != null && lastInstruction.OpCode == OpCodes.Ret)
            {
                // HACK: Convert the Ret instruction into a Nop
                // instruction so that the code will
                // fall through to the epilog
                lastInstruction.OpCode = OpCodes.Br;
                lastInstruction.Operand = _endLabel;
            }

            foreach (Instruction instruction in (IEnumerable<Instruction>) originalInstructions)
            {
                if (instruction.OpCode != OpCodes.Ret || instruction == lastInstruction)
                    continue;

                if (lastInstruction == null)
                    continue;

                // HACK: Modify all ret instructions to call
                // the epilog after execution
                instruction.OpCode = OpCodes.Br;
                instruction.Operand = lastInstruction;
            }

            // Emit the original instructions
            foreach (Instruction instruction in originalInstructions)
            {
                IL.Append(instruction);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Rewrites the instructions in the target method body.
        /// </summary>
        /// <param name="method">The target method.</param>
        /// <param name="IL">The <see cref="CilWorker"/> instance that represents the method body.</param>
        /// <param name="oldInstructions">The IL instructions of the original method body.</param>
        protected override void RewriteMethodBody(MethodDefinition method, CilWorker IL,
                                                  IEnumerable<Instruction> oldInstructions)
        {
            if (IsExcluded(method))
            {
                AddOriginalInstructions(IL, oldInstructions);
                return;
            }

            VariableDefinition interceptionDisabled = method.AddLocal<bool>();
            VariableDefinition invocationInfo = method.AddLocal<IInvocationInfo>();
            VariableDefinition aroundInvokeProvider = method.AddLocal<IAroundInvokeProvider>();
            VariableDefinition methodReplacementProvider = method.AddLocal<IMethodReplacementProvider>();

            VariableDefinition returnValue = method.AddLocal<object>();
            VariableDefinition classMethodReplacementProvider = method.AddLocal<IMethodReplacementProvider>();

            Func<ModuleDefinition, MethodReference> getInstanceMethodReplacementProviderMethod =
                module => module.Import(typeof (IMethodReplacementHost).GetMethod("get_MethodBodyReplacementProvider"));

            var parameters = new MethodBodyRewriterParameters(IL,
                                                              oldInstructions,
                                                              interceptionDisabled,
                                                              invocationInfo, returnValue,
                                                              aroundInvokeProvider,
                                                              methodReplacementProvider,
                                                              classMethodReplacementProvider,
                                                              getInstanceMethodReplacementProviderMethod,
                                                              typeof (AroundMethodBodyRegistry));

            var emitter = new InvocationInfoEmitter(true);

            IInstructionEmitter getMethodReplacementProvider =
                new GetMethodReplacementProvider(methodReplacementProvider, method,
                                                 getInstanceMethodReplacementProviderMethod);

            IInstructionEmitter getInterceptionDisabled = new GetInterceptionDisabled(parameters);
            ISurroundMethodBody surroundMethodBody = new SurroundMethodBody(parameters, "AroundMethodBodyProvider");
            IInstructionEmitter getClassMethodReplacementProvider = new GetClassMethodReplacementProvider(parameters,
                                                                                                          module =>
                                                                                                          module.Import(
                                                                                                              typeof (
                                                                                                                  MethodBodyReplacementProviderRegistry
                                                                                                                  ).
                                                                                                                  GetMethod
                                                                                                                  ("GetProvider")));
            IInstructionEmitter addMethodReplacement = new AddMethodReplacementImplementation(parameters);

            var rewriter = new InterceptAndSurroundMethodBody(emitter, getInterceptionDisabled, surroundMethodBody,
                                                              getMethodReplacementProvider,
                                                              getClassMethodReplacementProvider, addMethodReplacement,
                                                              parameters);

            // Determine whether or not the method should be intercepted
            rewriter.Rewrite(method, IL, oldInstructions);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Emits the call to the <see cref="IAfterInvoke"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that points to the current method body.</param>
        public void Emit(CilWorker IL)
        {
            ModuleDefinition module = IL.GetModule();

            // instanceAroundInvoke.AfterInvoke(info, returnValue);
            Emit(IL, module, _surroundingImplementation, _invocationInfo, _returnValue);

            // classAroundInvoke.AfterInvoke(info, returnValue);
            Emit(IL, module, _surroundingClassImplementation, _invocationInfo, _returnValue);
        }
        /// <summary>
        /// Emits the instructions that obtain the <see cref="IAroundInvoke"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that points to the current method body.</param>
        public void Emit(CilWorker IL)
        {
            var method = IL.GetMethod();
            var declaringType = method.DeclaringType;
            var module = declaringType.Module;

            var getSurroundingImplementation = module.Import(_getSurroundingImplementationMethod);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Call, getSurroundingImplementation);
            IL.Emit(OpCodes.Stloc, _surroundingClassImplementation);
        }
        /// <summary>
        /// Emits the instructions that obtain the <see cref="IAroundInvoke"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that points to the current method body.</param>
        public void Emit(CilWorker IL)
        {
            MethodDefinition method = IL.GetMethod();
            TypeDefinition declaringType = method.DeclaringType;
            ModuleDefinition module = declaringType.Module;

            MethodReference getSurroundingImplementation = module.Import(_getSurroundingImplementationMethod);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Call, getSurroundingImplementation);
            IL.Emit(OpCodes.Stloc, _surroundingClassImplementation);
        }
Ejemplo n.º 10
0
        public ParameterContext(CilWorker worker, TypeReference interfaceType, MethodReference currentMethod, VariableDefinition currentArguments, VariableDefinition currentArgument, TypeReference targetDependency, MethodDefinition adapterConstructor, ParameterReference param)
        {
            CilWorker = worker;
            CurrentArguments = currentArguments;
            CurrentArgument = currentArgument;
            TargetDependency = targetDependency;

            Parameter = param;
            InterfaceType = interfaceType;
            AdapterConstructor = adapterConstructor;
            CurrentMethod = currentMethod;
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Saves the return value from a given method call.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param>
        public void Emit(CilWorker IL)
        {
            ModuleDefinition module = IL.GetModule();
            TypeReference voidType = module.ImportType(typeof (void));
            bool returnTypeIsValueType = _returnType != voidType && _returnType.IsValueType;

            if (_returnType is GenericParameter || returnTypeIsValueType)
                IL.Create(OpCodes.Box, _returnType);

            if (_returnType != voidType)
                IL.Create(OpCodes.Stloc, _returnValue);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Saves the return value from a given method call.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param>
        public void Emit(CilWorker IL)
        {
            var module = IL.GetModule();
            var voidType = module.ImportType(typeof (void));
            var returnTypeIsValueType = _returnType != voidType && _returnType.IsValueType;

            if (_returnType is GenericParameter || returnTypeIsValueType)
                IL.Create(OpCodes.Box, _returnType);

            if (_returnType != voidType)
                IL.Create(OpCodes.Stloc, _returnValue);
        }
        public void EmitNewObject(MethodDefinition hostMethod, CilWorker IL, MethodReference targetConstructor,
                                  TypeReference concreteType)
        {
            ParameterDefinitionCollection parameters = targetConstructor.Parameters;
            Instruction skipInterception = IL.Create(OpCodes.Nop);

            SaveConstructorArguments(IL, parameters);
            EmitCreateMethodActivationContext(hostMethod, IL, concreteType);

            // Skip the interception if an activator cannot be found
            EmitGetActivator(hostMethod, IL, skipInterception);

            IL.Emit(OpCodes.Stloc, _currentActivator);

            IL.Emit(OpCodes.Ldloc, _currentActivator);
            IL.Emit(OpCodes.Brfalse, skipInterception);

            // Determine if the activator can instantiate the method from the
            // current context
            IL.Emit(OpCodes.Ldloc, _currentActivator);
            IL.Emit(OpCodes.Ldloc, _methodContext);
            IL.Emit(OpCodes.Callvirt, _canActivate);
            IL.Emit(OpCodes.Brfalse, skipInterception);

            // Use the activator to create the object instance
            EmitCreateInstance(IL);

            // }
            Instruction endCreate = IL.Create(OpCodes.Nop);
            IL.Emit(OpCodes.Br, endCreate);
            // else {
            IL.Append(skipInterception);

            // Restore the arguments that were popped off the stack
            // by the list of constructor arguments
            int parameterCount = parameters.Count;
            for (int index = 0; index < parameterCount; index++)
            {
                ParameterDefinition currentParameter = parameters[index];

                IL.Emit(OpCodes.Ldloc, _constructorArguments);
                IL.Emit(OpCodes.Ldc_I4, index);
                IL.Emit(OpCodes.Callvirt, _getItem);
                IL.Emit(OpCodes.Unbox_Any, currentParameter.ParameterType);
            }

            IL.Emit(OpCodes.Newobj, targetConstructor);
            // }

            IL.Append(endCreate);
        }
Ejemplo n.º 14
0
        protected override void RewriteMethodBody(MethodDefinition method, CilWorker IL, IEnumerable<Instruction> oldInstructions)
        {
            var newInstructions = new Queue<Instruction>();
            foreach (var instruction in oldInstructions)
            {
                if (!ShouldReplace(instruction, method))
                {
                    IL.Append(instruction);
                    continue;
                }

                Replace(instruction, method, IL);
            }
        }
        public void Emit(CilWorker IL)
        {
            var module = IL.GetModule();
            var method = IL.GetMethod();

            var getProvider = _resolveGetProviderMethod(module);

            var pushThis = method.HasThis ? OpCodes.Ldarg_0 : OpCodes.Ldnull;
            IL.Emit(pushThis);

            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Call, getProvider);
            IL.Emit(OpCodes.Stloc, _classMethodReplacementProvider);
        }
        public void Emit(CilWorker IL)
        {
            var module = IL.GetModule();

            IL.Emit(OpCodes.Ldloc, _aroundInvokeProvider);
            IL.Emit(OpCodes.Brfalse, _skipGetSurroundingImplementation);

            // var surroundingImplementation = this.GetSurroundingImplementation(this, invocationInfo);
            var getSurroundingImplementation = module.ImportMethod<IAroundInvokeProvider>("GetSurroundingImplementation");
            IL.Emit(OpCodes.Ldloc, _aroundInvokeProvider);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Callvirt, getSurroundingImplementation);
            IL.Emit(OpCodes.Stloc, _surroundingImplementation);
        }
        protected override void Replace(Instruction currentInstruction, MethodDefinition method, CilWorker IL)
        {
            var constructor = (MethodReference) currentInstruction.Operand;
            TypeReference concreteType = constructor.DeclaringType;
            ParameterDefinitionCollection parameters = constructor.Parameters;

            if (!_emitter.ShouldIntercept(constructor, concreteType, method))
            {
                // Reuse the old instruction instead of emitting a new one
                IL.Append(currentInstruction);
                return;
            }

            _emitter.EmitNewObject(method, IL, constructor, concreteType);
        }
Ejemplo n.º 18
0
        public void AddEpilog(CilWorker IL)
        {
            var skipEpilog = IL.Create(OpCodes.Nop);

            // if (!IsInterceptionDisabled && surroundingImplementation != null) {
            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, skipEpilog);

            // surroundingImplementation.AfterInvoke(invocationInfo, returnValue);
            var emitAfterInvoke = new EmitAfterInvoke(_surroundingImplementation, _surroundingClassImplementation, _invocationInfo, _returnValue);
            emitAfterInvoke.Emit(IL);

            // }
            IL.Append(skipEpilog);
        }
        /// <summary>
        /// Adds method body interception to the target method.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param>
        public void Emit(CilWorker IL)
        {
            MethodDefinition method = IL.GetMethod();
            TypeReference returnType = method.ReturnType.ReturnType;

            Instruction endLabel = IL.Create(OpCodes.Nop);
            Instruction executeOriginalInstructions = IL.Create(OpCodes.Nop);

            // Execute the method body replacement if and only if
            // interception is enabled
            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, executeOriginalInstructions);

            Instruction invokeReplacement = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, _methodReplacementProvider);
            IL.Emit(OpCodes.Brtrue, invokeReplacement);

            IL.Emit(OpCodes.Ldloc, _classMethodReplacementProvider);
            IL.Emit(OpCodes.Brtrue, invokeReplacement);

            IL.Emit(OpCodes.Br, executeOriginalInstructions);
            IL.Append(invokeReplacement);

            // This is equivalent to the following code:
            // var replacement = provider.GetMethodReplacement(info);
            var invokeMethodReplacement = new InvokeMethodReplacement(executeOriginalInstructions,
                                                                      _methodReplacementProvider,
                                                                      _classMethodReplacementProvider, _invocationInfo);
            invokeMethodReplacement.Emit(IL);

            IL.Emit(OpCodes.Br, endLabel);

            #region The original instruction block

            IL.Append(executeOriginalInstructions);
            var addOriginalInstructions = new AddOriginalInstructions(_oldInstructions, endLabel);
            addOriginalInstructions.Emit(IL);

            #endregion

            // Mark the end of the method body
            IL.Append(endLabel);

            var saveReturnValue = new SaveReturnValue(returnType, _returnValue);
            saveReturnValue.Emit(IL);
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Emits the call to the <see cref="IAfterInvoke"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that points to the current method body.</param>
        public void Emit(CilWorker IL)
        {
            var targetMethod = IL.GetMethod();
            var declaringType = targetMethod.DeclaringType;
            var module = declaringType.Module;

            var getSurroundingClassImplementation = new GetSurroundingClassImplementation(_invocationInfo,
                _surroundingClassImplementation,
                _registryType.GetMethod(
                    "GetSurroundingImplementation"));

            // var classAroundInvoke = AroundInvokeRegistry.GetSurroundingImplementation(info);
            getSurroundingClassImplementation.Emit(IL);

            // classAroundInvoke.BeforeInvoke(info);
            var skipInvoke = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, _surroundingClassImplementation);
            IL.Emit(OpCodes.Brfalse, skipInvoke);

            var beforeInvoke = module.ImportMethod<IBeforeInvoke>("BeforeInvoke");

            // surroundingImplementation.BeforeInvoke(invocationInfo);
            IL.Emit(OpCodes.Ldloc, _surroundingClassImplementation);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Callvirt, beforeInvoke);

            IL.Append(skipInvoke);

            // if (surroundingImplementation != null) {
            if (!targetMethod.HasThis)
                return;

            var skipInvoke1 = IL.Create(OpCodes.Nop);
            IL.Emit(OpCodes.Ldloc, _surroundingImplementation);
            IL.Emit(OpCodes.Brfalse, skipInvoke1);

            var beforeInvoke1 = module.ImportMethod<IBeforeInvoke>("BeforeInvoke");

            // surroundingImplementation.BeforeInvoke(invocationInfo);
            IL.Emit(OpCodes.Ldloc, _surroundingImplementation);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Callvirt, beforeInvoke1);

            IL.Append(skipInvoke1);
            // }
        }
Ejemplo n.º 21
0
        public void AddProlog(CilWorker IL)
        {
            var method = IL.GetMethod();
            _surroundingImplementation = method.AddLocal<IAroundInvoke>();
            _surroundingClassImplementation = method.AddLocal<IAroundInvoke>();

            var skipProlog = IL.Create(OpCodes.Nop);
            var declaringType = method.DeclaringType;
            var module = declaringType.Module;
            var modifiableType = module.ImportType<IModifiableType>();

            if (method.HasThis)
            {
                IL.Emit(OpCodes.Ldarg_0);
                IL.Emit(OpCodes.Isinst, modifiableType);
                IL.Emit(OpCodes.Brfalse, skipProlog);
            }

            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, skipProlog);

            // var provider = this.MethodReplacementProvider;

            if (_getMethodReplacementProvider != null)
                _getMethodReplacementProvider.Emit(IL);

            var getAroundInvokeProvider = new GetAroundInvokeProvider(_aroundInvokeProvider);
            getAroundInvokeProvider.Emit(IL);

            // if (aroundInvokeProvider != null ) {
            var skipGetSurroundingImplementation = IL.Create(OpCodes.Nop);
            var getSurroundingImplementationInstance = new GetSurroundingImplementationInstance(_aroundInvokeProvider,
                _invocationInfo, _surroundingImplementation, skipGetSurroundingImplementation);

            getSurroundingImplementationInstance.Emit(IL);

            // }

            IL.Append(skipGetSurroundingImplementation);
            var emitBeforeInvoke = new EmitBeforeInvoke(_invocationInfo, _surroundingClassImplementation,
                                                        _surroundingImplementation, _registryType);
            emitBeforeInvoke.Emit(IL);

            IL.Append(skipProlog);
        }
        /// <summary>
        /// Emits the instructions that obtain the <see cref="IMethodReplacementProvider"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> instance.</param>
        public void Emit(CilWorker IL)
        {
            MethodDefinition method = _hostMethod;
            TypeDefinition declaringType = method.DeclaringType;
            ModuleDefinition module = declaringType.Module;

            if (!method.HasThis)
            {
                IL.Emit(OpCodes.Ldnull);
                IL.Emit(OpCodes.Stloc, _methodReplacementProvider);
                return;
            }

            MethodReference getProvider = _resolveGetProviderMethod(module);
            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Callvirt, getProvider);
            IL.Emit(OpCodes.Stloc, _methodReplacementProvider);
        }
        public void Emit(CilWorker IL)
        {
            var method = _hostMethod;
            var declaringType = method.DeclaringType;
            var module = declaringType.Module;

            if (!method.HasThis)
            {
                IL.Emit(OpCodes.Ldnull);
                IL.Emit(OpCodes.Stloc, _methodReplacementProvider);
                return;
            }

            var getProvider = _resolveGetProviderMethod(module);
            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Callvirt, getProvider);
            IL.Emit(OpCodes.Stloc, _methodReplacementProvider);
        }
Ejemplo n.º 24
0
        public void Emit(CilWorker IL)
        {
            var method = IL.GetMethod();
            var module = IL.GetModule();

            // var aroundInvokeProvider = this.AroundInvokeProvider;
            var getAroundInvokeProvider = module.ImportMethod<IModifiableType>("get_AroundInvokeProvider");

            if (!method.HasThis)
            {
                IL.Emit(OpCodes.Ldnull);
                IL.Emit(OpCodes.Stloc, _aroundInvokeProvider);
                return;
            }

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Callvirt, getAroundInvokeProvider);
            IL.Emit(OpCodes.Stloc, _aroundInvokeProvider);
        }
        /// <summary>
        /// Rewrites a target method using the given CilWorker.
        /// </summary>
        /// <param name="method">The target method.</param>
        /// <param name="IL">The CilWorker that will be used to rewrite the target method.</param>
        /// <param name="oldInstructions">The original instructions from the target method body.</param>
        public void Rewrite(MethodDefinition method, CilWorker IL,
                            IEnumerable<Instruction> oldInstructions)
        {
            MethodDefinition targetMethod = _parameters.TargetMethod;
            CilWorker worker = targetMethod.GetILGenerator();
            ModuleDefinition module = worker.GetModule();

            _getInterceptionDisabled.Emit(worker);

            // Construct the InvocationInfo instance
            Instruction skipInvocationInfo = worker.Create(OpCodes.Nop);
            worker.Emit(OpCodes.Ldloc, _parameters.InterceptionDisabled);
            worker.Emit(OpCodes.Brtrue, skipInvocationInfo);

            MethodDefinition interceptedMethod = targetMethod;
            _emitter.Emit(targetMethod, interceptedMethod, _parameters.InvocationInfo);

            Instruction skipGetReplacementProvider = IL.Create(OpCodes.Nop);

            // var provider = this.MethodReplacementProvider;
            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, skipGetReplacementProvider);

            _getInstanceMethodReplacementProvider.Emit(IL);
            _surroundMethodBody.AddProlog(worker);

            IL.Append(skipGetReplacementProvider);

            worker.Append(skipInvocationInfo);
            _getClassMethodReplacementProvider.Emit(worker);

            TypeReference returnType = targetMethod.ReturnType.ReturnType;
            _addMethodReplacement.Emit(worker);

            // Save the return value
            TypeReference voidType = module.Import(typeof (void));
            _surroundMethodBody.AddEpilog(worker);

            //if (returnType != voidType)
            //    worker.Emit(OpCodes.Ldloc, _parameters.ReturnValue);

            worker.Emit(OpCodes.Ret);
        }
Ejemplo n.º 26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MethodBodyRewriterParameters"/> class.
 /// </summary>
 /// <param name="IL">The CilWorker that is responsible for the current method body.</param>
 /// <param name="oldInstructions">The value indicating the list of old instructions in the current method body.</param>
 /// <param name="interceptionDisabled">The value that determines whether or not interception is disabled.</param>
 /// <param name="invocationInfo">The local variable that will store the <see cref="IInvocationInfo"/> instance.</param>
 /// <param name="returnValue">The value indicating the local variable that will store the return value.</param>
 /// <param name="methodReplacementProvider">The <see cref="IMethodReplacementProvider"/> instance.</param>
 /// <param name="aroundInvokeProvider">The <see cref="IAroundInvokeProvider"/> instance.</param>
 /// <param name="classMethodReplacementProvider">The class-level<see cref="IMethodReplacementProvider"/> instance.</param>
 /// <param name="getMethodReplacementProviderMethod">The functor that resolves the GetMethodReplacementProvider method.</param>
 /// <param name="registryType">The interception registry type that will be responsible for handling class-level interception events.</param>
 public MethodBodyRewriterParameters(CilWorker IL, IEnumerable<Instruction> oldInstructions, 
     VariableDefinition interceptionDisabled,
     VariableDefinition invocationInfo,
     VariableDefinition returnValue,
     VariableDefinition methodReplacementProvider,
     VariableDefinition aroundInvokeProvider,
     VariableDefinition classMethodReplacementProvider,
     Func<ModuleDefinition, MethodReference> getMethodReplacementProviderMethod, Type registryType)
 {
     _cilWorker = IL;
     _oldInstructions = oldInstructions;
     _interceptionDisabled = interceptionDisabled;
     _invocationInfo = invocationInfo;
     _returnValue = returnValue;
     _methodReplacementProvider = methodReplacementProvider;
     _aroundInvokeProvider = aroundInvokeProvider;
     _classMethodReplacementProvider = classMethodReplacementProvider;
     _getMethodReplacementProviderMethod = getMethodReplacementProviderMethod;
     _registryType = registryType;
 }
        /// <summary>
        /// Emits the call to obtain the <see cref="IAroundInvokeProvider"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param>
        public void Emit(CilWorker IL)
        {
            MethodDefinition method = IL.GetMethod();
            ModuleDefinition module = IL.GetModule();

            // var aroundInvokeProvider = this.AroundInvokeProvider;
            string propertyName = string.Format("get_{0}", _providerName);
            MethodReference getAroundInvokeProvider = module.ImportMethod<IAroundInvokeHost>(propertyName);

            if (!method.HasThis)
            {
                IL.Emit(OpCodes.Ldnull);
                IL.Emit(OpCodes.Stloc, _aroundInvokeProvider);
                return;
            }

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Callvirt, getAroundInvokeProvider);
            IL.Emit(OpCodes.Stloc, _aroundInvokeProvider);
        }
Ejemplo n.º 28
0
        public void Emit(CilWorker IL)
        {
            var module = IL.GetModule();
            var method = IL.GetMethod();
            var returnType = method.ReturnType.ReturnType;
            var methodReplacement = MethodDefinitionExtensions.AddLocal(method, typeof(IInterceptor));

            GetMethodReplacementInstance(method, IL, methodReplacement, _methodReplacementProvider, _invocationInfo);

            var skipGetClassMethodReplacement = IL.Create(OpCodes.Nop);
            IL.Emit(OpCodes.Ldloc, methodReplacement);
            IL.Emit(OpCodes.Brtrue, skipGetClassMethodReplacement);

            GetMethodReplacementInstance(method, IL, methodReplacement, _classMethodReplacementProvider, _invocationInfo);

            IL.Append(skipGetClassMethodReplacement);
            IL.Emit(OpCodes.Ldloc, methodReplacement);
            IL.Emit(OpCodes.Brfalse, _executeOriginalInstructions);

            // var returnValue = replacement.Intercept(info);
            InvokeInterceptor(module, IL, methodReplacement, returnType, _invocationInfo);
        }
Ejemplo n.º 29
0
        private static void Emit(CilWorker IL, ModuleDefinition module,
                                 VariableDefinition surroundingImplementation,
                                 VariableDefinition invocationInfo,
                                 VariableDefinition returnValue)
        {
            Instruction skipInvoke = IL.Create(OpCodes.Nop);

            Instruction skipPrint = IL.Create(OpCodes.Nop);
            IL.Emit(OpCodes.Ldloc, surroundingImplementation);
            IL.Emit(OpCodes.Brtrue, skipPrint);

            IL.Append(skipPrint);
            IL.Emit(OpCodes.Ldloc, surroundingImplementation);
            IL.Emit(OpCodes.Brfalse, skipInvoke);

            MethodReference aroundInvoke = module.ImportMethod<IAfterInvoke>("AfterInvoke");
            IL.Emit(OpCodes.Ldloc, surroundingImplementation);
            IL.Emit(OpCodes.Ldloc, invocationInfo);
            IL.Emit(OpCodes.Ldloc, returnValue);
            IL.Emit(OpCodes.Callvirt, aroundInvoke);

            IL.Append(skipInvoke);
        }
Ejemplo n.º 30
0
        private static void GetMethodReplacementInstance(MethodDefinition method,
            CilWorker IL,
            VariableDefinition methodReplacement,
            VariableDefinition methodReplacementProvider, VariableDefinition invocationInfo)
        {
            var declaringType = method.DeclaringType;
            var module = declaringType.Module;
            var pushInstance = method.HasThis ? IL.Create(OpCodes.Ldarg_0) : IL.Create(OpCodes.Ldnull);

            var getReplacement = module.ImportMethod<IMethodReplacementProvider>("GetMethodReplacement");
            IL.Emit(OpCodes.Ldloc, methodReplacementProvider);

            var skipGetMethodReplacement = IL.Create(OpCodes.Nop);
            IL.Emit(OpCodes.Brfalse, skipGetMethodReplacement);
            IL.Emit(OpCodes.Ldloc, methodReplacementProvider);

            IL.Append(pushInstance);
            IL.Emit(OpCodes.Ldloc, invocationInfo);
            IL.Emit(OpCodes.Callvirt, getReplacement);
            IL.Emit(OpCodes.Stloc, methodReplacement);

            IL.Append(skipGetMethodReplacement);
        }
        internal static MethodBody Clone(MethodBody body, MethodDefinition parent, ImportContext context)
        {
            MethodBody nb = new MethodBody(parent);

            nb.MaxStack   = body.MaxStack;
            nb.InitLocals = body.InitLocals;
            nb.CodeSize   = body.CodeSize;

            CilWorker worker = nb.CilWorker;

            if (body.HasVariables)
            {
                foreach (VariableDefinition var in body.Variables)
                {
                    nb.Variables.Add(new VariableDefinition(
                                         var.Name, var.Index, parent,
                                         context.Import(var.VariableType)));
                }
            }

            foreach (Instruction instr in body.Instructions)
            {
                Instruction ni = new Instruction(instr.OpCode);

                switch (instr.OpCode.OperandType)
                {
                case OperandType.InlineParam:
                case OperandType.ShortInlineParam:
                    if (instr.Operand == body.Method.This)
                    {
                        ni.Operand = nb.Method.This;
                    }
                    else
                    {
                        int param = body.Method.Parameters.IndexOf((ParameterDefinition)instr.Operand);
                        ni.Operand = parent.Parameters [param];
                    }
                    break;

                case OperandType.InlineVar:
                case OperandType.ShortInlineVar:
                    int var = body.Variables.IndexOf((VariableDefinition)instr.Operand);
                    ni.Operand = nb.Variables [var];
                    break;

                case OperandType.InlineField:
                    ni.Operand = context.Import((FieldReference)instr.Operand);
                    break;

                case OperandType.InlineMethod:
                    ni.Operand = context.Import((MethodReference)instr.Operand);
                    break;

                case OperandType.InlineType:
                    ni.Operand = context.Import((TypeReference)instr.Operand);
                    break;

                case OperandType.InlineTok:
                    if (instr.Operand is TypeReference)
                    {
                        ni.Operand = context.Import((TypeReference)instr.Operand);
                    }
                    else if (instr.Operand is FieldReference)
                    {
                        ni.Operand = context.Import((FieldReference)instr.Operand);
                    }
                    else if (instr.Operand is MethodReference)
                    {
                        ni.Operand = context.Import((MethodReference)instr.Operand);
                    }
                    break;

                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                case OperandType.InlineSwitch:
                    break;

                default:
                    ni.Operand = instr.Operand;
                    break;
                }

                worker.Append(ni);
            }

            for (int i = 0; i < body.Instructions.Count; i++)
            {
                Instruction instr = nb.Instructions [i];
                Instruction oldi  = body.Instructions [i];

                if (instr.OpCode.OperandType == OperandType.InlineSwitch)
                {
                    Instruction [] olds    = (Instruction [])oldi.Operand;
                    Instruction [] targets = new Instruction [olds.Length];

                    for (int j = 0; j < targets.Length; j++)
                    {
                        targets [j] = GetInstruction(body, nb, olds [j]);
                    }

                    instr.Operand = targets;
                }
                else if (instr.OpCode.OperandType == OperandType.ShortInlineBrTarget || instr.OpCode.OperandType == OperandType.InlineBrTarget)
                {
                    instr.Operand = GetInstruction(body, nb, (Instruction)oldi.Operand);
                }
            }

            if (!body.HasExceptionHandlers)
            {
                return(nb);
            }

            foreach (ExceptionHandler eh in body.ExceptionHandlers)
            {
                ExceptionHandler neh = new ExceptionHandler(eh.Type);
                neh.TryStart     = GetInstruction(body, nb, eh.TryStart);
                neh.TryEnd       = GetInstruction(body, nb, eh.TryEnd);
                neh.HandlerStart = GetInstruction(body, nb, eh.HandlerStart);
                neh.HandlerEnd   = GetInstruction(body, nb, eh.HandlerEnd);

                switch (eh.Type)
                {
                case ExceptionHandlerType.Catch:
                    neh.CatchType = context.Import(eh.CatchType);
                    break;

                case ExceptionHandlerType.Filter:
                    neh.FilterStart = GetInstruction(body, nb, eh.FilterStart);
                    neh.FilterEnd   = GetInstruction(body, nb, eh.FilterEnd);
                    break;
                }

                nb.ExceptionHandlers.Add(neh);
            }

            return(nb);
        }