예제 #1
0
        private static void Instrument (
                                      AssemblyDefinition assembly,
                                      TypeDefinition type,
                                       Instruction instruction,
                                       MethodReference countReference,
                                       MethodDefinition method,
                                       ILProcessor worker,
                                       string lastLine,
                                       InstrumentConfig config,
                                       TextWriter writer,
                                       ref int instrumentIndex)
        {
            //if the previous instruction is a Prefix instruction then this instruction MUST go with it.
            //we cannot put an instruction between the two.
            if (instruction.Previous != null && instruction.Previous.OpCode.OpCodeType == OpCodeType.Prefix)
                return;

            if (config.HasOffset (method.FullName, instruction.Offset))
                return;

            if (lastLine != null && config.HasLine (method.FullName, lastLine)) {
                return;
            }

            var lineNumStart = -1;
            var lineNumEnd = -1;
            if (instruction.SequencePoint != null) {
                lineNumStart = instruction.SequencePoint.StartLine;
                lineNumEnd = instruction.SequencePoint.EndLine;
            }

            var parentTypeRef = type;
            while (parentTypeRef.DeclaringType != null)
                parentTypeRef = parentTypeRef.DeclaringType;

            var line = string.Join ("\t",
                                   assembly.Name,  //0
                                   parentTypeRef.FullName,//1
                                   method.FullName, //2 
                                   lineNumStart, //3
                                   lineNumEnd, //4 
                                   instruction.Offset, //5
                                   instruction.ToString ().Replace ("\n", " "), //6
                                   instruction.SequencePoint?.Document.Url); //7

   
            writer.WriteLine (line);

            var pathParamLoadInstruction = worker.Create (OpCodes.Ldstr, config.HitsPathPrefix);
            var lineParamLoadInstruction = worker.Create (OpCodes.Ldc_I4, instrumentIndex);
            var registerInstruction = worker.Create (OpCodes.Call, countReference);

            //inserting method before instruction  because after will not happen after a method Ret instruction
            worker.InsertBefore (instruction, pathParamLoadInstruction);
            worker.InsertAfter (pathParamLoadInstruction, lineParamLoadInstruction);
            worker.InsertAfter (lineParamLoadInstruction, registerInstruction);

            ++instrumentIndex;

            //change try/finally etc to point to our first instruction if they referenced the one we inserted before
            foreach (var handler in method.Body.ExceptionHandlers) {
                if (handler.FilterStart == instruction)
                    handler.FilterStart = pathParamLoadInstruction;

                if (handler.TryStart == instruction)
                    handler.TryStart = pathParamLoadInstruction;
                if (handler.TryEnd == instruction)
                    handler.TryEnd = pathParamLoadInstruction;

                if (handler.HandlerStart == instruction)
                    handler.HandlerStart = pathParamLoadInstruction;
                if (handler.HandlerEnd == instruction)
                    handler.HandlerEnd = pathParamLoadInstruction;
            }

            //change instructions with a target instruction if they referenced the one we inserted before to be our first instruction
            foreach (var iteratedInstruction in method.Body.Instructions) {
                var operand = iteratedInstruction.Operand;
                if (operand == instruction) {
                    iteratedInstruction.Operand = pathParamLoadInstruction;
                    continue;
                }

                if (!(operand is Instruction []))
                    continue;

                var operands = (Instruction [])operand;
                for (var i = 0; i < operands.Length; ++i) {
                    if (operands [i] == instruction)
                        operands [i] = pathParamLoadInstruction;
                }
            }
        }
