/// <summary> /// Aspect method to use for method call substition /// </summary> /// <param name="typeBuilder"></param> /// <param name="il"></param> /// <param name="method"></param> /// <param name="replaceMethod">Replace Method</param> /// <returns></returns> internal bool MethodCall(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.Cil.ILProcessor il, Mono.Cecil.MethodDefinition method, Mono.Cecil.MethodDefinition replaceMethod) { if (!replaceMethod.IsStatic) { return(false); } var attrs = method.GetCustomAttributes <StaticMethodReplacerAttribute>(); MethodInfo meth = null; foreach (var attr in attrs) { var staticType = attr.staticMethodType; var smeth = staticType.GetMethod(replaceMethod.Name, BindingFlags.Static | BindingFlags.Public); if (smeth != null) { meth = smeth; } } if (meth == null) { return(false); } il.Emit(Mono.Cecil.Cil.OpCodes.Call, meth); return(true); }
public CodegenEmitter( Mono.Cecil.Cil.ILProcessor processor, RegisterAllocation <CilCodegenRegister> registerAllocation) { this.Processor = processor; this.RegisterAllocation = registerAllocation; this.branchTargets = new Dictionary <BasicBlockTag, CilInstruction>(); this.pendingTargets = new List <BasicBlockTag>(); this.patches = new List <CilOpInstruction>(); this.registerUseCounters = new Dictionary <Mono.Cecil.Cil.VariableDefinition, int>(); }
public BytecodeTranslator(AnalysisNet.Types.MethodDefinition methodDefinition, IDictionary <AnalysisNetTac.Values.IVariable, Cecil.Cil.VariableDefinition> variableDefinitions, IDictionary <AnalysisNetTac.Values.IVariable, Cecil.ParameterDefinition> parameterDefinitions, ReferenceGenerator referenceGenerator, Cecil.Cil.ILProcessor processor) { this.methodDefinition = methodDefinition; this.processor = processor; this.variableDefinitions = variableDefinitions; this.parameterDefinitions = parameterDefinitions; this.referenceGenerator = referenceGenerator; }
/// <summary> /// Weave field into current aspect /// </summary> /// <param name="il">IL Generator</param> /// <param name="field">Field</param> /// <param name="fieldMethod">Field Method</param> private void BlockField(Mono.Cecil.Cil.ILProcessor il, Mono.Cecil.FieldDefinition field, MethodInfo fieldMethod) { var fieldName = field.Name; // Return if it is a backing field if (fieldName.IndexOf("k__BackingField") >= 0) { return; } var aspect = field.GetCustomAttribute <MemberInterceptionAspect>() ?? field.DeclaringType.GetCustomAttribute <MemberInterceptionAspect>() ?? field.DeclaringType.Module.Assembly.GetCustomAttribute <MemberInterceptionAspect>(); if (!ILWeaver.IsValidAspectFor(field, aspect)) { return; } var fieldType = field.FieldType; var isStatic = field.IsStatic; var fieldLocal = il.DeclareLocal(fieldType); var memberLocal = il.DeclareLocal(typeof(MemberContext)); var aspectField = ILWeaver.TypeFieldAspects[field.DeclaringType.FullName][aspect.GetType().FullName]; // Store current get field value il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, fieldLocal); // MemberContext(object instance, string locationName, object value) il.Emit(isStatic ? Mono.Cecil.Cil.OpCodes.Ldnull : Mono.Cecil.Cil.OpCodes.Ldarg_0); il.Emit(Mono.Cecil.Cil.OpCodes.Ldstr, fieldName); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, fieldLocal); if (fieldType.IsValueType) { il.Emit(Mono.Cecil.Cil.OpCodes.Box, fieldType); } il.Emit(Mono.Cecil.Cil.OpCodes.Newobj, MemberContextCtor); il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, memberLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Ldsfld, aspectField); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, memberLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, fieldMethod); // Load value back to stack and reflect changes if any il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, memberLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, MemberContextValueMethod); // Convert to expected type il.Emit(fieldType.IsValueType ? Mono.Cecil.Cil.OpCodes.Unbox_Any : Mono.Cecil.Cil.OpCodes.Isinst, fieldType); }
/// <summary> /// Aspect method to use for method call substition /// </summary> /// <param name="typeBuilder"></param> /// <param name="il"></param> /// <param name="method"></param> /// <param name="replaceMethod">Replace Method</param> /// <returns></returns> internal bool MethodCall(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.Cil.ILProcessor il, Mono.Cecil.MethodDefinition method, Mono.Cecil.MethodDefinition replaceMethod) { var methodName = method.Name.Replace("~", string.Empty); var isRecursive = methodName == replaceMethod.Name; var declaringType = replaceMethod.DeclaringType; var methodCall = replaceMethod; if (isRecursive) { methodCall = typeBuilder.GetMethodEx(methodCall.Name, methodCall.ReturnType, methodCall.Parameters.Select(x => x.ParameterType).ToArray()); il.Emit(Mono.Cecil.Cil.OpCodes.Tail); } il.Emit(declaringType.IsValueType || replaceMethod.IsStatic || methodCall.ReturnType.IsValueType ? Mono.Cecil.Cil.OpCodes.Call : Mono.Cecil.Cil.OpCodes.Callvirt, methodCall); il.Emit(Mono.Cecil.Cil.OpCodes.Ret); return(true); }
public IDictionary <Model.Bytecode.Instruction, IList <Mono.Cecil.Cil.Instruction> > CreateInstructions(Model.Types.MethodDefinition methodDefinition, Mono.Cecil.MethodDefinition methodDef, IDictionary <AnalysisNet.ThreeAddressCode.Values.IVariable, Cecil.Cil.VariableDefinition> variableDefinitions, IDictionary <AnalysisNet.ThreeAddressCode.Values.IVariable, Cecil.ParameterDefinition> parameterDefinitions) { Cecil.Cil.ILProcessor ilProcessor = methodDef.Body.GetILProcessor(); BytecodeTranslator translator = new BytecodeTranslator(methodDefinition, variableDefinitions, parameterDefinitions, ReferenceGenerator, ilProcessor); // analysis net instruction -> [cecil instructions] IDictionary <AnalysisNet.Bytecode.Instruction, IList <Cecil.Cil.Instruction> > mappingTranslatedInstructions = translator.Translate(); IEnumerable <Cecil.Cil.Instruction> instructions = mappingTranslatedInstructions.Values.SelectMany(l => l); foreach (Mono.Cecil.Cil.Instruction ins in instructions) { ilProcessor.Append(ins); } return(mappingTranslatedInstructions); }
public Mono.Cecil.Cil.Instruction CreateInstruction(Mono.Cecil.Cil.ILProcessor worker, Mono.Cecil.Cil.OpCode opcode) { throw new NotImplementedException(); }
/// <summary> /// Aspect code to inject at the beginning of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void BeginBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { }
/// <summary> /// Aspect code to inject at the end of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void EndBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { il.Emit(Mono.Cecil.Cil.OpCodes.Ldsfld, field); il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_1); il.Emit(Mono.Cecil.Cil.OpCodes.Sub); il.Emit(Mono.Cecil.Cil.OpCodes.Stsfld, field); }
/// <summary> /// Aspect code to inject at the beginning of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void BeginBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { field = method.DeclaringType.DefineField("<unsafe>_" + method.Name, typeof(int), Mono.Cecil.FieldAttributes.Static | Mono.Cecil.FieldAttributes.Private); var notZero = il.DefineLabel(); il.Emit(Mono.Cecil.Cil.OpCodes.Ldsfld, field); il.Emit(Mono.Cecil.Cil.OpCodes.Brfalse, notZero); il.Emit(Mono.Cecil.Cil.OpCodes.Newobj, typeof(ConcurrentAccessException).GetConstructor(Type.EmptyTypes)); il.Emit(Mono.Cecil.Cil.OpCodes.Throw); il.MarkLabel(notZero); il.Emit(Mono.Cecil.Cil.OpCodes.Ldsfld, field); il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_1); il.Emit(Mono.Cecil.Cil.OpCodes.Add); il.Emit(Mono.Cecil.Cil.OpCodes.Stsfld, field); }
/// <summary> /// Aspect code to inject at the beginning of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void BeginBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { if (method.IsStatic) { return; } if (method.IsConstructor) { il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0); il.Emit(Mono.Cecil.Cil.OpCodes.Call, typeof(ThreadAffinityAttribute).GetMethod("SetInstanceThread")); return; } il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0); il.Emit(Mono.Cecil.Cil.OpCodes.Call, typeof(ThreadAffinityAttribute).GetMethod("ThrowIfInstanceThreadNotMatch")); }
/// <summary> /// Aspect code to inject at the end of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void EndBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { il.BeginCatchBlock(typeof(System.Exception)); il.EndExceptionBlock(); }
/// <summary> /// Aspect code to inject at the end of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void EndBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { il.BeginFinallyBlock(); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, @lock); il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, ExitMethod); il.EndExceptionBlock(); }
/// <summary> /// Aspect code to inject at the beginning of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void BeginBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { var aspectType = this.GetType(); var hasExLabel = il.DefineLabel(); var exceptionLocal = il.DeclareLocal(typeof(Exception)); var offset = method.IsStatic ? 0 : 1; var paraMethod = method; var parameterType = parameter.ParameterType; var parameterDeclaringType = paraMethod.DeclaringType; var aspect = parameter.GetCustomAttribute(aspectType); if (aspect == null) { return; } var aspectField = ILWeaver.TypeFieldAspects[parameterDeclaringType.FullName][aspectType.FullName]; il.Emit(Mono.Cecil.Cil.OpCodes.Ldsfld, aspectField); il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg, parameter.Index + offset); if (parameterType.IsValueType) { il.Emit(Mono.Cecil.Cil.OpCodes.Box, parameterType); } il.Emit(Mono.Cecil.Cil.OpCodes.Ldstr, parameter.Name); il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_1); il.Emit(Mono.Cecil.Cil.OpCodes.Ldtoken, paraMethod); il.Emit(Mono.Cecil.Cil.OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[] { typeof(RuntimeMethodHandle) })); il.Emit(Mono.Cecil.Cil.OpCodes.Isinst, typeof(MethodInfo)); il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4, parameter.Index); il.Emit(Mono.Cecil.Cil.OpCodes.Call, GetParameterContractAspectMethod); il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, ValidateContractMethod); il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, exceptionLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, exceptionLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Brfalse, hasExLabel); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, exceptionLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Throw); il.MarkLabel(hasExLabel); }
/// <summary> /// Weave field into current aspect /// </summary> /// <param name="il">IL Generator</param> /// <param name="field">Field</param> private void BlockGetField(Mono.Cecil.Cil.ILProcessor il, Mono.Cecil.FieldDefinition field) { BlockField(il, field, GetValueMethod); }
/// <summary> /// Aspect code to inject at the end of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void EndBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { var meth = method; var module = typeBuilder.Module; var returnType = meth.ReturnType.ReflectionType(); if (returnType == typeof(void) || !(meth.Name.StartsWith("get_") || meth.Parameters.Count == 0)) { return; } var isPrimitive = returnType.IsPrimitive(); var isStatic = method.IsStatic; if (autoField != null) { //var local = il.DeclareLocal(returnType); //il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, 0); //il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, local); if (!isStatic) { il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0); } il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, 0); if (isPrimitive) { il.Emit(Mono.Cecil.Cil.OpCodes.Newobj, typeof(Nullable <>).MakeGenericType(returnType) .GetConstructor(new Type[] { returnType })); } il.Emit(isStatic ? Mono.Cecil.Cil.OpCodes.Stsfld : Mono.Cecil.Cil.OpCodes.Stfld, autoField); } il.MarkLabel(autoLabel); if (autoField != null) { if (!isStatic) { il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0); } il.Emit(isStatic ? Mono.Cecil.Cil.OpCodes.Ldsflda : Mono.Cecil.Cil.OpCodes.Ldflda, autoField); if (isPrimitive) { returnType = typeof(Nullable <>).MakeGenericType(returnType); il.Emit(Mono.Cecil.Cil.OpCodes.Call, module.Import(returnType.GetMethod("get_Value"))); } il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, 0); } }
/// <summary> /// Aspect code to inject at the beginning of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void BeginBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { var meth = method; var module = typeBuilder.Module; var returnType = meth.ReturnType.ReflectionType(); if (returnType == typeof(void) || !(meth.Name.StartsWith("get_") || meth.Parameters.Count == 0)) { return; } var isStatic = meth.IsStatic; var isPrimitive = returnType.IsPrimitive(); if (isPrimitive) { returnType = typeof(Nullable <>).MakeGenericType(returnType); } autoField = method.DeclaringType.DefineField("<auto_lazy>_" + meth.Name, returnType, isStatic ? Mono.Cecil.FieldAttributes.Static | Mono.Cecil.FieldAttributes.Private : Mono.Cecil.FieldAttributes.Private); autoLabel = il.DefineLabel(); if (!isStatic) { il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0); } il.Emit(isStatic ? Mono.Cecil.Cil.OpCodes.Ldsflda : Mono.Cecil.Cil.OpCodes.Ldflda, autoField); if (isPrimitive) { il.Emit(Mono.Cecil.Cil.OpCodes.Call, module.Import(returnType.GetMethod("get_HasValue"))); } il.Emit(isPrimitive ? Mono.Cecil.Cil.OpCodes.Brtrue : Mono.Cecil.Cil.OpCodes.Brfalse, autoLabel); }
public static void Inject(string input_assembly_path, string output_assembly_path, string logger_assembly_path, string logger_type_name, string before_call_log_method_name, string log_attribute_name) { System.Diagnostics.Debug.Assert(System.IO.File.Exists(input_assembly_path)); if (input_assembly_path != output_assembly_path) { if (System.IO.File.Exists(output_assembly_path)) { System.IO.File.Delete(output_assembly_path); } System.IO.File.Copy(input_assembly_path, output_assembly_path); System.Diagnostics.Debug.Assert(System.IO.File.Exists(output_assembly_path)); } var assembly_resolver = new Mono.Cecil.DefaultAssemblyResolver(); string input_assembly_directory = System.IO.Path.GetDirectoryName(input_assembly_path); assembly_resolver.AddSearchDirectory(input_assembly_directory); #if SILVERLIGHT Microsoft.Silverlight.Build.Tasks.GetSilverlightFrameworkPath path_task = new Microsoft.Silverlight.Build.Tasks.GetSilverlightFrameworkPath(); path_task.RegistryBase = "Software\\Microsoft\\Microsoft SDKs\\Silverlight"; path_task.Execute(); assembly_resolver.AddSearchDirectory(path_task.SilverlightPath); foreach (string path in path_task.SilverlightSDKPaths) { assembly_resolver.AddSearchDirectory(path); } #endif Mono.Cecil.AssemblyDefinition injectible_assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly(output_assembly_path, new Mono.Cecil.ReaderParameters { AssemblyResolver = assembly_resolver }); System.Diagnostics.Debug.Assert(System.IO.File.Exists(logger_assembly_path)); Mono.Cecil.AssemblyDefinition logger_assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly(logger_assembly_path); Mono.Cecil.TypeDefinition logger_type = logger_assembly.MainModule.GetType(logger_type_name); System.Diagnostics.Debug.Assert(logger_type != null); Mono.Cecil.MethodDefinition before_callback_method_info = logger_type.Methods.First(m => m.Name == before_call_log_method_name); Mono.Cecil.MethodReference before_callback_reference = injectible_assembly.MainModule.Import(before_callback_method_info); //make sure to get System.Object.ToString method from assembly compatible with the injected assembly #if SILVERLIGHT string core_assembly_path = path_task.SilverlightPath + "mscorlib.dll"; Mono.Cecil.AssemblyDefinition core_assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly(core_assembly_path); Mono.Cecil.TypeDefinition object_type = core_assembly.MainModule.GetType("System.Object"); Mono.Cecil.MethodDefinition to_string_method_info = object_type.Methods.First(m => m.Name == "ToString"); #else System.Reflection.MethodInfo to_string_method_info = typeof(System.Object).GetMethod("ToString"); #endif Mono.Cecil.MethodReference to_string_reference = injectible_assembly.MainModule.Import(to_string_method_info); foreach (Mono.Cecil.TypeDefinition type_definition in injectible_assembly.MainModule.Types) { bool is_type_logable = type_definition.CustomAttributes.Any(a => a.AttributeType.FullName == log_attribute_name); foreach (Mono.Cecil.MethodDefinition method_definition in type_definition.Methods) { bool is_method_logable = is_type_logable || method_definition.CustomAttributes.Any(a => a.AttributeType.FullName == log_attribute_name); if (is_method_logable) { Mono.Cecil.Cil.ILProcessor processor = method_definition.Body.GetILProcessor(); System.Collections.Generic.List <Mono.Cecil.Cil.Instruction> original_instructions = new System.Collections.Generic.List <Mono.Cecil.Cil.Instruction>(); original_instructions.AddRange(method_definition.Body.Instructions); method_definition.Body.Instructions.Clear(); #region parameters int method_parameters_count = method_definition.Parameters.Count; int local_variables_count = method_definition.Body.Variables.Count; int arguments_array_index = local_variables_count; // Create an array of type System.String with the same number of elements as count of method parameters // Add metadata for a new variable of type System.String[] to method body // .locals init (System.String[] V_0) Mono.Cecil.ArrayType arguments = new Mono.Cecil.ArrayType(injectible_assembly.MainModule.TypeSystem.String); method_definition.Body.Variables.Add(new Mono.Cecil.Cil.VariableDefinition((Mono.Cecil.TypeReference)arguments)); method_definition.Body.InitLocals = true; method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Ldc_I4, method_parameters_count)); method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Newarr, injectible_assembly.MainModule.TypeSystem.String)); // This instruction will store the address of the newly created array in the newly added local variable, which is at index = local_variables_count method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Stloc, arguments_array_index)); #region parameters_to_string // Instance methods have an an implicit argument called "this" // so in that case we need to refer to actual arguments with +1 position int parameter_offset = method_definition.IsStatic ? 0 : 1; for (int i = 0; i < method_parameters_count; ++i) { // load argument array and current index method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Ldloc, arguments_array_index)); method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Ldc_I4, i)); // load argument method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Ldarga, i + parameter_offset)); // convert argument to string Mono.Cecil.TypeReference argument_type = method_definition.Parameters[i].ParameterType; method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Constrained, argument_type)); method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Callvirt, to_string_reference)); // store string in array method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Stelem_Ref)); } #endregion parameters_to_string string method_signature = method_definition.ToString(); // load method signature method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Ldstr, method_signature)); // load parameters array method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Ldloc, arguments_array_index)); #endregion parameters // load before call instruction method_definition.Body.Instructions.Add(processor.Create(Mono.Cecil.Cil.OpCodes.Call, before_callback_reference)); foreach (var IL in original_instructions) { method_definition.Body.Instructions.Add(IL); } } } } injectible_assembly.Write(output_assembly_path); }
/// <summary> /// Aspect code to inject at the beginning of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void BeginBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { var meth = method; lockWasTokenLocal = il.DeclareLocal(typeof(bool)); tempLocal = il.DeclareLocal(typeof(object)); il.Emit(method.IsStatic ? Mono.Cecil.Cil.OpCodes.Ldnull : Mono.Cecil.Cil.OpCodes.Ldarg_0); il.Emit(Mono.Cecil.Cil.OpCodes.Call, GetLockObjectMethod); il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, tempLocal); il.BeginExceptionBlock(); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, tempLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloca, lockWasTokenLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Call, EnterMethod); }
/// <summary> /// Aspect code to inject at the end of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void EndBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { il.BeginFinallyBlock(); var takenLabel = il.DefineLabel(); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, lockWasTokenLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Brfalse, takenLabel); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, tempLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Call, ExitMethod); il.MarkLabel(takenLabel); il.EndExceptionBlock(); }
/// <summary> /// Aspect code to inject at the beginning of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void BeginBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { var isSetProperty = method.Name.StartsWith("set_") && !method.IsStatic; if (!isSetProperty) { return; } il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0); il.Emit(Mono.Cecil.Cil.OpCodes.Call, ThrowIfFrozenMethod); }
/// <summary> /// Weave event invoke /// </summary> /// <param name="il">IL Generator</param> /// <param name="method">Method</param> /// <param name="field">Field</param> private void BlockInvokeEvent(Mono.Cecil.Cil.ILProcessor il, Mono.Cecil.MethodDefinition method, Mono.Cecil.FieldDefinition field) { var isStatic = method.IsStatic; var eventContext = il.DeclareLocal(typeof(EventContext)); var locals = new List <Mono.Cecil.Cil.VariableDefinition>(); var objLocal = il.DeclareLocal(typeof(object[])); var parameters = method.Parameters; var parameterLength = parameters.Count; var fieldDeclaringType = field.DeclaringType; var aspect = field.GetCustomAttribute <EventInterceptionAspect>() ?? fieldDeclaringType.GetCustomAttribute <EventInterceptionAspect>() ?? fieldDeclaringType.Module.Assembly.GetCustomAttribute <EventInterceptionAspect>(); if (!ILWeaver.IsValidAspectFor(field, aspect, allowEvents: true)) { return; } var aspectField = ILWeaver.TypeFieldAspects[fieldDeclaringType.FullName][aspect.GetType().FullName]; il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4, parameterLength); il.Emit(Mono.Cecil.Cil.OpCodes.Newarr, typeof(object)); il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, objLocal); for (var i = 0; i < parameterLength; i++) { var parameter = parameters[i]; var parameterType = parameter.ParameterType; var local = il.DeclareLocal(parameterType); il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, local); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, objLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4, parameterLength - i - 1); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, local); if (parameterType.IsValueType) { il.Emit(Mono.Cecil.Cil.OpCodes.Box, parameterType); } il.Emit(Mono.Cecil.Cil.OpCodes.Stelem_Ref); locals.Add(local); } if (!isStatic) { il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0); } il.Emit(Mono.Cecil.Cil.OpCodes.Ldnull); il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4, 1); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, objLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Newobj, EventContextCtor); il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, eventContext); //InvokeEventMethod il.Emit(Mono.Cecil.Cil.OpCodes.Ldsfld, aspectField); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, eventContext); il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, InvokeEventMethod); //Restore original invoke event parameters //locals.Reverse(); foreach (var local in locals) { il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, local); } }
/// <summary> /// Aspect code to inject at the beginning of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void BeginBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { var methodName = method.Name; var isSetProperty = methodName.StartsWith("set_") && !method.IsStatic; if (!isSetProperty) { return; } il.Emit(Mono.Cecil.Cil.OpCodes.Ldstr, methodName.Substring(4)); il.Emit(Mono.Cecil.Cil.OpCodes.Newobj, typeof(ObjectReadOnlyException).GetConstructor(new[] { typeof(string) })); il.Emit(Mono.Cecil.Cil.OpCodes.Throw); }
/// <summary> /// Aspect code to inject at the beginning of weaved method /// </summary> /// <param name="typeBuilder">Type Builder</param> /// <param name="method">Method</param> /// <param name="parameter">Parameter</param> /// <param name="il">ILGenerator</param> internal void BeginBlock(Mono.Cecil.TypeDefinition typeBuilder, Mono.Cecil.MethodDefinition method, Mono.Cecil.ParameterDefinition parameter, Mono.Cecil.Cil.ILProcessor il) { var meth = method; var returnType = meth.ReturnType.ReflectionType(); @lock = il.DeclareLocal(typeof(Thread.ReaderWriterLockSlim)); il.Emit(method.IsStatic ? Mono.Cecil.Cil.OpCodes.Ldnull : Mono.Cecil.Cil.OpCodes.Ldarg_0); il.Emit(Mono.Cecil.Cil.OpCodes.Call, GetLockMethod); il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, @lock); il.BeginExceptionBlock(); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, @lock); il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, EnterMethod); }