]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Soup up printing so dwarf-print can be used to compare dwarf vs dwarf_edit/dwarf_output.
authorRoland McGrath <roland@redhat.com>
Sat, 4 Jul 2009 03:03:39 +0000 (20:03 -0700)
committerRoland McGrath <roland@redhat.com>
Sat, 4 Jul 2009 03:16:22 +0000 (20:16 -0700)
libdw/ChangeLog
libdw/c++/dwarf
libdw/c++/dwarf_data
libdw/c++/edit-values.cc
libdw/c++/values.cc
tests/ChangeLog
tests/print-die.hh
tests/run-dwarf-attributes.sh
tests/run-dwarf_edit.sh

index a8e54a22cba3df663af1abdaa7b0317e9940f66a..fef45842ff36370b5fa7dd52cde036aff65b64e4 100644 (file)
@@ -1,5 +1,12 @@
 2009-07-03  Roland McGrath  <roland@redhat.com>
 
+       * c++/dwarf: Give line info stubby to_string methods.
+       * c++/dwarf_data: Likewise.
+       * c++/edit-values.cc: Likewise.
+
+       * c++/dwarf: Fix location_attr iterators.
+       * c++/values.cc: Likewise.
+
        * Makefile.am (AM_CXXFLAGS): New variable (from ../src/Makefile.am).
 
        * c++/dwarf: Fix range_list canonicalizing comparisons.
index 7f7757dca90a1fbe61ad6012a49e2d8f30d97aef..d31d0107f1f68103f6384d0f0288ce9bcfe0c7f1 100644 (file)
@@ -332,7 +332,7 @@ namespace elfutils
       public:
 
        inline const_iterator ()
-         : _m_raw (), _m_end ()
+         : _m_raw (), _m_end (raw::end ())
        {
        }
 
@@ -671,11 +671,22 @@ namespace elfutils
        }
 
        inline const_iterator (const debug_info_entry &die, ptrdiff_t offset)
-         : _m_die (die), _m_offset (offset), _m_attr () {}
+         : _m_die (die), _m_offset (offset), _m_attr ()
+       {}
+
+       inline const_iterator (ptrdiff_t offset)
+         : _m_die (), _m_offset (offset), _m_attr ()
+       {}
 
       public:
+       // Default constructor: invalid for anything but operator=.
+       inline const_iterator ()
+         : _m_die (), _m_offset (-1), _m_attr ()
+       {}
+
        inline const_iterator (const const_iterator &i)
-         : _m_die (i._m_die), _m_offset (i._m_offset), _m_attr (i._m_attr) {}
+         : _m_die (i._m_die), _m_offset (i._m_offset), _m_attr (i._m_attr)
+       {}
 
        inline const_iterator &operator= (const const_iterator &other)
        {
@@ -702,6 +713,9 @@ namespace elfutils
                                         (void *) this, _m_offset);
          _m_die.xif (result < 0);
          _m_offset = result;
+         if (result == 1)
+           // End iterators have no live pointers.
+           _m_die._m_die.addr = NULL;
          return *this;
        }
        inline const_iterator operator++ (int) // postfix
@@ -723,9 +737,9 @@ namespace elfutils
        const_iterator i = const_iterator (_m_die, 0);
        return ++i;
       }
-      inline const_iterator end () const
+      static inline const_iterator end ()
       {
-       return const_iterator (_m_die, 1);
+       return const_iterator (1);
       }
 
       // XXX can do faster internal (?)
@@ -1238,146 +1252,6 @@ namespace elfutils
       }
     };
 
