/*! @file CoverageReaderQEMU.cc * @brief CoverageReaderQEMU Implementation * * This file contains the implementation of the functions supporting * reading the QEMU coverage data files. */ #include "covoar-config.h" #include #include #include #include #include #include "app_common.h" #include "CoverageReaderQEMU.h" #include "CoverageMap.h" #include "ExecutableInfo.h" #include "qemu-traces.h" #if HAVE_OPEN64 #define OPEN fopen64 #else #define OPEN fopen #endif namespace Coverage { CoverageReaderQEMU::CoverageReaderQEMU() { BranchInfoAvailable = true; } CoverageReaderQEMU::~CoverageReaderQEMU() { } void CoverageReaderQEMU::processFile( const char* const file, ExecutableInfo* const executableInformation ) { struct trace_header header; uintptr_t i; int status; FILE* traceFile; uint8_t taken; uint8_t notTaken; uint8_t branchInfo; taken = TargetInfo->qemuTakenBit(); notTaken = TargetInfo->qemuNotTakenBit(); branchInfo = taken | notTaken; // // Open the coverage file and read the header. // traceFile = ::OPEN( file, "r" ); if (!traceFile) { std::ostringstream what; what << "Unable to open " << file; throw rld::error( what, "CoverageReaderQEMU::processFile" ); } status = ::fread( &header, sizeof(trace_header), 1, traceFile ); if (status != 1) { ::fclose( traceFile ); std::ostringstream what; what << "Unable to read header from " << file; throw rld::error( what, "CoverageReaderQEMU::processFile" ); } // // Read ENTRIES number of trace entries. // #define ENTRIES 1024 while (true) { CoverageMapBase *aCoverageMap = NULL; struct trace_entry entries[ENTRIES]; struct trace_entry *entry; int num_entries; // Read and process each line of the coverage file. num_entries = ::fread( entries, sizeof(struct trace_entry), ENTRIES, traceFile ); if (num_entries == 0) break; // Get the coverage map for each entry. Note that the map is // the same for each entry in the coverage map for (int count=0; countgetCoverageMap( entry->pc ); // Ensure that coverage map exists. if (!aCoverageMap) continue; // Set was executed for each TRACE_OP_BLOCK if (entry->op & TRACE_OP_BLOCK) { for (i=0; isize; i++) { aCoverageMap->setWasExecuted( entry->pc + i ); } } // Determine if additional branch information is available. if ( (entry->op & branchInfo) != 0 ) { uint32_t a = entry->pc + entry->size - 1; while (!aCoverageMap->isStartOfInstruction(a)) a--; if (entry->op & taken) { aCoverageMap->setWasTaken( a ); } else if (entry->op & notTaken) { aCoverageMap->setWasNotTaken( a ); } } } } ::fclose( traceFile ); } }