/*! @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 <limits.h>
#include <iostream>
#include <iomanip>
#include <rld.h>
#include <rtems-utils.h>
#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;
}
}