コード例 #1
0
    public void Process()
    {
        if (Method.Body.Instructions.Count > 0)
        {
            var ilProcessor = Method.Body.GetILProcessor();
            var body        = Method.Body;
            FoundUsageInType();
            string eventName = string.Empty;
            foreach (var attribute in Method.CustomAttributes)
            {
                if (attribute.AttributeType.FullName.Equals("EventLogger.EventNameAttribute"))
                {
                    eventName = attribute.ConstructorArguments[0].Value.ToString();
                    Method.CustomAttributes.Remove(attribute);
                    break;
                }
            }

            Instruction firstInstruction = Method.Body.Instructions.FirstOrDefault();
            var         returnFixer      = new ReturnFixer
            {
                Method = Method
            };
            returnFixer.MakeLastStatementReturn();

            List <Instruction> startingInstructions = new List <Instruction>();
            List <Instruction> endingInstructions   = new List <Instruction>();

            endingInstructions.AddRange(GetEventInstruction("Method calling Finished."));

            if (!string.IsNullOrEmpty(eventName))
            {
                startingInstructions.AddRange(SetEventNameInstruction(eventName));
                endingInstructions.AddRange(SetEventNameInstruction(""));
            }
            startingInstructions.AddRange(GetEventInstruction("Method calling started."));

            var tryLeaveInstructions = Instruction.Create(OpCodes.Leave_S, returnFixer.NopBeforeReturn);
            var finallyInstructions  = Instruction.Create(OpCodes.Endfinally);
            ilProcessor.InsertBefore(firstInstruction, startingInstructions);

            ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, tryLeaveInstructions);
            ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, endingInstructions);
            ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, finallyInstructions);

            var beforeReturn = Instruction.Create(OpCodes.Nop);
            var handler      = new ExceptionHandler(ExceptionHandlerType.Finally)
            {
                TryStart     = firstInstruction,
                TryEnd       = tryLeaveInstructions.Next,
                HandlerStart = endingInstructions.FirstOrDefault(),
                HandlerEnd   = finallyInstructions.Next
            };

            body.ExceptionHandlers.Add(handler);
            body.InitLocals = true;
            body.OptimizeMacros();
        }
    }
コード例 #2
0
    void ContinueProcessing()
    {
        body = Method.Body;

        body.SimplifyMacros();

        var ilProcessor = body.GetILProcessor();

        var returnFixer = new ReturnFixer
        {
            Method = Method
        };

        returnFixer.MakeLastStatementReturn();

        exceptionVariable = new VariableDefinition(ModuleWeaver.ExceptionType);
        body.Variables.Add(exceptionVariable);
        messageVariable = new VariableDefinition(ModuleWeaver.ModuleDefinition.TypeSystem.String);
        body.Variables.Add(messageVariable);
        paramsArrayVariable = new VariableDefinition(ModuleWeaver.ObjectArray);
        body.Variables.Add(paramsArrayVariable);


        var tryCatchLeaveInstructions = Instruction.Create(OpCodes.Leave, returnFixer.NopBeforeReturn);

        var methodBodyFirstInstruction = GetMethodBodyFirstInstruction();

        var catchInstructions = GetCatchInstructions().ToList();

        ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, tryCatchLeaveInstructions);

        ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, catchInstructions);

        var handler = new ExceptionHandler(ExceptionHandlerType.Catch)
        {
            CatchType    = ModuleWeaver.ExceptionType,
            TryStart     = methodBodyFirstInstruction,
            TryEnd       = tryCatchLeaveInstructions.Next,
            HandlerStart = catchInstructions.First(),
            HandlerEnd   = catchInstructions.Last().Next
        };

        body.ExceptionHandlers.Add(handler);

        body.InitLocals = true;
        body.OptimizeMacros();
    }
