Exemple #1
0
        public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction,
                                   MethodDefinition originalCall)
        {
            VariableDefinition jpcVar = visitor.CreateJoinPointContextLocal();

            WeaveStrategyUtilities.SetJoinPointContext(visitor, (MethodReference)originalCall, filterAction);

            MethodBase      mi           = typeof(CacheAction).GetMethod("getCachedValue", new Type[] { typeof(JoinPointContext) });
            MethodReference methodToCall = CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, mi);

            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, methodToCall));

            Instruction noCache = visitor.Worker.Create(OpCodes.Nop);

            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Brfalse, noCache));

            // Load JoinPointContext
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));

            // Get returnvalue
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextGetReturnValue)));

            // Check if returnvalue is value type, then unbox, else cast
            if (originalCall.ReturnType.ReturnType.IsValueType || originalCall.ReturnType.ReturnType is GenericParameter)
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Unbox_Any, originalCall.ReturnType.ReturnType));
            }
            else
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Castclass, originalCall.ReturnType.ReturnType));
            }
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ret));
            visitor.Instructions.Add(noCache);
        }
Exemple #2
0
        public override void Generate(ICecilInliningInstructionVisitor visitor, MethodDefinition originalCall, MethodDefinition conditionMethod)
        {
            // We need to get the MethodInfo object and place it on the stack so we can supply it to the FMC.
            //
            // Load the current method base. This is a trick in IL (.NET2) to get the MethodBase using lightweight reflection.
            // See for more information: http://www.interact-sw.co.uk/iangblog/2005/08/31/methodinfofromtoken
            // In IL code:
            // ldtoken method void SomeClass::SomeMethod()
            // call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
            //

            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldtoken, visitor.TargetAssemblyDefinition.MainModule.Import(originalCall)));

            if (originalCall.GenericParameters.Count > 0 || originalCall.DeclaringType.GenericParameters.Count > 0)
            {
                // If it is a generic we have to add the declaring type token. This is not directly supported in tools like Reflector.
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldtoken, visitor.TargetAssemblyDefinition.MainModule.Import(originalCall.DeclaringType)));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.GetMethodFromHandleExt)));
            }
            else
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.GetMethodFromHandle)));
            }


            // We now have a MethodBase object on the stack. Return control to the caller and let them call the FMC.
        }
Exemple #3
0
        /// <summary>
        /// Weaves the error action.
        /// </summary>
        /// <param name="visitor">The visitor.</param>
        /// <param name="filterAction">The filter action.</param>
        /// <param name="originalCall">The original call.</param>
        /// <remarks>
        /// Generate exception throw
        /// </remarks>
        /// <example>
        /// The following construction should be created:
        /// <code>
        /// throw new Exception();
        /// </code>
        /// or in IL code:
        /// <code>
        /// newobj instance void [mscorlib]System.Exception::.ctor()
        /// throw
        /// </code>
        /// </example>
        public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction,
                                   MethodDefinition originalCall)
        {
            // Create an exception
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Newobj,
                                                           CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                CachedMethodDefinition.ExceptionConstructor)));

            // Throw the exception
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Throw));
        }
Exemple #4
0
        public static void SetInnerCall(ICecilInliningInstructionVisitor visitor, MethodReference method)
        {
            MethodDefinition methodDef = CecilUtilities.ResolveMethod(
                visitor.Method.DeclaringType, method.Name, method);

            // Get the weaveMethod to which the innercall is directed
            WeaveMethod weaveMethod = visitor.WeaveType.GetMethod(methodDef.ToString());

            //if(weaveMethod == null)
            //{
            //    // if using MethodReference failed, try using the MethodDefinition (in some cases the ToString
            //    // leads to different signatures).
            //    MethodDefinition methodDef = CecilUtilities.ResolveMethodDefinition(method);
            //    if(methodDef != null)
            //    {
            //        weaveMethod = visitor.WeaveType.GetMethod(method.ToString());
            //    }

            if (weaveMethod == null)
            {
                // If weave method could not be found, this means that the method
                // does not have filters woven and so no inner call context needs
                // to be set.

                return;
            }
            //}

            // Load the this parameter
            if (!visitor.Method.HasThis || visitor.Method.DeclaringType.IsValueType)
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull));
            }
            else
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This));
            }

            // Load the methodId
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldc_I4, weaveMethod.Id));

            // Call the SetInnerCall
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.SetInnerCall)));
        }