-    /* A location attribute yields a location expression.
-       Either it's a single expression, or a map of PC to location.  */
-    class location_attr
-    {
-      friend class attr_value;
-    private:
-      attr_value _m_attr;
-
-      location_attr (const attr_value &attr) : _m_attr (attr) {}
-
-      inline bool same (const location_attr &it) const
-      {
-       return _m_attr.same (it._m_attr);
-      }
-
-      template<typename pair>
-      struct nonempty : public std::unary_function<pair, bool>
-      {
-       inline bool operator () (const pair &x)
-       {
-         return !x.second.empty ();
-       }
-      };
-
-      template<typename pair>
-      struct any : public std::unary_function<pair, bool>
-      {
-       inline bool operator () (const pair &)
-       {
-         return true;
-       }
-      };
-
-    public:
-      typedef size_t size_type;
-      typedef ptrdiff_t difference_type;
-      // XXX need proper type for exprs
-      typedef const_vector<uint8_t> mapped_type;
-      typedef std::pair< ::Dwarf_Addr, ::Dwarf_Addr> key_type; // XXX reloc
-      typedef std::pair<const key_type, mapped_type> value_type;
-      class const_iterator;    // below
-
-      std::string to_string () const;
-
-      bool is_list () const;
-
-      inline mapped_type location () const
-      {
-       if (is_list ())
-         throw std::runtime_error ("location is list, not single location");
-       return _m_attr.constant_block ();
-      }
-
-      inline const_iterator begin () const;
-      inline const_iterator end () const;
-
-      inline bool empty () const
-      {
-       if (is_list ())
-         return std::find_if (begin (), end (),
-                              nonempty<value_type> ()) == end ();
-       return location ().empty ();
-      }
-      inline size_type size () const
-      {
-       if (is_list ())
-         return std::count_if (begin (), end (), any<value_type> ());
-       return location ().empty () ? 0 : 1;
-      }
-
-      template<typename other_attr>
-      bool operator== (const other_attr &other) const
-      {
-       if (empty ())
-         return (other.empty ()
-                 || std::find_if (other.begin (), other.end (),
-                                  nonempty<typename other_attr::value_type> ()
-                                  ) == other.end ());
-       if (!is_list ())
-         return (!other.is_list () && !other.empty ()
-                 && location () == other.location ());
-
-       return other.is_list () && subr::container_equal (*this, other);
-      }
-      template<typename other_file>
-      inline bool operator!= (const other_file &other) const
-      {
-       return !(*this == other);
-      }
-
-      /*
-       XXX missing: find, at; by key_type or by PC
-       XXX worse than that: multiple overlapping matches!
-       */
-    };
-
-    class location_attr::const_iterator
-      : public std::iterator<std::input_iterator_tag, location_attr::value_type>
-    {
-      friend class location_attr;
-    private:
-      ::Dwarf_Addr _m_base;    // XXX reloc
-      ::Dwarf_Addr _m_begin;   // XXX reloc
-      ::Dwarf_Addr _m_end;     // XXX reloc
-      location_attr _m_attr;
-      ptrdiff_t _m_offset;
-
-      const_iterator (const location_attr &loc, ptrdiff_t offset)
-       : _m_base (-1), _m_begin (1), _m_end (0),
-         _m_attr (loc), _m_offset (offset) {}
-
-    public:
-
-      inline bool operator== (const const_iterator &it) const
-      {
-       return _m_offset == it._m_offset && _m_attr.same (it._m_attr);
-      }
-      inline bool operator!= (const const_iterator &it) const
-      {
-       return !(*this == it);
-      };
-
-      const_iterator &operator++ (); // prefix
-      inline const_iterator operator++ (int) // postfix
-      {
-       const_iterator prev = *this;
-       ++*this;
-       return prev;
-      }
-
-      inline value_type operator* () const
-      {
-       if (unlikely (_m_offset == 1))
-         throw std::runtime_error ("dereferencing end iterator");
-
-       return value_type (key_type (_m_base + _m_begin, _m_base + _m_end),
-                          _m_attr.location ());
-      }
-    };
-
     /* The DW_AT_ranges attribute yields a range list.
        XXX reloc
        This is equivalent to unordered_set<pair<Dwarf_Addr, Dwarf_Addr> >.  */
