/* * PhxCommonWriteCxpReg() * Write to a 32 bit CXP register in camera. */ public unsafe Phx.etStat PhxCommonWriteCxpReg( uint hCamera, /* PHX handle */ uint dwAddress, /* Address of the camera register */ uint dwValue, /* Value to write */ uint dwTimeout /* Timeout for operation */ ) { Phx.etStat eStat = Phx.etStat.PHX_OK; uint dwSize = sizeof(uint); dwValue = htonl(dwValue); eStat = Phx.PHX_ControlWrite(hCamera, Phx.etControlPort.PHX_REGISTER_DEVICE, ref dwAddress, ref dwValue, ref dwSize, dwTimeout); return(eStat); }
/* * PhxCommonGetCxpDiscoveryStatus() * Checks if CXP camera is discovered. */ public Phx.etStat PhxCommonGetCxpDiscoveryStatus( uint hCamera, uint dwTimeoutSec, ref bool fIsDiscovered ) { Phx.etStat eStat = Phx.etStat.PHX_OK; uint dwIndex = 0; Console.WriteLine("Checking for CXP camera discovery..."); fIsDiscovered = false; while (dwIndex++ < dwTimeoutSec * 2) /* Sleep between two attempts is only 500 ms */ { Phx.etCxpInfo eDiscoveryStatus = 0; eStat = Phx.PHX_ParameterGet(hCamera, Phx.etParam.PHX_CXP_INFO, ref eDiscoveryStatus); if (Phx.etStat.PHX_OK != eStat) { goto Exit; } if ((int)Phx.etCxpInfo.PHX_CXP_CAMERA_DISCOVERED == ((int)eDiscoveryStatus & (int)(Phx.etCxpInfo.PHX_CXP_CAMERA_DISCOVERED))) { fIsDiscovered = true; break; } Console.Write("."); System.Threading.Thread.Sleep(500); } Console.WriteLine(""); if (fIsDiscovered) { Console.WriteLine("CXP camera is discovered."); } else { Console.WriteLine("CXP camera was not discovered."); } Exit: return(eStat); }
/// <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> /// Creates a new instance of the EmitPhase class. /// </summary> /// <param name="config">The phase list container.</param> /// <returns>New EmitPhase object.</returns> public static EmitPhase New(Phx.Phases.PhaseConfiguration config) { EmitPhase emitPhase = new EmitPhase(); emitPhase.Initialize(config, "Emit"); return emitPhase; }
/// <summary> /// Encode the instrumented IR. /// </summary> /// <param name="unit">Instrumented unit.</param> protected override void Execute(Phx.Unit unit) { Phx.PE.Writer.EncodeUnit(unit); }
/// <summary> /// Initializes a new instance of the EncodePhase class. /// </summary> /// <param name="config">The phase list container.</param> /// <returns>New EncodePhase object.</returns> public static EncodePhase New(Phx.Phases.PhaseConfiguration config) { EncodePhase encodePhase = new EncodePhase(); encodePhase.Initialize(config, "Encode"); return encodePhase; }
/* * phxlive() * Simple live capture application code, using image conversion in order to reduce * the amount of PCI bandwidth used. */ unsafe static int phxlive( Phx.etParamValue eBoardNumber, /* Board number, i.e. 1, 2, or 0 for next available */ Phx.etParamValue eChannelNumber, /* Channel number */ String strConfigFileName, /* Name of config file */ PhxCommon.tCxpRegisters sCameraRegs /* Camera CXP registers */ ) { Phx.etStat eStat = Phx.etStat.PHX_OK; /* Status variable */ Phx.etParamValue eAcqType = 0; /* Parameter for use with PHX_ParameterSet/Get calls */ Pbl.etPblParamValue eBayCol = 0; Phx.etParamValue eParamValue = 0; Pbl.etPblParamValue ePblCaptureFormat = 0; Phx.etParamValue eCamSrcCol = 0; Phx.etParamValue eCaptureFormat = Phx.etParamValue.PHX_BUS_FORMAT_MONO8; Phx.etParamValue eCamFormat = 0; uint dwBufferReadyLast = 0; /* Previous BufferReady count value */ IntPtr pParamValue = IntPtr.Zero; IntPtr pConfigFile = IntPtr.Zero; PhxCommon myPhxCommon = new PhxCommon(); Phx.PHX_AcquireCallBack PHX_Callback = new Phx.PHX_AcquireCallBack(phxlive_callback); Phx.stImageBuff[] asImageBuffers = null; /* Capture buffer array */ uint[] ahCaptureBuffers = null; /* Capture buffer handle array */ tPhxLive sPhxLive; /* User defined event context */ uint hCamera = 0; /* Camera handle */ uint hDisplay = 0; /* Display handle */ uint hDisplayBuffer = 0; /* Display buffer handle */ uint dwAcqNumBuffers = 0; uint dwBufferWidth = 0; uint dwBufferHeight = 0; uint dwBufferStride = 0; uint dwCamSrcDepth = 0; bool fDebayer = false; bool fCameraIsCxp = false; bool fIsCxpCameraDiscovered = false; /* Create a Phx handle */ eStat = Phx.PHX_Create(ref hCamera, Phx.PHX_ErrHandlerDefault); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Set the configuration file name */ if (!String.IsNullOrEmpty(strConfigFileName)) { pConfigFile = Marshal.UnsafeAddrOfPinnedArrayElement(PhxCommon.GetBytesFromString(strConfigFileName), 0); eStat = Phx.PHX_ParameterSet(hCamera, Phx.etParam.PHX_CONFIG_FILE, ref pConfigFile); if (Phx.etStat.PHX_OK != eStat) { goto Error; } } /* Set the board number */ eStat = Phx.PHX_ParameterSet(hCamera, Phx.etParam.PHX_BOARD_NUMBER, ref eBoardNumber); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Set the channel number */ eStat = Phx.PHX_ParameterSet(hCamera, Phx.etParam.PHX_CHANNEL_NUMBER, ref eChannelNumber); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Open the board using the above configuration file */ eStat = Phx.PHX_Open(hCamera); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Read various parameter values in order to generate the capture buffers. */ eStat = Phx.PHX_ParameterGet(hCamera, Phx.etParam.PHX_ROI_XLENGTH, ref dwBufferWidth); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Phx.PHX_ParameterGet(hCamera, Phx.etParam.PHX_ROI_YLENGTH, ref dwBufferHeight); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Phx.PHX_ParameterGet(hCamera, Phx.etParam.PHX_CAM_SRC_DEPTH, ref dwCamSrcDepth); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Phx.PHX_ParameterGet(hCamera, Phx.etParam.PHX_CAM_SRC_COL, ref eCamSrcCol); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Phx.PHX_ParameterGet(hCamera, Phx.etParam.PHX_BUS_FORMAT, ref eCaptureFormat); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Phx.PHX_ParameterGet(hCamera, Phx.etParam.PHX_CAM_FORMAT, ref eCamFormat); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Phx.PHX_ParameterGet(hCamera, Phx.etParam.PHX_ACQ_FIELD_MODE, ref eAcqType); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Phx.PHX_ParameterGet(hCamera, Phx.etParam.PHX_ACQ_NUM_BUFFERS, ref dwAcqNumBuffers); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Interlaced Camera in Field Mode */ if (Phx.etParamValue.PHX_CAM_INTERLACED == eCamFormat && (Phx.etParamValue.PHX_ACQ_FIELD_12 == eAcqType || Phx.etParamValue.PHX_ACQ_FIELD_21 == eAcqType || Phx.etParamValue.PHX_ACQ_FIELD_NEXT == eAcqType || Phx.etParamValue.PHX_ACQ_FIELD_1 == eAcqType || Phx.etParamValue.PHX_ACQ_FIELD_2 == eAcqType)) { dwBufferHeight /= 2; } /* Determine PHX_BUS_FORMAT based on the camera format */ eStat = myPhxCommon.PhxCommonGetBusFormat(eCamSrcCol, dwCamSrcDepth, eCaptureFormat, ref eCaptureFormat); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Determine bayer format */ fDebayer = true; if (Phx.etParamValue.PHX_CAM_SRC_BAYER_BG == eCamSrcCol) { eBayCol = Pbl.etPblParamValue.PBL_BAY_COL_BLU; } else if (Phx.etParamValue.PHX_CAM_SRC_BAYER_GB == eCamSrcCol) { eBayCol = Pbl.etPblParamValue.PBL_BAY_COL_GRNB; } else if (Phx.etParamValue.PHX_CAM_SRC_BAYER_GR == eCamSrcCol) { eBayCol = Pbl.etPblParamValue.PBL_BAY_COL_GRNR; } else if (Phx.etParamValue.PHX_CAM_SRC_BAYER_RG == eCamSrcCol) { eBayCol = Pbl.etPblParamValue.PBL_BAY_COL_RED; } else { fDebayer = false; } /* Update the PHX_BUS_FORMAT, as it may have changed (above) */ eStat = Phx.PHX_ParameterSet(hCamera, (Phx.etParam.PHX_BUS_FORMAT | Phx.etParam.PHX_CACHE_FLUSH), ref eCaptureFormat); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Read back the Buffer Stride */ eStat = Phx.PHX_ParameterGet(hCamera, Phx.etParam.PHX_BUF_DST_XLENGTH, ref dwBufferStride); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Init the array of capture buffer handles */ ahCaptureBuffers = new uint[dwAcqNumBuffers]; /* Init the array of image buffers */ asImageBuffers = new Phx.stImageBuff[dwAcqNumBuffers + 1]; /* Create and initialise our capture buffers (not associated with display) */ for (int i = 0; i < dwAcqNumBuffers; i++) { /* We create a capture buffer for our double buffering */ eStat = Pbl.PBL_BufferCreate(ref ahCaptureBuffers[i], Pbl.etPblBufferMode.PBL_BUFF_SYSTEM_MEM_DIRECT, 0, hCamera, myPhxCommon.PhxCommonDisplayErrorHandler); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Initialise our capture buffer */ eStat = Pbl.PBL_BufferParameterSet(ahCaptureBuffers[i], Pbl.etPblParam.PBL_BUFF_WIDTH, ref dwBufferWidth); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Pbl.PBL_BufferParameterSet(ahCaptureBuffers[i], Pbl.etPblParam.PBL_BUFF_HEIGHT, ref dwBufferHeight); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Pbl.PBL_BufferParameterSet(ahCaptureBuffers[i], Pbl.etPblParam.PBL_BUFF_STRIDE, ref dwBufferStride); if (Phx.etStat.PHX_OK != eStat) { goto Error; } ePblCaptureFormat = (Pbl.etPblParamValue)eCaptureFormat; eStat = Pbl.PBL_BufferParameterSet(ahCaptureBuffers[i], Pbl.etPblParam.PBL_DST_FORMAT, ref ePblCaptureFormat); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Pbl.PBL_BufferInit(ahCaptureBuffers[i]); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Set up the type of Bayer conversion required */ if (fDebayer) { Pbl.etPblParamValue ePblParamValue = Pbl.etPblParamValue.PBL_BAY_DEC_DUP; eStat = Pbl.PBL_BufferParameterSet(ahCaptureBuffers[i], Pbl.etPblParam.PBL_BUFF_BAYDEC, ref ePblParamValue); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Pbl.PBL_BufferParameterSet(ahCaptureBuffers[i], Pbl.etPblParam.PBL_BUFF_BAYCOL, ref eBayCol); if (Phx.etStat.PHX_OK != eStat) { goto Error; } } /* Build up our array of capture buffers */ Pbl.PBL_BufferParameterGet(ahCaptureBuffers[i], Pbl.etPblParam.PBL_BUFF_ADDRESS, ref asImageBuffers[i].pvAddress); asImageBuffers[i].pvContext = (IntPtr)ahCaptureBuffers[i]; } /* Terminate the array */ asImageBuffers[dwAcqNumBuffers].pvAddress = System.IntPtr.Zero; asImageBuffers[dwAcqNumBuffers].pvContext = System.IntPtr.Zero; /* The above code has created dwAcqNumBuffers acquisition buffers. * Therefore ensure that the Phoenix is configured to use this number, by overwriting * the value already loaded from the config file. */ eStat = Phx.PHX_ParameterSet(hCamera, Phx.etParam.PHX_ACQ_NUM_BUFFERS, ref dwAcqNumBuffers); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* These are 'direct' buffers, so we must tell Phoenix about them * so that it can capture data directly into them. */ eStat = Phx.PHX_ParameterSet(hCamera, Phx.etParam.PHX_BUF_DST_XLENGTH, ref dwBufferStride); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Phx.PHX_ParameterSet(hCamera, Phx.etParam.PHX_BUF_DST_YLENGTH, ref dwBufferHeight); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eStat = Phx.PHX_ParameterSet(hCamera, Phx.etParam.PHX_DST_PTRS_VIRT, asImageBuffers); if (Phx.etStat.PHX_OK != eStat) { goto Error; } eParamValue = Phx.etParamValue.PHX_DST_PTR_USER_VIRT; eStat = Phx.PHX_ParameterSet(hCamera, (Phx.etParam.PHX_DST_PTR_TYPE | Phx.etParam.PHX_CACHE_FLUSH | Phx.etParam.PHX_FORCE_REWRITE), ref eParamValue); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* We create our display with a NULL hWnd, this will automatically create an image window. */ eStat = Pdl.PDL_DisplayCreate(ref hDisplay, IntPtr.Zero, hCamera, myPhxCommon.PhxCommonDisplayErrorHandler); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* We create a display buffer (indirect) */ eStat = Pdl.PDL_BufferCreate(ref hDisplayBuffer, hDisplay, Pdl.etPdlBufferMode.PDL_BUFF_SYSTEM_MEM_INDIRECT); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Initialise the display, this associates the display buffer with the display */ eStat = Pdl.PDL_DisplayInit(hDisplay); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Enable FIFO Overflow events */ eParamValue = Phx.etParamValue.PHX_INTRPT_FIFO_OVERFLOW; eStat = Phx.PHX_ParameterSet(hCamera, Phx.etParam.PHX_INTRPT_SET, ref eParamValue); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Setup our own event context */ eStat = Phx.PHX_ParameterSet(hCamera, Phx.etParam.PHX_EVENT_CONTEXT, (void *)&sPhxLive); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Check if camera is CXP */ eStat = Phx.PHX_ParameterGet(hCamera, Phx.etParam.PHX_BOARD_VARIANT, ref eParamValue); if (Phx.etStat.PHX_OK != eStat) { goto Error; } if (Phx.etParamValue.PHX_BOARD_FBD_4XCXP6_2PE8 == eParamValue || Phx.etParamValue.PHX_BOARD_FBD_2XCXP6_2PE8 == eParamValue || Phx.etParamValue.PHX_BOARD_FBD_1XCXP6_2PE8 == eParamValue) { fCameraIsCxp = true; } /* Check that camera is discovered (only applies to CXP) */ if (fCameraIsCxp) { myPhxCommon.PhxCommonGetCxpDiscoveryStatus(hCamera, 10, ref fIsCxpCameraDiscovered); if (!fIsCxpCameraDiscovered) { goto Error; } } /* Now start our capture, using the callback method */ eStat = Phx.PHX_StreamRead(hCamera, Phx.etAcq.PHX_START, PHX_Callback); if (Phx.etStat.PHX_OK != eStat) { goto Error; } /* Now start camera */ if (fCameraIsCxp && 0 != sCameraRegs.dwAcqStartAddress) { eStat = myPhxCommon.PhxCommonWriteCxpReg(hCamera, sCameraRegs.dwAcqStartAddress, sCameraRegs.dwAcqStartValue, 800); if (Phx.etStat.PHX_OK != eStat) { goto Error; } } /* Continue processing data until the user presses a key in the console window * or a FIFO overflow is detected. */ Console.WriteLine("Press a key to exit"); while (0 == myPhxCommon.PhxCommonKbHit()) { /* Wait here until either: * (a) The user aborts the wait by pressing a key in the console window * (b) The BufferReady event occurs indicating that the image is complete * (c) The FIFO overflow event occurs indicating that the image is corrupt * Keep calling the sleep function to avoid burning CPU cycles */ while (0 == myPhxCommon.PhxCommonKbHit() && !sPhxLive.fBufferReady && !sPhxLive.fFifoOverflow) { System.Threading.Thread.Sleep(10); } if (dwBufferReadyLast != sPhxLive.dwBufferReadyCount) { uint dwStaleBufferCount; /* If the processing is too slow to keep up with acquisition, * then there may be more than 1 buffer ready to process. * The application can either be designed to process all buffers * knowing that it will catch up, or as here, throw away all but the * latest */ dwStaleBufferCount = sPhxLive.dwBufferReadyCount - dwBufferReadyLast; dwBufferReadyLast += dwStaleBufferCount; /* Throw away all but the last image */ if (1 < dwStaleBufferCount) { do { eStat = Phx.PHX_StreamRead(hCamera, Phx.etAcq.PHX_BUFFER_RELEASE, IntPtr.Zero); if (Phx.etStat.PHX_OK != eStat) { goto Error; } dwStaleBufferCount--; } while (dwStaleBufferCount > 1); } } sPhxLive.fBufferReady = false; Phx.stImageBuff stBuffer; stBuffer.pvAddress = IntPtr.Zero; stBuffer.pvContext = IntPtr.Zero; /* Get the info for the last acquired buffer */ eStat = Phx.PHX_StreamRead(hCamera, Phx.etAcq.PHX_BUFFER_GET, ref stBuffer); if (Phx.etStat.PHX_OK != eStat) { eStat = Phx.PHX_StreamRead(hCamera, Phx.etAcq.PHX_BUFFER_RELEASE, IntPtr.Zero); if (Phx.etStat.PHX_OK != eStat) { goto Error; } continue; } /* Process the newly acquired buffer, * which in this simple example is a call to display the data. * For our display function we use the pvContext member variable to * pass a display buffer handle. * Alternatively the actual video data can be accessed at stBuffer.pvAddress */ byte[] wtf = new byte[4036608]; Marshal.Copy(stBuffer.pvAddress, wtf, 0, 4036608); // Console.WriteLine(wtf[0].ToString()); for (int i = 50000; i < 500000; i++) { wtf[i] = 0; } Marshal.Copy(wtf, 0, stBuffer.pvAddress, 4036608); uint hBufferHandle = (uint)stBuffer.pvContext; /* This copies/converts data from the direct capture buffer to the indirect display buffer */ eStat = Pil.PIL_Convert(hBufferHandle, hDisplayBuffer); if (Phx.etStat.PHX_OK != eStat) { eStat = Phx.PHX_StreamRead(hCamera, Phx.etAcq.PHX_BUFFER_RELEASE, IntPtr.Zero); if (Phx.etStat.PHX_OK != eStat) { goto Error; } continue; } Pdl.PDL_BufferPaint(hDisplayBuffer); /* Having processed the data, release the buffer ready for further image data */ eStat = Phx.PHX_StreamRead(hCamera, Phx.etAcq.PHX_BUFFER_RELEASE, IntPtr.Zero); if (Phx.etStat.PHX_OK != eStat) { goto Error; } } /* In this simple example we abort the processing loop on an error condition (FIFO overflow). * However handling of this condition is application specific, and generally would involve * aborting the current acquisition, and then restarting. */ if (sPhxLive.fFifoOverflow) { Console.WriteLine("FIFO Overflow detected. Aborting."); } Error: /* Now cease all captures */ if (0 != hCamera) { /* Stop camera */ if (fIsCxpCameraDiscovered && 0 != sCameraRegs.dwAcqStopAddress) { myPhxCommon.PhxCommonWriteCxpReg(hCamera, sCameraRegs.dwAcqStopAddress, sCameraRegs.dwAcqStopValue, 800); } /* Stop frame grabber */ Phx.PHX_StreamRead(hCamera, Phx.etAcq.PHX_ABORT, IntPtr.Zero); } Console.WriteLine("Exiting"); return(0); }
/// <summary> /// Create a new InstrumentationPhase object. /// </summary> /// <param name="config">The phase list container.</param> /// <param name="logger"> /// Logger to save information about the basic blocks in the assembly. /// </param> /// <returns>A new InstrumentationPhase object.</returns> public static InstrumentPhase New(Phx.Phases.PhaseConfiguration config, LogWriter logger) { InstrumentPhase instrumentPhase = new InstrumentPhase(); instrumentPhase.Initialize(config, "CodeCoverage instrumentation phase"); #if PHX_DEBUG_SUPPORT instrumentPhase.PhaseControl = InstrumentPhase.InstrumentPhaseControl; #endif instrumentPhase.Log = logger; return instrumentPhase; }
/// <summary> /// Get a symbol representing a function that takes an unsigned integer /// parameter. /// </summary> /// <param name="unit">Module calling the function.</param> /// <param name="assembly">Name of the assembly.</param> /// <param name="type">Name of the class.</param> /// <param name="method">Name of the function.</param> /// <returns>FunctionSymbol representing the function.</returns> private static Phx.Symbols.FunctionSymbol GetFunctionSymbol(Phx.PEModuleUnit unit, string assembly, string type, string method) { // Look the function up in the cache Phx.Symbols.FunctionSymbol functionSymbol = null; if (FunctionSymbols.TryGetValue(unit, out functionSymbol) && functionSymbol != null) { return functionSymbol; } // Create symbols for the assemblies and types Phx.Symbols.AssemblySymbol assemblySymbol = GetAssemblySymbol(unit, assembly); Phx.Symbols.MsilTypeSymbol typeSymbol = GetTypeSymbol(unit, type, assemblySymbol); // Build a symbol reference Phx.Types.FunctionTypeBuilder builder = Phx.Types.FunctionTypeBuilder.New(unit.TypeTable); builder.Begin(); builder.CallingConventionKind = Phx.Types.CallingConventionKind.ClrCall; builder.AppendReturnParameter(unit.TypeTable.VoidType); builder.AppendParameter(unit.TypeTable.UInt32Type); // Create the function symbol Phx.Name name = Phx.Name.New(unit.Lifetime, method); functionSymbol = Phx.Symbols.FunctionSymbol.New(unit.SymbolTable, 0, name, builder.GetFunctionType(), Phx.Symbols.Visibility.GlobalReference); typeSymbol.InsertInLexicalScope(functionSymbol, name); // Create a type Phx.Types.AggregateType aggregate = Phx.Types.AggregateType.NewDynamicSize(unit.TypeTable, typeSymbol); aggregate.IsDefinition = false; aggregate.AppendMethodSymbol(functionSymbol); // Cache the function FunctionSymbols[unit] = functionSymbol; return functionSymbol; }
/// <summary> /// Get a symbol representing a type in the assembly. /// </summary> /// <param name="unit">Module calling the type.</param> /// <param name="type">Name of the type.</param> /// <param name="assembly">Assembly containing the type.</param> /// <returns>Symbol representing the type.</returns> private static Phx.Symbols.MsilTypeSymbol GetTypeSymbol(Phx.ModuleUnit unit, string type, Phx.Symbols.AssemblySymbol assembly) { Phx.Symbols.MsilTypeSymbol typeSymbol = null; // Look for any existing symbol foreach (Phx.Symbols.Symbol symbol in unit.SymbolTable.AllSymbols) { Phx.Symbols.MsilTypeSymbol s = symbol as Phx.Symbols.MsilTypeSymbol; if (s != null && s.NameString.Equals(type)) { typeSymbol = s; break; } } if (typeSymbol == null) { // Create the symbol if not found Phx.Name classTypeName = Phx.Name.New(unit.Lifetime, type); typeSymbol = Phx.Symbols.MsilTypeSymbol.New(unit.SymbolTable, classTypeName, 0); // Add the type to the assembly's scope assembly.InsertInLexicalScope(typeSymbol, classTypeName); } return typeSymbol; }
/// <summary> /// Get a symbol representing the assembly. /// </summary> /// <param name="unit">Module calling the assembly.</param> /// <param name="assembly">Name of the assembly.</param> /// <returns>Symbol representing the assembly.</returns> private static Phx.Symbols.AssemblySymbol GetAssemblySymbol(Phx.ModuleUnit unit, string assembly) { Phx.Symbols.AssemblySymbol assemblySymbol = null; // Look for any existing symbol foreach (Phx.Symbols.Symbol symbol in unit.SymbolTable.AllSymbols) { Phx.Symbols.AssemblySymbol s = symbol as Phx.Symbols.AssemblySymbol; if (s != null && s.NameString.Equals(assembly)) { assemblySymbol = s; break; } } if (assemblySymbol == null) { // Create the assembly manifest Phx.Name name = Phx.Name.New(unit.Lifetime, assembly); Phx.Version version = Phx.Version.New(unit.Lifetime); // A bug in Phx.Version ToString renders this field incorrect in // the debugger, FYI. version.MajorVersion = (ushort)CoverageVisitAssemblyVersion.Major; version.MinorVersion = (ushort)CoverageVisitAssemblyVersion.Minor; version.BuildNumber = (ushort)CoverageVisitAssemblyVersion.Build; version.RevisionNumber = (ushort)CoverageVisitAssemblyVersion.Revision; Phx.Manifest manifest = Phx.Manifest.New(unit.Lifetime); manifest.Name = name; manifest.HashAlgorithm = 0x00008004; manifest.Version = version; if (!string.IsNullOrEmpty(CoverageVisitAssemblyPublicKey)) { byte[] key = PublicKeyTokenToBytes(CoverageVisitAssemblyPublicKey); if (key != null) { Phx.PublicKey pk = Phx.PublicKey.New(unit.Lifetime); pk.IsPublicKeyToken = true; pk.KeyLength = (uint)key.Length; pk.Key = key; manifest.PublicKey = pk; } } // Create the assembly symbol if not found assemblySymbol = Phx.Symbols.AssemblySymbol.New(null, manifest, name, unit.SymbolTable); } return assemblySymbol; }
/// <summary> /// Inject a call to the coverage function with the id of a basic block /// before its first instruction. /// </summary> /// <param name="function">Function being instrumented.</param> /// <param name="coverageVisit"> /// Coverage function to call before each block. /// </param> /// <param name="block"> /// The id of the block to pass to the coverage function. /// </param> /// <param name="blockStartInstruction"> /// First instruction of the basic block. /// </param> private static void InjectCoverageCall(Phx.FunctionUnit function, Phx.Symbols.FunctionSymbol coverageVisit, uint block, Phx.IR.Instruction blockStartInstruction) { Phx.Types.Table typeTable = function.ParentUnit.TypeTable; if (function.FlowGraph == null) { function.BuildFlowGraph(); } // Create the instructions Phx.IR.Operand blockOperand = Phx.IR.ImmediateOperand.New(function, typeTable.UInt32Type, (uint)block); Phx.IR.Instruction loadBlock = Phx.IR.ValueInstruction.NewUnaryExpression(function, Phx.Targets.Architectures.Msil.Opcode.ldc, typeTable.UInt32Type, blockOperand); loadBlock.DestinationOperand.Register = Phx.Targets.Architectures.Msil.Register.SR0; Phx.IR.Instruction callCoverage = Phx.IR.CallInstruction.New(function, Phx.Targets.Architectures.Msil.Opcode.call, coverageVisit); // Insert the instructions blockStartInstruction.InsertBefore(loadBlock); callCoverage.AppendSource(loadBlock.DestinationOperand); loadBlock.DestinationOperand.BreakExpressionTemporary(); loadBlock.DebugTag = blockStartInstruction.DebugTag; blockStartInstruction.InsertBefore(callCoverage); }
/// <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; bool skipBlock = first == last; if (!skipBlock) { Log.StartBlock( BlockCounter, first.GetMsilOffset(), first.GetFileName(), first.GetLineNumber(), first.GetColumnNumber(), last.GetLineNumberEnd(), last.GetColumnNumberEnd()); } Phx.Symbols.FunctionSymbol coverageVisit = GetFunctionSymbol(module, CoverageVisitAssembly, CoverageVisitType, CoverageVisitMethod); if (!skipBlock) { 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 if (!skipBlock) { 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(); }