Exemple #5
0
        public static void RestoreArguments(ICecilInliningInstructionVisitor visitor,
                                            MethodReference originalMethod, VariableDefinition joinPointContextVariable)
        {
            foreach (ParameterDefinition param in originalMethod.Parameters)
            {
                int ordinal = param.Sequence - 1;// (originalMethod.HasThis ? 1 : 0);

                //check for reference:
                if (param.ParameterType.FullName.EndsWith("&"))
                {
                    if (visitor.FilterType == FilterType.InputFilter)
                    {
                        //
                        // Store value from out/ref into JPC
                        //

                        // Load jpc
                        visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable));

                        // Load ordinal
                        visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldc_I4, ordinal));

                        // Load param
                        visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, param));

                        // Load value
                        visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldobj, param.ParameterType));

                        // If valuetype, box
                        if (param.ParameterType.IsValueType || param.ParameterType is GenericParameter)
                        {
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Box, param.ParameterType));
                        }

                        // Store value
                        // Call the SetArgumentValue(int16, object) function
                        visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                                       CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                            CachedMethodDefinition.JoinPointContextSetArgumentValue)));
                    }
                }
            }
        }
Exemple #6
0
        public static void LoadSelfObject(ICecilInliningInstructionVisitor visitor, VariableDefinition joinPointContextVariable)
        {
            if (visitor.FilterType == FilterType.InputFilter)
            {
                // Load this
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This));
            }
            else
            {
                // Load JoinPointContext
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable));

                // Call get_StartTarget in JoinPointContext
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call,
                                                               CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                    CachedMethodDefinition.JoinPointContextGetStartTarget)));

                // Do a cast
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Castclass, visitor.CalledMethod.DeclaringType));
            }
        }
Exemple #7
0
        public static void StoreReturnValue(ICecilInliningInstructionVisitor visitor,
                                            MethodReference originalCall, VariableDefinition joinPointContextVariable)
        {
            // Store returnvalue
            if (!originalCall.ReturnType.ReturnType.FullName.Equals(CecilUtilities.VoidType))
            {
                // Check if returnvalue is value type, then box
                if (originalCall.ReturnType.ReturnType.IsValueType || originalCall.ReturnType.ReturnType is GenericParameter)
                {
                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Box, originalCall.ReturnType.ReturnType));
                }

                // Load jpc
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable));

                // Call set_ReturnValue in JoinPointContext
                visitor.Instructions.Add(visitor.Worker.Create(
                                             OpCodes.Call,
                                             CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                  CachedMethodDefinition.JoinPointContextSetReturnValue)));
            }
        }
Exemple #8
0
        public static void SetJoinPointContext(
            ICecilInliningInstructionVisitor visitor,
            MethodReference originalCall, FilterAction filterAction)
        {
            VariableDefinition jpcVar = visitor.CreateJoinPointContextLocal();

            // Store current target
            if (filterAction.Target.Equals(FilterAction.InnerTarget) ||
                filterAction.Target.Equals(FilterAction.SelfTarget))
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                               CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                    CachedMethodDefinition.JoinPointContextGetStartTarget)));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                               CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                    CachedMethodDefinition.JoinPointContextSetCurrentTarget)));
            }
            else if (visitor.Method.HasThis)
            {
                TypeDefinition  parentType = CecilUtilities.ResolveTypeDefinition(visitor.Method.DeclaringType);
                FieldDefinition field      = parentType.Fields.GetField(filterAction.Target);
                if (field == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              Properties.Resources.FieldNotFound, filterAction.Target));
                }
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldfld, field));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                               CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                    CachedMethodDefinition.JoinPointContextSetCurrentTarget)));
            }
            else
            {
                // set to null for static methods
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                               CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                    CachedMethodDefinition.JoinPointContextSetCurrentTarget)));
            }

            // store current selector
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldstr, filterAction.Selector));
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                           CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                CachedMethodDefinition.JoinPointContextSetCurrentSelector)));


            // Store substitution target
            //if (filterAction.SubstitutionTarget.Equals(FilterAction.InnerTarget) ||
            //    filterAction.SubstitutionTarget.Equals(FilterAction.SelfTarget))
            //{
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
            //        CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
            //            CachedMethodDefinition.JoinPointContextGetStartTarget)));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
            //        CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
            //            CachedMethodDefinition.JoinPointContextGetSubstitutionTarget)));
            //}
            //else if (visitor.Method.HasThis)
            //{
            //    TypeDefinition parentType = CecilUtilities.ResolveTypeDefinition(visitor.Method.DeclaringType);
            //    FieldDefinition field = parentType.Fields.GetField(filterAction.SubstitutionTarget);
            //    if (field == null)
            //    {
            //        throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
            //            Properties.Resources.FieldNotFound, filterAction.SubstitutionTarget));
            //    }
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldfld, field));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
            //        CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
            //            CachedMethodDefinition.JoinPointContextSetSubstitutionTarget)));
            //}
            //else
            //{
            //    // set to null for static methods
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
            //        CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
            //            CachedMethodDefinition.JoinPointContextSetSubstitutionTarget)));
            //}

            // store substitution selector
            // TODO no longer relevant
            //visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            //visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldstr, filterAction.SubstitutionSelector));
            //visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
            //	CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
            //		CachedMethodDefinition.JoinPointContextSetSubstitutionSelector)));
        }
