/// <summary> /// Write out the instrumented binary. /// </summary> /// <param name="unit">Instrumented unit.</param> protected override void Execute(Phx.Unit unit) { if (!unit.IsPEModuleUnit) { return; } // Write the instrumented binary Phx.PEModuleUnit executable = unit.AsPEModuleUnit; Phx.PE.Writer writer = Phx.PE.Writer.New( Phx.GlobalData.GlobalLifetime, Application.Output.GetValue(null), null, // Writing an instrumented PDB currently crashes executable, executable.SymbolTable, executable.Architecture, executable.Runtime); writer.Write(); }
/// <summary> /// Inject code coverage information into a function. /// </summary> /// <param name="unit">The function to instrument.</param> protected override void Execute(Phx.Unit unit) { // Only instrument MSIL functions if (!unit.IsFunctionUnit) { return; } Phx.FunctionUnit function = unit.AsFunctionUnit; if (!function.Architecture.NameString.Equals("Msil")) { return; } Phx.PEModuleUnit module = function.ParentUnit.AsPEModuleUnit; Phx.Symbols.FunctionSymbol functionSymbol = function.FunctionSymbol; Phx.Types.FunctionType functionType = functionSymbol.FunctionType; // Create the method signature List <string> parameterTypes = new List <string>(); foreach (Phx.Types.Parameter parameter in functionType.UserDefinedParameters) { parameterTypes.Add(parameter.Type.ToString()); } string methodName = string.Format( CultureInfo.InvariantCulture, "{0}({1})", functionSymbol.NameString, string.Join(", ", parameterTypes.ToArray())); // Build the control flow graph for the current function function.BuildFlowGraph(); Phx.Graphs.FlowGraph flow = function.FlowGraph; // Log method details string typeName = (functionSymbol.EnclosingAggregateType != null) ? functionSymbol.EnclosingAggregateType.TypeSymbol.NameString : "<Module>"; Log.StartMethod( methodName, typeName, flow.StartBlock.FirstInstruction.GetFileName(), flow.StartBlock.FirstInstruction.GetLineNumber()); // Create a mapping of the disassembled from instructions to the // basic block IDs so we can use them for coverage viewing. Dictionary <Phx.IR.Instruction, uint> dissassembly = new Dictionary <Phx.IR.Instruction, uint>(); // Instrument and log the blocks for the current function. Log.StartBlocks(); foreach (Phx.Graphs.BasicBlock block in flow.BasicBlocks) { // Find the first real instruction in the block Phx.IR.Instruction first = null; foreach (Phx.IR.Instruction instruction in block.Instructions) { // Save the instructions to be dumped later dissassembly.Add(instruction, BlockCounter); // Ignore instructions that aren't actually "real" if (first == null && instruction.IsReal) { Phx.Common.Opcode opcode = instruction.Opcode as Phx.Common.Opcode; if (opcode == Phx.Common.Opcode.ReturnFinally || opcode == Phx.Common.Opcode.Leave || opcode == Phx.Common.Opcode.Unreached || opcode == Phx.Common.Opcode.ExitTypeFilter) { continue; } first = instruction; } } // Inject a code coverage visitor call before the first // instruction of the basic block if (first != null) { // Log the basic block Phx.IR.Instruction last = block.LastInstruction; Log.StartBlock( BlockCounter, first.GetMsilOffset(), first.GetFileName(), first.GetLineNumber(), first.GetColumnNumber(), last.GetLineNumberEnd(), last.GetColumnNumberEnd()); Phx.Symbols.FunctionSymbol coverageVisit = GetFunctionSymbol(module, CoverageVisitAssembly, CoverageVisitType, CoverageVisitMethod); InjectCoverageCall(function, coverageVisit, BlockCounter, first); #if LogBlockDissassembly // Dump the disassembly for the current block Log.StartBlockDisassembly(); foreach (Phx.IR.Instruction instruction in block.Instructions) { Log.WriteBlockDisassembly( instruction.GetMsilOffset(), instruction.ToString(), BlockCounter); } Log.EndBlockDisassembly(); #endif Log.EndBlock(); } // Increment the number of basic blocks BlockCounter++; } function.DeleteFlowGraph(); Log.EndBlocks(); // Dump the disassembly for the current method Log.StartMethodDisassembly(); foreach (KeyValuePair <Phx.IR.Instruction, uint> pair in dissassembly) { Log.WriteBlockDisassembly( pair.Key.GetMsilOffset(), pair.Key.ToString(), pair.Value); } Log.EndMethodDisassembly(); Log.EndMethod(); }
/// <summary> /// Encode the instrumented IR. /// </summary> /// <param name="unit">Instrumented unit.</param> protected override void Execute(Phx.Unit unit) { Phx.PE.Writer.EncodeUnit(unit); }