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