diff options
author | Chris Johns <chrisj@rtems.org> | 2018-08-06 09:41:08 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2018-08-07 09:11:29 +1000 |
commit | 99c90b3353bf5b638dcfd87803e4aaf02adf3219 (patch) | |
tree | 06261fff19936db1f0db82383d02ba9eb2e75ed8 /tester/covoar | |
parent | linkers/exeinfo: Add an inlines report and DWARF data dump. (diff) | |
download | rtems-tools-99c90b3353bf5b638dcfd87803e4aaf02adf3219.tar.bz2 |
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/covoar')
-rw-r--r-- | tester/covoar/CoverageMapBase.cc | 372 | ||||
-rw-r--r-- | tester/covoar/CoverageMapBase.h | 185 | ||||
-rw-r--r-- | tester/covoar/DesiredSymbols.cc | 33 | ||||
-rw-r--r-- | tester/covoar/ExecutableInfo.cc | 41 | ||||
-rw-r--r-- | tester/covoar/ExecutableInfo.h | 32 | ||||
-rw-r--r-- | tester/covoar/ObjdumpProcessor.cc | 122 | ||||
-rw-r--r-- | tester/covoar/covoar.cc | 20 | ||||
-rw-r--r-- | tester/covoar/wscript | 4 |
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', |