@@ -1409,7 +1283,7 @@ namespace elfutils
        : public std::iterator<std::input_iterator_tag, value_type>
       {
        friend class range_list;
-      private:
+      protected:
        ::Dwarf_Addr _m_base;   // XXX reloc
        ::Dwarf_Addr _m_begin;  // XXX reloc
        ::Dwarf_Addr _m_end;    // XXX reloc
@@ -1419,9 +1293,15 @@ namespace elfutils
        const_iterator (Dwarf_Attribute *, ptrdiff_t);
 
       public:
+       // Default constructor: only valid for operator=.
+       inline const_iterator ()
+         : _m_base (-1), _m_begin (0), _m_end (0), _m_cu (NULL), _m_offset (-1)
+       {}
+
        inline const_iterator (const const_iterator &i)
          : _m_base (i._m_base), _m_begin (i._m_begin), _m_end (i._m_end),
-           _m_cu (i._m_cu), _m_offset (i._m_offset) {}
+           _m_cu (i._m_cu), _m_offset (i._m_offset)
+       {}
 
        inline value_type operator* () const
        {
@@ -1522,6 +1402,162 @@ namespace elfutils
       }
     };
 
+    /* A location attribute yields a location expression.
+       Either it's a single expression, or a map of PC to location.  */
+    class location_attr
+    {
+      friend class attr_value;
+    private:
+      attr_value _m_attr;
+
+      location_attr (const attr_value &attr) : _m_attr (attr) {}
+
+      inline bool same (const location_attr &it) const
+      {
+       return _m_attr.same (it._m_attr);
+      }
+
+      template<typename pair>
+      struct nonempty : public std::unary_function<pair, bool>
+      {
+       inline bool operator () (const pair &x)
+       {
+         return !x.second.empty ();
+       }
+      };
+
+      template<typename pair>
+      struct any : public std::unary_function<pair, bool>
+      {
+       inline bool operator () (const pair &)
+       {
+         return true;
+       }
+      };
+
+    public:
+      typedef size_t size_type;
+      typedef ptrdiff_t difference_type;
+      // XXX need proper type for exprs
+      typedef const_vector<uint8_t> mapped_type;
+      typedef std::pair< ::Dwarf_Addr, ::Dwarf_Addr> key_type; // XXX reloc
+      typedef std::pair<const key_type, mapped_type> value_type;
+
+      std::string to_string () const;
+
+      bool is_list () const;
+
+      inline mapped_type location () const
+      {
+       if (is_list ())
+         throw std::runtime_error ("location is list, not single location");
+       return _m_attr.constant_block ();
+      }
+
+      class const_iterator
+       : public range_list::const_iterator
+      {
+       friend class location_attr;
+      private:
+       ::Dwarf_Block _m_block;
+
+       void advance ();
+
+       inline const_iterator (Dwarf_Attribute *attr, ptrdiff_t offset)
+         : range_list::const_iterator (attr, offset), _m_block ()
+       {}
+
+      public:
+       typedef location_attr::value_type value_type;
+
+       inline const_iterator ()
+         : _m_block ()
+       {}
+
+       inline const_iterator (const const_iterator &i)
+         : range_list::const_iterator (i), _m_block (i._m_block)
+       {}
+
+       inline const_iterator &operator= (const const_iterator &i)
+       {
+         range_list::const_iterator::operator= (i);
+         _m_block = i._m_block;
+         return *this;
+       }
+
+       inline bool operator== (const const_iterator &it) const
+       {
+         return _m_block.data == it._m_block.data;
+       }
+       inline bool operator!= (const const_iterator &it) const
+       {
+         return !(*this == it);
+       };
+
+       const_iterator &operator++ (); // prefix
+       inline const_iterator operator++ (int) // postfix
+       {
+         const_iterator prev = *this;
+         ++*this;
+         return prev;
+       }
+
+       inline value_type operator* () const
+       {
+         if (unlikely (_m_block.data == NULL))
+           throw std::runtime_error ("dereferencing end iterator");
+
+         return value_type (key_type (_m_base + _m_begin, _m_base + _m_end),
+                            const_vector<uint8_t> (_m_block));
+       }
+      };
+
+      const_iterator begin () const;
+      inline const_iterator end () const
+      {
+       return const_iterator (_m_attr.thisattr (), 1);
+      }
+
+      inline bool empty () const
+      {
+       if (is_list ())
+         return std::find_if (begin (), end (),
+                              nonempty<value_type> ()) == end ();
+       return location ().empty ();
+      }
+      inline size_type size () const
+      {
+       if (is_list ())
+         return subr::length (begin (), end ());
+       return location ().empty () ? 0 : 1;
+      }
+
+      template<typename other_attr>
+      bool operator== (const other_attr &other) const
+      {
+       if (empty ())
+         return (other.empty ()
+                 || std::find_if (other.begin (), other.end (),
+                                  nonempty<typename other_attr::value_type> ()
+                                  ) == other.end ());
+       if (!is_list ())
+         return (!other.is_list () && !other.empty ()
+                 && location () == other.location ());
+
+       return other.is_list () && subr::container_equal (*this, other);
+      }
+      template<typename other_file>
+      inline bool operator!= (const other_file &other) const
+      {
+       return !(*this == other);
+      }
+
+      /*
+       XXX missing: find, at; by key_type or by PC
+       XXX worse than that: multiple overlapping matches!
+       */
+    };
+
     // This describes a CU's directory table, a simple array of strings.
     class directory_table
     {
@@ -1553,6 +1589,8 @@ namespace elfutils
       inline directory_table (const directory_table &t)
        : _m_files (t._m_files) {}
 
+      std::string to_string () const;
+
       typedef const char *const *const_iterator;
 
       inline bool empty () const
@@ -1739,6 +1777,8 @@ namespace elfutils
        return *this;
       }
 