コード例 #3
0
    void ContinueProcessing()
    {
        body = Method.Body;

        body.SimplifyMacros();

        var ilProcessor = body.GetILProcessor();

        var returnFixer = new ReturnFixer
        {
            Method = Method
        };
        returnFixer.MakeLastStatementReturn();

        exceptionVariable = new VariableDefinition(ModuleWeaver.ExceptionType);
        body.Variables.Add(exceptionVariable);
        messageVariable = new VariableDefinition(ModuleWeaver.ModuleDefinition.TypeSystem.String);
        body.Variables.Add(messageVariable);
        paramsArrayVariable = new VariableDefinition(ModuleWeaver.ObjectArray);
        body.Variables.Add(paramsArrayVariable);


        var tryCatchLeaveInstructions = Instruction.Create(OpCodes.Leave, returnFixer.NopBeforeReturn);

        var methodBodyFirstInstruction = GetMethodBodyFirstInstruction();

        var catchInstructions = GetCatchInstructions().ToList();

        ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, tryCatchLeaveInstructions);

        ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, catchInstructions);

        var handler = new ExceptionHandler(ExceptionHandlerType.Catch)
        {
            CatchType = ModuleWeaver.ExceptionType,
            TryStart = methodBodyFirstInstruction,
            TryEnd = tryCatchLeaveInstructions.Next,
            HandlerStart = catchInstructions.First(),
            HandlerEnd = catchInstructions.Last().Next
        };

        body.ExceptionHandlers.Add(handler);

        body.InitLocals = true;
        body.OptimizeMacros();
    }
コード例 #4
0
        void ContinueProcessing()
        {
            body = Method.Body;

            body.SimplifyMacros();

            var ilProcessor = body.GetILProcessor();

            var returnFixer = new ReturnFixer
            {
                Method = Method
            };

            returnFixer.MakeLastStatementReturn();

            var tryBlockLeaveInstructions   = Instruction.Create(OpCodes.Leave, returnFixer.NopBeforeReturn);
            var catchBlockLeaveInstructions = Instruction.Create(OpCodes.Leave, returnFixer.NopBeforeReturn);

            var methodBodyFirstInstruction = GetMethodBodyFirstInstruction();

            var catchBlockInstructions = GetCatchInstructions(catchBlockLeaveInstructions).ToList();

            ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, tryBlockLeaveInstructions);

            ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, catchBlockInstructions);

            var handler = new ExceptionHandler(ExceptionHandlerType.Catch)
            {
                CatchType    = ModuleWeaver.ExceptionType,
                TryStart     = methodBodyFirstInstruction,
                TryEnd       = tryBlockLeaveInstructions.Next,
                HandlerStart = catchBlockInstructions.First(),
                HandlerEnd   = catchBlockInstructions.Last().Next
            };

            body.ExceptionHandlers.Add(handler);

            body.InitLocals = true;
            body.OptimizeMacros();
        }
