[PATCH v3 15/22] rtemstoolkit/dwarf: Fixes for getting source lines.

Chris Johns chrisj at rtems.org
Mon Jun 18 02:29:13 UTC 2018


---
 rtemstoolkit/rld-dwarf.cpp | 260 +++++++++++++++++++++++++--------------------
 rtemstoolkit/rld-dwarf.h   |  34 +++---
 2 files changed, 160 insertions(+), 134 deletions(-)

diff --git a/rtemstoolkit/rld-dwarf.cpp b/rtemstoolkit/rld-dwarf.cpp
index 15cf8e2..674ac8f 100644
--- a/rtemstoolkit/rld-dwarf.cpp
+++ b/rtemstoolkit/rld-dwarf.cpp
@@ -85,6 +85,28 @@ namespace rld
       end_sequence = b ? true : false;
     }
 
+    address::address (const address& orig, const sources& source)
+      : addr (orig.addr),
+        source (&source),
+        source_index (orig.source_index),
+        source_line (orig.source_line),
+        begin_statement (orig.begin_statement),
+        block (orig.block),
+        end_sequence (orig.end_sequence)
+    {
+    }
+
+    address::address (const address& orig, dwarf_address addr)
+      : addr (addr),
+        source (orig.source),
+        source_index (orig.source_index),
+        source_line (orig.source_line),
+        begin_statement (orig.begin_statement),
+        block (orig.block),
+        end_sequence (orig.end_sequence)
+    {
+    }
+
     address::address (const address& orig)
       : addr (orig.addr),
         source (orig.source),
@@ -173,6 +195,12 @@ namespace rld
       return *this;
     }
 
+    bool
+    address::operator < (const address& rhs) const
+    {
+      return addr < rhs.addr;
+    }
+
     line_addresses::line_addresses (file&             debug,
                                     debug_info_entry& die)
       : debug (debug),
@@ -186,15 +214,6 @@ namespace rld
       }
     }
 
-    line_addresses::line_addresses (line_addresses&& orig)
-      : debug (orig.debug),
-        lines (orig.lines),
-        count_ (orig.count_)
-    {
-      orig.lines = nullptr;
-      orig.count_ = 0;
-    }
-
     line_addresses::~line_addresses ()
     {
       if (lines && count_ > 0)
@@ -220,12 +239,13 @@ namespace rld
       return lines[index];
     }
 
-    sources::sources (file& debug, debug_info_entry& die)
+    sources::sources (file& debug, dwarf_offset die_offset)
       : debug (debug),
         source (nullptr),
         count (0),
-        die_offset (die.offset ())
+        die_offset (die_offset)
     {
+      debug_info_entry die (debug, die_offset);
       die.source_files (source, count);
     }
 
@@ -243,16 +263,6 @@ namespace rld
       die.source_files (source, count);
     }
 