+      std::string to_string () const;
+
       typedef subr::indexed_iterator<line_table> const_iterator;
 
       inline bool empty () const
@@ -1802,6 +1842,8 @@ namespace elfutils
        return *this;
       }
 
+      std::string to_string () const;
+
       inline const directory_table include_directories () const
       {
        return directory_table (_m_files);
@@ -2092,8 +2134,8 @@ namespace elfutils
        const dwarf *_m_file;   // XXX
        ::Dwarf_Off _m_next;    // XXX
 
-       inline const_iterator (const dwarf &file, ::Dwarf_Off next)
-         : _m_file (&file), _m_next (next) {}
+       inline const_iterator (const dwarf &file)
+         : _m_file (&file), _m_next (0) {}
 
       public:
        inline const_iterator ()
@@ -2124,7 +2166,7 @@ namespace elfutils
 
        inline bool operator== (const const_iterator &other) const
        {
-         return _m_file == other._m_file && _m_next == other._m_next;
+         return _m_next == other._m_next && _m_file == other._m_file;
        }
        inline bool operator!= (const const_iterator &other) const
        {
@@ -2136,6 +2178,9 @@ namespace elfutils
          // XXX should be rewritten to use libdw_findcu internals
          // slow way for first crack to avoid DSO issues
          _m_next = _m_file->nextcu (_m_next, _m_die.thisdie ());
+         if (_m_next == (::Dwarf_Off) -1)
+           // End iterators have no file pointer.
+           _m_file = NULL;
          return *this;
        }
        inline const_iterator operator++ (int) // postfix
@@ -2148,12 +2193,12 @@ namespace elfutils
 
       const_iterator begin () const
       {
-       const_iterator it (_m_file, 0);
+       const_iterator it (_m_file);
        return ++it;
       }
-      inline const_iterator end () const
+      static inline const_iterator end ()
       {
-       return const_iterator (_m_file, -1);
+       return const_iterator ();
       }
     };
     inline raw_compile_units raw_compile_units () const
