]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Split out dwarf_path_finder from dwarf_ref_tracker::tracker.
authorRoland McGrath <roland@redhat.com>
Mon, 6 Jul 2009 09:03:52 +0000 (02:03 -0700)
committerRoland McGrath <roland@redhat.com>
Mon, 6 Jul 2009 09:03:52 +0000 (02:03 -0700)
libdw/ChangeLog
libdw/c++/dwarf_tracker

index fef45842ff36370b5fa7dd52cde036aff65b64e4..8fef9dc461f09214281d0cfead116397230abaa2 100644 (file)
@@ -1,3 +1,8 @@
+2009-07-06  Roland McGrath  <roland@redhat.com>
+
+       * c++/dwarf_tracker (tracker): Break out private class into ...
+       (dwarf_path_finder): ... here.
+
 2009-07-03  Roland McGrath  <roland@redhat.com>
 
        * c++/dwarf: Give line info stubby to_string methods.
index f12b3a101ec8b92f244a774c3f7daf8878c70d37..1a442a42fb8106ba2449d3bd7ebdf79023ff4f84 100644 (file)
 
 namespace elfutils
 {
-  // Standard tracker.
-  template<class dwarf1, class dwarf2>
-  class dwarf_ref_tracker : public dwarf_tracker_base<dwarf1, dwarf2>
+  // Basic tracker of tree-walk paths to DIEs.
+  template<typename dw>
+  class dwarf_path_finder
   {
-  private:
-    typedef dwarf_tracker_base<dwarf1, dwarf2> _base;
-
   public:
-    typedef typename _base::cu1 cu1;
-    typedef typename _base::cu2 cu2;
-    typedef typename _base::die1 die1;
-    typedef typename _base::die2 die2;
-    typedef typename _base::dwarf1_ref dwarf1_ref;
+    typedef typename dw::compile_units::const_iterator cu;
+    typedef typename dw::debug_info_entry::children_type::const_iterator die;
+
+    /* We maintain the current path down the logical DIE tree from the CU
+       as a stack of iterators pointing to the DIE at each level.  */
+    typedef std::list<die> die_path;
 
   private:
-    template<typename cu, typename die>
-    struct tracker
+    // We use a singleton list of a default-constructed iterator as a marker.
+    static inline const die_path bad_die_path ()
     {
-      /* We maintain the current path down the logical DIE tree from the CU
-        as a stack of iterators pointing to the DIE at each level.  */
-      typedef std::list<die> die_path;
+      return die_path (1);
+    }
+    static inline bool bad_die_path (const die_path &path)
+    {
+      typename die_path::const_iterator it = path.begin ();
+      if (it == path.end ())
+       return false;
+      const die &elt = *it;
+      return ++it == path.end () && elt == die ();
+    }
 
-      // We use a singleton list of a default-constructed iterator as a marker.
-      static inline const die_path bad_die_path ()
-      {
-       return die_path (1);
-      }
-      static inline bool bad_die_path (const die_path &path)
-      {
-       typename die_path::const_iterator it = path.begin ();
-       if (it == path.end ())
-         return false;
-       const die &elt = *it;
-       return ++it == path.end () && elt == die ();
-      }
+    /* We record every DIE we have seen here, mapping its .identity ()
+       to the die_path of parent DIEs taken to reach it.  */
+    typedef std::tr1::unordered_map< ::Dwarf_Off, const die_path> die_map;
+    die_map *_m_seen;
+    bool _m_delete_seen;
 
-      /* We record every DIE we have seen here, mapping its .identity ()
-        to the die_path of parent DIEs taken to reach it.  */
-      typedef std::tr1::unordered_map< ::Dwarf_Off, const die_path> die_map;
-      die_map *_m_seen;
-      bool _m_delete_seen;
+    cu _m_root;
 
-      cu _m_root;
+    die_path _m_path;
 
-      die_path _m_path;
+  public:
+    // Default constructor: an original tracker.
+    inline dwarf_path_finder ()
+      : _m_seen (new die_map), _m_delete_seen (true)
+    {}
 
-      // Default constructor: an original tracker.
-      inline tracker ()
-       : _m_seen (new die_map), _m_delete_seen (true)
-      {}
+    // Construct a derived tracker: does its own walk, but sharing caches.
+    inline dwarf_path_finder (const dwarf_path_finder &proto,
+                             const die_path &context, const die &there)
+      : _m_seen (proto._m_seen), _m_delete_seen (false),
+       _m_root (proto._m_root), _m_path (context)
+    {
+      _m_path.push_back (there);
+    }
 
-      // Construct a derived tracker: does its own walk, but sharing caches.
-      inline tracker (const tracker &proto,
-                     const die_path &context, const die &there)
-       : _m_seen (proto._m_seen), _m_delete_seen (false),
-         _m_root (proto._m_root), _m_path (context)
+    inline ~dwarf_path_finder ()
+    {
+      if (_m_delete_seen)
+       {
+         delete _m_seen;
+         // We should never be left with a partial walk on the books.
+         assert (_m_path.empty ());
+       }
+    }
+
+    // Main hooks for a normal walk.
+
+    /* A walk object does set-up work when constructed and tear-down
+       work when destroyed, so tear-down is done even for exceptions.  */
+    struct walk
+    {
+      dwarf_path_finder *_m_tracker;
+      inline walk (dwarf_path_finder *w, const cu &root)
+       : _m_tracker (w)
       {
-       _m_path.push_back (there);
+       assert (_m_tracker->_m_path.empty ());
+       _m_tracker->_m_root = root;
       }
-
-      inline ~tracker ()
+      inline ~walk ()
       {
-       if (_m_delete_seen)
-         {
-           delete _m_seen;
-           // We should never be left with a partial walk on the books.
-           assert (_m_path.empty ());
-         }
+       assert (_m_tracker->_m_path.empty ());
+       _m_tracker->_m_root = cu ();
       }
+    };
 
-      // Main hooks for a normal walk.
-
-      /* A walk object does set-up work when constructed and tear-down
-        work when destroyed, so tear-down is done even for exceptions.  */
-      struct walk
+    /* A step object does pre-order work when constructed and post-order
+       work when destroyed, so post-order is done even for exceptions.
+       While this object lives, HERE is on the _m_path stack.  */
+    struct step
+    {
+      dwarf_path_finder *_m_walker;
+      inline step (dwarf_path_finder *w, const die &here)
+       : _m_walker (w)
       {
-       tracker *_m_tracker;
-       inline walk (tracker *w, const cu &root)
-         : _m_tracker (w)
-       {
-         assert (_m_tracker->_m_path.empty ());
-         _m_tracker->_m_root = root;
-       }
-       inline ~walk ()
-       {
-         assert (_m_tracker->_m_path.empty ());
-         _m_tracker->_m_root = cu ();
-       }
-      };
+       // Record the path down from the CU to see this DIE.
+       _m_walker->_m_seen->insert (std::make_pair (here->identity (),
+                                                   _m_walker->_m_path));
 
-      /* A step object does pre-order work when constructed and post-order
-        work when destroyed, so post-order is done even for exceptions.
-        While this object lives, HERE is on the _m_path stack.  */
-      struct step
+       // Append this DIE to the path we'll record for its children.
+       _m_walker->_m_path.push_back (here);
+      }
+      inline ~step ()
       {
-       tracker *_m_walker;
-       inline step (tracker *w, const die &here)
-         : _m_walker (w)
-       {
-         // Record the path down from the CU to see this DIE.
-         _m_walker->_m_seen->insert (std::make_pair (here->identity (),
-                                                     _m_walker->_m_path));
+       _m_walker->_m_path.pop_back ();
+      }
+    };
 
-         // Append this DIE to the path we'll record for its children.
-         _m_walker->_m_path.push_back (here);
-       }
-       inline ~step ()
+    // Random access to a DIE, find the path of the walk that gets there.
+    inline const die_path &path_to (const die &a)
+    {
+      ::Dwarf_Off id = a->identity ();
+      std::pair<typename die_map::iterator, bool> found
+       = _m_seen->insert (std::make_pair (id, bad_die_path ()));
+      if (found.second
+         /* It's not in our _m_seen map.  Our main walk recording
+            into _m_seen is exhaustive, so this can only be a forward
+            reference.  That is, we didn't already hit this DIE in
+            our top-level walk and so it is not in _m_seen yet.
+
+            We must do a separate walk to find it.  Since we know
+            this is a forward reference, we don't have to start a
+            fresh walk from the root, just momentarily wind forward
+            from where we are.  */
+         && !walk_down_to (a, found.first)
+         && !walk_over_to (a, found.first)
+         && !walk_up_to (a, found.first))
+       throw std::runtime_error ("DIE not reachable from CU!");
+      assert (&found.first->second != NULL);
+      assert (!bad_die_path (found.first->second));
+      return found.first->second;
+    }
+
+  private:
+    inline bool walk_to (const typename die::value_type &here,
+                        const die &there, typename die_map::iterator &cache)
+    {
+      return walk_to (here.children ().begin (),
+                     here.children ().end (),
+                     there, cache);
+    }
+
+    bool walk_to (die it, const die &end,
+                 const die &there, typename die_map::iterator &cache)
+    {
+      for (; it != end; ++it)
        {
-         _m_walker->_m_path.pop_back ();
+         if (it == there)
+           {
+             /* We can't keep the old CACHE iterator and avoid this
+                find (hash lookup), because there could have been
+                other insertions in the map since it was taken.
+                Those can invalidate old iterators.  */
+             cache = _m_seen->find (there->identity ());
+             _m_seen->erase (cache);
+             cache = _m_seen->insert (cache,
+                                      std::make_pair (there->identity (),
+                                                      _m_path));
+             return true;
+           }
+         else
+           {
+             /* Do "step into" even for !has_children ()
+                because it records this child in _m_seen,
+                which we will rely on later.  */
+             step into (this, it);
+             const typename die::value_type &child = *it;
+             if (child.has_children () && walk_to (child, there, cache))
+               return true;
+           }
        }
-      };
+      return false;
+    }
+
+    /* First descend into the current DIE's children.
+       _m_path already has the current DIE, so it is ready to go.  */
+    // XXX is a reference to an owned DIE really possible??
+    inline bool walk_down_to (const die &there,
+                             typename die_map::iterator &cache)
+    {
+      const die &start = _m_path.back ();
+      const typename die::value_type &here = *start;
+
+      /* It's common to have a reference to the next sibling DIE.
+        So bypass the descent to HERE's children if THERE is
+        HERE's immediate next sibling.  */
+      if (!here.has_children () || there == ++die (start))
+       return false;
+
+      return walk_to (here, there, cache);
+    }
 