コード例 #5
0
    private void Inject()
    {
        body = Method.Body;

        body.SimplifyMacros();

        var ilProcessor = body.GetILProcessor();

        var returnFixer = new ReturnFixer
        {
            Method = Method
        };

        returnFixer.MakeLastStatementReturn();

        var methodBodyFirstInstruction = GetMethodBodyFirstInstruction();

        var startInstructions = new List <Instruction>();

        startInstructions.AddRange(GetStartInstructions());

        foreach (var instruction in startInstructions)
        {
            ilProcessor.InsertBefore(methodBodyFirstInstruction, instruction);
        }

        var paramInstructions = GetParamInstructions();

        paramInstructions.Reverse();

        if (paramInstructions.Any())
        {
            foreach (var instruction in paramInstructions)
            {
                ilProcessor.InsertAfter(startInstructions.Last(), instruction);
            }
        }

        ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, GetReturnValueInstructions(returnFixer.ReturnVariable));

        var tryCatchLeaveInstructions = Instruction.Create(OpCodes.Leave, returnFixer.NopBeforeReturn);
        var catchInstructions         = new List <Instruction>();

        catchInstructions.AddRange(GetCatchInstructions());
        ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, tryCatchLeaveInstructions);
        ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, catchInstructions);

        var endInstructions = new List <Instruction>();

        endInstructions.AddRange(GetEndInstructions());
        var finallyInstruction = Instruction.Create(OpCodes.Endfinally);

        endInstructions.Add(finallyInstruction);
        endInstructions.Reverse();

        foreach (var instruction in endInstructions)
        {
            ilProcessor.InsertAfter(catchInstructions.Last(), instruction);
        }

        var handler = new ExceptionHandler(ExceptionHandlerType.Catch)
        {
            CatchType    = ExceptionType,
            TryStart     = methodBodyFirstInstruction,
            TryEnd       = tryCatchLeaveInstructions.Next,
            HandlerStart = catchInstructions.First(),
            HandlerEnd   = catchInstructions.Last().Next
        };

        body.ExceptionHandlers.Add(handler);

        handler = new ExceptionHandler(ExceptionHandlerType.Finally)
        {
            TryStart     = methodBodyFirstInstruction,
            TryEnd       = catchInstructions.Last().Next,
            HandlerStart = catchInstructions.Last().Next,
            HandlerEnd   = finallyInstruction.Next
        };

        body.ExceptionHandlers.Add(handler);

        var         instructions         = body.Instructions;
        Instruction doubleDupInstruction = null;

        for (var index = 0; index < instructions.Count; index++)
        {
            var instruction = instructions[index];

            if (instruction.OpCode == OpCodes.Dup && instructions[index + 1].OpCode == OpCodes.Dup)
            {
                doubleDupInstruction = instructions[index + 1];
            }

            if (instruction.OpCode == OpCodes.Pop && doubleDupInstruction != null)
            {
                var extraPopInstruction = instructions[index];
                ilProcessor.Remove(extraPopInstruction);
                ilProcessor.InsertAfter(doubleDupInstruction, extraPopInstruction);
                doubleDupInstruction = null;
            }
        }

        body.InitLocals = true;
        body.OptimizeMacros();
    }
コード例 #6
0
        /// <summary>
        /// Generates stub to receive the CLR call and then call the dynamic language code.
        /// </summary>
        private void EmitClrCallStub(ILGen cg)
        {
            List <ReturnFixer> fixers = new List <ReturnFixer>(0);

            // Create strongly typed return type from the site.
            // This will, among other things, generate tighter code.
            Type[] siteTypes = MakeSiteSignature(_parameterTypes);

            CallSite callSite = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(siteTypes), _invokeBinder);
            Type     siteType = callSite.GetType();

            Type     convertSiteType = null;
            CallSite convertSite     = null;

            if (_returnType != typeof(void))
            {
                convertSite     = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(typeof(object), _returnType), _convertBinder);
                convertSiteType = convertSite.GetType();
            }

            LocalBuilder convertSiteLocal = null;
            FieldInfo    convertTarget    = null;

            if (_returnType != typeof(void))
            {
                // load up the conversion logic on the stack
                convertSiteLocal = cg.DeclareLocal(convertSiteType);
                EmitConstantGet(cg, ConvertSiteIndex, convertSiteType);

                cg.Emit(OpCodes.Dup);
                cg.Emit(OpCodes.Stloc, convertSiteLocal);

                convertTarget = convertSiteType.GetDeclaredField("Target");
                cg.EmitFieldGet(convertTarget);
                cg.Emit(OpCodes.Ldloc, convertSiteLocal);
            }

            // load up the invoke logic on the stack
            LocalBuilder site = cg.DeclareLocal(siteType);

            EmitConstantGet(cg, CallSiteIndex, siteType);
            cg.Emit(OpCodes.Dup);
            cg.Emit(OpCodes.Stloc, site);

            FieldInfo target = siteType.GetDeclaredField("Target");

            cg.EmitFieldGet(target);
            cg.Emit(OpCodes.Ldloc, site);

            EmitConstantGet(cg, TargetIndex, typeof(object));

            for (int i = 0; i < _parameterTypes.Length; i++)
            {
                if (_parameterTypes[i].IsByRef)
                {
                    ReturnFixer rf = ReturnFixer.EmitArgument(cg, i + 1, _parameterTypes[i]);
                    if (rf != null)
                    {
                        fixers.Add(rf);
                    }
                }
                else
                {
                    cg.EmitLoadArg(i + 1);
                }
            }

            // emit the invoke for the call
            cg.EmitCall(target.FieldType, "Invoke");

            // emit the invoke for the convert
            if (_returnType == typeof(void))
            {
                cg.Emit(OpCodes.Pop);
            }
            else
            {
                cg.EmitCall(convertTarget.FieldType, "Invoke");
            }

            // fixup any references
            foreach (ReturnFixer rf in fixers)
            {
                rf.FixReturn(cg);
            }

            cg.Emit(OpCodes.Ret);
        }
