[PATCH 5/5] tester/covoar: Integrate DWARF function data.

Chris Johns chrisj at rtems.org
Mon Aug 6 00:43:22 UTC 2018


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.
---
 tester/covoar/CoverageMapBase.cc  | 372 ++++++++++++++++++--------------------
 tester/covoar/CoverageMapBase.h   | 185 ++++++++++---------
 tester/covoar/DesiredSymbols.cc   |  33 ++--
 tester/covoar/ExecutableInfo.cc   |  41 ++++-
 tester/covoar/ExecutableInfo.h    |  32 ++--
 tester/covoar/ObjdumpProcessor.cc | 122 +++----------
 tester/covoar/covoar.cc           |  20 +-
 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.
@@ -76,25 +137,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
@@ -144,6 +137,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.
      */
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',
-- 
2.15.1




More information about the devel mailing list