-      // Random access to a DIE, find the path of the walk that gets there.
-      inline const die_path &path_to (const die &a)
+    /* A step_back object pops the current DIE off _m_path when
+       constructed, and pushes it back when destroyed.  */
+    struct step_back
+    {
+      dwarf_path_finder *_m_walker;
+      const die _m_here;
+      inline step_back (dwarf_path_finder *w, die &copy)
+       : _m_walker (w), _m_here (w->_m_path.back ())
       {
-       ::Dwarf_Off id = a->identity ();
-       std::pair<typename die_map::iterator, bool> found
-         = _m_seen->insert (std::make_pair (id, bad_die_path ()));
-       if (found.second
-           /* It's not in our _m_seen map.  Our main walk recording
-              into _m_seen is exhaustive, so this can only be a forward
-              reference.  That is, we didn't already hit this DIE in
-              our top-level walk and so it is not in _m_seen yet.
-
-              We must do a separate walk to find it.  Since we know
-              this is a forward reference, we don't have to start a
-              fresh walk from the root, just momentarily wind forward
-              from where we are.  */
-           && !walk_down_to (a, found.first)
-           && !walk_over_to (a, found.first)
-           && !walk_up_to (a, found.first))
-         throw std::runtime_error ("DIE not reachable from CU!");
-       assert (&found.first->second != NULL);
-       assert (!bad_die_path (found.first->second));
-       return found.first->second;
+       w->_m_path.pop_back ();
+       copy = _m_here;
       }
-
-      inline bool walk_to (const typename die::value_type &here,
-                          const die &there, typename die_map::iterator &cache)
+      inline ~step_back ()
       {
-       return walk_to (here.children ().begin (),
-                       here.children ().end (),
-                       there, cache);
+       _m_walker->_m_path.push_back (_m_here);
       }
+    };
+
+    /* Now wind the walk forward starting from the current DIE's
+       immediate sibling.  */
+    inline bool walk_over_to (const die &there,
+                             typename die_map::iterator &cache)
+    {
+      die next;
+      step_back from (this, next);
+      ++next;
+
+      return walk_to (next, (_m_path.empty ()
+                            ? (*_m_root).children ().end ()
+                            : _m_path.back ()->children ().end ()),
+                     there, cache);
+    }
 
