]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Working dwarf_edit copy-construction with ref-maker.
authorRoland McGrath <roland@redhat.com>
Fri, 3 Jul 2009 07:29:59 +0000 (00:29 -0700)
committerRoland McGrath <roland@redhat.com>
Fri, 3 Jul 2009 07:29:59 +0000 (00:29 -0700)
libdw/ChangeLog
libdw/Makefile.am
libdw/c++/dwarf
libdw/c++/dwarf_comparator
libdw/c++/dwarf_data
libdw/c++/dwarf_edit
libdw/c++/dwarf_output
libdw/c++/dwarf_ref_maker [new file with mode: 0644]
libdw/c++/dwarf_tracker
libdw/c++/subr.hh
src/dwarfcmp.cc

index 3c1b98d597fa153cf090356f24a903f33edc5931..68c292c66a6ff0bad7187296135d03ff7f906099 100644 (file)
@@ -1,3 +1,11 @@
+2009-07-03  Roland McGrath  <roland@redhat.com>
+
+       * c++/dwarf_edit: Fix copy construction using a ref-maker.
+       * c++/dwarf_data: Updates.
+       * c++/subr.hh: Updates.
+       * c++/dwarf_ref_maker: New file.
+       * Makefile.am (pkginclude_HEADERS): Add it.
+
 2009-07-02  Roland McGrath  <roland@redhat.com>
 
        * c++/dwarf: Get rid of VS::unit_reference.
index f358840c47de8e91f572f917a7a10fefc3410597..7fb3171c8db378924f694d52edba5898a88bdc61 100644 (file)
@@ -50,7 +50,8 @@ include_HEADERS = dwarf.h
 pkginclude_HEADERS = libdw.h \
                     c++/subr.hh c++/dwarf_data \
                     c++/dwarf c++/dwarf_edit c++/dwarf_output \
-                    c++/dwarf_tracker c++/dwarf_comparator
+                    c++/dwarf_tracker c++/dwarf_ref_maker \
+                    c++/dwarf_comparator
 
 libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
                  dwarf_getpubnames.c dwarf_getabbrev.c dwarf_tag.c \
index 3958cd1f66c567e41c5e338411873a1485980f78..212bcb39ac658c9cec85c5cd05cc7d76486b0c02 100644 (file)
@@ -449,6 +449,8 @@ namespace elfutils
       class attributes_type;
       attributes_type attributes () const;
 
+      class const_pointer;
+
       inline int tag () const
       {
        int t = ::dwarf_tag (thisdie ());
@@ -857,6 +859,9 @@ namespace elfutils
        }
       };
 
+      // Actually always const.
+      typedef const_iterator iterator;
+
       const_iterator begin () const
       {
        return const_iterator (raw_children_type::begin ());
@@ -878,6 +883,10 @@ namespace elfutils
       }
     };
 
+    class debug_info_entry::const_pointer
+      : public debug_info_entry::children_type::const_iterator
+    {};
+
   private:
     static inline bool skip_sibling (const attribute &attr)
     {
@@ -1112,7 +1121,7 @@ namespace elfutils
       inline std::string to_string () const;
 
       // Return an iterator on which * will yield the referent debug_info_entry.
-      inline debug_info_entry::raw_children_type::const_iterator
+      inline debug_info_entry::children_type::const_iterator
       reference () const
       {
        return (debug_info_entry::raw_children_type::const_iterator
index 4373f6309e0dd84a8d18ecdb6b29f3b4c50aedf2..62556596baba657d7c2530d6c9d9bc3b603d7289 100644 (file)
@@ -67,6 +67,7 @@ namespace elfutils
     typedef typename dwarf2_die::children_type::const_iterator die2;
     typedef typename dwarf1_die::attributes_type::const_iterator attr1;
     typedef typename dwarf2_die::attributes_type::const_iterator attr2;
+    typedef typename dwarf1_die::children_type::iterator dwarf1_ref;
 
     // This object is created to start a walk and destroyed to finish one.
     struct walk
@@ -162,7 +163,6 @@ namespace elfutils
                               const left_context_type &, const die1 &,
                               const right_context_type &, const die2 &)
     {}
-
   };
 
   template<class dwarf1, class dwarf2,
@@ -219,7 +219,7 @@ namespace elfutils
     inline bool match (const cu1_it &a, const cu2_it &b)
     {
       typename tracker::walk in (&_m_tracker, a, b);
-      return match (static_cast<die1> (*a), static_cast<die2> (*b));
+      return match (*a, *b);
     }
 
     inline bool match (const die1 &a, const die2 &b)
index dff1bd3ec26528e842d953d39dd97498bc8a4a32..9ee162544a637b501a14f880203ba8769c449dab 100644 (file)
@@ -683,7 +683,7 @@ namespace elfutils
 
       template<typename flavor, typename input, typename arg_type>
       static inline value_dispatch *
-      make (flavor *&result, const input &x, const arg_type &arg)
+      make (flavor *&result, const input &x, arg_type &arg)
       {
        return result = new flavor (x, arg);
       }
@@ -693,7 +693,7 @@ namespace elfutils
        inline value_string () {}
 
        template<typename string, typename arg_type>
-       inline value_string (const string &s, const arg_type &arg)
+       inline value_string (const string &s, arg_type &arg)
          : std::string (s)
        {}
 
@@ -709,7 +709,7 @@ namespace elfutils
       struct value_identifier : public value_string
       {
        template<typename id, typename arg_type>
-       inline value_identifier (const id &s, const arg_type &arg)
+       inline value_identifier (const id &s, arg_type &arg)
          : value_string (s, arg)
        {}
       };
@@ -733,9 +733,11 @@ namespace elfutils
        {}
 
        template<typename iter, typename tracker>
-       inline value_reference (const iter &i, tracker *t)
-         : ref ()
-       {}
+       inline value_reference (const iter &i, tracker &t)
+         : ref ()              // Invalid until t.finish ().
+       {
+         t.refer (&ref, i);
+       }
       };
 
       struct value_flag : public value_dispatch
