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(); } }
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(); }
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); }