private void InsertEndTrace( AssemblyDefinition assembly, MethodDefinition method, int count, Instruction beforeReturn, Instruction firstInstruction, Instruction lastRet) { ILProcessor ilProcessor = method.Body.GetILProcessor(); var instructions = new List <Instruction>(); instructions.Add(ilProcessor.Create(OpCodes.Ldloc, count)); instructions.Add(ilProcessor.Create(OpCodes.Callvirt, WeaverUtil.ImportMethod <ItemTracer>(assembly, "Dispose"))); instructions.Add(ilProcessor.Create(OpCodes.Nop)); instructions.Add(ilProcessor.Create(OpCodes.Endfinally)); instructions.ForEach(x => { ilProcessor.InsertBefore(lastRet, x); }); var handlerFinally = new ExceptionHandler(ExceptionHandlerType.Finally) { TryStart = firstInstruction, TryEnd = beforeReturn, HandlerStart = beforeReturn, HandlerEnd = lastRet }; method.Body.ExceptionHandlers.Add(handlerFinally); }
public override void Weave(AssemblyDefinition assembly, MethodDefinition method) { method.Body.InitLocals = true; ILProcessor ilProcessor = method.Body.GetILProcessor(); var count = method.Body.Variables.Count; method.Body.Variables.Add(new VariableDefinition(WeaverUtil.ImportType <Exception>(assembly))); method.Body.Variables.Add(new VariableDefinition(WeaverUtil.ImportType <PKTracer.Framework.Tracer.ExceptionTracer>(assembly))); var lastRet = FixReturns(method); var firstInstruction = FirstInstructionSkipCtor(method); var beforeReturn = Instruction.Create(OpCodes.Nop); ilProcessor.InsertBefore(lastRet, beforeReturn); var instructions = new List <Instruction>(); instructions.Add(ilProcessor.Create(OpCodes.Stloc, count)); instructions.Add(ilProcessor.Create(OpCodes.Nop)); instructions.Add(ilProcessor.Create(OpCodes.Ldstr, assembly.Name.Name)); instructions.Add(ilProcessor.Create(OpCodes.Ldloc, count)); instructions.Add(ilProcessor.Create(OpCodes.Callvirt, WeaverUtil.ImportMethod <Exception>(assembly, "get_Message"))); instructions.Add(ilProcessor.Create(OpCodes.Newobj, method.Module.Import(typeof(PKTracer.Framework.Tracer.ExceptionTracer).GetConstructors()[0]))); instructions.Add(ilProcessor.Create(OpCodes.Stloc, count + 1)); instructions.Add(ilProcessor.Create(OpCodes.Ldloc, count + 1)); instructions.Add(ilProcessor.Create(OpCodes.Callvirt, WeaverUtil.ImportMethod <PKTracer.Framework.Tracer.ExceptionTracer>(assembly, "Dispose"))); instructions.Add(ilProcessor.Create(OpCodes.Nop)); instructions.Add(ilProcessor.Create(OpCodes.Ldloc, count)); instructions.Add(ilProcessor.Create(OpCodes.Throw)); instructions.ForEach(x => { ilProcessor.InsertBefore(lastRet, x); }); var handlerCatch = new ExceptionHandler(ExceptionHandlerType.Catch) { TryStart = firstInstruction, TryEnd = beforeReturn, HandlerStart = beforeReturn, HandlerEnd = lastRet, CatchType = WeaverUtil.ImportType <Exception>(assembly) }; method.Body.ExceptionHandlers.Add(handlerCatch); }
public override void Weave(AssemblyDefinition assembly, MethodDefinition method) { ILProcessor ilProcessor = method.Body.GetILProcessor(); var objTracingInstructions = new List <Instruction>(); TypeSpecification referencedTypeSpec = null; MetadataType paramMetaData; TypeReference typeObject = assembly.MainModule.TypeSystem.Object; bool pointerToValueTypeVariable = false; int intMethodParamsCount = method.Parameters.Count; int intArrayVarNumber = method.Body.Variables.Count; ArrayType objArrType = new ArrayType(typeObject); method.Body.Variables.Add(new VariableDefinition((TypeReference)objArrType)); method.Body.InitLocals = true; //objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldstr,method.ToString())); objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, intMethodParamsCount)); objTracingInstructions.Add(ilProcessor.Create(OpCodes.Newarr, typeObject)); objTracingInstructions.Add(ilProcessor.Create(OpCodes.Stloc, intArrayVarNumber)); // Loop over all the parameters of method and add their value to object[] // ------------------------------------------------------------ for (int i = 0; i < intMethodParamsCount; i++) { paramMetaData = method.Parameters[i].ParameterType.MetadataType; if (paramMetaData == MetadataType.UIntPtr || paramMetaData == MetadataType.FunctionPointer || paramMetaData == MetadataType.IntPtr || paramMetaData == MetadataType.Pointer) { // We don't want to log values of these parameters, so skip // this iteration break; } objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldloc, intArrayVarNumber)); objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldc_I4, i)); // Instance methods have an an implicit argument called "this" // and hence, we need to refer to actual arguments with +1 position // whereas, in case of static methods, "this" argument is not there // ------------------------------------------------------------ if (method.IsStatic) { objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldarg, i)); } else { objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldarg, i + 1)); } // Reset boolean flag variable to false pointerToValueTypeVariable = false; // If aparameter is passed by reference then you need to use ldind // ------------------------------------------------------------ TypeReference paramType = method.Parameters[i].ParameterType; if (paramType.IsByReference) { referencedTypeSpec = paramType as TypeSpecification; //Trace.WriteLine(string.Format("Parameter Name:{0}, Type:{1}", metDef.Parameters[i].Name, metDef.Parameters[i].ParameterType.Name)); if (referencedTypeSpec != null) { switch (referencedTypeSpec.ElementType.MetadataType) { //Indirect load value of type int8 as int32 on the stack case MetadataType.Boolean: case MetadataType.SByte: objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldind_I1)); pointerToValueTypeVariable = true; break; // Indirect load value of type int16 as int32 on the stack case MetadataType.Int16: objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldind_I2)); pointerToValueTypeVariable = true; break; // Indirect load value of type int32 as int32 on the stack case MetadataType.Int32: objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldind_I4)); pointerToValueTypeVariable = true; break; // Indirect load value of type int64 as int64 on the stack // Indirect load value of type unsigned int64 as int64 on the stack (alias for ldind.i8) case MetadataType.Int64: case MetadataType.UInt64: objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldind_I8)); pointerToValueTypeVariable = true; break; // Indirect load value of type unsigned int8 as int32 on the stack case MetadataType.Byte: objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldind_U1)); pointerToValueTypeVariable = true; break; // Indirect load value of type unsigned int16 as int32 on the stack case MetadataType.UInt16: case MetadataType.Char: objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldind_U2)); pointerToValueTypeVariable = true; break; // Indirect load value of type unsigned int32 as int32 on the stack case MetadataType.UInt32: objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldind_U4)); pointerToValueTypeVariable = true; break; // Indirect load value of type float32 as F on the stack case MetadataType.Single: objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldind_R4)); pointerToValueTypeVariable = true; break; // Indirect load value of type float64 as F on the stack case MetadataType.Double: objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldind_R8)); pointerToValueTypeVariable = true; break; // Indirect load value of type native int as native int on the stack case MetadataType.IntPtr: case MetadataType.UIntPtr: objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldind_I)); pointerToValueTypeVariable = true; break; default: // Need to check if it is a value type instance, in which case // we use ldobj instruction to copy the contents of value type // instance to stack and then box it if (referencedTypeSpec.ElementType.IsValueType) { objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldobj, referencedTypeSpec.ElementType)); pointerToValueTypeVariable = true; } else { // It is a reference type so just use reference the pointer objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldind_Ref)); pointerToValueTypeVariable = false; } break; } } else { // We dont have complete details about the type of referenced parameter // So we will just ignore this parameter value } } // If it is a value type then you need to box the instance as we are going // to add it to an array which is of type object (reference type) // ------------------------------------------------------------ if (paramType.IsValueType || pointerToValueTypeVariable) { if (pointerToValueTypeVariable) { // Box the dereferenced parameter type objTracingInstructions.Add(ilProcessor.Create(OpCodes.Box, referencedTypeSpec.ElementType)); } else { // Box the parameter type objTracingInstructions.Add(ilProcessor.Create(OpCodes.Box, paramType)); } } // Store parameter in object[] array // ------------------------------------------------------------ objTracingInstructions.Add(ilProcessor.Create(OpCodes.Stelem_Ref)); } // Load address of array variable on evaluation stack, to pass // it as a paremter // ------------------------------------------------------------ objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldloc, tracerIndex)); objTracingInstructions.Add(ilProcessor.Create(OpCodes.Ldloc, intArrayVarNumber)); if (this.Parameters.DecodeParameters) { objTracingInstructions.Add(ilProcessor.Create(OpCodes.Callvirt, WeaverUtil.ImportMethod <ItemTracer>(assembly, "SetParametersWithDecode"))); } else { objTracingInstructions.Add(ilProcessor.Create(OpCodes.Callvirt, WeaverUtil.ImportMethod <ItemTracer>(assembly, "SetParameters"))); } for (var i = objTracingInstructions.Count - 1; i >= 0; i--) { ilProcessor.InsertAfter(lastInstruction, objTracingInstructions[i]); } }