@@ -2421,19 +2466,6 @@ namespace elfutils
     return attributes_type::attributes_type (raw_attributes ());
   }
 
-  inline dwarf::location_attr::const_iterator
-  dwarf::location_attr::begin () const
-  {
-    const_iterator it (*this, 0);
-    if (is_list ())
-      ++it;
-    return it;
-  }
-  inline dwarf::location_attr::const_iterator dwarf::location_attr::end () const
-  {
-    return const_iterator (*this, 1);
-  }
-
   // Explicit specializations.
   template<>
   std::string to_string<dwarf::attribute> (const dwarf::attribute &);
index 28eeef0be3c94a47bf61133968321ae7732f82f4..8e765c5ed5c127da8ec2ddee60c834f2149acfaf 100644 (file)
@@ -188,6 +188,8 @@ namespace elfutils
       directory_table (const table &other)
        : _base (other.begin (), other.end ()) {}
 
+      std::string to_string () const;
+
       template<typename table>
       inline bool operator== (const table &other) const
       {
@@ -393,6 +395,8 @@ namespace elfutils
       template<typename table>
       line_table (const table &other) : _base (other.begin (), other.end ()) {}
 
+      std::string to_string () const;
+
       template<typename table>
       inline bool operator== (const table &other) const
       {
@@ -435,6 +439,8 @@ namespace elfutils
        return *this;
       }
 
+      std::string to_string () const;
+
       inline directory_table &include_directories ()
       {
        return this->first;
index 7640b4caa8ee1a0c94ea4820d3e3694493b89355..d1b441670c2f952fd3b386b76c9b6f661d94aa8b 100644 (file)
@@ -75,9 +75,3 @@ dwarf_data::source_file::to_string () const
   os << "{\"" << _m_name << "," << _m_mtime << "," << _m_size << "}";
   return os.str ();
 }
-
-std::string
-dwarf_data::location_attr::to_string () const
-{
-  return is_list () ? "XXX-loclist" : "XXX-expr";
-}
index 0ba451b27e7dcfedc88b438eb5dc3da808694bf2..37e5122c0330841cc9028cb9b06ad9add52e6c5e 100644 (file)
@@ -153,10 +153,10 @@ hex_string (Dwarf_Word value, const char *before = "", const char *after = "")
 }
 
 static string
-dec_string (Dwarf_Word value)
+dec_string (Dwarf_Word value, const char *before = "", const char *after = "")
 {
   std::ostringstream os;
-  os << value;
+  os << before << value << after;
   return os.str ();
 }
 
@@ -191,7 +191,9 @@ value_string (const value_type &value)
     case dwarf::VS_rangelistptr:
       return value.ranges ().to_string ();
 
-    case dwarf::VS_lineptr:    // XXX punt for now, treat as constant
+    case dwarf::VS_lineptr:
+      return value.line_info ().to_string ();
+
     case dwarf::VS_macptr:     // XXX punt for now, treat as constant
     case dwarf::VS_constant:
       return hex_string (value.constant ());
@@ -200,8 +202,10 @@ value_string (const value_type &value)
       return value.dwarf_constant ().to_string ();
 
     case dwarf::VS_source_line:
+      return dec_string (value.source_line ());
+
     case dwarf::VS_source_column:
-      return dec_string (value.constant ());
+      return dec_string (value.source_column ());
 
     case dwarf::VS_identifier:
       return plain_string (value.identifier ());
@@ -547,36 +551,130 @@ dwarf::location_attr::is_list () const
   return true;
 }
 