@@ -747,7 +749,7 @@ namespace elfutils
        {}
 
        template<typename arg_type>
-       inline value_flag (bool t, const arg_type &arg)
+       inline value_flag (bool t, arg_type &arg)
          : flag (t)
        {}
       };
@@ -762,7 +764,7 @@ namespace elfutils
        {}
 
        template<typename arg_type>
-       inline value_address (::Dwarf_Addr x, const arg_type &arg)
+       inline value_address (::Dwarf_Addr x, arg_type &arg)
          : addr (x)
        {}
       };
@@ -772,7 +774,7 @@ namespace elfutils
        inline value_rangelistptr () {}
 
        template<typename list, typename arg_type>
-       inline value_rangelistptr (const list &other, const arg_type &arg)
+       inline value_rangelistptr (const list &other, arg_type &arg)
          : range_list (other)
        {}
       };
@@ -782,7 +784,7 @@ namespace elfutils
        inline value_lineptr () {}
 
        template<typename table, typename arg_type>
-       inline value_lineptr (const table &other, const arg_type &arg)
+       inline value_lineptr (const table &other, arg_type &arg)
          : impl::line_info_table (other)
        {}
       };
@@ -800,7 +802,7 @@ namespace elfutils
        {}
 
        template<typename arg_type>
-       inline value_constant (::Dwarf_Word x, const arg_type &arg)
+       inline value_constant (::Dwarf_Word x, arg_type &arg)
          : word (x)
        {}
       };
@@ -811,7 +813,7 @@ namespace elfutils
        inline value_constant_block () {}
 
        template<typename block, typename arg_type>
-       inline value_constant_block (const block &b, const arg_type &arg)
+       inline value_constant_block (const block &b, arg_type &arg)
          : std::vector<uint8_t> (b.begin (), b.end ())
        {}
       };
@@ -821,7 +823,7 @@ namespace elfutils
        inline value_dwarf_constant () {}
 
        template<typename constant, typename arg_type>
-       inline value_dwarf_constant (const constant &other, const arg_type &arg)
+       inline value_dwarf_constant (const constant &other, arg_type &arg)
          : dwarf_enum (other)
        {}
       };
@@ -831,7 +833,7 @@ namespace elfutils
        inline value_source_file () {}
 
        template<typename file, typename arg_type>
-       inline value_source_file (const file &other, const arg_type &arg)
+       inline value_source_file (const file &other, arg_type &arg)
          : source_file (other)
        {}
       };
@@ -845,7 +847,7 @@ namespace elfutils
        {}
 
        template<typename arg_type>
-       inline value_source_line (unsigned int m, const arg_type &arg)
+       inline value_source_line (unsigned int m, arg_type &arg)
          : n (m)
        {}
       };
@@ -858,23 +860,29 @@ namespace elfutils
        inline value_location () {}
 
        template<typename loc, typename arg_type>
-       inline value_location (const loc &other, const arg_type &arg)
+       inline value_location (const loc &other, arg_type &arg)
          : location_attr (other)
        {}
       };
     };
 