예제 #2
0
        private static void Instrument(Instruction instruction,
                                       MethodReference countReference,
                                       MethodDefinition method,
                                       ILProcessor worker,
                                       string lastLine,
                                       InstrumentConfig config,
                                       TextWriter writer,
                                       ref int instrumentIndex)
        {
            //if the previous instruction is a Prefix instruction then this instruction MUST go with it.
            //we cannot put an instruction between the two.
            if (instruction.Previous != null && instruction.Previous.OpCode.OpCodeType == OpCodeType.Prefix)
                return;

            if (config.HasOffset(method.FullName, instruction.Offset))
                return;

            if (lastLine != null && config.HasLine(method.FullName, lastLine)) {
                return;
            }

            var lineNum = -1;
            if (instruction.SequencePoint != null)
                lineNum = instruction.SequencePoint.StartLine;

            var line = string.Join(", ",
                                   "Method: " + method.FullName,
                                   "Line: " + lineNum,
                                   "Offset: " + instruction.Offset,
                                   "Instruction: " + instruction);

            writer.WriteLine(line);

            var pathParamLoadInstruction = worker.Create(OpCodes.Ldstr, config.HitsPath);
            var lineParamLoadInstruction = worker.Create(OpCodes.Ldc_I4, instrumentIndex);
            var registerInstruction = worker.Create(OpCodes.Call, countReference);

            //inserting method before instruction  because after will not happen after a method Ret instruction
            worker.InsertBefore(instruction, pathParamLoadInstruction);
            worker.InsertAfter(pathParamLoadInstruction, lineParamLoadInstruction);
            worker.InsertAfter(lineParamLoadInstruction, registerInstruction);

            ++instrumentIndex;

            //change try/finally etc to point to our first instruction if they referenced the one we inserted before
            foreach (var handler in method.Body.ExceptionHandlers) {
                if (handler.FilterStart == instruction)
                    handler.FilterStart = pathParamLoadInstruction;

                if (handler.TryStart == instruction)
                    handler.TryStart = pathParamLoadInstruction;
                if (handler.TryEnd == instruction)
                    handler.TryEnd = pathParamLoadInstruction;

                if (handler.HandlerStart == instruction)
                    handler.HandlerStart = pathParamLoadInstruction;
                if (handler.HandlerEnd == instruction)
                    handler.HandlerEnd = pathParamLoadInstruction;
            }

            //change instructions with a target instruction if they referenced the one we inserted before to be our first instruction
            foreach (var iteratedInstruction in method.Body.Instructions) {
                var operand = iteratedInstruction.Operand;
                if (operand == instruction) {
                    iteratedInstruction.Operand = pathParamLoadInstruction;
                    continue;
                }

                if (!(operand is Instruction[]))
                    continue;

                var operands = (Instruction[])operand;
                for (var i = 0; i < operands.Length; ++i) {
                    if (operands[i] == instruction)
                        operands[i] = pathParamLoadInstruction;
                }
            }
        }
예제 #3
0
        private static void Instrument(Instruction instruction,
                                       MethodReference countReference,
                                       MethodDefinition method,
                                       ILProcessor worker,
                                       string lastLine,
                                       InstrumentConfig config,
                                       TextWriter writer,
                                       ref int instrumentIndex)
        {
            //if the previous instruction is a Prefix instruction then this instruction MUST go with it.
            //we cannot put an instruction between the two.
            if (instruction.Previous != null && instruction.Previous.OpCode.OpCodeType == OpCodeType.Prefix)
            {
                return;
            }

            if (config.HasOffset(method.FullName, instruction.Offset))
            {
                return;
            }

            if (lastLine != null && config.HasLine(method.FullName, lastLine))
            {
                return;
            }

            var lineNum       = -1;
            var sequencePoint = method.DebugInformation.GetSequencePoint(instruction);

            if (sequencePoint != null)
            {
                lineNum = sequencePoint.StartLine;
            }

            var line = string.Join(", ",
                                   "Method: " + method.FullName,
                                   "Line: " + lineNum,
                                   "Offset: " + instruction.Offset,
                                   "Instruction: " + instruction);

            writer.WriteLine(line);

            var pathParamLoadInstruction = worker.Create(OpCodes.Ldstr, config.HitsPathPrefix);
            var lineParamLoadInstruction = worker.Create(OpCodes.Ldc_I4, instrumentIndex);
            var registerInstruction      = worker.Create(OpCodes.Call, countReference);

            //inserting method before instruction  because after will not happen after a method Ret instruction
            worker.InsertBefore(instruction, pathParamLoadInstruction);
            worker.InsertAfter(pathParamLoadInstruction, lineParamLoadInstruction);
            worker.InsertAfter(lineParamLoadInstruction, registerInstruction);

            ++instrumentIndex;

            //change try/finally etc to point to our first instruction if they referenced the one we inserted before
            foreach (var handler in method.Body.ExceptionHandlers)
            {
                if (handler.FilterStart == instruction)
                {
                    handler.FilterStart = pathParamLoadInstruction;
                }

                if (handler.TryStart == instruction)
                {
                    handler.TryStart = pathParamLoadInstruction;
                }
                if (handler.TryEnd == instruction)
                {
                    handler.TryEnd = pathParamLoadInstruction;
                }

                if (handler.HandlerStart == instruction)
                {
                    handler.HandlerStart = pathParamLoadInstruction;
                }
                if (handler.HandlerEnd == instruction)
                {
                    handler.HandlerEnd = pathParamLoadInstruction;
                }
            }

            //change instructions with a target instruction if they referenced the one we inserted before to be our first instruction
            foreach (var iteratedInstruction in method.Body.Instructions)
            {
                var operand = iteratedInstruction.Operand;
                if (operand == instruction)
                {
                    iteratedInstruction.Operand = pathParamLoadInstruction;
                    continue;
                }

                if (!(operand is Instruction[]))
                {
                    continue;
                }

                var operands = (Instruction[])operand;
                for (var i = 0; i < operands.Length; ++i)
                {
                    if (operands[i] == instruction)
                    {
                        operands[i] = pathParamLoadInstruction;
                    }
                }
            }
        }