+inline void
+dwarf::location_attr::const_iterator::advance ()
+{
+  xif (_m_cu, range_list_advance (IDX_debug_loc, _m_cu,
+                                 _m_base, _m_begin, _m_end, _m_offset,
+                                 &_m_block.data));
+  if (_m_offset > 1)
+    _m_offset += 2 + (_m_block.length
+                     = read_2ubyte_unaligned_inc (_m_cu->dbg, _m_block.data));
+  else
+    // End iterator.
+    _m_block = Dwarf_Block ();
+}
+
+dwarf::location_attr::const_iterator
+dwarf::location_attr::begin () const
+{
+  const_iterator i (_m_attr.thisattr (), 0);
+  if (is_list ())
+    i.advance ();
+  else
+    xif (_m_attr.thisattr (),
+        dwarf_formblock (_m_attr.thisattr (), &i._m_block) < 0);
+
+  return i;
+}
+
 dwarf::location_attr::const_iterator &
 dwarf::location_attr::const_iterator::operator++ ()
 {
   if (unlikely (_m_offset == 1))
     throw std::runtime_error ("incrementing end iterator");
-  else if (_m_offset == 0)
+
+  if (_m_offset == 0)
     // Singleton, now at end.
     _m_offset = 1;
   else
-    {
-      // Advance to next list entry.
-      xif (_m_attr._m_attr.thisattr (),
-          range_list_advance (IDX_debug_loc, _m_attr._m_attr._m_attr.cu,
-                              _m_base, _m_begin, _m_end, _m_offset,
-                              &_m_attr._m_attr._m_attr.valp));
-      if (_m_offset > 1)
-       {
-         _m_attr._m_attr._m_attr.form = DW_FORM_block2;
-         _m_offset += read_2ubyte_unaligned (_m_attr._m_attr._m_attr.cu->dbg,
-                                             _m_attr._m_attr._m_attr.valp);
-       }
-    }
+    // Advance to next list entry.
+    advance ();
 
   return *this;
 }
 
+template<typename locattr>
+static string
+locattr_string (const locattr *loc)
+{
+  return (loc->is_list () ? dec_string (loc->size (), "{loclist ", " entries}")
+         : "{locexpr}");
+}
+
 string
 dwarf::location_attr::to_string () const
 {
-  if (is_list ())
-    return hex_string (_m_attr.constant (), "#");
-  return "XXX-expr";
+  return locattr_string (this);
 }
+
+string
+dwarf_data::location_attr::to_string () const
+{
+  return locattr_string (this);
+}
+\f
+// dwarf::line_info_table
+
+template<typename line_info_table>
+static inline std::string
+line_info_string (const line_info_table *table)
+{
+  return ("[" + table->include_directories ().to_string ()
+         + ", " + table->lines ().to_string () + "]");
+}
+
+std::string
+dwarf::line_info_table::to_string () const
+{
+  return line_info_string (this);
+}
+
+namespace elfutils
+{
+  template<>
+  std::string
+  dwarf_edit::line_info_table::to_string () const
+  {
+    return line_info_string (this);
+  }
+
+};
+\f
+// dwarf::directory_table
+
+static std::string
+dirtable_string (size_t ndirs)
+{
+  return dec_string (ndirs, "{", " dirs}");
+}
+
+std::string
+dwarf::directory_table::to_string () const
+{
+  return dirtable_string (_m_files->ndirs);
+}
+
+std::string
+dwarf_data::directory_table::to_string () const
+{
+  return dirtable_string (size ());
+}
+\f
+// dwarf::line_table
+
+std::string
+dwarf::line_table::to_string () const
+{
+  return dec_string (_m_lines->nlines, "{", " line entries}");
+}
+
+namespace elfutils
+{
+  template<>
+  std::string
+  dwarf_edit::line_table::to_string () const
+  {
+    return dec_string (size (), "{", " line entries}");
+  }
+};
index af678b693fd85e09ff89ecfab9609ad9ee67dbcb..3865aa13fd84607673af9ba3afd259607c54be9a 100644 (file)
@@ -1,5 +1,10 @@
 2009-07-03  Roland McGrath  <roland@redhat.com>
 