+    // Forward decl.
+    template<class impl, typename v = value<impl> > class attributes_type;
+
     template<class impl, typename vw = value<impl> >
     class attr_value
     {
+      friend class attributes_type<impl, vw>;
+
     private:
       typename vw::value_dispatch *_m_value;
+      typedef typename impl::debug_info_entry::pointer die_ptr;
 
-      template<typename value, typename arg_type = nothing>
+      template<typename value, typename arg_type = const nothing>
       struct init
       {
        inline init (attr_value *av,
-                    const value &other, const arg_type &arg = arg_type ())
+                    const value &other, arg_type &arg = arg_type ())
        {
          switch (other.what_space ())
            {
@@ -921,6 +929,14 @@ namespace elfutils
        }
       };
 
+      // This kosher only when freshly default-constructed.
+      template<typename value, typename arg_type>
+      inline void set (const value &other, arg_type &arg)
+      {
+       assert (_m_value == NULL);
+       init<value, arg_type> me (this, other, arg);
+      }
+
       template<typename flavor>
       inline flavor &const_variant () const
       {
@@ -954,10 +970,10 @@ namespace elfutils
       }
 
       template<typename value, typename arg_type>
-      attr_value (const value &other, const arg_type &arg)
+      attr_value (const value &other, arg_type &arg)
        : _m_value (NULL)
       {
-       init<value, arg_type> me (this, other, arg);
+       set (this, other, arg);
       }
 
       inline attr_value ()
@@ -1017,12 +1033,12 @@ namespace elfutils
        return variant<typename vw::value_address> ().addr;
       }
 
-      inline typename impl::debug_info_entry::pointer &reference () const
+      inline die_ptr &reference () const
       {
        return variant<typename vw::value_reference> ().ref;
       }
 
-      inline typename impl::debug_info_entry::pointer &reference ()
+      inline die_ptr &reference ()
       {
        return variant<typename vw::value_reference> ().ref;
       }
@@ -1220,7 +1236,7 @@ namespace elfutils
       }
     };
 
-    template<class impl, typename arg = nothing, typename v = value<impl> >
+    template<class impl, typename v>
     class attributes_type
       : public std::map<int, attr_value<impl, v> >
     {
@@ -1232,13 +1248,34 @@ namespace elfutils
       inline attributes_type () {}
 
     public: // XXX should be protected
+
+      /* We don't use the base_type (begin, end) iterator constructor here
+        for good reason.  The ref-maker needs to collect back-pointers
+        into our mapped_value (attr_value) objects.  It would not fly to
+        have that done in a temporary attr_value object that gets copied
+        into the map cell by assignment.  We must make sure that when a
+        value_reference is constructed, it is really the one sitting in
+        our map that the ref-maker will want to update later.  */
       template<typename input, typename arg_type>
-      inline attributes_type (const input &other, const arg_type &c)
-       : base_type (subr::argify2nd<input, attributes_type, arg_type>
+      inline attributes_type (const input &other, arg_type &c)
+       : base_type ()
+      {
+       for (typename input::const_iterator attr = other.begin ();
+            attr != other.end ();
+            ++attr)
+         (*this)[(*attr).first].set ((*attr).second, c);
+      }
+
+#if 0
+      // dwarf_output probably will do it this way (?)
+      template<typename input, typename arg_type>
+      inline attributes_type (const input &other, arg_type &c)
+       : base_type (subr::argify2nd<input, attributes_type, arg_type &>
                     (other.begin (), c),
-                    subr::argify2nd<input, attributes_type, arg_type>
+                    subr::argify2nd<input, attributes_type, arg_type &>
                     (other.end (), c))
       {}
+#endif
 
     public:
       typedef typename base_type::key_type key_type;
index 3139aa604b550776eea904c0c64a630973a3be72..321565c872c6f38dcaac97417197a7cd58b0b412 100644 (file)
@@ -52,7 +52,7 @@
 
 #include "dwarf"
 #include "dwarf_data"
-#include "dwarf_tracker"
+#include "dwarf_ref_maker"
 
 /* Read the comments for elfutils::dwarf first.
 
@@ -108,14 +108,23 @@ namespace elfutils
       {
        friend class debug_info_entry;
       private:
-        children_type () {}
+        inline children_type () {}
 
        template<typename input, typename tracker>
-       children_type (const input &other, tracker *t)
-         : std::list<debug_info_entry>
-           (subr::argify<input, children_type, tracker *> (other.begin (), t),
-            subr::argify<input, children_type, tracker *> (other.end (), t))
-       {}
+       inline children_type (const input &other, tracker &t)
+       {
+         for (typename input::const_iterator in = other.begin ();
+              in != other.end ();
+              ++in)
+           {
+             /* Don't copy-construct the entry from *in here because that
+                copies it again into the list and destroys the first copy.  */
+             push_back (debug_info_entry ());
+             iterator out = --end ();
+             out->set (*in, t);
+             t.equivalence (out, in);
+           }
+       }
 
       public:
        typedef debug_info_entry value_type;
@@ -144,18 +153,35 @@ namespace elfutils
        inline attributes_type () {}
 
        template<typename attrs, typename tracker>
-       inline attributes_type (const attrs &other, tracker *t)
+       inline attributes_type (const attrs &other, tracker &t)
          : base_type (other, t)
        {}
       };
 
-    private:
-      const int _m_tag;
+    protected:
+      int _m_tag;
       attributes_type _m_attributes;
       children_type _m_children;
 