Exemple #9
0
        public static void LoadArguments(ICecilInliningInstructionVisitor visitor,
                                         MethodReference originalMethod, VariableDefinition joinPointContextVariable)
        {
            foreach (ParameterDefinition param in originalMethod.Parameters)
            {
                int ordinal = param.Sequence - 1;// -(originalMethod.HasThis ? 1 : 0);

                //check for reference:
                if (param.ParameterType.FullName.EndsWith("&"))
                {
                    if (visitor.FilterType == FilterType.InputFilter)
                    {
                        // For out parameters that are value type, check whether a value was set
                        if ((param.Attributes & Mono.Cecil.ParameterAttributes.Out) == Mono.Cecil.ParameterAttributes.Out &&
                            param.ParameterType.IsValueType)
                        {
                            //
                            // Store value from joinpointcontext into out
                            //

                            // Load param
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, param));

                            // Load jpc
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable));

                            // Load the ordinal
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldc_I4, ordinal));

                            // Call the GetArgumentValue(int16) function
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                                           CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                                CachedMethodDefinition.JoinPointContextGetArgumentValue)));

                            // Duplicate value
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Dup));

                            // Load null
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull));

                            // Check equals
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ceq));

                            // If not null, branch
                            Instruction falseNop = visitor.Worker.Create(OpCodes.Nop);
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Brfalse, falseNop));

                            // True branch

                            // Pop unnecessary argument value
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Pop));

                            // Jump to end (let parameter on the stack
                            Instruction endNop = visitor.Worker.Create(OpCodes.Nop);
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Br, endNop));

                            // End True branch

                            // False branch

                            // Nop instruction
                            visitor.Instructions.Add(falseNop);

                            // Unbox value
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Unbox_Any, param.ParameterType));

                            // Store value
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Stobj, param.ParameterType));

                            // Load param
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, param));

                            // End False branch

                            // End nop instruction
                            visitor.Instructions.Add(endNop);
                        }
                        else
                        {
                            //
                            // Store value from joinpointcontext into out
                            //

                            // Load param
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, param));

                            // Duplicate
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Dup));

                            // Load jpc
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable));

                            // Load the ordinal
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldc_I4, ordinal));

                            // Call the GetArgumentValue(int16) function
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                                           CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                                CachedMethodDefinition.JoinPointContextGetArgumentValue)));

                            // If valuetype unbox, else cast
                            if (param.ParameterType.IsValueType || param.ParameterType is GenericParameter)
                            {
                                // Unbox value
                                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Unbox_Any, param.ParameterType));
                            }
                            else
                            {
                                // Cast
                                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Castclass, param.ParameterType));
                            }

                            // Store value
                            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Stobj, param.ParameterType));
                        }
                    }
                }
                else                 //not a reference parameter
                {
                    // Load jpc
                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable));

                    // Load the ordinal
                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldc_I4, ordinal));

                    // Call the GetArgumentValue(int16) function
                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                                   CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                        CachedMethodDefinition.JoinPointContextGetArgumentValue)));

                    // Check if parameter is value type, then unbox
                    if (param.ParameterType.IsValueType || param.ParameterType is GenericParameter)
                    {
                        visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Unbox_Any, param.ParameterType));
                    }
                    else
                    {
                        visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Castclass, param.ParameterType));
                    }
                }
            }
        }