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; } } }
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; } } }
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; } } } }