예제 #1
0
        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);
        }
예제 #3
0
        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]);
            }
        }