コード例 #7
0
        /// <summary>
        /// Generates stub to receive the CLR call and then call the dynamic language code.
        /// </summary>
        private object[] EmitClrCallStub(ILGen cg)
        {
            List <ReturnFixer> fixers = new List <ReturnFixer>(0);

            ArgumentInfo[] args = new ArgumentInfo[_parameters.Length];
            for (int i = 0; i < args.Length; i++)
            {
                args[i] = Expression.PositionalArg(i);
            }
            ConvertBinder convert = _context.CreateConvertBinder(_returnType, true);
            InvokeBinder  action  = _context.CreateInvokeBinder(args);


            // Create strongly typed return type from the site.
            // This will, among other things, generate tighter code.
            Type[] siteTypes = MakeSiteSignature();

            Type     siteType = DynamicSiteHelpers.MakeCallSiteType(siteTypes);
            CallSite callSite = DynamicSiteHelpers.MakeSite(action, siteType);

            Type     convertSiteType = null;
            CallSite convertSite     = null;

            if (_returnType != typeof(void))
            {
                convertSiteType = DynamicSiteHelpers.MakeCallSiteType(typeof(object), _returnType);
                convertSite     = DynamicSiteHelpers.MakeSite(convert, convertSiteType);
            }

            // build up constants array
            object[]  constants = new object[] { TargetPlaceHolder, callSite, convertSite };
            const int TargetIndex = 0, CallSiteIndex = 1, ConvertSiteIndex = 2;

            LocalBuilder convertSiteLocal = null;
            FieldInfo    convertTarget    = null;

            if (_returnType != typeof(void))
            {
                // load up the conversesion logic on the stack
                convertSiteLocal = cg.DeclareLocal(convertSiteType);
                EmitConstantGet(cg, ConvertSiteIndex, convertSiteType);

                cg.Emit(OpCodes.Dup);
                cg.Emit(OpCodes.Stloc, convertSiteLocal);

                convertTarget = convertSiteType.GetField("Target");
                cg.EmitFieldGet(convertTarget);
                cg.Emit(OpCodes.Ldloc, convertSiteLocal);
            }

            // load up the invoke logic on the stack
            LocalBuilder site = cg.DeclareLocal(siteType);

            EmitConstantGet(cg, CallSiteIndex, siteType);
            cg.Emit(OpCodes.Dup);
            cg.Emit(OpCodes.Stloc, site);

            FieldInfo target = siteType.GetField("Target");

            cg.EmitFieldGet(target);
            cg.Emit(OpCodes.Ldloc, site);

            EmitConstantGet(cg, TargetIndex, typeof(object));

            for (int i = 0; i < _parameters.Length; i++)
            {
                if (_parameters[i].ParameterType.IsByRef)
                {
                    ReturnFixer rf = ReturnFixer.EmitArgument(cg, i + 1, _parameters[i].ParameterType);
                    if (rf != null)
                    {
                        fixers.Add(rf);
                    }
                }
                else
                {
                    cg.EmitLoadArg(i + 1);
                }
            }

            // emit the invoke for the call
            cg.EmitCall(target.FieldType, "Invoke");

            // emit the invoke for the convert
            if (_returnType == typeof(void))
            {
                cg.Emit(OpCodes.Pop);
            }
            else
            {
                cg.EmitCall(convertTarget.FieldType, "Invoke");
            }

            // fixup any references
            foreach (ReturnFixer rf in fixers)
            {
                rf.FixReturn(cg);
            }

            cg.Emit(OpCodes.Ret);
            return(constants);
        }
