summaryrefslogtreecommitdiff
path: root/tester
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2018-08-06 09:41:08 +1000
committerChris Johns <chrisj@rtems.org>2018-08-07 09:11:29 +1000
commit99c90b3353bf5b638dcfd87803e4aaf02adf3219 (patch)
tree06261fff19936db1f0db82383d02ba9eb2e75ed8 /tester
parentf450227669787627547c0da120400eda2fc92e08 (diff)
tester/covoar: Integrate DWARF function data.
Use DAWRF function data to create the executable coverage maps. Integrate the existing objdump processing with this data. - Refactor CoverageMapBase to have the address ranges and address info as separate objects. Move the to address info into a vector. Add support for multiple address ranges. - DesiredSymbols is only interested in function symbols. - ExecutableInfo creates coverage maps from DWARF function data. - Add warning flags to the covoar build. - Varous C++11 refactoring.
Diffstat (limited to 'tester')
-rw-r--r--tester/covoar/CoverageMapBase.cc372
-rw-r--r--tester/covoar/CoverageMapBase.h185
-rw-r--r--tester/covoar/DesiredSymbols.cc33
-rw-r--r--tester/covoar/ExecutableInfo.cc41
-rw-r--r--tester/covoar/ExecutableInfo.h32
-rw-r--r--tester/covoar/ObjdumpProcessor.cc122
-rw-r--r--tester/covoar/covoar.cc20
-rw-r--r--tester/covoar/wscript4
8 files changed, 381 insertions, 428 deletions
diff --git a/tester/covoar/CoverageMapBase.cc b/tester/covoar/CoverageMapBase.cc
index 87c8e8f..ad0080d 100644
--- a/tester/covoar/CoverageMapBase.cc
+++ b/tester/covoar/CoverageMapBase.cc
@@ -11,98 +11,135 @@
#include <iostream>
#include <iomanip>
+#include <rld.h>
+
#include "CoverageMapBase.h"
namespace Coverage {
- CoverageMapBase::CoverageMapBase(
- const std::string& exefileName,
- uint32_t low,
- uint32_t high
- )
+ AddressInfo::AddressInfo ()
+ : isStartOfInstruction (false),
+ wasExecuted (false),
+ isBranch (false),
+ isNop (false),
+ wasTaken (false),
+ wasNotTaken (false)
{
- uint32_t a;
- AddressRange range;
+ }
- range.fileName = exefileName;
- range.lowAddress = low;
- range.highAddress = high;
- Ranges.push_back( range );
+ AddressRange::AddressRange ()
+ : lowAddress(0),
+ highAddress(0)
+ {
+ }
- Size = high - low + 1;
+ AddressRange::AddressRange (const std::string& name,
+ uint32_t lowAddress,
+ uint32_t highAddress)
+ : fileName (name),
+ lowAddress (lowAddress),
+ highAddress (highAddress)
+ {
+ info.resize( size( ) );
+ }
- Info = new perAddressInfo[ Size ];
+ size_t AddressRange::size () const
+ {
+ return highAddress - lowAddress + 1;
+ }
- for (a = 0; a < Size; a++) {
+ bool AddressRange::inside (uint32_t address) const
+ {
+ return address >= lowAddress && address <= highAddress;
+ }
- perAddressInfo *i = &Info[ a ];
+ 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];
+ }
- i->isStartOfInstruction = false;
- i->wasExecuted = 0;
- i->isBranch = false;
- i->isNop = false;
- i->wasTaken = 0;
- i->wasNotTaken = 0;
- }
+ 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];
}
- CoverageMapBase::~CoverageMapBase()
+ void AddressRange::dump (std::ostream& out, bool show_slots) const
{
- if (Info)
- delete Info;
+ 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;
+ }
+ }
}
- void CoverageMapBase::Add( uint32_t low, uint32_t high )
+ CoverageMapBase::CoverageMapBase(
+ const std::string& exefileName,
+ uint32_t low,
+ uint32_t high
+ ) : exefileName (exefileName)
{
- AddressRange range;
+ Ranges.push_back( AddressRange( exefileName, low, high ) );
+ }
- range.lowAddress = low;
- range.highAddress = high;
- Ranges.push_back( range );
+ CoverageMapBase::~CoverageMapBase()
+ {
}
- bool CoverageMapBase::determineOffset(
- uint32_t address,
- uint32_t *offset
- )const
+ void CoverageMapBase::Add( uint32_t low, uint32_t high )
{
- AddressRanges::const_iterator itr;
+ Ranges.push_back( AddressRange( exefileName, low, high ) );
+ }
- for ( auto& r : Ranges ) {
- if ((address >= r.lowAddress) && (address <= r.highAddress)){
- *offset = address - r.lowAddress;
+ bool CoverageMapBase::validAddress( const uint32_t address ) const
+ {
+ for ( auto r : Ranges )
+ if (r.inside( address ))
return true;
- }
- }
- *offset = 0;
return false;
}
-
void CoverageMapBase::dump( void ) const
{
- fprintf( stderr, "Coverage Map Contents:\n" );
- /*
- * XXX - Dump is only marking the first Address Range.
- */
- for (uint32_t a = 0; a < Size; a++) {
- perAddressInfo* entry = &Info[ a ];
- std::cerr << std::hex << std::setfill('0')
- << "0x" << a + Ranges.front().lowAddress
- << "- isStartOfInstruction:"
- << (char*) (entry->isStartOfInstruction ? "yes" : "no")
- << " wasExecuted:"
- << (char*) (entry->wasExecuted ? "yes" : "no")
- << std::endl
- << " isBranch:"
- << (char*) (entry->isBranch ? "yes" : "no")
- << " wasTaken:"
- << (char*) (entry->wasTaken ? "yes" : "no")
- << " wasNotTaken:"
- << (char*) (entry->wasNotTaken ? "yes" : "no")
- << std::dec << std::setfill(' ')
- << std::endl;
- }
+ 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(
@@ -114,15 +151,14 @@ namespace Coverage {
uint32_t start;
AddressRange range;
-
- status = getRange( address, &range );
+ status = getRange( address, range );
if ( status != true )
return status;
start = address;
while (start >= range.lowAddress ) {
- if (Info[ start - range.lowAddress ].isStartOfInstruction) {
+ if (isStartOfInstruction( start - range.lowAddress )) {
*beginning = start;
status = true;
break;
@@ -136,258 +172,192 @@ namespace Coverage {
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
+ bool CoverageMapBase::getRange( uint32_t address, AddressRange& range ) const
{
for ( auto r : Ranges ) {
- if ((address >= r.lowAddress) && (address <= r.highAddress)){
- range->lowAddress = r.lowAddress;
- range->highAddress = r.highAddress;
+ if (r.inside( address )) {
+ range.lowAddress = r.lowAddress;
+ range.highAddress = r.highAddress;
+ range.info = r.info;
return true;
}
}
-
- range->lowAddress = 0;
- range->highAddress = 0;
-
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" );
}
- uint32_t CoverageMapBase::getSize() const
+ const AddressInfo& CoverageMapBase::getInfo( uint32_t address ) const
{
- return Size;
+ 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
)
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
- return;
-
- Info[ offset ].isStartOfInstruction = true;
+ if ( validAddress( address ) )
+ getInfo( address ).isStartOfInstruction = true;
}
bool CoverageMapBase::isStartOfInstruction( uint32_t address ) const
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return false;
-
- return Info[ offset ].isStartOfInstruction;
+ return getInfo( address ).isStartOfInstruction;
}
void CoverageMapBase::setWasExecuted( uint32_t address )
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
- return;
-
- Info[ offset ].wasExecuted += 1;
+ if ( validAddress( address ) )
+ getInfo( address ).wasExecuted += 1;
}
void CoverageMapBase::sumWasExecuted( uint32_t address, uint32_t addition)
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
- return;
-
- Info[ offset ].wasExecuted += addition;
+ if ( validAddress( address ) )
+ getInfo( address ).wasExecuted += addition;
}
bool CoverageMapBase::wasExecuted( uint32_t address ) const
{
- uint32_t offset;
- bool result;
-
- result = true;
-
- if (determineOffset( address, &offset ) != true)
- result = false;
-
- if (Info[ offset ].wasExecuted <= 0)
- result = false;
-
+ bool result = false;
+ if ( validAddress( address ) && (getInfo( address ).wasExecuted > 0))
+ result = true;
return result;
}
uint32_t CoverageMapBase::getWasExecuted( uint32_t address ) const
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return 0;
-
- return Info[ offset ].wasExecuted;
+ return getInfo( address ).wasExecuted;
}
void CoverageMapBase::setIsBranch(
uint32_t address
)
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
- return;
-
- Info[ offset ].isBranch = true;
+ if ( validAddress( address ) )
+ getInfo( address ).isBranch = true;
}
bool CoverageMapBase::isNop( uint32_t address ) const
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return false;
-
- return Info[ offset ].isNop;
+ return getInfo( address ).isNop;
}
void CoverageMapBase::setIsNop(
uint32_t address
)
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return;
-
- Info[ offset ].isNop = true;
+ getInfo( address ).isNop = true;
}
bool CoverageMapBase::isBranch( uint32_t address ) const
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return false;
-
- return Info[ offset ].isBranch;
+ return getInfo( address ).isBranch;
}
void CoverageMapBase::setWasTaken(
uint32_t address
)
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return;
-
- Info[ offset ].wasTaken += 1;
+ getInfo( address ).wasTaken += 1;
}
void CoverageMapBase::setWasNotTaken(
uint32_t address
)
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return;
-
- Info[ offset ].wasNotTaken += 1;
+ getInfo( address ).wasNotTaken += 1;
}
bool CoverageMapBase::wasAlwaysTaken( uint32_t address ) const
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return false;
-
- return (Info[ offset ].wasTaken &&
- !Info[ offset ].wasNotTaken);
+ const AddressInfo& info = getInfo( address );
+ return info.wasTaken && !info.wasNotTaken;
}
bool CoverageMapBase::wasNeverTaken( uint32_t address ) const
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return false;
-
- return (!Info[ offset ].wasTaken &&
- Info[ offset ].wasNotTaken);
+ const AddressInfo& info = getInfo( address );
+ return !info.wasTaken && info.wasNotTaken;
}
bool CoverageMapBase::wasNotTaken( uint32_t address ) const
{
- uint32_t offset;
- bool result;
-
- result = true;
-
- if (determineOffset( address, &offset ) != true)
- result = false;
-
- if (Info[ offset ].wasNotTaken <= 0)
- result = false;
-
- return result;
+ 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)
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
- return;
-
- Info[ offset ].wasNotTaken += addition;
+ if ( validAddress( address ) )
+ getInfo( address ).wasNotTaken += addition;
}
uint32_t CoverageMapBase::getWasNotTaken( uint32_t address ) const
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return 0;
-
- return Info[ offset ].wasNotTaken;
+ return getInfo( address ).wasNotTaken;
}
bool CoverageMapBase::wasTaken( uint32_t address ) const
{
- uint32_t offset;
- bool result;
-
- result = true;
-
- if (determineOffset( address, &offset ) != true)
+ bool result = true;
+ if ( !validAddress( address ) )
result = false;
-
- if (Info[ offset ].wasTaken <= 0)
+ else if ( getInfo( address ).wasTaken <= 0 )
result = false;
-
return result;
}
void CoverageMapBase::sumWasTaken( uint32_t address, uint32_t addition)
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return;
-
- Info[ offset ].wasTaken += addition;
+ getInfo( address ).wasTaken += addition;
}
uint32_t CoverageMapBase::getWasTaken( uint32_t address ) const
{
- uint32_t offset;
-
- if (determineOffset( address, &offset ) != true)
+ if ( !validAddress( address ) )
return 0;
-
- return Info[ offset ].wasTaken;
+ return getInfo( address ).wasTaken;
}
}
diff --git a/tester/covoar/CoverageMapBase.h b/tester/covoar/CoverageMapBase.h
index c8cd90f..6ad76d3 100644
--- a/tester/covoar/CoverageMapBase.h
+++ b/tester/covoar/CoverageMapBase.h
@@ -9,45 +9,106 @@
#include <stdint.h>
#include <string>
+#include <vector>
#include <list>
namespace Coverage {
- /*! @class CoverageMapBase
- *
- * This is the base class for Coverage Map implementations.
+ /*!
+ * This structure defines the information that is gathered and
+ * tracked per address.
*/
- class CoverageMapBase {
+ struct AddressInfo {
- public:
+ AddressInfo ();
/*!
- * This structure identifies the low and high addresses
- * of one range. Note:: There may be more than one address
- * range per symbol.
+ * This member indicates that the address is the start of
+ * an instruction.
+ */
+ bool isStartOfInstruction;
+ /*!
+ * This member indicates how many times the address was executed.
+ */
+ uint32_t wasExecuted;
+ /*!
+ * This member indicates that the address is a branch instruction.
+ */
+ bool isBranch;
+ /*!
+ * This member indicates that the address is a NOP instruction.
+ */
+ bool isNop;
+ /*!
+ * When isBranch is TRUE, this member indicates that the branch
+ * instruction at the address was taken.
+ */
+ uint32_t wasTaken;
+ /*!
+ * When isBranch is TRUE, this member indicates that the branch
+ * instruction at the address was NOT taken.
*/
- struct AddressRange {
- /*!
- * This is the file from which this originated.
- */
- std::string fileName;
+ uint32_t wasNotTaken;
- /*!
- * This is the low address of the address map range.
- */
- uint32_t lowAddress;
+ };
- /*!
- * This is the high address of the address map range.
- */
- uint32_t highAddress;
+ typedef std::vector < AddressInfo > AddressInfos;
- };
+ /*!
+ * This structure identifies the low and high addresses
+ * of one range. Note:: There may be more than one address
+ * range per symbol.
+ */
+ struct AddressRange {
+
+ AddressRange ();
+ AddressRange (const std::string& name,
+ uint32_t lowAddress,
+ uint32_t highAddress);
+
+ size_t size () const;
+
+ bool inside (uint32_t address) const;
+
+ AddressInfo& get (uint32_t address);
+ const AddressInfo& get (uint32_t address) const;
+
+ void dump (std::ostream& out, bool show_slots = false) const;
+
+ /*!
+ * This is the file from which this originated.
+ */
+ std::string fileName;
+
+ /*!
+ * This is the low address of the address map range.
+ */
+ uint32_t lowAddress;
+
+ /*!
+ * This is the high address of the address map range.
+ */
+ uint32_t highAddress;
- /*
- * This type identifies a list of ranges.
+ /*!
+ * The address info for this range.
*/
- typedef std::list< AddressRange > AddressRanges;
+ AddressInfos info;
+
+ };
+
+ /*
+ * This type identifies a list of ranges.
+ */
+ typedef std::vector< AddressRange > AddressRanges;
+
+ /*! @class CoverageMapBase
+ *
+ * This is the base class for Coverage Map implementations.
+ */
+ class CoverageMapBase {
+
+ public:
/*!
* This method constructs a CoverageMapBase instance.
@@ -77,25 +138,16 @@ namespace Coverage {
void Add( uint32_t low, uint32_t high );
/*!
- * This method returns true and sets the offset if
- * the address falls with the bounds of an address range
- * in the RangeList.
- *
- * @param[in] address specifies the address to find
- * @param[out] offset contains the offset from the low
- * address of the address range.
- *
- * @return Returns TRUE if the address range can be found
- * and FALSE if it was not.
- */
- bool determineOffset( uint32_t address, uint32_t *offset ) const;
-
- /*!
* This method prints the contents of the coverage map to stdout.
*/
void dump( void ) const;
/*!
+ * Address valid?
+ */
+ bool validAddress( const uint32_t address ) const;
+
+ /*!
* This method will return the low address of the first range in
* the RangeList.
*
@@ -116,7 +168,7 @@ namespace Coverage {
* @return Returns TRUE if the address range can be found
* and FALSE if it was not.
*/
- bool getRange( uint32_t address, AddressRange *range ) const;
+ bool getRange( uint32_t address, AddressRange& range ) const;
/*!
* This method returns the size of the address range.
@@ -125,7 +177,6 @@ namespace Coverage {
*/
uint32_t getSize() const;
-
/*!
* This method returns the address of the beginning of the
* instruction that contains the specified address.
@@ -358,41 +409,12 @@ namespace Coverage {
*/
bool wasTaken( uint32_t address ) const;
- protected:
-
- /*!
- * This structure defines the information that is gathered and
- * tracked per address.
- */
- struct perAddressInfo {
- /*!
- * This member indicates that the address is the start of
- * an instruction.
- */
- bool isStartOfInstruction;
- /*!
- * This member indicates how many times the address was executed.
- */
- uint32_t wasExecuted;
- /*!
- * This member indicates that the address is a branch instruction.
- */
- bool isBranch;
- /*!
- * This member indicates that the address is a NOP instruction.
- */
- bool isNop;
- /*!
- * When isBranch is TRUE, this member indicates that the branch
- * instruction at the address was taken.
- */
- uint32_t wasTaken;
- /*!
- * When isBranch is TRUE, this member indicates that the branch
- * instruction at the address was NOT taken.
- */
- uint32_t wasNotTaken;
- };
+ private:
+
+ /*!
+ * The executable file name.
+ */
+ std::string exefileName;
/*!
*
@@ -401,16 +423,15 @@ namespace Coverage {
AddressRanges Ranges;
/*!
- *
- * This variable contains the size of the code block.
+ * Range checked access to the info.
*/
- uint32_t Size;
+ AddressInfo& getInfo(uint32_t offset);
/*!
- * This is a dynamically allocated array of data that is
- * kept for each address.
+ * Constant range checked access to the info.
*/
- perAddressInfo* Info;
+ const AddressInfo& getInfo(uint32_t offset) const;
+
};
}
diff --git a/tester/covoar/DesiredSymbols.cc b/tester/covoar/DesiredSymbols.cc
index a38860a..60d22c3 100644
--- a/tester/covoar/DesiredSymbols.cc
+++ b/tester/covoar/DesiredSymbols.cc
@@ -96,11 +96,13 @@ namespace Coverage {
for (auto& kv : symbols.globals()) {
const rld::symbols::symbol& sym = *(kv.second);
- set[sym.name()] = *(new SymbolInformation);
+ if (sym.type() == sym.st_func)
+ set[sym.name()] = *(new SymbolInformation);
}
for (auto& kv : symbols.weaks()) {
const rld::symbols::symbol& sym = *(kv.second);
- set[sym.name()] = *(new SymbolInformation);
+ if (sym.type() == sym.st_func)
+ set[sym.name()] = *(new SymbolInformation);
}
} catch (...) {
cache.close();
@@ -345,9 +347,10 @@ namespace Coverage {
<< "unified coverage maps for "
<< symbolName
<< " with different sizes ("
- << exefileName << '/' << itr->second.stats.sizeInBytes
- << "!= "
- << itr->second.sourceFile->getFileName() << '/' << size << ')'
+ << rld::path::basename(exefileName) << '/' << itr->second.stats.sizeInBytes
+ << " != "
+ << rld::path::basename(itr->second.sourceFile->getFileName())
+ << '/' << size << ')'
<< std::endl;
if ( itr->second.stats.sizeInBytes < size )
@@ -450,14 +453,7 @@ namespace Coverage {
const std::string& symbolName
) const
{
- if (set.find( symbolName ) == set.end()) {
- #if 0
- std::cerr << "Warning: Unable to find symbol " << symbolName
- << std::endl;
- #endif
- return false;
- }
- return true;
+ return set.find( symbolName ) == set.end() ? false : true;
}
void DesiredSymbols::mergeCoverageMap(
@@ -476,23 +472,26 @@ namespace Coverage {
throw rld::error( what, "DesiredSymbols::mergeCoverageMap" );
}
+ SymbolInformation& sinfo = itr->second;
+
// Ensure that the source and destination coverage maps
// are the same size.
// Changed from ERROR msg to INFO, because size mismatch is not
// treated as error anymore. 2015-07-20
- uint32_t dMapSize = itr->second.stats.sizeInBytes;
+ uint32_t dMapSize = sinfo.stats.sizeInBytes;
uint32_t sBaseAddress = sourceCoverageMap->getFirstLowAddress();
uint32_t sMapSize = sourceCoverageMap->getSize();
- if (dMapSize != sMapSize) {
+ if (dMapSize != 0 && dMapSize != sMapSize) {
std::cerr << "INFO: DesiredSymbols::mergeCoverageMap - Unable to merge "
<< "coverage map for " << symbolName
- << " because the sizes are different"
+ << " because the sizes are different ("
+ << "size: " << dMapSize << ", source: " << sMapSize << ')'
<< std::endl;
return;
}
// Merge the data for each address.
- CoverageMapBase* destinationCoverageMap = itr->second.unifiedCoverageMap;
+ CoverageMapBase* destinationCoverageMap = sinfo.unifiedCoverageMap;
for (uint32_t dAddress = 0; dAddress < dMapSize; dAddress++) {
diff --git a/tester/covoar/ExecutableInfo.cc b/tester/covoar/ExecutableInfo.cc
index 710b25c..0a629b7 100644
--- a/tester/covoar/ExecutableInfo.cc
+++ b/tester/covoar/ExecutableInfo.cc
@@ -19,19 +19,36 @@ namespace Coverage {
ExecutableInfo::ExecutableInfo(
const char* const theExecutableName,
- const char* const theLibraryName
+ const char* const theLibraryName,
+ bool verbose
) : executable(theExecutableName),
loadAddress(0)
{
- if (theLibraryName)
+ 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();
+
+ 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());
+ }
+ }
+ }
}
ExecutableInfo::~ExecutableInfo()
@@ -95,7 +112,17 @@ namespace Coverage {
return &theSymbolTable;
}
- CoverageMapBase* ExecutableInfo::createCoverageMap (
+ 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,
@@ -113,7 +140,6 @@ namespace Coverage {
theMap = itr->second;
theMap->Add( lowAddress, highAddress );
}
- return theMap;
}
void ExecutableInfo::getSourceAndLine(
@@ -135,10 +161,9 @@ namespace Coverage {
}
void ExecutableInfo::mergeCoverage( void ) {
- ExecutableInfo::CoverageMaps::iterator itr;
-
- for (itr = coverageMaps.begin(); itr != coverageMaps.end(); itr++) {
- SymbolsToAnalyze->mergeCoverageMap( (*itr).first, (*itr).second );
+ for (auto& cm : coverageMaps) {
+ if (SymbolsToAnalyze->isDesired( cm.first ))
+ SymbolsToAnalyze->mergeCoverageMap( cm.first, cm.second );
}
}
diff --git a/tester/covoar/ExecutableInfo.h b/tester/covoar/ExecutableInfo.h
index 9106db3..dcb4dcb 100644
--- a/tester/covoar/ExecutableInfo.h
+++ b/tester/covoar/ExecutableInfo.h
@@ -37,7 +37,8 @@ namespace Coverage {
*/
ExecutableInfo(
const char* const theExecutableName,
- const char* const theLibraryName = NULL
+ const char* const theLibraryName = NULL,
+ bool verbose = false
);
/*!
@@ -95,21 +96,13 @@ namespace Coverage {
SymbolTable* getSymbolTable( void );
/*!
- * This method creates a coverage map for the specified symbol.
+ * This method finds a coverage map for the specified symbol.
*
- * @param[in] exefileName specifies the source of the information
* @param[in] symbolName specifies the name of the symbol
- * @param[in] lowAddress specifies the low address of the coverage map
- * @param[in] highAddress specifies the high address of the coverage map
*
- * @return Returns a pointer to the coverage map
+ * @return Returns a reference to the coverage map
*/
- CoverageMapBase* createCoverageMap (
- const std::string& exefileName,
- const std::string& symbolName,
- uint32_t lowAddress,
- uint32_t highAddress
- );
+ CoverageMapBase& findCoverageMap( const std::string& symbolName );
/*!
* This method gets the source location, the file and line number given an
@@ -145,6 +138,21 @@ namespace Coverage {
private:
/*!
+ * This method creates a coverage map for the specified symbol.
+ *
+ * @param[in] exefileName specifies the source of the information
+ * @param[in] symbolName specifies the name of the symbol
+ * @param[in] lowAddress specifies the low address of the coverage map
+ * @param[in] highAddress specifies the high address of the coverage map
+ */
+ void createCoverageMap (
+ const std::string& exefileName,
+ const std::string& symbolName,
+ uint32_t lowAddress,
+ uint32_t highAddress
+ );
+
+ /*!
* The ELF executable.
*/
rld::files::object executable;
diff --git a/tester/covoar/ObjdumpProcessor.cc b/tester/covoar/ObjdumpProcessor.cc
index c98dad7..b4c60c6 100644
--- a/tester/covoar/ObjdumpProcessor.cc
+++ b/tester/covoar/ObjdumpProcessor.cc
@@ -29,63 +29,17 @@ namespace Coverage {
void finalizeSymbol(
ExecutableInfo* const executableInfo,
std::string& symbolName,
- uint32_t lowAddress,
- uint32_t highAddress,
ObjdumpProcessor::objdumpLines_t instructions
) {
+ // Find the symbol's coverage map.
+ CoverageMapBase& coverageMap = executableInfo->findCoverageMap( symbolName );
- CoverageMapBase* aCoverageMap = NULL;
- uint32_t endAddress = highAddress;
- ObjdumpProcessor::objdumpLines_t::iterator itr, fnop, lnop;
- ObjdumpProcessor::objdumpLines_t::reverse_iterator ritr;
- SymbolInformation* symbolInfo = NULL;
- SymbolTable* theSymbolTable;
-
- //
- // Remove trailing nop instructions.
- //
-
- // First find the last instruction.
- for (ritr = instructions.rbegin();
- ritr != instructions.rend();
- ritr++) {
- if (ritr->isInstruction)
- break;
- }
-
- // If an instruction was found and it is a nop, ...
- if ((ritr != instructions.rend()) && (ritr->isNop)) {
-
- // save it as the last nop. Note that we must account for
- // the difference between a forward and a reverse iterator.
- lnop = ritr.base();
- lnop--;
- endAddress -= lnop->nopSize;
-
- // Now look for the first nop in the sequence of trailing nops.
- fnop = lnop;
- ritr++;
- for (; ritr != instructions.rend(); ritr++) {
- if (ritr->isNop) {
- fnop = ritr.base();
- fnop--;
- endAddress -= fnop->nopSize;
- }
- else
- break;
- }
-
- // Erase trailing nops. The erase operation wants the first
- // parameter to point to the first item to erase and the second
- // parameter to point to the item beyond the last item to erase.
- if ( fnop == lnop )
- instructions.erase( fnop );
- else
- instructions.erase( fnop, ++lnop );
- }
+ uint32_t lowAddress = coverageMap.getFirstLowAddress();
+ uint32_t size = coverageMap.getSize();
+ uint32_t highAddress = lowAddress + size;
// If there are NOT already saved instructions, save them.
- symbolInfo = SymbolsToAnalyze->find( symbolName );
+ SymbolInformation* symbolInfo = SymbolsToAnalyze->find( symbolName );
if (symbolInfo->instructions.empty()) {
symbolInfo->sourceFile = executableInfo;
symbolInfo->baseAddress = lowAddress;
@@ -93,32 +47,20 @@ namespace Coverage {
}
// Add the symbol to this executable's symbol table.
- theSymbolTable = executableInfo->getSymbolTable();
+ SymbolTable* theSymbolTable = executableInfo->getSymbolTable();
theSymbolTable->addSymbol(
- symbolName, lowAddress, endAddress - lowAddress + 1
+ symbolName, lowAddress, highAddress - lowAddress + 1
);
- // Create a coverage map for the symbol.
- aCoverageMap = executableInfo->createCoverageMap(
- executableInfo->getFileName().c_str(), symbolName, lowAddress, endAddress
- );
-
- if (aCoverageMap) {
-
- // Mark the start of each instruction in the coverage map.
- for (itr = instructions.begin();
- itr != instructions.end();
- itr++ ) {
-
- aCoverageMap->setIsStartOfInstruction( itr->address );
- }
-
- // Create a unified coverage map for the symbol.
- SymbolsToAnalyze->createCoverageMap(
- executableInfo->getFileName().c_str(), symbolName,
- endAddress - lowAddress + 1
- );
+ // Mark the start of each instruction in the coverage map.
+ for (auto& instruction : instructions) {
+ coverageMap.setIsStartOfInstruction( instruction.address );
}
+
+ // Create a unified coverage map for the symbol.
+ SymbolsToAnalyze->createCoverageMap(
+ executableInfo->getFileName().c_str(), symbolName, size
+ );
}
ObjdumpProcessor::ObjdumpProcessor()
@@ -353,18 +295,14 @@ namespace Coverage {
getFile( executableInformation->getLibraryName(), objdumpFile, err );
while ( true ) {
-
// Get the line.
objdumpFile.read_line( line );
if ( line.empty() ) {
-
// If we are currently processing a symbol, finalize it.
if (processSymbol) {
finalizeSymbol(
executableInformation,
currentSymbol,
- startAddress,
- executableInformation->getLoadAddress() + offset,
theInstructions
);
fprintf(
@@ -388,6 +326,9 @@ namespace Coverage {
lineInfo.nopSize = 0;
lineInfo.isBranch = false;
+ instruction[0] = '\0';
+ ID[0] = '\0';
+
// Look for the start of a symbol's objdump and extract
// offset and symbol (i.e. offset <symbolname>:).
items = sscanf(
@@ -407,7 +348,6 @@ namespace Coverage {
// If all items found, we are at the beginning of a symbol's objdump.
if ((items == 3) && (terminator1 == ':')) {
-
endAddress = executableInformation->getLoadAddress() + offset - 1;
// If we are currently processing a symbol, finalize it.
@@ -415,8 +355,6 @@ namespace Coverage {
finalizeSymbol(
executableInformation,
currentSymbol,
- startAddress,
- endAddress,
theInstructions
);
}
@@ -441,20 +379,17 @@ namespace Coverage {
&& (jumpTableID.find( "+0x" ) != std::string::npos)
&& processSymbol )
{
+ endAddress = executableInformation->getLoadAddress() + offset - 1;
- endAddress = executableInformation->getLoadAddress() + offset - 1;
-
- // If we are currently processing a symbol, finalize it.
- if ( processSymbol ) {
- finalizeSymbol(
- executableInformation,
- currentSymbol,
- startAddress,
- endAddress,
- theInstructions
+ // If we are currently processing a symbol, finalize it.
+ if ( processSymbol ) {
+ finalizeSymbol(
+ executableInformation,
+ currentSymbol,
+ theInstructions
);
- }
- processSymbol = false;
+ }
+ processSymbol = false;
}
else if (processSymbol) {
@@ -467,7 +402,6 @@ namespace Coverage {
// If it looks like an instruction ...
if ((items == 3) && (terminator1 == ':') && (terminator2 == '\t')) {
-
// update the line's information, save it and ...
lineInfo.address =
executableInformation->getLoadAddress() + instructionOffset;
diff --git a/tester/covoar/covoar.cc b/tester/covoar/covoar.cc
index 6e06071..36c24c3 100644
--- a/tester/covoar/covoar.cc
+++ b/tester/covoar/covoar.cc
@@ -247,10 +247,12 @@ int covoar(
if (!coverageFileNames.empty()) {
if (dynamicLibrary) {
executableInfo = new Coverage::ExecutableInfo(
- singleExecutable, dynamicLibrary
+ singleExecutable, dynamicLibrary, Verbose
);
} else {
- executableInfo = new Coverage::ExecutableInfo( singleExecutable );
+ executableInfo = new Coverage::ExecutableInfo(
+ singleExecutable, nullptr, Verbose
+ );
}
executablesToAnalyze.push_back( executableInfo );
@@ -272,7 +274,9 @@ int covoar(
std::cerr << "warning: Unable to read coverage file: " << coverageFileName
<< std::endl;
} else {
- executableInfo = new Coverage::ExecutableInfo( argv[i] );
+ executableInfo = new Coverage::ExecutableInfo(
+ argv[i], nullptr, Verbose
+ );
executablesToAnalyze.push_back( executableInfo );
coverageFileNames.push_back( coverageFileName );
}
@@ -573,15 +577,7 @@ int main(
}
catch (std::exception e)
{
- int status;
- char* realname;
- realname = abi::__cxa_demangle (e.what(), 0, 0, &status);
- std::cerr << "error: exception: " << realname << " [";
- ::free (realname);
- const std::type_info &ti = typeid (e);
- realname = abi::__cxa_demangle (ti.name(), 0, 0, &status);
- std::cerr << realname << "] " << e.what () << std::endl << std::flush;
- ::free (realname);
+ rld::output_std_exception(e, std::cerr);
ec = 11;
}
catch (...)
diff --git a/tester/covoar/wscript b/tester/covoar/wscript
index 645052f..d447117 100644
--- a/tester/covoar/wscript
+++ b/tester/covoar/wscript
@@ -106,8 +106,8 @@ def build(bld):
'Target_m68k.cc',
'Target_powerpc.cc',
'Target_sparc.cc'],
- cflags = ['-O2', '-g'],
- cxxflags = ['-std=c++11', '-O2', '-g'],
+ cflags = ['-O2', '-g', '-Wall'],
+ cxxflags = ['-std=c++11', '-O2', '-g', '-Wall'],
includes = ['.'] + rtl_includes)
bld.program(target = 'trace-converter',