+      // This is can only be used by the children_type constructor,
+      // which immediately calls set.
+      inline debug_info_entry ()
+       : _m_tag (-1), _m_attributes (), _m_children ()
+      {}
+
+      template<typename die_type, typename arg_type>
+      inline void set (const die_type &die, arg_type &arg)
+      {
+       _m_attributes.clear ();
+       _m_children.clear ();
+       _m_tag = die.tag ();
+       _m_attributes.swap (attributes_type (die.attributes (), arg));
+       _m_children.swap (children_type (die.children (), arg));
+      }
+
     public:
-      debug_info_entry (int t) : _m_tag (t)
+      inline debug_info_entry (int t)
+       : _m_tag (t), _m_attributes (), _m_children ()
       {
        if (unlikely (t <= 0))
          throw std::invalid_argument ("invalid tag");
@@ -164,7 +190,7 @@ namespace elfutils
       /* The template constructor lets us copy in from any class that has
         compatibly iterable containers for attributes and children.  */
       template<typename die_type, typename tracker>
-      debug_info_entry (const die_type &die, tracker *t)
+      debug_info_entry (const die_type &die, tracker &t)
        : _m_tag (die.tag ()),
          _m_attributes (die.attributes (), t),
          _m_children (die.children (), t)
@@ -239,7 +265,7 @@ namespace elfutils
       // XXX should be private
     public:
       template<typename die_type, typename tracker>
-      inline compile_unit (const die_type &die, tracker *t)
+      inline compile_unit (const die_type &die, tracker &t)
        : debug_info_entry (die, t)
       {
        if (die.tag () != ::DW_TAG_compile_unit)
@@ -260,17 +286,32 @@ namespace elfutils
       typedef std::list<compile_unit> _base;
 
       // Default constructor: an empty container, no CUs.
-      inline compile_units ()
-      {}
+      inline compile_units () {}
 
       // Constructor copying CUs from input container.
       template<typename input, typename tracker>
-      inline compile_units (const input &units, tracker *t)
-       : _base (subr::argify<input, compile_units, tracker *>
+      inline compile_units (const input &other, tracker &t)
+      {
+       for (typename input::const_iterator in = other.begin ();
+            in != other.end ();
+            ++in)
+         {
+           /* Don't copy-construct the entry from *in here because that
+              copies it again into the list and destroys the first copy.  */
+           push_back (compile_unit ());
+           iterator out = --end ();
+           out->set (*in, t);
+         }
+      }
+#if 0                          // dwarf_output might use this (?)
+      template<typename input, typename tracker>
+      inline compile_units (const input &units, tracker &t)
+       : _base (subr::argify<input, compile_units, tracker &>
                 (units.begin (), t),
-                subr::argify<input, compile_units, tracker *>
+                subr::argify<input, compile_units, tracker &>
                 (units.end (), t))
       {}
+#endif
 
     public:
       typedef compile_unit value_type;
@@ -316,13 +357,30 @@ namespace elfutils
 
   public:
     // Default constructor: an empty container, no CUs.
-    inline dwarf_edit () {}
+    inline dwarf_edit ()
+      : _m_units ()
+    {}
 
     // Constructor copying CUs from an input file (dwarf or dwarf_edit).
     template<typename input, typename tracker>
-    dwarf_edit (const input &dw, tracker *t)
-      : _m_units (dw.compile_units (), t)
-    {}
+    inline dwarf_edit (const input &dw, tracker &t,
+                      subr::guard<tracker> guard = subr::guard<tracker> ())
+      : _m_units (dw.compile_units (), guard (t))
+    {
+      guard.clear ();
+    }
+
+    // Copying constructor with default ref-maker.
+    template<typename input>
+    inline dwarf_edit (const input &dw,
+                      dwarf_ref_maker<dwarf_edit, input> t
+                      = dwarf_ref_maker<dwarf_edit, input> (),
+                      subr::guard<dwarf_ref_maker<dwarf_edit, input> > guard
+                      = subr::guard<dwarf_ref_maker<dwarf_edit, input> > ())
+      : _m_units (dw.compile_units (), guard (t))
+    {
+      guard.clear ();
+    }
 
     template<typename file>
     inline bool operator== (const file &other) const
index c224d362376fcbbc573a89c779544da5e926f1a7..c9f1bf80923d71c4e0f10422f4faa242f9f764f0 100644 (file)
@@ -79,7 +79,7 @@ namespace elfutils
   private:
     template<typename input>
     static inline const input &
-    collect (dwarf_output_collector *c,
+    collect (dwarf_output_collector &c,
             const subr::auto_ref<const input> &p)
     {
       return static_cast<const input &> (p);
@@ -87,7 +87,7 @@ namespace elfutils
 
     template<typename input>
     static inline const debug_info_entry &
-    collect (dwarf_output_collector *,
+    collect (dwarf_output_collector &,
             const typename input::debug_info_entry &);
 
   public:
@@ -116,7 +116,7 @@ namespace elfutils
       /* The template constructor lets us copy in from any class that has
         compatibly iterable containers for attributes and children.  */
       template<typename die_type>
-      debug_info_entry (const die_type &die, dwarf_output_collector *c)
+      debug_info_entry (const die_type &die, dwarf_output_collector &c)
        : _m_tag (die.tag ()),
          _m_attributes (die.attributes ()),
          _m_children (die.children ()),
@@ -188,11 +188,11 @@ namespace elfutils
       template<typename input>
       struct make
        : public std::binary_function<typename input::value_type,
-                                     dwarf_output_collector *,
+                                     dwarf_output_collector &,
                                      _base::value_type>
       {
        _base::value_type operator () (const typename input::value_type &cu,
-                                      dwarf_output_collector *c) const
+                                      dwarf_output_collector &c) const
        {
          return _base::value_type (collect (c, cu));
        }
@@ -205,7 +205,7 @@ namespace elfutils
 
       // Constructor copying CUs from input container.
       template<typename input>
-      compile_units (const input &units, dwarf_output_collector *c)
+      compile_units (const input &units, dwarf_output_collector &c)
        : _base ()
       {
        for (typename input::const_iterator it = units.begin ();
@@ -226,7 +226,7 @@ namespace elfutils
        return !(*this == other);
       }
 
-      void recollect (dwarf_output_collector *c)
+      void recollect (dwarf_output_collector &c)
       {
        std::transform (begin (), end (), begin (),
                        std::bind2nd (make<compile_units> (), c));
@@ -251,7 +251,7 @@ namespace elfutils
     // Constructor copying CUs from an input file (can be any of dwarf,
     // dwarf_edit, or dwarf_output).
     template<typename input>
-    dwarf_output (const input &dw, dwarf_output_collector *c)
+    dwarf_output (const input &dw, dwarf_output_collector &c)
       : _m_units (dw.compile_units (), c)
     {}
 
@@ -289,18 +289,18 @@ namespace elfutils
 
     template<typename input>
     static inline const std::string &
-    collect_string (dwarf_output_collector *, const input &);
+    collect_string (dwarf_output_collector &c, const input &);
 
     /* An iterator adapter for use in iterator-based constructors.
        collectify (iterator) yields an iterator on input where *i
        constructs output::value_type (input::value_type v, collector).  */
     template<typename input, typename output>
     static inline typename subr::argifier<input, output,
-                                         dwarf_output_collector *>::result_type
+                                         dwarf_output_collector &>::result_type
     collectify (const typename input::const_iterator &in,
-               dwarf_output_collector *c)
+               dwarf_output_collector &c)
     {
-      return subr::argifier<input, output, dwarf_output_collector *> (c) (in);
+      return subr::argifier<input, output, dwarf_output_collector &> (c) (in);
     }
 
     struct value_wrapper
@@ -311,7 +311,7 @@ namespace elfutils
        const std::string &_m_str;
 
        template<typename string>
-       inline value_string (const string &s, dwarf_output_collector *c)
+       inline value_string (const string &s, dwarf_output_collector &c)
          : _m_str (collect_string (c, s))
        {}
 
@@ -345,7 +345,7 @@ namespace elfutils
 
       template<typename input>
       static inline value_dispatch *
-      make (value_string *&result, const input &x, dwarf_output_collector *c)
+      make (value_string *&result, const input &x, dwarf_output_collector &c)
       {
        return result = new value_string (x, c);
       }
@@ -369,7 +369,7 @@ namespace elfutils
         children_type () {}
 
        template<typename input>
-       inline children_type (const input &other, dwarf_output_collector *c)
+       inline children_type (const input &other, dwarf_output_collector &c)
          : std::list<debug_info_entry>
            (collectify<input, children_type> (other.begin (), c),
             collectify<input, children_type> (other.end (), c))
@@ -383,18 +383,15 @@ namespace elfutils
       typedef children_type::const_iterator pointer;
 
       class attributes_type
-       : public dwarf_data::attributes_type<dwarf_output,
-                                            dwarf_output_collector *,
-                                            value_wrapper>
+       : public dwarf_data::attributes_type<dwarf_output, value_wrapper>
       {
        friend class debug_info_entry;
       private:
        typedef dwarf_data::attributes_type<dwarf_output,
-                                           dwarf_output_collector *,
                                            value_wrapper> base_type;
 
        template<typename input>
-       inline attributes_type (const input &other, dwarf_output_collector *c)
+       inline attributes_type (const input &other, dwarf_output_collector &c)
          : base_type (other, c)
        {}
       };
@@ -406,7 +403,7 @@ namespace elfutils
 
     public:
       template<typename die_type>
-      debug_info_entry (const die_type &die, dwarf_output_collector *c)
+      debug_info_entry (const die_type &die, dwarf_output_collector &c)
        : _m_tag (die.tag ()),
          _m_attributes (die.attributes (), c),
          _m_children (die.children (), c)
@@ -473,7 +470,7 @@ namespace elfutils
       // XXX should be private
     public:
       template<typename die_type>
-      compile_unit (const die_type &die, dwarf_output_collector *c)
+      compile_unit (const die_type &die, dwarf_output_collector &c)
        : debug_info_entry (die, c)
       {
        if (die.tag () != ::DW_TAG_compile_unit)
@@ -501,7 +498,7 @@ namespace elfutils
 
       // Constructor copying CUs from input container.
       template<typename input>
-      compile_units (const input &units, dwarf_output_collector *c)
+      compile_units (const input &units, dwarf_output_collector &c)
        : _base (collectify<input, compile_units> (units.begin (), c),
                 collectify<input, compile_units> (units.end (), c))
       {
@@ -546,7 +543,7 @@ namespace elfutils
     // Constructor copying CUs from an input file (can be any of dwarf,
     // dwarf_edit, or dwarf_output).
     template<typename input>
-    dwarf_output (const input &dw, dwarf_output_collector *c)
+    dwarf_output (const input &dw, dwarf_output_collector &c)
       : _m_units (dw.compile_units (), c)
     {}
 
@@ -578,13 +575,20 @@ namespace elfutils
     subr::value_set<std::string> _m_strings;
     subr::value_set<dwarf_output::range_list> _m_ranges;
 
+  public:
+
+    template<typename die1, typename die2> // XXX
+    inline void equivalence (const die1 &a, const die2 &b) {}
+
+    template<typename die1, typename die2> // XXX
+    inline void refer (die1 *ref, const die2 &b) {}
   };
 
   template<typename input>
   inline const std::string &
-  dwarf_output::collect_string (dwarf_output_collector *c, const input &s)
+  dwarf_output::collect_string (dwarf_output_collector &c, const input &s)
   {
-    return c->_m_strings.add (s);
+    return c._m_strings.add (s);
   }
 
 };
diff --git a/libdw/c++/dwarf_ref_maker b/libdw/c++/dwarf_ref_maker
new file mode 100644 (file)
index 0000000..1bceeca
--- /dev/null
@@ -0,0 +1,178 @@
+/* elfutils::dwarf_ref_maker -- -*- C++ -*- template type specification
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   In addition, as a special exception, Red Hat, Inc. gives You the
+   additional right to link the code of Red Hat elfutils with code licensed
+   under any Open Source Initiative certified open source license
+   (http://www.opensource.org/licenses/index.php) which requires the
+   distribution of source code with any binary distribution and to
+   distribute linked combinations of the two.  Non-GPL Code permitted under
+   this exception must only link to the code of Red Hat elfutils through
+   those well defined interfaces identified in the file named EXCEPTION
+   found in the source code files (the "Approved Interfaces").  The files
+   of Non-GPL Code may instantiate templates or use macros or inline
+   functions from the Approved Interfaces without causing the resulting
+   work to be covered by the GNU General Public License.  Only Red Hat,
+   Inc. may make changes or additions to the list of Approved Interfaces.
+   Red Hat's grant of this exception is conditioned upon your not adding
+   any new exceptions.  If you wish to add a new Approved Interface or
+   exception, please contact Red Hat.  You must obey the GNU General Public
+   License in all respects for all of the Red Hat elfutils code and other
+   code used in conjunction with Red Hat elfutils except the Non-GPL Code
+   covered by this exception.  If you modify this file, you may extend this
+   exception to your version of the file, but you are not obligated to do
+   so.  If you do not wish to provide this exception without modification,
+   you must delete this exception statement from your version and license
+   this file solely under the GPL without exception.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifndef _ELFUTILS_DWARF_REF_MAKER
+#define _ELFUTILS_DWARF_REF_MAKER      1
+
+#include "dwarf"
+#include <tr1/unordered_map>
+#include <vector>
+
+namespace elfutils
+{
+  // Prototypical stub for reference maker object.
+  // This keeps no state and can't really be used.
+  template<class output, class input>
+  struct dwarf_ref_maker_base
+  {
+    typedef typename input::debug_info_entry input_entry;
+    typedef typename input_entry::children_type::const_iterator input_ref;
+    typedef typename output::debug_info_entry::pointer output_ref;
+
+    // These are called around a whole-file construction.
+    inline void start () {}
+
+    // If called, all pointers passed in since start () before are bogus.
+    inline void abort () {}
+
+    // Construction is complete: now snap in all recorded references.
+    inline void finish (output &file) {}
+
+    // The referenced output DIE has been constructed to match the input DIE.
+    inline void equivalence (const output_ref &to, const input_ref &from)
+    {
+    }
+
+    // *REF is an uninitialized attr_value.reference ().
+    // It's meant to refer to the output DIE equivalent to the given input DIE.
+    inline void refer (output_ref *ref, const input_ref &target)
+    {
+      throw std::logic_error ("dwarf_ref_maker_base cannot make references");
+    }
+  };
+
+  // Simple maker used for a single copy-construction.
+  template<class output, class input>
+  class dwarf_ref_maker : public dwarf_ref_maker_base<output, input>
+  {
+  public:
+    typedef typename input::debug_info_entry input_entry;
+    typedef typename output::debug_info_entry output_entry;
+    typedef typename input_entry::children_type::const_iterator input_ref;
+    typedef typename output_entry::children_type::iterator output_ref;
+
+  private:
+
+    struct seen
+    {
+      bool _m_known;
+      output_ref _m_out;
+      std::vector<output_ref *> _m_refs;
+
+      inline seen ()
+       : _m_known (false), _m_out (), _m_refs ()
+      {}
+
+      inline void resolve ()
+      {
+       for (; !_m_refs.empty (); _m_refs.pop_back ())
+         *_m_refs.back () = _m_out;
+      }
+
+      inline void resolve (const output_ref &to)
+      {
+       _m_out = to;
+       _m_known = true;
+       resolve ();
+      }
+
+      inline void refer (output_ref *out)
+      {
+       _m_refs.push_back (out);
+       if (_m_known)
+         resolve ();
+      }
+    };
+
+    std::tr1::unordered_map< ::Dwarf_Off, seen> _m_map;
+
+  public:
+    inline dwarf_ref_maker ()
+      : _m_map ()
+    {}
+
+    inline dwarf_ref_maker (const dwarf_ref_maker &other)
+      : _m_map ()
+    {
+      if (unlikely (!other._m_map.empty ()))
+       throw std::logic_error
+         ("dwarf_ref_maker copy constructs only from default-constructed");
+    }
+
+    inline ~dwarf_ref_maker ()
+    {}
+
+    inline void abort ()
+    {
+      _m_map.clear ();
+    }
+
+    inline void equivalence (const output_ref &out, const input_ref &in)
+    {
+      _m_map[in->identity ()].resolve (out);
+    }
+
+    inline void refer (output_ref *out, const input_ref &in)
+    {
+      _m_map[in->identity ()].refer (out);
+    }
+
+    inline void finish (output &file)
+    {
+      while (_m_map.begin () != _m_map.end ())
+       if (_m_map.begin ()->second._m_known)
+         _m_map.erase (_m_map.begin ());
+       else
+         throw std::logic_error ("construction finished with unresolved refs");
+    }
+  };
+
+};
+
+#endif // <elfutils/dwarf_ref_maker>
index c27a737f899327603811b2c1fb4360e46396298f..67c1ae73316a294daa8f1fb26ea1639fcb3cc641 100644 (file)
@@ -69,6 +69,7 @@ namespace elfutils
     typedef typename _base::cu2 cu2;
     typedef typename _base::die1 die1;
     typedef typename _base::die2 die2;
+    typedef typename _base::dwarf1_ref dwarf1_ref;
 
   private:
     template<typename cu, typename die>
index d1b4c7062a0e67d02f66a4579d4cc3c11cb83625..b768abe705a7d5282971383daab8f753d578b0a2 100644 (file)
@@ -578,20 +578,21 @@ namespace elfutils
     /* A wrapped_input_iterator is like an input::const_iterator,
        but *i returns wrapper (*i) instead; wrapper returns element
        (or const element & or something).  */
-    template<typename input, typename wrapper,
+    template<typename input, class wrapper,
             typename element = typename wrapper::result_type>
     class wrapped_input_iterator : public input::const_iterator
     {
     private:
       typedef typename input::const_iterator _base;
 
-      wrapper *_m_wrapper;
+      wrapper _m_wrapper;
 
     public:
       typedef element value_type;
 
-      inline wrapped_input_iterator (const _base &i, wrapper &w)
-       : _base (static_cast<_base> (i)), _m_wrapper (&w)
+      template<typename arg_type>
+      inline wrapped_input_iterator (const _base &i, const arg_type &arg)
+       : _base (static_cast<_base> (i)), _m_wrapper (arg)
       {}
 
       inline wrapped_input_iterator (const wrapped_input_iterator &i)
@@ -600,7 +601,7 @@ namespace elfutils
 
       inline typename wrapper::result_type operator* () const
       {
-       return (*_m_wrapper) (_base::operator* ());
+       return _m_wrapper (_base::operator* ());
       }
     };
 
@@ -622,8 +623,15 @@ namespace elfutils
       struct maker
        : public std::unary_function<inlet, outlet>
       {
-       arg_type _m_arg;
-       explicit inline maker (const arg_type &c) : _m_arg (c) {}
+       const arg_type _m_arg;
+
+       inline maker (const arg_type &c)
+         : _m_arg (c)
+       {}
+
+       inline maker (const maker &m)
+         : _m_arg (m._m_arg)
+       {}
 
        inline outlet operator () (const inlet &x) const
        {
@@ -635,7 +643,7 @@ namespace elfutils
        : _m_maker (c)
       {}
 
-      typedef subr::wrapped_input_iterator<input, maker> result_type;
+      typedef wrapped_input_iterator<input, maker> result_type;
 
       inline result_type operator () (const inny &i)
       {
@@ -662,17 +670,19 @@ namespace elfutils
 
       /* Wrapper worker passed to wrapped_input_iterator.
         This object holds the collector pointer.  */
-      struct maker
-       : public std::unary_function<inlet, outlet>
+      struct pair_maker
+       : public argifier<input, output, arg_type>::maker
       {
-       arg_type _m_arg;
-       explicit inline maker (const arg_type &c) : _m_arg (c) {}
+       typedef typename argifier<input, output, arg_type>::maker maker;
+
+       inline pair_maker (const arg_type &c) : maker (c) {}
+       inline pair_maker (const pair_maker &m) : maker (m) {}
 
        inline outlet operator () (const inlet &x) const
        {
          return std::make_pair (x.first,
                                 typename outlet::second_type (x.second,
-                                                              _m_arg));
+                                                              this->_m_arg));
        }
       } _m_maker;
 
@@ -680,7 +690,7 @@ namespace elfutils
        : _m_maker (c)
       {}
 
-      typedef subr::wrapped_input_iterator<input, maker> const_iterator;
+      typedef subr::wrapped_input_iterator<input, pair_maker> const_iterator;
 
       inline const_iterator operator () (const inny &i)
       {
@@ -695,6 +705,85 @@ namespace elfutils
       return argifier2nd<input, output, arg_type> (arg) (in);
     }
 
+    /* A guard object is intended to be ephemeral, existing solely to be
+       destroyed in exception paths where it was not cleared explicitly.
+       In that case, it calls tracker::soiled ().
+
+       For convenience, it can be constructed from a tracker reference or
+       pointer, or default-constructed and then filled.  It's fillable by
+       calling the guard object as a function, passing it the tracker
+       reference or pointer, which it passes through on return:
+
+              guard<tracker> g;
+              use (g (t));
+              g.clear ();
+
+       This first calls T.start ().  When G goes out of scope,
+       it calls T.abort () iff G.clear () was never called.  */
+
+    template<typename tracker>
+    class guard
+    {
+    private:
+      tracker *_m_tracker;
+
+      inline void start ()
+      {
+       _m_tracker->start ();
+      }
+
+    public:
+      inline guard (tracker *t)
+       : _m_tracker (t)
+      {
+       start ();
+      }
+
+      inline guard (tracker &t)
+       : _m_tracker (&t)
+      {
+       start ();
+      }
+
+      inline guard ()
+       : _m_tracker (NULL)
+      {}
+
+      inline tracker *operator () (tracker *t)
+      {
+       _m_tracker = t;
+       start ();
+       return t;
+      }
+
+      inline tracker &operator () (tracker &t)
+      {
+       _m_tracker = &t;
+       start ();
+       return t;
+      }
+
+      inline operator tracker * () const
+      {
+       return _m_tracker;
+      }
+
+      inline operator tracker & () const
+      {
+       return *_m_tracker;
+      }
+
+      inline void clear ()
+      {
+       _m_tracker = NULL;
+      }
+
+      inline ~guard ()
+      {
+       if (unlikely (_m_tracker != NULL))
+         _m_tracker->abort ();
+      }
+    };
   };
 };
 
index 677a5bebae85f756bb82bdae41e77d3d822d0ede..71e06292e7bc30963541a049f29ab34cd6ffcf98 100644 (file)
@@ -325,28 +325,28 @@ main (int argc, char *argv[])
 
       if (test_writer)
        {
-         dwarf_ref_tracker<dwarf_edit, dwarf> t1;
-         dwarf_ref_tracker<dwarf_edit, dwarf> t2;
-         dwarf_edit edit1 (file1, &t1);
-         dwarf_edit edit2 (file2, &t2);
+         dwarf_edit edit1 (file1);
+         dwarf_edit edit2 (file2);
          test_classes (file1, file2, edit1, edit2, same);
 
+         /*
          {
            dwarf_output_collector c1;
            dwarf_output_collector c2;
-           dwarf_output out1 (file1, &c1);
-           dwarf_output out2 (file2, &c2);
+           dwarf_output out1 (file1, c1);
+           dwarf_output out2 (file2, c2);
            test_classes (file1, file2, out1, out2, same);
            test_classes (edit1, edit2, out1, out2, same);
          }
          {
            dwarf_output_collector c1;
            dwarf_output_collector c2;
-           dwarf_output out1 (edit1, &c1);
-           dwarf_output out2 (edit2, &c2);
+           dwarf_output out1 (edit1, c1);
+           dwarf_output out2 (edit2, c2);
            test_classes (file1, file2, out1, out2, same);
            test_classes (edit1, edit2, out1, out2, same);
          }
+         */
        }
 
       result = !same;