private Instruction EmitCodeInit(TypeReference role, Instruction instructionBeforeInit, ILProcessor il) { var current = instructionBeforeInit; current = InsertAfter(il, current, il.Create(OpCodes.Ldarg_0)); current = InsertAfter(il, current, il.Create(OpCodes.Call, ResolveInitReference(role))); return current; }
public void ModifyAssembly(string fileName) { MethodInfo writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }); // ReaderParameters { ReadWrite = true } is necessary to later write the file using (ModuleDefinition module = ModuleDefinition.ReadModule(fileName, new ReaderParameters { ReadWrite = true })) { // Modify the assembly TypeDefinition[] types = module.Types.ToArray(); MethodReference methodReference = module.ImportReference(writeLineMethod); foreach (var type in types) { foreach (MethodDefinition methodToChange in type.Methods) { string sentence = String.Concat("Code added in ", methodToChange.Name); Mono.Cecil.Cil.ILProcessor ilProcessor = methodToChange.Body.GetILProcessor(); Mono.Cecil.Cil.Instruction loadStringInstruction = ilProcessor.Create(OpCodes.Ldstr, sentence); Mono.Cecil.Cil.Instruction callInstruction = ilProcessor.Create(OpCodes.Call, methodReference); Mono.Cecil.Cil.Instruction methodFirstInstruction = methodToChange.Body.Instructions[0]; ilProcessor.InsertBefore(methodFirstInstruction, loadStringInstruction); ilProcessor.InsertAfter(loadStringInstruction, callInstruction); } } module.Write(); // Write to the same file that was used to open the file } }
private void InterceptMethod(ILProcessor processor, TypeReference typeReference, Instruction instruction, string name) { var typeDefinition = typeReference.Resolve(); var attributeConstructor = typeDefinition.Methods.First(x => x.Name == ".ctor"); var attributeMethod = typeDefinition.Methods.First(x => x.Name == name); processor.InsertBefore(instruction, processor.Create(OpCodes.Newobj, attributeConstructor)); processor.InsertBefore(instruction, processor.Create(OpCodes.Call, _getCurrentMethod)); processor.InsertBefore(instruction, processor.Create(OpCodes.Call, attributeMethod)); }
private Instruction EmitStateClassCreation(TypeReference role, Instruction instructionBeforeCreation, ILProcessor il) { var current = instructionBeforeCreation; var stateClassFieldReference = ResolveStateClassField(role); // don't emit this code if the state field and property was not implemented // TODO: this needs to be checked before, possibly at the conflict resolution stage if (stateClassFieldReference != null) { current = InsertAfter(il, current, il.Create(OpCodes.Ldarg_0)); current = InsertAfter(il, current, il.Create(OpCodes.Newobj, role.ResolveStateClassCtor())); current = InsertAfter(il, current, il.Create(OpCodes.Stfld, stateClassFieldReference)); } return current; }
private void ProcessCachedStaticFieldPattern(ILProcessor il, Instruction queryInvocation) { MethodReference predicateMethod = GetMethodReferenceFromStaticFieldPattern(queryInvocation); il.InsertBefore(queryInvocation, il.Create(OpCodes.Ldtoken, predicateMethod)); // At this point the stack is like this: // runtime method handle, delegate reference, ObjectContainer il.Replace(queryInvocation, il.Create(OpCodes.Call, InstantiateGenericMethod( _NativeQueryHandler_ExecuteInstrumentedStaticDelegateQuery, GetQueryCallExtent(queryInvocation)))); }
public void ModifyCallScope(MethodDefinition renamedMethod, MethodDefinition interceptorMethod, ILProcessor il, MethodInterceptionScopeType interceptionScope) { if (interceptionScope == MethodInterceptionScopeType.Deep) { foreach (var module in Type.Assembly.Definition.Modules) { foreach (var type in module.Types.ToList()) { if (type.Methods == null || type.Methods.Count == 0) continue; foreach (var method in type.Methods.ToList()) { if (Context.Marker.HasMarker(method, Method.MethodMarker)) continue; if (method == null || method.Body == null || method.Body.Instructions == null || method.Body.Instructions.Count() == 0) continue; foreach (var instruction in method.Body.Instructions.ToList()) { if (instruction.OpCode == OpCodes.Call && instruction.Operand == renamedMethod) { var processor = method.Body.GetILProcessor(); processor.InsertAfter(instruction, il.Create(OpCodes.Call, interceptorMethod)); processor.Remove(instruction); } } } } } } }
private Instruction AddConditionGoto(ILProcessor ilp, Instruction last, Instruction stateMachineStarting) { var shouldRunSynchronouslyMethod = _engine.GetMethod<Func<ActorCore, bool>> (a => a.ShouldRunSynchronously ()); var loadThis = ilp.Create (OpCodes.Ldarg_0); var loadField = ilp.Create (OpCodes.Ldfld, _actorMixin); var callMethod = ilp.Create (OpCodes.Call, shouldRunSynchronouslyMethod); var gotoNext = ilp.Create (OpCodes.Brtrue_S, stateMachineStarting); ilp.InsertAfter (last, loadThis); ilp.InsertAfter (loadThis, loadField); ilp.InsertAfter (loadField, callMethod); ilp.InsertAfter (callMethod, gotoNext); return gotoNext; }
private void ProcessPredicateCreationPattern(ILProcessor il, Instruction queryInvocation) { MethodReference predicateMethod = GetMethodReferenceFromInlinePredicatePattern(queryInvocation); Instruction ldftn = GetNthPrevious(queryInvocation, 2); il.InsertBefore(ldftn, il.Create(OpCodes.Dup)); il.InsertBefore(queryInvocation, il.Create(OpCodes.Ldtoken, predicateMethod)); // At this point the stack is like this: // runtime method handle, delegate reference, target object, ObjectContainer il.Replace(queryInvocation, il.Create(OpCodes.Call, InstantiateGenericMethod( _NativeQueryHandler_ExecuteInstrumentedDelegateQuery, GetQueryCallExtent(queryInvocation)))); }
public MethodBodyPatcher(string methodName, MethodDefinition method) { _methodName = methodName; _methodBody = method.Body; _processor = _methodBody.GetILProcessor(); _realBodyStart = _methodBody.Instructions.First(); _realBodyEnd = _methodBody.Instructions.Last(); _markStart1BeforeCreateArgumentsArray = _processor.Create(OpCodes.Nop); _markStart2BeforeCreateMethodExecutionArgs = _processor.Create(OpCodes.Nop); _markStart3BeforeOnEntryCall = _processor.Create(OpCodes.Nop); _markStart4BeforeRealBodyStartExceptionHandler = _processor.Create(OpCodes.Nop); _markEnd1NewRealBodyEnd = _processor.Create(OpCodes.Nop); _markEnd2BeforeOnExitCall = _processor.Create(OpCodes.Nop); _markRetNew = EndsWithThrow ? _processor.Create(OpCodes.Throw) : _processor.Create(OpCodes.Ret); }
protected override void ImplementProceed(MethodDefinition methodInfo, MethodBody methodBody, ILProcessor il, FieldReference methodInfoField, MethodReference proceed, Action<ILProcessor> emitProceedTarget, MethodReference proceedTargetMethod, OpCode proceedOpCode) { // If T is an interface, then we want to check if target is null; if so, we want to just return the default value var targetNotNull = il.Create(OpCodes.Nop); EmitProxyFromProceed(il); il.Emit(OpCodes.Ldfld, ClassWeaver.Target); // Load "target" from "this" il.Emit(OpCodes.Brtrue, targetNotNull); // If target is not null, jump below CecilExtensions.CreateDefaultMethodImplementation(methodBody.Method, il); il.Append(targetNotNull); // Mark where the previous branch instruction should jump to base.ImplementProceed(methodInfo, methodBody, il, methodInfoField, proceed, emitProceedTarget, proceedTargetMethod, proceedOpCode); }
public static Instruction ParseInstruction(ILProcessor processor, TypeDefinition type, XElement instrXML) { string fieldName = instrXML.Attribute("Field").Value; FieldDefinition field = type.Fields.FirstOrDefault(f => f.Name == fieldName); if (field == null) { Console.WriteLine("Couldn't find field named " + fieldName); return null; } return processor.Create(OpCodes.Ldfld, field); }
/// <summary> /// Emits the instructions that call <see cref="IInitialize.Initialize"/> on a given service instance. /// </summary> /// <param name="il"></param> /// <param name="module">The host module.</param> /// <param name="serviceInstance">The local variable that points to the current service instance.</param> public void Initialize(ILProcessor il, ModuleDefinition module, VariableDefinition serviceInstance) { var body = il.Body; var method = body.Method; var declaringType = method.DeclaringType; var targetField = GetTargetField(declaringType); if (targetField == null) return; var initializeType = module.ImportType<IInitialize>(); il.Emit(OpCodes.Ldloc, serviceInstance); il.Emit(OpCodes.Isinst, initializeType); var initializeMethod = module.ImportMethod<IInitialize>("Initialize"); var skipInitializationCall = il.Create(OpCodes.Nop); il.Emit(OpCodes.Brfalse, skipInitializationCall); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetField); GetServiceHash(il, module, serviceInstance); var containsMethod = module.ImportMethod<Dictionary<int, int>>("ContainsKey"); il.Emit(OpCodes.Callvirt, containsMethod); il.Emit(OpCodes.Brtrue, skipInitializationCall); // if (!__initializedServices.ContainsKey(currentService.GetHashCode()) { il.Emit(OpCodes.Ldloc, serviceInstance); il.Emit(OpCodes.Isinst, initializeType); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Callvirt, initializeMethod); // __initializedServices.Add(hashCode, 0); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetField); GetServiceHash(il, module, serviceInstance); il.Emit(OpCodes.Ldc_I4_1); var addMethod = module.ImportMethod<Dictionary<int, int>>("Add"); il.Emit(OpCodes.Callvirt, addMethod); il.Append(skipInitializationCall); }
public static Instruction ParseInstruction(ILProcessor processor, TypeDefinition type, XElement instrXML) { string assemblyName = instrXML.Attribute("Assembly").Value; string typeName = instrXML.Attribute("Type").Value; string methodName = instrXML.Attribute("Method").Value; // Get Assembly AssemblyDefinition assembly = Program.GetAssembly(assemblyName); if (assembly == null) return null; // Get Type TypeDefinition typeDefinition = assembly.MainModule.GetType(typeName); // Get Method MethodDefinition methodDefinition = typeDefinition.Methods.Single(m => m.Name == methodName); MethodReference methodReference = Program.GetAssembly("Assembly-CSharp").MainModule.Import(methodDefinition); // Generic Parameter Check if (instrXML.HasElements) { List<TypeReference> genericParameters = new List<TypeReference>(); foreach (XElement genericParameter in instrXML.Elements("GenericParameter")) { var gPAssemblyName = genericParameter.Attribute("Assembly").Value; var gPType = genericParameter.Attribute("Type").Value; AssemblyDefinition gPAssembly = Program.GetAssembly(gPAssemblyName); TypeDefinition gPTypeDefinition = gPAssembly.MainModule.GetType(gPType); TypeReference gPTypeReference = Program.GetAssembly("Assembly-CSharp").MainModule.Import(gPTypeDefinition); genericParameters.Add(gPTypeReference); } methodReference = methodReference.MakeGeneric(genericParameters.ToArray()); } // Return Instruction return processor.Create(OpCodes.Call, methodReference); }
protected override void ImplementProceed(MethodDefinition methodInfo, MethodBody methodBody, ILProcessor il, FieldReference methodInfoField, MethodReference proceed, Action<ILProcessor> emitProceedTarget, MethodReference proceedTargetMethod, OpCode proceedOpCode) { if (methodInfo.IsAbstract) { CecilExtensions.CreateDefaultMethodImplementation(methodInfo, il); } else { var targetNotNull = il.Create(OpCodes.Nop); EmitProxyFromProceed(il); il.Emit(OpCodes.Ldfld, target); // Load "target" from "this" il.Emit(OpCodes.Brtrue, targetNotNull); // If target is not null, jump below base.ImplementProceed(methodInfo, methodBody, il, methodInfoField, proceed, _ => EmitProxyFromProceed(il), callBaseMethod, OpCodes.Call); il.Append(targetNotNull); // Mark where the previous branch instruction should jump to base.ImplementProceed(methodInfo, methodBody, il, methodInfoField, proceed, emitProceedTarget, proceedTargetMethod, proceedOpCode); } }
public static int ToNop(ILProcessor ilp, Instruction ins, bool sameSize) { if (ins == null) return 0; int size = ins.GetSize(); ins.OpCode = OpCodes.Nop; ins.Operand = null; if (sameSize) { for (int i = 1; i < size; i++) { Instruction newIns = ilp.Create(OpCodes.Nop); ilp.InsertAfter(ins, newIns); } } else { size = 1; } return size; }
public static void GetMethod(Instruction i, ILProcessor proc, ModuleDefinition baseModule) { if (i.Operand is FieldReference && ((FieldReference)i.Operand).FullName.Contains("Monocle.Sprite`1<System.Int32> TowerFall.AwardInfo/<>c__DisplayClass") && ((FieldReference)i.Operand).FullName.Contains("::sprite")) { Stored = Instruction.Create(OpCodes.Ldfld, i.Operand as FieldReference); } if (i.OpCode == OpCodes.Callvirt && i.Next.OpCode != OpCodes.Br_S && ((MethodReference)i.Operand).FullName == "System.Void Monocle.Sprite`1<System.Int32>::Add(T,System.Int32)") { TypeDefinition graphicsComponent = baseModule.GetType("Monocle.GraphicsComponent"); var fieldReference = graphicsComponent.Fields.Single(f => f.Name == "Zoom"); var instr = Instruction.Create(OpCodes.Stfld, fieldReference); var ldinstr = Instruction.Create(i.Next.OpCode); proc.InsertAfter(i, instr); proc.InsertAfter(i, proc.Create(OpCodes.Ldc_R4, (float)0.7)); proc.InsertAfter(i, Stored); proc.InsertAfter(i, ldinstr); } }
public Instruction ParseInstruction(ILProcessor processor, TypeDefinition type, XmlNode instrXml) { Instruction instr = null; string nameOpCode = instrXml.Attributes["OpCode"].Value; if (nameOpCode == "Call") { string assemblyName = instrXml.Attributes["Assembly"].Value; string classToAddName = instrXml.Attributes["Class"].Value; string methodToAddName = instrXml.Attributes["Method"].Value; ModuleDefinition module = null; // We search in which assembly should we pull the method if (assemblyName == "CSharp-Assembly") { module = this.CSharpAssembly.MainModule; } else if (assemblyName == "PhiScript") { module = this.PhiAssembly.MainModule; } else { // Error handling Console.WriteLine("Couldn't find assembly named " + assemblyName); return null; } TypeDefinition typeToAdd = module.Types.FirstOrDefault(t => t.Name == classToAddName); if (typeToAdd == null) { Console.WriteLine("Couldn't find type/class named " + classToAddName); return null; } MethodDefinition methodToAdd = typeToAdd.Methods.FirstOrDefault(m => m.Name == methodToAddName); if (methodToAdd == null) { Console.WriteLine("Couldn't find method named " + methodToAddName); return null; } MethodReference methodToAddImported = this.CSharpAssembly.MainModule.Import(methodToAdd); instr = processor.Create(OpCodes.Call, methodToAddImported); } else if (nameOpCode == "Ldc.I4") { int value = Int32.Parse(instrXml.Attributes["Value"].Value); instr = processor.Create(OpCodes.Ldc_I4, value); } else if (nameOpCode == "Ldfld") { string fieldName = instrXml.Attributes["Field"].Value; FieldDefinition field = type.Fields.FirstOrDefault(f => f.Name == fieldName); if (field == null) { Console.WriteLine("Couldn't find field named " + field); } instr = processor.Create(OpCodes.Ldfld, field); } else if (nameOpCode == "Ldarg_0") { instr = processor.Create(OpCodes.Ldarg_0); } else { Console.WriteLine("Couldn't find OpCode named " + nameOpCode); } return instr; }
static int EmitParameters(MethodDefinition method, MethodDefinition native, MethodBody body, ILProcessor il) { int i; for (i = 0; i < method.Parameters.Count; i++) { var parameter = method.Parameters[i]; var p = method.Module.Import(method.Parameters[i].ParameterType); il.Emit(OpCodes.Ldarg, i); if (p.Name.Contains("Int32") && native.Parameters[i].ParameterType.Name.Contains("IntPtr")) { // This is a convenience Int32 overload for an IntPtr (size_t) parameter. // We need to convert the loaded argument to IntPtr. il.Emit(OpCodes.Conv_I); } else if (p.Name == "StringBuilder") { EmitStringBuilderParameter(method, parameter, body, il); } else if (p.Name == "String" && !p.IsArray) { EmitStringParameter(method, parameter, body, il); } else if (p.IsByReference) { body.Variables.Add(new VariableDefinition(new PinnedType(p))); var index = body.Variables.Count - 1; il.Emit(OpCodes.Stloc, index); il.Emit(OpCodes.Ldloc, index); il.Emit(OpCodes.Conv_I); } else if (p.IsArray) { if (p.Name != method.Module.Import(typeof(string[])).Name) { // .Net treats 1d arrays differently than higher rank arrays. // 1d arrays are directly supported by instructions such as ldlen and ldelema. // Higher rank arrays must be accessed through System.Array methods such as get_Length. // 1d array: // check array is not null // check ldlen array > 0 // ldc.i4.0 // ldelema // 2d array: // check array is not null // check array.get_Length() > 0 // ldc.i4.0 // ldc.i4.0 // call instance T& T[0..., 0...]::Address(int32, int32) // Mono treats everything as a 1d array. // Interestingly, the .Net approach works on both Mono and .Net. // The Mono approach fails when using high-rank arrays on .Net. // We should report a bug to http://bugzilla.xamarin.com // Pin the array and pass the address // of its first element. var array = (ArrayType)p; var element_type = p.GetElementType(); body.Variables.Add(new VariableDefinition(new PinnedType(new ByReferenceType(element_type)))); int pinned_index = body.Variables.Count - 1; var empty = il.Create(OpCodes.Ldc_I4, 0); var pin = il.Create(OpCodes.Ldarg, i); var end = il.Create(OpCodes.Stloc, pinned_index); // if (array == null) goto empty il.Emit(OpCodes.Brfalse, empty); // else if (array.Length != 0) goto pin il.Emit(OpCodes.Ldarg, i); if (array.Rank == 1) { il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); } else { var get_length = method.Module.Import( mscorlib.MainModule.GetType("System.Array").Methods.First(m => m.Name == "get_Length")); il.Emit(OpCodes.Callvirt, get_length); } il.Emit(OpCodes.Brtrue, pin); // empty: IntPtr ptr = IntPtr.Zero il.Append(empty); il.Emit(OpCodes.Conv_U); il.Emit(OpCodes.Br, end); // pin: &array[0] il.Append(pin); if (array.Rank == 1) { // 1d array (vector), address is taken by ldelema il.Emit(OpCodes.Ldc_I4, 0); il.Emit(OpCodes.Ldelema, element_type); } else { // 2d-3d array, address must be taken as follows: // call instance T& T[0..., 0..., 0...]::Address(int, int, int) ByReferenceType t_ref = array.ElementType.MakeByReferenceType(); MethodReference get_address = new MethodReference("Address", t_ref, array); for (int r = 0; r < array.Rank; r++) { get_address.Parameters.Add(new ParameterDefinition(TypeInt32)); } get_address.HasThis = true; // emit the get_address call for (int r = 0; r < array.Rank; r++) { il.Emit(OpCodes.Ldc_I4, 0); } il.Emit(OpCodes.Call, get_address); } // end: fixed (IntPtr ptr = &array[0]) il.Append(end); il.Emit(OpCodes.Ldloc, pinned_index); il.Emit(OpCodes.Conv_I); } else { EmitStringArrayParameter(method, parameter, body, il); } } } return i; }
private int TrackMethodExit(MethodDefinition method, MethodReference target, XNodeOut node, ILProcessor processor, int pos) { // really annoying, we need to box value type that are returned by the target method to pass to xray exit method // if the return type is generic msil returns something like !0, but we can't box !0, we have to resolve it from the function declaration // hence all the code below var resolved = ResolveGenericMethod(target); var returnType = resolved.ReturnType; if (Build.TrackReturnValue && returnType.FullName != VoidRef.FullName) { // this is key, duplicate the head of the stack, and we'll pass this to the xray method exit function to be recorded AddInstruction(method, ++pos, processor.Create(OpCodes.Dup)); // if it's a value type or generic param then box because method exit takes an object as a param if (returnType.IsValueType || returnType.IsGenericParameter) AddInstruction(method, ++pos, processor.Create(OpCodes.Box, returnType)); AddInstruction(method, ++pos, processor.Create(OpCodes.Ldc_I4, node.ID)); // push id AddInstruction(method, ++pos, processor.Create(OpCodes.Call, MethodExitWithValueRef)); // call exit with object and id } // else not tracking return value else { AddInstruction(method, ++pos, processor.Create(OpCodes.Ldc_I4, node.ID)); AddInstruction(method, ++pos, processor.Create(OpCodes.Call, MethodExitRef)); } return pos; }
private void TrackMethodEnterParams(MethodDefinition method, int nodeId, ILProcessor processor, bool hasThis) { // add local variable for parameter array that gets passed to method enter method.Body.Variables.Add(new VariableDefinition(ObjectArrayRef)); int varPos = method.Body.Variables.Count - 1; int pos = 0; int firstArg = 0; int paramCount = method.Parameters.Count; int paramPos = 0; if (hasThis) { firstArg = 1; paramCount--; } // create new object array with the same number of elements as there are arguments in function AddInstruction(method, pos++, processor.Create(OpCodes.Ldc_I4, paramCount)); AddInstruction(method, pos++, processor.Create(OpCodes.Newarr, ObjectRef)); // store array in local variable AddInstruction(method, pos++, processor.Create(OpCodes.Stloc, varPos)); // why doesnt cecil optimize this call? for (int i = firstArg; i < method.Parameters.Count; i++, paramPos++) { var paramType = method.Parameters[i].ParameterType; var argOffset = method.IsStatic ? 0 : 1; // put array, index, and arg on stack and push AddInstruction(method, pos++, processor.Create(OpCodes.Ldloc, varPos)); AddInstruction(method, pos++, processor.Create(OpCodes.Ldc_I4, paramPos)); AddInstruction(method, pos++, processor.Create(OpCodes.Ldarg, i + argOffset)); // index 0 is this, though for static may not be bool box = (paramType.IsValueType || paramType.IsGenericParameter); TypeReference boxType = paramType; // if reference type if (paramType is ByReferenceType) { var refType = paramType as ByReferenceType; // load value of what ref address on stack is pointing to AddInstruction(method, pos++, processor.Create(OpCodes.Ldobj, refType.ElementType)); // if element type is value type, or generic (possible??? test this case) then box box = (refType.ElementType.IsValueType || refType.ElementType.IsGenericParameter); boxType = refType.ElementType; } // box value or generic types if (box) AddInstruction(method, pos++, processor.Create(OpCodes.Box, boxType)); // set element AddInstruction(method, pos++, processor.Create(OpCodes.Stelem_Ref)); } // put object[], and node id on stack, and call MethodEnterWithParams AddInstruction(method, pos++, processor.Create(OpCodes.Ldloc, varPos)); AddInstruction(method, pos++, processor.Create(OpCodes.Ldc_I4, nodeId)); AddInstruction(method, pos++, processor.Create(OpCodes.Call, MethodEnterWithParamsRef)); }
private IEnumerable<Instruction> GetAttributeInstanceInstructions( ILProcessor processor, ICustomAttribute attribute, MethodDefinition method, VariableDefinition attributeVariableDefinition, VariableDefinition methodVariableDefinition) { var getMethodFromHandleRef = this._referenceFinder.GetMethodReference(typeof(MethodBase), md => md.Name == "GetMethodFromHandle" && md.Parameters.Count == 2); var getTypeof = this._referenceFinder.GetMethodReference(typeof(Type), md => md.Name == "GetTypeFromHandle"); var ctor = this._referenceFinder.GetMethodReference(typeof(Activator), md => md.Name == "CreateInstance" && md.Parameters.Count == 1); /* // Code size 23 (0x17) .maxstack 1 .locals init ([0] class SimpleTest.IntersectMethodsMarkedByAttribute i) IL_0000: nop IL_0001: ldtoken SimpleTest.IntersectMethodsMarkedByAttribute IL_0006: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) IL_000b: call object [mscorlib]System.Activator::CreateInstance(class [mscorlib]System.Type) IL_0010: castclass SimpleTest.IntersectMethodsMarkedByAttribute IL_0015: stloc.0 IL_0016: ret */ return new List<Instruction> { processor.Create(OpCodes.Nop), processor.Create(OpCodes.Ldtoken, method), processor.Create(OpCodes.Ldtoken, method.DeclaringType), processor.Create(OpCodes.Call, getMethodFromHandleRef), // Push method onto the stack, GetMethodFromHandle, result on stack processor.Create(OpCodes.Stloc_S, methodVariableDefinition), // Store method in __fody$method processor.Create(OpCodes.Nop), processor.Create(OpCodes.Ldtoken, attribute.AttributeType), processor.Create(OpCodes.Call,getTypeof), processor.Create(OpCodes.Call,ctor), processor.Create(OpCodes.Castclass, attribute.AttributeType), processor.Create(OpCodes.Stloc_S, attributeVariableDefinition), /* * processor.Create(OpCodes.Ldloc_S, methodVariableDefinition), processor.Create(OpCodes.Ldtoken, attribute.AttributeType), processor.Create(OpCodes.Call, getTypeFromHandleRef), // Push method + attribute onto the stack, GetTypeFromHandle, result on stack processor.Create(OpCodes.Ldc_I4_0), processor.Create(OpCodes.Callvirt, getCustomAttributesRef), // Push false onto the stack (result still on stack), GetCustomAttributes processor.Create(OpCodes.Ldc_I4_0), processor.Create(OpCodes.Ldelem_Ref), // Get 0th index from result processor.Create(OpCodes.Castclass, attribute.AttributeType), processor.Create(OpCodes.Stloc_S, attributeVariableDefinition) // Cast to attribute stor in __fody$attribute */ }; }
private static IList<Instruction> GetTryCatchLeaveInstructions(ILProcessor processor, Instruction methodBodyReturnInstruction) { return new[] { processor.Create(OpCodes.Leave_S, methodBodyReturnInstruction) }; }
private static IEnumerable<Instruction> GetTaskContinuationInstructions(ILProcessor processor, VariableDefinition retvalVariableDefinition, VariableDefinition attributeVariableDefinition, MethodReference taskContinuationMethodReference) { if (retvalVariableDefinition != null) { var tr = retvalVariableDefinition.VariableType; if (tr.FullName.Contains("System.Threading.Tasks.Task")) return new[] { processor.Create(OpCodes.Ldloc_S, attributeVariableDefinition), processor.Create(OpCodes.Ldloc_S, retvalVariableDefinition), processor.Create(OpCodes.Callvirt, taskContinuationMethodReference), }; } return new Instruction[0]; }
private static IList<Instruction> GetSaveRetvalInstructions(ILProcessor processor, VariableDefinition retvalVariableDefinition) { return retvalVariableDefinition == null || processor.Body.Instructions.All(i => i.OpCode != OpCodes.Ret) ? new Instruction[0] : new[] { processor.Create(OpCodes.Stloc_S, retvalVariableDefinition) }; }
private static IList<Instruction> GetMethodBodyReturnInstructions(ILProcessor processor, VariableDefinition retvalVariableDefinition) { var instructions = new List<Instruction>(); if (retvalVariableDefinition != null) instructions.Add(processor.Create(OpCodes.Ldloc_S, retvalVariableDefinition)); instructions.Add(processor.Create(OpCodes.Ret)); return instructions; }
private static List<Instruction> GetCatchHandlerInstructions(ILProcessor processor, VariableDefinition attributeVariableDefinition, VariableDefinition exceptionVariableDefinition, MethodReference onExceptionMethodRef) { // Store the exception in __fody$exception // Call __fody$attribute.OnExcetion("{methodName}", __fody$exception) // rethrow return new List<Instruction> { processor.Create(OpCodes.Stloc_S, exceptionVariableDefinition), processor.Create(OpCodes.Ldloc_S, attributeVariableDefinition), processor.Create(OpCodes.Ldloc_S, exceptionVariableDefinition), processor.Create(OpCodes.Callvirt, onExceptionMethodRef), processor.Create(OpCodes.Rethrow) }; }
private static void Emit(ILProcessor ip, ModuleDefinition mod, VariableDefinition arrayVar, VariableDefinition indexVar, Dictionary<int, Instruction> braces, OpValue[] ops, int i) { OpValue op = ops[i]; switch (op.OpCode) { case BFOpCode.Increment: ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldelem_I4); ip.Emit(OpCodes.Ldc_I4, op.Data); ip.Emit(OpCodes.Add); ip.Emit(OpCodes.Stelem_I4); break; case BFOpCode.Decrement: ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldelem_I4); ip.Emit(OpCodes.Ldc_I4, op.Data); ip.Emit(OpCodes.Sub); ip.Emit(OpCodes.Stelem_I4); break; case BFOpCode.ShiftRight: ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldc_I4, op.Data); ip.Emit(OpCodes.Add); ip.Emit(OpCodes.Stloc, indexVar); break; case BFOpCode.ShiftLeft: ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldc_I4, op.Data); ip.Emit(OpCodes.Sub); ip.Emit(OpCodes.Stloc, indexVar); break; case BFOpCode.Output: ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldelem_I4); ip.Emit(OpCodes.Conv_I1); ip.Emit(OpCodes.Call, mod.Import(typeof(Console).GetMethod("Write", new[] { typeof(char) }))); break; case BFOpCode.Input: ip.Emit(OpCodes.Call, mod.Import(typeof(Console).GetMethod("Read", new Type[0]))); ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldelem_I4); ip.Emit(OpCodes.Conv_I1); break; case BFOpCode.CondLeft: var leftB = ip.Create(OpCodes.Ldloc, arrayVar); var rightB = ip.Create(OpCodes.Nop); ip.Append(leftB); braces[i] = leftB; braces[op.Data] = rightB; ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldelem_I4); ip.Emit(OpCodes.Brfalse, rightB); ip.Emit(OpCodes.Nop); break; case BFOpCode.CondRight: ip.Emit(OpCodes.Br, braces[op.Data]); ip.Append(braces[i]); break; case BFOpCode.Assign: ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldc_I4, op.Data); ip.Emit(OpCodes.Stelem_I4); break; } }
/// <summary> /// Emits the instructions that will instantiate each property value and assign it to the target property. /// </summary> /// <param name="serviceMap">The service map that contains the application dependencies.</param> /// <param name="targetMethod">The target method.</param> /// <param name="module">The module that hosts the container type.</param> /// <param name="il">The <see cref="ILProcessor"/> that points to the target method body.</param> /// <param name="property">The target property.</param> /// <param name="curentDependency">The <see cref="IDependency"/> that describes the service instance that will be assigned to the target property.</param> private static void EmitPropertySetter(IDictionary<IDependency, IImplementation> serviceMap, MethodDefinition targetMethod, ModuleDefinition module, ILProcessor il, PropertyInfo property, IDependency curentDependency) { // Push the target onto the stack il.Emit(OpCodes.Dup); // Get the code that will instantiate the property value var propertyValueImplementation = serviceMap[curentDependency]; propertyValueImplementation.Emit(curentDependency, serviceMap, targetMethod); // Call the setter var setterMethod = property.GetSetMethod(); var setter = module.Import(setterMethod); var callInstruction = setterMethod.IsVirtual ? il.Create(OpCodes.Callvirt, setter) : il.Create(OpCodes.Call, setter); il.Append(callInstruction); }
private static IEnumerable<Instruction> GetCallOnEntryInstructions( ILProcessor processor, VariableDefinition attributeVariableDefinition, MethodReference onEntryMethodRef) { // Call __fody$attribute.OnEntry() return new List<Instruction> { processor.Create(OpCodes.Ldloc, attributeVariableDefinition), processor.Create(OpCodes.Callvirt, onEntryMethodRef), }; }
public static Instruction ParseInstruction(ILProcessor processor, TypeDefinition type, XElement instrXML) { int value = int.Parse(instrXML.Attribute("Value").Value); return processor.Create(OpCodes.Ldloc_S, processor.Body.Variables[value]); }
private static IList<Instruction> GetCallOnExitInstructions(ILProcessor processor, VariableDefinition attributeVariableDefinition, MethodReference onExitMethodRef) { // Call __fody$attribute.OnExit() return new List<Instruction> { processor.Create(OpCodes.Ldloc_S, attributeVariableDefinition), //processor.Create(OpCodes.Ldarg_0), processor.Create(OpCodes.Callvirt, onExitMethodRef) }; }