+       * print-die.hh: Grok --sort-attrs option to canonicalize order.
+       Fix ref assignment to produce consistent numbering.
+       * run-dwarf_edit.sh: Update expected output.
+       * run-dwarf-attributes.sh: Likewise.
+
        * Makefile.am (AM_CXXFLAGS): New variable (from ../src/Makefile.am).
 
        * print-die.hh: Grok --edit/--output options to print a copied object.
index 29e000c705a8026a7fd32d78f64584ec7a16d24a..2934c0e78b60f1062846961fa713799af0efb6bc 100644 (file)
 #include <ostream>
 #include <iomanip>
 #include <tr1/unordered_map>
+#include <functional>
+#include <algorithm>
 
 #include "c++/dwarf_edit"
 #include "c++/dwarf_output"
 
 static bool print_offset;
+static bool sort_attrs;
 
 static enum { copy_none, copy_edit, copy_output } make_copy;
 
@@ -60,6 +63,13 @@ print_die_main (int &argc, char **&argv, unsigned int &depth)
       ++argv;
     }
 
+  if (argc > 1 && !strcmp (argv[1], "--sort-attrs"))
+    {
+      sort_attrs = true;
+      --argc;
+      ++argv;
+    }
+
   if (argc > 1 && !strcmp (argv[1], "--edit"))
     {
       make_copy = copy_edit;
@@ -81,14 +91,76 @@ print_die_main (int &argc, char **&argv, unsigned int &depth)
     }
 }
 
+static int next_ref = 1;
 typedef tr1::unordered_map< ::Dwarf_Off, int> refs_map;
 
+template<typename attrs_type,
+        void (*act) (const typename attrs_type::value_type &, refs_map &)
+        >
+class attr_walker
+{
+private:
+  refs_map &refs;
+  inline attr_walker (refs_map &r) : refs (r) {}
+
+  typedef typename attrs_type::const_iterator iterator;
+  typedef typename iterator::value_type attr_type;
+
+public:
+  inline void operator () (const pair<int, iterator> &p) const
+  {
+    (*act) (*p.second, refs);
+  }
+
+  static inline void walk (const attrs_type &attrs, refs_map &r)
+  {
+    if (attrs_type::ordered || !sort_attrs)
+      for (iterator i = attrs.begin (); i != attrs.end (); ++i)
+       (*act) (*i, r);
+    else
+      {
+       map<int, iterator> sorted;
+       for (iterator i = attrs.begin (); i != attrs.end (); ++i)
+         sorted[(*i).first] = i;
+       for_each (sorted.begin (), sorted.end (),
+                 attr_walker<attrs_type, act> (r));
+      }
+  }
+};
+
+template<typename attrs_type>
+void
+print_attr (const typename attrs_type::value_type &attr, refs_map &refs)
+{
+  if (!print_offset && attr.second.what_space () == dwarf::VS_reference)
+    cout << " " << dwarf::attributes::name (attr.first) << "=\"#ref"
+        << dec << refs[attr.second.reference ()->identity ()] << "\"";
+  else
+    cout << " " << to_string (attr);
+}
+
+template<typename attrs_type>
 static void
-finish_refs_map (refs_map &refs)
+print_attrs (const attrs_type &attrs, refs_map &refs)
 {
-  int id = 0;
-  for (refs_map::iterator it = refs.begin (); it != refs.end (); ++it)
-    it->second = ++id;
+  attr_walker<attrs_type, print_attr<attrs_type> >::walk (attrs, refs);
+}
+
+template<typename attrs_type>
+void
+prewalk_attr (const typename attrs_type::value_type &attr, refs_map &refs)
+{
+  if (attr.second.what_space () == dwarf::VS_reference
+      && refs.insert (make_pair (attr.second.reference ()->identity (),
+                                next_ref)).second)
+    ++next_ref;
+}
+
+template<typename attrs_type>
+static void
+prewalk_attrs (const attrs_type &attrs, refs_map &refs)
+{
+  attr_walker<attrs_type, prewalk_attr<attrs_type> >::walk (attrs, refs);
 }
 
 template<typename file>