-    sources::sources (sources&& orig)
-      : debug (orig.debug),
-        source (orig.source),
-        count (orig.count),
-        die_offset (orig.die_offset)
-    {
-      orig.source = nullptr;
-      orig.count = 0;
-    }
-
     sources::~sources ()
     {
       dealloc ();
@@ -263,7 +273,7 @@ namespace rld
     {
       if (index <= 0 || index > count)
         return "unknown";
-      return source[index - 1];
+      return std::string (source[index - 1]);
     }
 
     void
@@ -274,7 +284,7 @@ namespace rld
         /*
          * The elftoolchain cleans the memory up and there is no compatible
          * call we can put here so adding the required code causes is a double
-         * free results in a crash.
+         * free resulting in a crash.
          */
         if (false)
         {
@@ -330,21 +340,8 @@ namespace rld
         libdwarf_error_check ("debug_info_entry:debug_info_entry", dr, de);
     }
 
-    debug_info_entry::debug_info_entry (debug_info_entry&& orig)
-      : debug (orig.debug),
-        die (orig.die),
-        tag_ (orig.tag_),
-        offset_ (orig.offset_)
-    {
-      orig.die = nullptr;
-      orig.tag_ = 0;
-      orig.offset_ = 0;
-    }
-
     debug_info_entry::~debug_info_entry ()
     {
-      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
-        std::cout << "dwarf::debug_info_entry::~debug_info_entry" << std::endl;
       dealloc ();
     }
 
@@ -492,8 +489,8 @@ namespace rld
         offset_ (offset),
         pc_low_ (0),
         pc_high_ (0),
-        source_ (debug, die),
-        die_offset (die.offset ())
+        die_offset (die.offset ()),
+        source_ (debug, die_offset)
     {
       die.attribute (DW_AT_name, name_);
       name_ = name_;
@@ -505,6 +502,9 @@ namespace rld
       if (!die.attribute (DW_AT_high_pc, pc_high_, false))
         pc_high_ = ~0U;
 
+      if (pc_high_ < pc_low_)
+        pc_high_ += pc_low_;
+
       if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
       {
         std::cout << std::hex << std::setfill ('0')
@@ -522,49 +522,85 @@ namespace rld
 
       line_addresses lines (debug, die);
       dwarf_address  pc = 0;
+      bool           seq_check = true;
+      dwarf_address  seq_base = 0;
 
       for (size_t l = 0; l < lines.count (); ++l)
       {
-        address       addr (source_, lines[l]);
-        dwarf_address loc = addr.location ();
-        if (inside (loc) && loc >= pc)
+        address       daddr (source_, lines[l]);
+        dwarf_address loc = daddr.location ();
+        /*
+         * A CU's line program can have some sequences at the start where the
+         * address is incorrectly set to 0. Ignore these entries.
+         */
+        if (pc == 0)
         {
-          pc = loc;
-          addr_lines_[addr.location ()] = addr;
-          if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
+          if (!seq_check)
           {
-            std::cout << "dwarf::compilation_unit: "
-                      << std::hex << std::setw (8) << addr.location () << std::dec
-                      << " - "
-                      << (char) (addr.is_a_begin_statement () ? 'B' : '.')
-                      << (char) (addr.is_in_a_block () ? 'I' : '.')
-                      << (char) (addr.is_an_end_sequence () ? 'E' : '.')
-                      << " - "
-                      << rld::path::basename (addr.path ())
-                      << ':' << addr.line ()
-                      << std::endl;
+            seq_check = daddr.is_an_end_sequence ();
+            continue;
+          }
+          if (loc == 0)
+          {
+            seq_check = false;
+            continue;
           }
         }
+        /*
+         * A sequence of line program instruction may set the address to 0. Use
+         * the last location from the previous sequence as the sequence's base
+         * address. All locations will be offset from the that base until the
+         * end of this sequence.
+         */
+        if (loc == 0 && seq_base == 0)
+          seq_base = pc;
+        if (seq_base != 0)
+          loc += seq_base;
+        if (daddr.is_an_end_sequence ())
+          seq_base = 0;
+        address addr (daddr, loc);
+        if (loc >= pc_low_ && loc < pc_high_)
+        {
+          pc = loc;
+          addr_lines_.push_back (addr);
+        }
       }
-    }
 
-    compilation_unit::compilation_unit (compilation_unit&& orig)
-      : debug (orig.debug),
-        offset_ (orig.offset_),
-        name_ (orig.name_),
-        producer_ (orig.producer_),
-        pc_low_ (orig.pc_low_),
-        pc_high_ (orig.pc_high_),
-        source_ (std::move (orig.source_)),
-        addr_lines_ (orig.addr_lines_),
-        die_offset (orig.die_offset)
-    {
-      orig.name_.clear ();
-      orig.producer_.clear ();
-      orig.offset_ = 0;
-      orig.die_offset = 0;
-      orig.pc_low_ = 0;
-      orig.pc_high_ = 0;
+      if (!addr_lines_.empty ())
+      {
+        std::stable_sort (addr_lines_.begin (), addr_lines_.end ());
+        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
+        {
+          auto first = addr_lines_.begin ();
+          auto last = addr_lines_.end () - 1;
+          std::cout << "dwarf::compilation_unit: line_low=0x"
+                    << std::hex
+                    << std::setw (8) << first->location ()
+                    << ", line_high=0x"
+                    << std::setw (8) << last->location ()
+                    << std::dec
+                    << std::endl;
+        }
+      }
+
+      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
+      {
+        int lc = 0;
+        for (auto& l : addr_lines_)
+        {
+          std::cout << "dwarf::compilation_unit: " << std::setw (3) << ++lc
+                    << ": 0x"
+                    << std::hex << std::setw (8) << l.location () << std::dec
+                    << " - "
+                    << (char) (l.is_a_begin_statement () ? 'B' : '.')
+                    << (char) (l.is_in_a_block () ? 'I' : '.')
+                    << (char) (l.is_an_end_sequence () ? 'E' : '.')
+                    << " - "
+                    << rld::path::basename (l.path ())
+                    << ':' <<l.line ()
+                    << std::endl;
+        }
+      }
     }
 
     compilation_unit::compilation_unit (const compilation_unit& orig)
@@ -574,16 +610,16 @@ namespace rld
         producer_ (orig.producer_),
         pc_low_ (orig.pc_low_),
         pc_high_ (orig.pc_high_),
-        source_ (orig.source_),
-        addr_lines_ (orig.addr_lines_),
-        die_offset (orig.die_offset)
+        die_offset (orig.die_offset),
+        source_ (debug, die_offset)
     {
+      for (auto& line : orig.addr_lines_)
+        addr_lines_.push_back (address (line, source_));
+      std::stable_sort (addr_lines_.begin (), addr_lines_.end ());
     }
 
     compilation_unit::~compilation_unit ()
     {
-      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
-        std::cout << "dwarf::compilation_unit::~compilation_unit: " << name_ << std::endl;
     }
 
     std::string
@@ -614,39 +650,35 @@ namespace rld
     compilation_unit::get_source (const dwarf_address addr,
                                   address&            addr_line)
     {
-      if (addr_lines_.find (addr) == addr_lines_.end ())
-          return false;
-      addr_line = addr_lines_[addr];
-      return true;
+      if (!addr_lines_.empty () && inside (addr))
+      {
+        address last_loc;
+        for (auto& loc : addr_lines_)
+        {
+          if (addr <= loc.location ())
+          {
+            if (addr == loc.location ())
+              addr_line = loc;
+            else
+              addr_line = last_loc;
+            return addr_line.valid ();
+          }
+          last_loc = loc;
+        }
+      }
+      return false;
     }
 
     bool
     compilation_unit::inside (dwarf_unsigned addr) const
     {
-      return addr >= pc_low_ && addr < pc_high_;
-    }
-
-    compilation_unit&
-    compilation_unit::operator = (compilation_unit&& rhs)
-    {
-      if (this != &rhs)
+      if (!addr_lines_.empty ())
       {
-        debug = rhs.debug;
-        offset_ = rhs.offset_;
-        name_ = rhs.name_;
-        producer_ = rhs.producer_;
-        source_ = std::move (rhs.source_);
-        addr_lines_ = std::move (rhs.addr_lines_),
-        pc_low_ = rhs.pc_low_;
-        pc_high_ = rhs.pc_high_;
-        die_offset = rhs.die_offset;
-        rhs.offset_ = 0;
-        rhs.name_.clear ();
-        rhs.pc_low_ = -1;
-        rhs.pc_high_ = -1;
-        rhs.die_offset = 0;
+        auto first = addr_lines_.begin ();
+        auto last = addr_lines_.end () - 1;
+        return first->location () <= addr && addr <= last->location ();
       }
-      return *this;
+      return addr >= pc_low_ && addr < pc_high_;
     }
 
     compilation_unit&
@@ -663,9 +695,9 @@ namespace rld
         offset_ = rhs.offset_;
         name_ = rhs.name_;
         producer_ = rhs.producer_;
-        debug_info_entry die (debug, rhs.offset_);
-        source_ = sources (debug, die);
-        addr_lines_ = addresses (rhs.addr_lines_);
+        source_ = sources (debug, die_offset);
+        for (auto& line : rhs.addr_lines_)
+          addr_lines_.push_back (address (line, source_));
         pc_low_ = rhs.pc_low_;
         pc_high_ = rhs.pc_high_;
         die_offset = rhs.die_offset;
@@ -844,16 +876,14 @@ namespace rld
         r = cu.get_source (addr, line);
         if (r)
         {
-          if (match.valid ())
+          if (match.valid () &&
+              (match.is_an_end_sequence () || !!line.is_an_end_sequence ()))
+          {
+            match = line;
+          }
+          else
           {
-            if (match.is_an_end_sequence ())
-            {
-              match = line;
-            }
-            else if (!line.is_an_end_sequence ())
-            {
-              match = line;
-            }
+            match = line;
           }
         }
       }
diff --git a/rtemstoolkit/rld-dwarf.h b/rtemstoolkit/rld-dwarf.h
index c69cb9d..1207728 100644
--- a/rtemstoolkit/rld-dwarf.h
+++ b/rtemstoolkit/rld-dwarf.h
@@ -46,6 +46,8 @@ namespace rld
     {
     public:
       address (const sources& source, dwarf_line& line);
+      address (const address& orig, const sources& source);
+      address (const address& orig, dwarf_address addr);
       address (const address& orig);
       address ();
       ~address ();
@@ -90,6 +92,11 @@ namespace rld
        */
       address& operator = (const address& rhs);
 
+      /**
+       * Less than operator to allow sorting.
+       */
+      bool operator < (const address& rhs) const;
+
     private:
 
       dwarf_address  addr;
@@ -102,11 +109,9 @@ namespace rld
     };
 
     /**
-     * The addresses table is a map of the addresses in a CU to their line
-     * number.
+     * The addresses table is a vector sorted from low to high addresses..
      */
-    typedef std::map < const dwarf_address, address > addresses;
-
+    typedef std::vector < address > addresses;
 
     /**
      * Line addresses.
@@ -115,7 +120,6 @@ namespace rld
     {
     public:
       line_addresses (file& debug, debug_info_entry& die);
-      line_addresses (line_addresses&& orig);
       ~line_addresses ();
 
       /**
@@ -144,9 +148,9 @@ namespace rld
     class sources
     {
     public:
-      sources (file& debug, debug_info_entry& die);
+      sources (file& debug, dwarf_offset die_offset);
       sources (const sources& orig);
-      sources (sources&& orig);
+      //sources (sources&& orig);
       ~sources ();
 
       /**
@@ -186,7 +190,6 @@ namespace rld
       debug_info_entry (file& debug);
       debug_info_entry (file& debug, dwarf_die& die);
       debug_info_entry (file& debug, dwarf_offset offset);
-      debug_info_entry (debug_info_entry&& orig);
 
       /**
        * Destruct and clean up.
@@ -277,7 +280,6 @@ namespace rld
                         debug_info_entry& die,
                         dwarf_offset      offset);
       compilation_unit (const compilation_unit& orig);
-      compilation_unit (compilation_unit&& orig);
       ~compilation_unit ();
 
       /**
@@ -309,17 +311,11 @@ namespace rld
                        address&            addr_line);
 
       /**
-       * Is the address inside the CU? Becareful using this because not all CUs
-       * have these attributes set and the address range will be the entire
-       * address space.
+       * Is the address inside the CU? If the PC low and high attributes are
+       * valid they are used or the lines are checked.
        */
       bool inside (dwarf_unsigned addr) const;
 
-      /**
-       * Move assignment operator.
-       */
-      compilation_unit& operator = (compilation_unit&& rhs);
-
       /**
        * Copy assignment operator.
        */
@@ -334,10 +330,10 @@ namespace rld
       dwarf_unsigned pc_low_;     ///< The PC low address
       dwarf_unsigned pc_high_;    ///< The PC high address.
 
+      dwarf_offset   die_offset;  ///< The offset of the DIE in the image.
+
       sources        source_;     ///< Sources table for this CU.
       addresses      addr_lines_; ///< Address table.
-
-      dwarf_offset   die_offset;  ///< The offset of the DIE in the image.
     };
 
     typedef std::list < compilation_unit > compilation_units;
-- 
2.15.1




More information about the devel mailing list