コード例 #8
0
        public static void AddInstructionsInCatchBlock(this MethodBody body, Collection <Instruction> newInstructions, MethodReference methodCall)
        {
            /*
             *
             * body.SimplifyMacros();
             *
             * var instructions = body.Instructions;
             * var oldInstructions = instructions.ToArray();
             *
             * instructions.Clear();
             *
             * var branchOperandReplacements = new Dictionary<Instruction, Instruction>();
             * foreach (var ins in oldInstructions)
             * {
             *  if (ins.OpCode.Code == Code.Ret)
             *  {
             *      instructions.AddRange(newInstructions);
             *      branchOperandReplacements.Add(ins, newInstructions[0]); // all branches should go to our new instruction instead of directly going to ret
             *  }
             *
             *  instructions.Add(ins);
             * }
             *
             * // repair branching to ret instructions, so the branching is made to begining of injected code
             * foreach (var ins in instructions)
             * {
             *  if (ins.OpCode.FlowControl == FlowControl.Branch || ins.OpCode.FlowControl == FlowControl.Cond_Branch)
             *  {
             *      var branchOperand = (Instruction)ins.Operand;
             *
             *      Instruction newBranchOperand;
             *      if (branchOperandReplacements.TryGetValue(branchOperand, out newBranchOperand))
             *      {
             *          ins.Operand = newBranchOperand;
             *      }
             *  }
             * }
             *
             * // instructions.RemoveAt(14);
             * // instructions.Add(body.GetILProcessor().Create(OpCodes.Leave));
             * body.OptimizeMacros();
             *
             */

            /*
             *
             * var il = body.GetILProcessor();
             *
             * var write = il.Create(OpCodes.Call, body.Method.Module.Import(methodCall));
             *
             * // var write = il.Create(OpCodes.Call, body.Method.Module.Import(typeof(Console).GetMethod("WriteLine", new[] { typeof(object) })));
             * var ret = il.Create(OpCodes.Ret);
             * var leave = il.Create(OpCodes.Leave, ret);
             *
             * il.InsertAfter(
             *  body.Instructions.Last(),
             *  write);
             *
             * il.InsertAfter(write, leave);
             * il.InsertAfter(leave, ret);
             *
             * var handler = new ExceptionHandler(ExceptionHandlerType.Catch)
             * {
             *  TryStart = body.Instructions.First(),
             *  TryEnd = write,
             *  HandlerStart = write,
             *  HandlerEnd = ret,
             *  CatchType = body.Method.Module.Import(typeof(Exception)),
             * };
             *
             * body.ExceptionHandlers.Add(handler);
             */

            body.SimplifyMacros();

            var ilProcessor = body.GetILProcessor();

            var returnFixer = new ReturnFixer
            {
                Method = body.Method
            };

            returnFixer.MakeLastStatementReturn();

            // Create a basic Try/Cacth Block
            var tryBlockLeaveInstructions   = Instruction.Create(OpCodes.Leave, returnFixer.NopBeforeReturn);
            var catchBlockLeaveInstructions = Instruction.Create(OpCodes.Leave, returnFixer.NopBeforeReturn);

            // Get the first instruction to surround the Try/Catch Block
            var methodBodyFirstInstruction = GetMethodBodyFirstInstruction(body);

            var catchBlockInstructions = GetCatchInstructions(catchBlockLeaveInstructions, body.Method.Module.Import(methodCall)).ToList();

            ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, tryBlockLeaveInstructions);
            ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, catchBlockInstructions);

            var ExType = Type.GetType("System." + methodCall.Name);

            if (ExType == null)
            {
                ExType = Type.GetType("System.IO." + methodCall.Name);
            }

            var handler = new ExceptionHandler(ExceptionHandlerType.Catch)
            {
                CatchType    = body.Method.Module.Import(ExType),
                TryStart     = methodBodyFirstInstruction,
                TryEnd       = tryBlockLeaveInstructions.Next,
                HandlerStart = catchBlockInstructions.First(),
                HandlerEnd   = catchBlockInstructions.Last().Next
            };

            body.ExceptionHandlers.Add(handler);
        }