/*! @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 "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 { 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") << std::endl << " 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( void ) const { std::cerr << "Coverage Map Contents:" << std::endl; 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; } 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; } 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; } }