/*! @file ExecutableInfo.cc * @brief ExecutableInfo Implementation * * This file contains the implementation of the functionality * of the ExecutableInfo class. */ #include #include #include "ExecutableInfo.h" #include "app_common.h" #include "CoverageMap.h" #include "DesiredSymbols.h" #include "SymbolTable.h" namespace Coverage { ExecutableInfo::ExecutableInfo( const char* const theExecutableName, const char* const theLibraryName, bool verbose ) : executable(theExecutableName), loadAddress(0) { if (theLibraryName != nullptr) libraryName = theLibraryName; if (verbose) { std::cerr << "Loading executable " << theExecutableName; if (theLibraryName != nullptr) std::cerr << " (" << theLibraryName << ')'; std::cerr << std::endl; } executable.open(); executable.begin(); executable.load_symbols(symbols); debug.begin(executable.elf()); debug.load_debug(); debug.load_functions(); try { for (auto& cu : debug.get_cus()) { for (auto& func : cu.get_functions()) { if (func.has_machine_code() && (!func.is_inlined() || func.is_external())) { createCoverageMap (cu.name(), func.name(), func.pc_low(), func.pc_high() - 1); } } } } catch (...) { debug.end(); executable.end(); executable.close(); throw; } debug.end(); executable.end(); executable.close(); } ExecutableInfo::~ExecutableInfo() { } void ExecutableInfo::dumpCoverageMaps( void ) { ExecutableInfo::CoverageMaps::iterator itr; for (auto& cm : coverageMaps) { std::cerr << "Coverage Map for " << cm.first << std::endl; cm.second->dump(); } } void ExecutableInfo::dumpExecutableInfo( void ){ std::cout << std::endl << "== Executable info ==" << std::endl << "executable = " << getFileName () << std::endl << "library = " << libraryName << std::endl << "loadAddress = " << loadAddress << std::endl; theSymbolTable.dumpSymbolTable(); } CoverageMapBase* ExecutableInfo::getCoverageMap ( uint32_t address ) { CoverageMapBase* aCoverageMap = NULL; CoverageMaps::iterator it; std::string itsSymbol; // Obtain the coverage map containing the specified address. itsSymbol = theSymbolTable.getSymbol( address ); if (itsSymbol != "") { it = coverageMaps.find( itsSymbol ); aCoverageMap = (*it).second; } return aCoverageMap; } const std::string ExecutableInfo::getFileName ( void ) const { return executable.name().full(); } const std::string ExecutableInfo::getLibraryName( void ) const { return libraryName; } uint32_t ExecutableInfo::getLoadAddress( void ) const { return loadAddress; } SymbolTable* ExecutableInfo::getSymbolTable ( void ) { return &theSymbolTable; } CoverageMapBase& ExecutableInfo::findCoverageMap( const std::string& symbolName ) { CoverageMaps::iterator cmi = coverageMaps.find( symbolName ); if ( cmi == coverageMaps.end() ) throw rld::error (symbolName, "ExecutableInfo::findCoverageMap"); return *(cmi->second); } void ExecutableInfo::createCoverageMap ( const std::string& fileName, const std::string& symbolName, uint32_t lowAddress, uint32_t highAddress ) { CoverageMapBase *theMap; CoverageMaps::iterator itr; itr = coverageMaps.find( symbolName ); if ( itr == coverageMaps.end() ) { theMap = new CoverageMap( fileName, lowAddress, highAddress ); coverageMaps[ symbolName ] = theMap; } else { theMap = itr->second; theMap->Add( lowAddress, highAddress ); } } void ExecutableInfo::getSourceAndLine( const unsigned int address, std::string& line ) { std::string file; int lno; debug.get_source (address, file, lno); std::ostringstream ss; ss << file << ':' << lno; line = ss.str (); } bool ExecutableInfo::hasDynamicLibrary( void ) { return !libraryName.empty(); } void ExecutableInfo::mergeCoverage( void ) { for (auto& cm : coverageMaps) { if (SymbolsToAnalyze->isDesired( cm.first )) SymbolsToAnalyze->mergeCoverageMap( cm.first, cm.second ); } } void ExecutableInfo::setLoadAddress( uint32_t address ) { loadAddress = address; } }