-      bool walk_to (die it, const die &end,
-                   const die &there, typename die_map::iterator &cache)
+    /* A step_up object saves _m_path when constructed
+       and restores it when destroyed.  */
+    struct step_up
+    {
+      dwarf_path_finder *_m_walker;
+      die_path _m_save;
+      inline step_up (dwarf_path_finder *w)
+       : _m_walker (w), _m_save (w->_m_path)
       {
-       for (; it != end; ++it)
-         {
-           if (it == there)
-             {
-               /* We can't keep the old CACHE iterator and avoid this
-                  find (hash lookup), because there could have been
-                  other insertions in the map since it was taken.
-                  Those can invalidate old iterators.  */
-               cache = _m_seen->find (there->identity ());
-               _m_seen->erase (cache);
-               cache = _m_seen->insert (cache,
-                                        std::make_pair (there->identity (),
-                                                        _m_path));
-               return true;
-             }
-           else
-             {
-               /* Do "step into" even for !has_children ()
-                  because it records this child in _m_seen,
-                  which we will rely on later.  */
-               step into (this, it);
-               const typename die::value_type &child = *it;
-               if (child.has_children () && walk_to (child, there, cache))
-                 return true;
-             }
-         }
-       return false;
       }
-
-      /* First descend into the current DIE's children.
-        _m_path already has the current DIE, so it is ready to go.  */
-      // XXX is a reference to an owned DIE really possible??
-      inline bool walk_down_to (const die &there,
-                               typename die_map::iterator &cache)
+      inline ~step_up ()
       {
-       const die &start = _m_path.back ();
-       const typename die::value_type &here = *start;
-
-       /* It's common to have a reference to the next sibling DIE.
-          So bypass the descent to HERE's children if THERE is
-          HERE's immediate next sibling.  */
-       if (!here.has_children () || there == ++die (start))
-         return false;
-
-       return walk_to (here, there, cache);
+       _m_walker->_m_path.swap (_m_save);
       }
+    };
 
