[rtems-tools commit] covoar: Use DWARF to map addresses to source files and lines.
Chris Johns
chrisj at rtems.org
Tue Jun 19 03:42:45 UTC 2018
Module: rtems-tools
Branch: master
Commit: fb987e82be3e3d025875b6c39c92384c3e8a1c3e
Changeset: http://git.rtems.org/rtems-tools/commit/?id=fb987e82be3e3d025875b6c39c92384c3e8a1c3e
Author: Chris Johns <chrisj at rtems.org>
Date: Tue May 8 15:09:39 2018 +1000
covoar: Use DWARF to map addresses to source files and lines.
---
tester/covoar/CoverageMapBase.cc | 41 +++++++------
tester/covoar/DesiredSymbols.cc | 123 ++-------------------------------------
tester/covoar/ExecutableInfo.cc | 80 ++++++++++++++++---------
tester/covoar/ExecutableInfo.h | 41 ++++++++++---
tester/covoar/GcovData.cc | 29 +++++----
tester/covoar/covoar.cc | 2 +-
tester/covoar/wscript | 2 +-
7 files changed, 127 insertions(+), 191 deletions(-)
diff --git a/tester/covoar/CoverageMapBase.cc b/tester/covoar/CoverageMapBase.cc
index ed30603..d2b60d2 100644
--- a/tester/covoar/CoverageMapBase.cc
+++ b/tester/covoar/CoverageMapBase.cc
@@ -2,11 +2,10 @@
/*! @file CoverageMapBase.cc
* @brief CoverageMapBase Implementation
*
- * This file contains the implementation of the functions
+ * This file contains the implementation of the functions
* which provide a base level of functionality of a CoverageMap.
*/
-#include <libgen.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@@ -51,7 +50,7 @@ namespace Coverage {
if (Info)
delete Info;
}
-
+
void CoverageMapBase::Add( uint32_t low, uint32_t high )
{
AddressRange_t range;
@@ -60,9 +59,9 @@ namespace Coverage {
range.highAddress = high;
RangeList.push_back( range );
}
-
- bool CoverageMapBase::determineOffset(
- uint32_t address,
+
+ bool CoverageMapBase::determineOffset(
+ uint32_t address,
uint32_t *offset
)const
{
@@ -174,7 +173,7 @@ namespace Coverage {
)
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return;
@@ -184,7 +183,7 @@ namespace Coverage {
bool CoverageMapBase::isStartOfInstruction( uint32_t address ) const
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return false;
@@ -194,7 +193,7 @@ namespace Coverage {
void CoverageMapBase::setWasExecuted( uint32_t address )
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return;
@@ -204,7 +203,7 @@ namespace Coverage {
void CoverageMapBase::sumWasExecuted( uint32_t address, uint32_t addition)
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return;
@@ -215,7 +214,7 @@ namespace Coverage {
{
uint32_t offset;
bool result;
-
+
result = true;
if (determineOffset( address, &offset ) != true)
@@ -234,7 +233,7 @@ namespace Coverage {
if (determineOffset( address, &offset ) != true)
return 0;
- return Info[ offset ].wasExecuted;
+ return Info[ offset ].wasExecuted;
}
void CoverageMapBase::setIsBranch(
@@ -242,7 +241,7 @@ namespace Coverage {
)
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return;
@@ -252,7 +251,7 @@ namespace Coverage {
bool CoverageMapBase::isNop( uint32_t address ) const
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return false;
@@ -264,7 +263,7 @@ namespace Coverage {
)
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return;
@@ -274,7 +273,7 @@ namespace Coverage {
bool CoverageMapBase::isBranch( uint32_t address ) const
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return false;
@@ -286,7 +285,7 @@ namespace Coverage {
)
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return;
@@ -298,7 +297,7 @@ namespace Coverage {
)
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return;
@@ -308,7 +307,7 @@ namespace Coverage {
bool CoverageMapBase::wasAlwaysTaken( uint32_t address ) const
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return false;
@@ -319,7 +318,7 @@ namespace Coverage {
bool CoverageMapBase::wasNeverTaken( uint32_t address ) const
{
uint32_t offset;
-
+
if (determineOffset( address, &offset ) != true)
return false;
@@ -369,7 +368,7 @@ namespace Coverage {
bool result;
result = true;
-
+
if (determineOffset( address, &offset ) != true)
result = false;
diff --git a/tester/covoar/DesiredSymbols.cc b/tester/covoar/DesiredSymbols.cc
index 89f95ea..278498d 100644
--- a/tester/covoar/DesiredSymbols.cc
+++ b/tester/covoar/DesiredSymbols.cc
@@ -9,7 +9,6 @@
#undef __STRICT_ANSI__
#endif
-#include <libgen.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@@ -445,123 +444,13 @@ namespace Coverage {
)
{
- char* base;
- char* cStatus;
- char command[512];
- std::string fileName;
- CoverageRanges::ranges_t::iterator ritr;
- char rpath[PATH_MAX];
- FILE* tmpfile;
-
- // Open a temporary file for the uncovered ranges.
- tmpfile = fopen( "ranges1.tmp", "w" );
- if ( !tmpfile ) {
- fprintf(
- stderr,
- "ERROR: DesiredSymbols::determineSourceLines - "
- "unable to open %s\n",
- "ranges1.tmp"
- );
- exit(-1);
- }
-
- // Write the range addresses to the temporary file.
- for (ritr = theRanges->set.begin();
- ritr != theRanges->set.end();
- ritr++ ) {
- fprintf(
- tmpfile,
- "0x%08x\n0x%08x\n",
- ritr->lowAddress - theExecutable->getLoadAddress(),
- ritr->highAddress - theExecutable->getLoadAddress()
- );
- }
-
- fclose( tmpfile );
-
- // Invoke addr2line to generate the source lines for each address.
- if (theExecutable->hasDynamicLibrary())
- fileName = theExecutable->getLibraryName();
- else
- fileName = theExecutable->getFileName();
-
- sprintf(
- command,
- "%s -Ce %s <%s | dos2unix >%s",
- TargetInfo->getAddr2line(),
- fileName.c_str(),
- "ranges1.tmp",
- "ranges2.tmp"
- );
-
- if (system( command )) {
- fprintf(
- stderr,
- "ERROR: DesiredSymbols::determineSourceLines - "
- "command (%s) failed\n",
- command
- );
- exit( -1 );
- }
-
- // Open the addr2line output file.
- tmpfile = fopen( "ranges2.tmp", "r" );
- if ( !tmpfile ) {
- fprintf(
- stderr,
- "ERROR: DesiredSymbols::determineSourceLines - "
- "unable to open %s\n",
- "ranges2.tmp"
- );
- exit(-1);
+ for (auto& r : theRanges->set) {
+ std::string location;
+ theExecutable->getSourceAndLine(r.lowAddress, location);
+ r.lowSourceLine = rld::path::basename (location);
+ theExecutable->getSourceAndLine(r.highAddress, location);
+ r.highSourceLine = rld::path::basename (location);
}
-
- // Process the addr2line output.
- for (ritr = theRanges->set.begin();
- ritr != theRanges->set.end();
- ritr++ ) {
-
- cStatus = fgets( inputBuffer, MAX_LINE_LENGTH, tmpfile );
- if ( cStatus == NULL ) {
- fprintf(
- stderr,
- "ERROR: DesiredSymbols::determineSourceLines - "
- "Out of sync in addr2line output\n"
- );
- exit( -1 );
- }
- inputBuffer[ strlen(inputBuffer) - 1] = '\0';
-
- // Use only the base filename without directory path.
-#ifdef _WIN32
- #define realpath(N,R) _fullpath((R),(N),_MAX_PATH)
-#endif
- realpath( inputBuffer, rpath );
- base = basename( rpath );
-
- ritr->lowSourceLine = std::string( base );
-
- cStatus = fgets( inputBuffer, MAX_LINE_LENGTH, tmpfile );
- if ( cStatus == NULL ) {
- fprintf(
- stderr,
- "ERROR: DesiredSymbols::determineSourceLines - "
- "Out of sync in addr2line output\n"
- );
- exit( -1 );
- }
- inputBuffer[ strlen(inputBuffer) - 1] = '\0';
-
- // Use only the base filename without directory path.
- realpath( inputBuffer, rpath );
- base = basename( rpath );
-
- ritr->highSourceLine = std::string( base );
- }
-
- fclose( tmpfile );
- unlink( "ranges1.tmp" );
- unlink( "ranges2.tmp" );
}
SymbolInformation* DesiredSymbols::find(
diff --git a/tester/covoar/ExecutableInfo.cc b/tester/covoar/ExecutableInfo.cc
index c41d931..1755e93 100644
--- a/tester/covoar/ExecutableInfo.cc
+++ b/tester/covoar/ExecutableInfo.cc
@@ -7,6 +7,8 @@
#include <stdio.h>
+#include <rld.h>
+
#include "ExecutableInfo.h"
#include "app_common.h"
#include "CoverageMap.h"
@@ -18,24 +20,36 @@ namespace Coverage {
ExecutableInfo::ExecutableInfo(
const char* const theExecutableName,
const char* const theLibraryName
- )
+ ) : executable(theExecutableName),
+ loadAddress(0)
{
- executableName = theExecutableName;
- loadAddress = 0;
- libraryName = "";
if (theLibraryName)
libraryName = theLibraryName;
- theSymbolTable = new SymbolTable();
+ try {
+ executable.open();
+ executable.begin();
+ executable.load_symbols(symbols);
+ debug.begin(executable.elf());
+ debug.load_debug();
+ } catch (rld::error re) {
+ std::cerr << "error: "
+ << re.where << ": " << re.what
+ << std::endl;
+ exit(2);
+ } catch (...) {
+ exit(2);
+ }
}
ExecutableInfo::~ExecutableInfo()
{
- if (theSymbolTable)
- delete theSymbolTable;
+ debug.end();
+ executable.end();
+ executable.close();
}
void ExecutableInfo::dumpCoverageMaps( void ) {
- ExecutableInfo::coverageMaps_t::iterator itr;
+ ExecutableInfo::CoverageMaps::iterator itr;
for (itr = coverageMaps.begin(); itr != coverageMaps.end(); itr++) {
fprintf( stderr, "Coverage Map for %s\n", ((*itr).first).c_str() );;
@@ -44,21 +58,22 @@ namespace Coverage {
}
void ExecutableInfo::dumpExecutableInfo( void ){
- fprintf( stdout, "\n== Executable info ==\n");
- fprintf( stdout, "executableName = %s\n", executableName.c_str());
- fprintf( stdout, "libraryName = %s\n", libraryName.c_str());
- fprintf( stdout, "loadAddress = %u\n", loadAddress);
- theSymbolTable->dumpSymbolTable();
+ std::cout << std::endl
+ << "== Executable info ==" << std::endl
+ << "executable = " << getFileName () << std::endl
+ << "library = " << libraryName << std::endl
+ << "loadAddress = " << loadAddress << std::endl;
+ theSymbolTable.dumpSymbolTable();
}
CoverageMapBase* ExecutableInfo::getCoverageMap ( uint32_t address )
{
- CoverageMapBase* aCoverageMap = NULL;
- coverageMaps_t::iterator it;
- std::string itsSymbol;
+ CoverageMapBase* aCoverageMap = NULL;
+ CoverageMaps::iterator it;
+ std::string itsSymbol;
// Obtain the coverage map containing the specified address.
- itsSymbol = theSymbolTable->getSymbol( address );
+ itsSymbol = theSymbolTable.getSymbol( address );
if (itsSymbol != "") {
it = coverageMaps.find( itsSymbol );
aCoverageMap = (*it).second;
@@ -67,12 +82,12 @@ namespace Coverage {
return aCoverageMap;
}
- const std::string& ExecutableInfo::getFileName ( void ) const
+ const std::string ExecutableInfo::getFileName ( void ) const
{
- return executableName;
+ return executable.name().full();
}
- const std::string& ExecutableInfo::getLibraryName( void ) const
+ const std::string ExecutableInfo::getLibraryName( void ) const
{
return libraryName;
}
@@ -83,9 +98,9 @@ namespace Coverage {
}
- SymbolTable* ExecutableInfo::getSymbolTable ( void ) const
+ SymbolTable* ExecutableInfo::getSymbolTable ( void )
{
- return theSymbolTable;
+ return &theSymbolTable;
}
CoverageMapBase* ExecutableInfo::createCoverageMap (
@@ -95,8 +110,8 @@ namespace Coverage {
uint32_t highAddress
)
{
- CoverageMapBase *theMap;
- ExecutableInfo::coverageMaps_t::iterator itr;
+ CoverageMapBase *theMap;
+ ExecutableInfo::CoverageMaps::iterator itr;
itr = coverageMaps.find( symbolName );
if ( itr == coverageMaps.end() ) {
@@ -109,13 +124,26 @@ namespace Coverage {
return theMap;
}
+ void ExecutableInfo::getSourceAndLine(
+ const unsigned int address,
+ std::string& line
+ )
+ {
+ std::string file;
+ int lno;
+ debug.get_source (address, file, lno);
+ std::ostringstream ss;
+ ss << file << ':' << lno;
+ line = ss.str ();
+ }
+
bool ExecutableInfo::hasDynamicLibrary( void )
{
- return (libraryName != "");
+ return !libraryName.empty();
}
void ExecutableInfo::mergeCoverage( void ) {
- ExecutableInfo::coverageMaps_t::iterator itr;
+ ExecutableInfo::CoverageMaps::iterator itr;
for (itr = coverageMaps.begin(); itr != coverageMaps.end(); itr++) {
SymbolsToAnalyze->mergeCoverageMap( (*itr).first, (*itr).second );
diff --git a/tester/covoar/ExecutableInfo.h b/tester/covoar/ExecutableInfo.h
index 20ea9bf..9106db3 100644
--- a/tester/covoar/ExecutableInfo.h
+++ b/tester/covoar/ExecutableInfo.h
@@ -11,6 +11,10 @@
#include <stdint.h>
#include <string>
+#include <rld-dwarf.h>
+#include <rld-files.h>
+#include <rld-symbols.h>
+
#include "CoverageMapBase.h"
#include "SymbolTable.h"
@@ -67,14 +71,14 @@ namespace Coverage {
*
* @return Returns the executable's file name
*/
- const std::string& getFileName( void ) const;
+ const std::string getFileName( void ) const;
/*!
* This method returns the library name associated with the executable.
*
* @return Returns the executable's library name
*/
- const std::string& getLibraryName( void ) const;
+ const std::string getLibraryName( void ) const;
/*!
* This method returns the load address of the dynamic library
@@ -88,7 +92,7 @@ namespace Coverage {
*
* @return Returns a pointer to the symbol table.
*/
- SymbolTable* getSymbolTable( void ) const;
+ SymbolTable* getSymbolTable( void );
/*!
* This method creates a coverage map for the specified symbol.
@@ -108,6 +112,15 @@ namespace Coverage {
);
/*!
+ * This method gets the source location, the file and line number given an
+ * address.
+ */
+ void getSourceAndLine(
+ const unsigned int address,
+ std::string& location
+ );
+
+ /*!
* This method indicates whether a dynamic library has been
* associated with the executable.
*
@@ -132,15 +145,25 @@ namespace Coverage {
private:
/*!
- * This map associates a symbol with its coverage map.
+ * The ELF executable.
*/
- typedef std::map<std::string, CoverageMapBase *> coverageMaps_t;
- coverageMaps_t coverageMaps;
+ rld::files::object executable;
/*!
- * This member variable contains the name of the executable.
+ * The DWARF data to the ELF executable.
+ */
+ rld::dwarf::file debug;
+
+ /*!
+ * The executable's symbol table.
+ */
+ rld::symbols::table symbols;
+
+ /*!
+ * This map associates a symbol with its coverage map.
*/
- std::string executableName;
+ typedef std::map<std::string, CoverageMapBase *> CoverageMaps;
+ CoverageMaps coverageMaps;
/*!
* This member variable contains the name of a dynamic library
@@ -158,7 +181,7 @@ namespace Coverage {
* This member variable contains a pointer to the symbol table
* of the executable or library.
*/
- SymbolTable* theSymbolTable;
+ SymbolTable theSymbolTable;
};
}
diff --git a/tester/covoar/GcovData.cc b/tester/covoar/GcovData.cc
index 6d10337..2c033e5 100644
--- a/tester/covoar/GcovData.cc
+++ b/tester/covoar/GcovData.cc
@@ -11,7 +11,6 @@
* reading *.gcno and writing *.gcda files for gcov support
*/
-#include <libgen.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -61,7 +60,7 @@ namespace Gcov {
if ( (tempString == NULL) && (tempString2 == NULL) ){
fprintf(stderr, "ERROR: incorrect name of *.gcno file\n");
- }
+ }
else
{
strcpy( tempString, ".gcda"); // construct gcda file name
@@ -238,7 +237,7 @@ namespace Gcov {
status = readFrameHeader( &header, gcovFile);
if ( status <= 0 ){
- // Not printing error message because this
+ // Not printing error message because this
// happenns at the end of each file
return false;
}
@@ -260,11 +259,11 @@ namespace Gcov {
status = fread( &intBuffer, 4, header.length, gcovFile );
if ( status != (int) header.length){
- fprintf(
+ fprintf(
stderr, "Error while reading BLOCKS from gcov file...\n"
- "Header lenght is %u instead of %u\n",
- header.length,
- status
+ "Header lenght is %u instead of %u\n",
+ header.length,
+ status
);
return false;
}
@@ -478,15 +477,13 @@ namespace Gcov {
void GcovData::writeGcovFile( )
{
- char path[512];
- char command[512];
-
- //fprintf (stderr, "Attempting to run gcov for: %s\n", cFileName );
- strcpy( path, cFileName );
- dirname( path );
- sprintf( command, "( cd %s && gcov %s &>> gcov.log)", path, basename( cFileName ) );
- //fprintf (stderr, "> %s\n", command );
- system( command );
+ //std::cerr << "Attempting to run gcov for: " << cFileName << std::endl;
+ std::ostringstream command;
+ command << "( cd " << rld::path::dirname (cFileName)
+ << " && gcov " << rld::path::basename (cFileName)
+ << " &>> gcov.log)";
+ //std::cerr << "> " << command << std::endl;
+ system( command.str ().c_str () );
}
bool GcovData::processCounters( )
diff --git a/tester/covoar/covoar.cc b/tester/covoar/covoar.cc
index c6b0589..9608bc3 100644
--- a/tester/covoar/covoar.cc
+++ b/tester/covoar/covoar.cc
@@ -186,7 +186,7 @@ int main(
Coverage::ExecutableInfo* executableInfo = NULL;
std::string executableExtension = "exe";
std::string coverageExtension = "cov";
- Coverage::CoverageFormats_t coverageFormat;
+ Coverage::CoverageFormats_t coverageFormat = Coverage::COVERAGE_FORMAT_QEMU;
Coverage::CoverageReaderBase* coverageReader = NULL;
char* executable = NULL;
const char* explanations = NULL;
diff --git a/tester/covoar/wscript b/tester/covoar/wscript
index c0270d8..55d5ec9 100644
--- a/tester/covoar/wscript
+++ b/tester/covoar/wscript
@@ -70,7 +70,7 @@ def build(bld):
#
# The list of modules.
#
- modules = ['rld', 'elf', 'iberty']
+ modules = ['rld', 'dwarf', 'elf', 'iberty']
bld.stlib(target = 'ccovoar',
source = ['app_common.cc',
More information about the vc
mailing list