/*! @file CoverageMapBase.cc * @brief CoverageMapBase Implementation * * This file contains the implementation of the functions * which provide a base level of functionality of a CoverageMap. */ #include #include #include #include #include #include "CoverageMapBase.h" namespace Coverage { AddressInfo::AddressInfo() : isStartOfInstruction( false ), wasExecuted( false ), isBranch( false ), isNop( false ), wasTaken( false ), wasNotTaken( false ) { } AddressRange::AddressRange() : lowAddress( 0 ), highAddress( 0 ) { } AddressRange::AddressRange( const std::string& name, uint32_t lowAddress, uint32_t highAddress) : fileName( name ), lowAddress( lowAddress ), highAddress( highAddress ) { info.resize( size() ); } size_t AddressRange::size() const { return highAddress - lowAddress + 1; } bool AddressRange::inside( uint32_t address ) const { return address >= lowAddress && address <= highAddress; } AddressInfo& AddressRange::get( uint32_t address ) { if ( !inside( address ) ) { throw rld::error( "address outside range", "AddressRange::get" ); } size_t slot = address - lowAddress; if ( slot >= info.size () ) { throw rld::error( "address slot not found", "AddressRange::get" ); } return info[slot]; } const AddressInfo& AddressRange::get( uint32_t address ) const { if ( !inside( address ) ) { throw rld::error( "address outside range", "AddressRange::get" ); } size_t slot = address - lowAddress; if ( slot >= info.size() ) { throw rld::error( "address slot not found", "AddressRange::get" ); } return info[slot]; } void AddressRange::dump( std::ostream& out, bool show_slots ) const { rtems::utils::ostream_guard old_state( out ); out << std::hex << std::setfill( '0' ) << "Address range: low = " << std::setw( 8 ) << lowAddress << " high = " << std::setw( 8 ) << highAddress << std::endl; if (show_slots) { size_t slot = 0; for ( auto& i : info ) { out << std::hex << std::setfill( '0' ) << "0x" << std::setw( 8 ) << slot++ + lowAddress << "- isStartOfInstruction:" << (char*) ( i.isStartOfInstruction ? "yes" : "no" ) << " wasExecuted:" << (char*) ( i.wasExecuted ? "yes" : "no" ) << "\n isBranch:" << (char*) ( i.isBranch ? "yes" : "no" ) << " wasTaken:" << (char*) ( i.wasTaken ? "yes" : "no" ) << " wasNotTaken:" << (char*) ( i.wasNotTaken ? "yes" : "no" ) << std::dec << std::setfill( ' ' ) << std::endl; } } } CoverageMapBase::CoverageMapBase( const std::string& exefileName, uint32_t low, uint32_t high ) : exefileName( exefileName ) { Ranges.push_back( AddressRange( exefileName, low, high ) ); } CoverageMapBase::~CoverageMapBase() { } void CoverageMapBase::Add( uint32_t low, uint32_t high ) { Ranges.push_back( AddressRange( exefileName, low, high ) ); } bool CoverageMapBase::validAddress( const uint32_t address ) const { for ( auto& r : Ranges ) { if ( r.inside( address ) ) { return true; } } return false; } void CoverageMapBase::dump() const { std::cerr << "Coverage Map Contents\n"; for ( auto& r : Ranges ) { r.dump( std::cerr ); } } uint32_t CoverageMapBase::getSize() const { size_t size = 0; for ( auto& r : Ranges ) { size += r.size (); } return size; } uint32_t CoverageMapBase::getSizeOfRange( size_t index ) const { return Ranges.at( index ).size(); } bool CoverageMapBase::getBeginningOfInstruction( uint32_t address, uint32_t* beginning ) const { bool status = false; uint32_t start; AddressRange range; status = getRange( address, range ); if ( status != true ) { return status; } start = address; while ( start >= range.lowAddress ) { if ( isStartOfInstruction( start - range.lowAddress ) ) { *beginning = start; status = true; break; } else { start--; } } return status; } int32_t CoverageMapBase::getFirstLowAddress() const { /* * This is broken, do not trust it. */ return Ranges.front().lowAddress; } uint32_t CoverageMapBase::getLowAddressOfRange( size_t index ) const { return Ranges.at( index ).lowAddress; } bool CoverageMapBase::getRange( uint32_t address, AddressRange& range ) const { for ( auto r : Ranges ) { if ( r.inside( address ) ) { range.lowAddress = r.lowAddress; range.highAddress = r.highAddress; range.info = r.info; return true; } } return false; } AddressInfo& CoverageMapBase::getInfo( uint32_t address ) { for ( auto& r : Ranges ) { if ( r.inside( address ) ) { return r.get( address ); } } throw rld::error( "address out of bounds", "CoverageMapBase::getInfo" ); } const AddressInfo& CoverageMapBase::getInfo( uint32_t address ) const { for ( auto& r : Ranges ) { if ( r.inside( address ) ) { return r.get( address ); } } throw rld::error( "address out of bounds", "CoverageMapBase::getInfo" ); } void CoverageMapBase::setIsStartOfInstruction( uint32_t address ) { if ( validAddress( address ) ) { getInfo( address ).isStartOfInstruction = true; } } bool CoverageMapBase::isStartOfInstruction( uint32_t address ) const { if ( !validAddress( address ) ) { return false; } return getInfo( address ).isStartOfInstruction; } void CoverageMapBase::setWasExecuted( uint32_t address ) { if ( validAddress( address ) ) { getInfo( address ).wasExecuted += 1; } } void CoverageMapBase::sumWasExecuted( uint32_t address, uint32_t addition ) { if ( validAddress( address ) ) { getInfo( address ).wasExecuted += addition; } } bool CoverageMapBase::wasExecuted( uint32_t address ) const { bool result = false; if ( validAddress( address ) && ( getInfo( address ).wasExecuted > 0 ) ) { result = true; } return result; } uint32_t CoverageMapBase::getWasExecuted( uint32_t address ) const { if ( !validAddress( address ) ) { return 0; } return getInfo( address ).wasExecuted; } void CoverageMapBase::setIsBranch( uint32_t address ) { if ( validAddress( address ) ) { getInfo( address ).isBranch = true; } } bool CoverageMapBase::isNop( uint32_t address ) const { if ( !validAddress( address ) ) { return false; } return getInfo( address ).isNop; } void CoverageMapBase::setIsNop( uint32_t address ) { if ( !validAddress( address ) ) { return; } getInfo( address ).isNop = true; } bool CoverageMapBase::isBranch( uint32_t address ) const { if ( !validAddress( address ) ) { return false; } return getInfo( address ).isBranch; } void CoverageMapBase::setWasTaken( uint32_t address ) { if ( !validAddress( address ) ) { return; } getInfo( address ).wasTaken += 1; } void CoverageMapBase::setWasNotTaken( uint32_t address ) { if ( !validAddress( address ) ) { return; } getInfo( address ).wasNotTaken += 1; } bool CoverageMapBase::wasAlwaysTaken( uint32_t address ) const { if ( !validAddress( address ) ) { return false; } const AddressInfo& info = getInfo( address ); return info.wasTaken && !info.wasNotTaken; } bool CoverageMapBase::wasNeverTaken( uint32_t address ) const { if ( !validAddress( address ) ) { return false; } const AddressInfo& info = getInfo( address ); return !info.wasTaken && info.wasNotTaken; } bool CoverageMapBase::wasNotTaken( uint32_t address ) const { bool result = true; if ( !validAddress( address ) ) { result = false; } else if ( getInfo( address ).wasNotTaken <= 0 ) { result = false; } return result; } void CoverageMapBase::sumWasNotTaken( uint32_t address, uint32_t addition ) { if ( validAddress( address ) ) { getInfo( address ).wasNotTaken += addition; } } uint32_t CoverageMapBase::getWasNotTaken( uint32_t address ) const { if ( !validAddress( address ) ) { return 0; } return getInfo( address ).wasNotTaken; } bool CoverageMapBase::wasTaken( uint32_t address ) const { bool result = true; if ( !validAddress( address ) ) { result = false; } else if ( getInfo( address ).wasTaken <= 0 ) { result = false; } return result; } void CoverageMapBase::sumWasTaken( uint32_t address, uint32_t addition ) { if ( !validAddress( address ) ) { return; } getInfo( address ).wasTaken += addition; } uint32_t CoverageMapBase::getWasTaken( uint32_t address ) const { if ( !validAddress( address ) ) { return 0; } return getInfo( address ).wasTaken; } }