-      /* A step_back object pops the current DIE off _m_path when
-        constructed, and pushes it back when destroyed.  */
-      struct step_back
-      {
-       tracker *_m_walker;
-       const die _m_here;
-       inline step_back (tracker *w, die &copy)
-         : _m_walker (w), _m_here (w->_m_path.back ())
-       {
-         w->_m_path.pop_back ();
-         copy = _m_here;
-       }
-       inline ~step_back ()
-       {
-         _m_walker->_m_path.push_back (_m_here);
-       }
-      };
+    /* Now wind the walk forward starting from the current DIE's
+       parent's immediate sibling.  */
+    inline bool walk_up_to (const die &there,
+                           typename die_map::iterator &cache)
+    {
+      if (_m_path.empty ())
+       return false;
 
-      /* Now wind the walk forward starting from the current DIE's
-        immediate sibling.  */
-      inline bool walk_over_to (const die &there,
-                               typename die_map::iterator &cache)
-      {
-       die next;
-       step_back from (this, next);
-       ++next;
-
-       return walk_to (next, (_m_path.empty ()
-                              ? (*_m_root).children ().end ()
-                              : _m_path.back ()->children ().end ()),
-                       there, cache);
-      }
+      step_up from (this);
 
-      /* A step_up object saves _m_path when constructed
-        and restores it when destroyed.  */
-      struct step_up
-      {
-       tracker *_m_walker;
-       die_path _m_save;
-       inline step_up (tracker *w)
-         : _m_walker (w), _m_save (w->_m_path)
+      do
        {
+         _m_path.pop_back ();
+         assert (!_m_path.empty ());
+         if (walk_over_to (there, cache))
+           return true;
        }
-       inline ~step_up ()
-       {
-         _m_walker->_m_path.swap (_m_save);
-       }
-      };
-
-      /* Now wind the walk forward starting from the current DIE's
-        parent's immediate sibling.  */
-      inline bool walk_up_to (const die &there,
-                             typename die_map::iterator &cache)
-      {
-       if (_m_path.empty ())
-         return false;
+      while (!_m_path.empty ());
 
-       step_up from (this);
+      return false;
+    }
+  };
 
-       do
-         {
-           _m_path.pop_back ();
-           assert (!_m_path.empty ());
-           if (walk_over_to (there, cache))
-             return true;
-         }
-       while (!_m_path.empty ());
+  // Standard tracker.
+  template<class dwarf1, class dwarf2>
+  class dwarf_ref_tracker : public dwarf_tracker_base<dwarf1, dwarf2>
+  {
+  private:
+    typedef dwarf_tracker_base<dwarf1, dwarf2> _base;
 
-       return false;
-      }
-    };
+  public:
+    typedef typename _base::cu1 cu1;
+    typedef typename _base::cu2 cu2;
+    typedef typename _base::die1 die1;
+    typedef typename _base::die2 die2;
+    typedef typename _base::dwarf1_ref dwarf1_ref;
 
-    typedef tracker<cu1, die1> tracker1;
-    typedef tracker<cu2, die2> tracker2;
+  private:
+    typedef dwarf_path_finder<dwarf1> tracker1;
+    typedef dwarf_path_finder<dwarf2> tracker2;
 
     tracker1 _m_left;
     tracker2 _m_right;