@@ -99,10 +171,7 @@ prewalk_die (const typename file::debug_info_entry &die, refs_map &refs)
         = die.children ().begin (); i != die.children ().end (); ++i)
     prewalk_die<file> (*i, refs);
 
-  for (typename file::debug_info_entry::attributes_type::const_iterator i
-        = die.attributes ().begin (); i != die.attributes ().end (); ++i)
-    if ((*i).second.what_space () == dwarf::VS_reference)
-      refs[(*i).second.reference ()->identity ()];
+  prewalk_attrs (die.attributes (), refs);
 }
 
 template<typename file>
@@ -120,18 +189,10 @@ print_die (const typename file::debug_info_entry &die,
     {
       refs_map::const_iterator it = refs.find (die.identity ());
       if (it != refs.end ())
-       cout << " ref=\"" << hex << it->second << "\"";
+       cout << " ref=\"ref" << dec << it->second << "\"";
     }
 
-  for (typename file::debug_info_entry::attributes_type::const_iterator i
-        = die.attributes ().begin (); i != die.attributes ().end (); ++i)
-    {
-      if (!print_offset && (*i).second.what_space () == dwarf::VS_reference)
-       cout << " " << dwarf::attributes::name ((*i).first) << "=\"#"
-            << hex << refs[(*i).second.reference ()->identity ()] << "\"";
-      else
-       cout << " " << to_string (*i);
-    }
+  print_attrs (die.attributes (), refs);
 
   if (die.has_children ())
     {
@@ -163,10 +224,7 @@ print_cu (const typename file::compile_unit &cu, const unsigned int limit)
   refs_map refs;
 
   if (!print_offset)
-    {
-      prewalk_die<file> (die, refs);
-      finish_refs_map (refs);
-    }
+    prewalk_die<file> (die, refs);
 
   print_die<file> (die, 1, limit, refs);
 }
index 4aa170ba73f07bde9af6aca5873088c661ab635c..614721486998939c2f33d2a9c594df4d9600ef84 100755 (executable)
@@ -29,9 +29,9 @@ testfiles testfile
 
 testrun_compare ./dwarf-print --offsets --depth=1 testfile <<\EOF
 testfile:
- <compile_unit offset=[0xb] stmt_list=0 high_pc=0x804845a low_pc=0x804842c name="m.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=C89>...
- <compile_unit offset=[0xca] stmt_list=0x4b high_pc=0x8048466 low_pc=0x804845c name="b.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=C89>...
- <compile_unit offset=[0x15fc] stmt_list=0x1e0 high_pc=0x8048472 low_pc=0x8048468 name="f.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=C89>...
+ <compile_unit offset=[0xb] stmt_list=[{1 dirs}, {5 line entries}] high_pc=0x804845a low_pc=0x804842c name="m.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=C89>...
+ <compile_unit offset=[0xca] stmt_list=[{1 dirs}, {4 line entries}] high_pc=0x8048466 low_pc=0x804845c name="b.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=C89>...
+ <compile_unit offset=[0x15fc] stmt_list=[{1 dirs}, {4 line entries}] high_pc=0x8048472 low_pc=0x8048468 name="f.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=C89>...
 EOF
 
 exit 0
index 2ae53209c96327e50414bec9ed2b0c8f4f630ab7..88c103df738389804c2bf0b7d5347f2bca37f5ee 100755 (executable)
@@ -28,8 +28,8 @@
 testrun_compare ./dwarf_edit <<\EOF
 consed:
  <compile_unit name="source-file.c">
-  <base_type ref="0x1" name="int"/>
-  <subprogram name="foo" external=1 type="#0x1" description="foo"/>
+  <base_type ref="ref1" name="int"/>
+  <subprogram name="foo" external=1 type="#ref1" description="foo"/>
  </compile_unit>
 EOF