[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