MakeLastStatementReturn() 공개 정적인 메소드

public static MakeLastStatementReturn ( this method ) : void
method this
리턴 void
예제 #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();
    }
        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();
        }
    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
        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);
        }