]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
more fiddling
authorRoland McGrath <roland@redhat.com>
Wed, 1 Jul 2009 23:18:28 +0000 (16:18 -0700)
committerRoland McGrath <roland@redhat.com>
Wed, 1 Jul 2009 23:18:28 +0000 (16:18 -0700)
libdw/c++/dwarf_comparator
libdw/c++/dwarf_tracker
tests/run-dwarfcmp-self.sh

index 4f0f470c81b5c29d4f2162b1f61ba37005690e29..d0c18f24f0e699b27d61f56985bb6be685dce684 100644 (file)
@@ -68,18 +68,27 @@ namespace elfutils
     typedef typename dwarf1_die::attributes_type::const_iterator attr1;
     typedef typename dwarf2_die::attributes_type::const_iterator attr2;
 
-    inline void start_walk (const cu1 &a, const cu2 &b)
-    {
-    }
-    inline void finish_walk (const cu1 &a, const cu2 &b)
-    {
-    }
-    inline void pre_order (const die1 &a, const die2 &b)
+    // This object is created to start a walk and destroyed to finish one.
+    struct walk
     {
-    }
-    inline void post_order (const die1 &a, const die2 &b)
+      inline walk (dwarf_tracker_base *, const cu1 &a, const cu2 &b)
+      {
+      }
+      inline ~walk ()
+      {
+      }
+    };
+
+    // This object is created in pre-order and destroyed in post-order.
+    struct step
     {
-    }
+      inline step (dwarf_tracker_base *, const die1 &a, const die2 &b)
+      {
+      }
+      inline ~step ()
+      {
+      }
+    };
 
     inline void visit (const typename dwarf1::debug_info_entry &a,
                       const typename dwarf2::debug_info_entry &b)
@@ -169,55 +178,6 @@ namespace elfutils
 
   };
 
-  struct dwarf_tracker_utils
-  {
-    /* A walk object does start_walk when constructed and finish_walk
-       when destroyed, so finish_walk always runs even for exceptions.  */
-    template<typename tracker>
-    struct walk
-    {
-      typedef typename tracker::cu1 cu1;
-      typedef typename tracker::cu2 cu2;
-
-      tracker *_m_walker;
-      const cu1 &_m_a;
-      const cu2 &_m_b;
-
-      inline walk (tracker *w, const cu1 &a, const cu2 &b)
-       : _m_walker (w), _m_a (a), _m_b (b)
-      {
-       _m_walker->start_walk (_m_a, _m_b);
-      }
-      inline ~walk ()
-      {
-       _m_walker->finish_walk (_m_a, _m_b);
-      }
-    };
-
-    /* A step object does pre_order when constructed and post_order
-       when destroyed, so post_order always runs even for exceptions.  */
-    template<typename tracker>
-    struct step
-    {
-      typedef typename tracker::die1 die1;
-      typedef typename tracker::die2 die2;
-
-      tracker *_m_walker;
-      const die1 &_m_a;
-      const die2 &_m_b;
-
-      inline step (tracker *w, const die1 &a, const die2 &b)
-       : _m_walker (w), _m_a (a), _m_b (b)
-      {
-       _m_walker->pre_order (_m_a, _m_b);
-      }
-      inline ~step ()
-      {
-       _m_walker->post_order (_m_a, _m_b);
-      }
-    };
-  };
-
   template<class dwarf1, class dwarf2,
           bool ignore_refs = false,
           class tracker = dwarf_tracker_base<dwarf1, dwarf2>
@@ -242,7 +202,8 @@ namespace elfutils
       }
     };
 #define MATCHER(item) \
-    matcher<typename dwarf1::item, typename dwarf2::item>
+    matcher<typename dwarf1::item::const_iterator, \
+           typename dwarf2::item::const_iterator> (*this)
 
     inline bool match (const dwarf1 &a, const dwarf2 &b)
     {
@@ -260,8 +221,7 @@ namespace elfutils
       const cu1_it end1 = a.end ();
       const cu2_it end2 = b.end ();
       if (subr::container_equal
-         (it1, end1, it2, end2,
-          MATCHER (compile_units::const_iterator) (*this)))
+         (it1, end1, it2, end2, MATCHER (compile_units)))
        return true;
       _m_tracker.mismatch (it1, end1, it2, end2);
       return false;
@@ -271,7 +231,7 @@ namespace elfutils
     typedef typename dwarf2::debug_info_entry die2;
     inline bool match (const cu1_it &a, const cu2_it &b)
     {
-      dwarf_tracker_utils::walk<tracker> in (&_m_tracker, a, b);
+      typename tracker::walk in (&_m_tracker, a, b);
       return match (static_cast<die1> (*a), static_cast<die2> (*b));
     }
 
@@ -390,47 +350,49 @@ namespace elfutils
     typedef typename dwarf2::debug_info_entry::children_type children2;
     typedef typename children1::const_iterator cit1;
     typedef typename children2::const_iterator cit2;
-    struct die_matcher
-      : public std::binary_function<cit1, cit2, bool>
+
+    inline bool match_child (const cit1 &a, const cit2 &b)
     {
-      dwarf_comparator &_m_cmp;
-      die_matcher (dwarf_comparator &cmp)
-       : _m_cmp (cmp)
-      {}
+      typename tracker::step into (&_m_tracker, a, b);
+      return match (*a, *b);
+    }
 
-      inline bool operator () (const cit1 &a, const cit2 &b)
-      {
+    inline bool match (const cit1 &a, const cit2 &b)
+    {
 #if 0 // XXX
-       // Maybe the tracker has already cached a correspondence of DIEs.
-       typename tracker::reference_match matched;
-       if (_m_cmp._m_tracker.reference_matched
-           (matched,
-            _m_cmp._m_tracker.left_context (), a,
-            _m_cmp._m_tracker.right_context (), b))
+      // Maybe the tracker has already cached a correspondence of DIEs.
+      typename tracker::reference_match matched;
+      if (_m_tracker.reference_matched (matched,
+                                       _m_tracker.left_context (), a,
+                                       _m_tracker.right_context (), b))
+       {
+         std::cout << "short-circuit DIE match " << std::hex << a->offset ()
+                   << std::endl;
          return true;
+       }
 
-       if (matched.cannot_match ())
-         return false;
+      if (matched.cannot_match ())
+       return false;
 #endif
 
-       dwarf_tracker_utils::step<tracker> into (&_m_cmp._m_tracker, a, b);
-       bool result = _m_cmp.match (*a, *b);
+      bool result = match_child (a, b);
 
 #if 0 // XXX
-       // Let the tracker cache a result for its reference_matched.
-       matched.notice_match (b, result);
+      // Let the tracker cache a result for its reference_matched.
+      matched.notice_match (b, result);
 #endif
 
-       return result;
-      }
-    };
+      return result;
+    }
+
     inline bool match (const children1 &a, const children2 &b)
     {
       cit1 it1 = a.begin ();
       cit2 it2 = b.begin ();
       const cit1 end1 = a.end ();
       const cit2 end2 = b.end ();
-      if (subr::container_equal (it1, end1, it2, end2, die_matcher (*this)))
+      if (subr::container_equal (it1, end1, it2, end2,
+                                MATCHER (debug_info_entry::children_type)))
        return true;
       _m_tracker.mismatch (it1, end1, it2, end2);
       return false;
@@ -537,7 +499,11 @@ namespace elfutils
       // Maybe the tracker has already cached a correspondence of references.
       typename tracker::reference_match matched;
       if (_m_tracker.reference_matched (matched, lhs, ref1, rhs, ref2))
-       return true;
+       {
+         std::cout << "short-circuit ref match " << std::hex << a.offset ()
+                   << std::endl;
+         return true;
+       }
 
       if (matched.cannot_match ())
        return false;
index bc68a1fbd3db7945c84b8a24002924edd2d23bab..104a689d05f3ac46fa6832f9fbae2005ec05442d 100644 (file)
@@ -87,6 +87,7 @@ namespace elfutils
       cu _m_root;
 
       die_path _m_path;
+      const die_path *_m_context;
 
       // We use a singleton list of a default-constructed iterator as a marker.
       static inline const die_path bad_die_path ()
@@ -104,15 +105,17 @@ namespace elfutils
 
       // Default constructor: an original tracker.
       inline tracker ()
-       : _m_seen (new die_map), _m_delete_seen (true)
+       : _m_seen (new die_map), _m_delete_seen (true), _m_context (NULL)
       {}
 
       // 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)
+         _m_root (proto._m_root), _m_path (context), _m_context (&context)
       {
+       printf("derived tracker context %p from %p\n",
+              _m_context, proto._m_context);
        _m_path.push_back (there);
       }
 
@@ -123,55 +126,90 @@ namespace elfutils
            delete _m_seen;
            // We should never be left with a partial walk on the books.
            assert (_m_path.empty ());
+           assert (_m_context == NULL);
          }
       }
 
       // Main hooks for a normal walk.
 
-      inline void start_walk (const cu &a)
+      /* 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
       {
-       assert (_m_path.empty ());
-       _m_root = a;
-      }
+       tracker *_m_tracker;
+       inline walk (tracker *w, const cu &root)
+         : _m_tracker (w)
+       {
+         assert (_m_tracker->_m_path.empty ());
+         _m_tracker->_m_root = root;
+         //???   _m_tracker->_m_context = &(*_m_tracker->_m_seen)[(*root).identity ()];
+         printf("walk CU %#x context %p\n", (*root).offset (), _m_tracker->_m_context);
+       }
+       inline ~walk ()
+       {
+         assert (_m_tracker->_m_path.empty ());
+         _m_tracker->_m_root = cu ();
+         //???   _m_tracker->_m_context = NULL;
+       }
+      };
 
-      inline void finish_walk (const cu &a)
+      /* 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
       {
-       assert (_m_path.empty ());
-       _m_root = cu ();
-      }
+       tracker *_m_walker;
+       const die_path *_m_old_context;
+       inline step (tracker *w, const die &here)
+         : _m_walker (w), _m_old_context (w->_m_context)
+       {
+         _m_walker->print_path (_m_walker->_m_path, true, false, "pre_order", here);
+
+         printf ("ctx{%p} %d vs path %u\n",
+                 _m_walker->_m_context,
+                 _m_walker->_m_context?
+                 _m_walker->_m_context->size():-1,_m_walker->_m_path.size());
+
+         // Record the path down from the CU to see this DIE.
+         _m_walker->_m_context = &(_m_walker->_m_seen->insert
+                                   (std::make_pair (here->identity (),
+                                                    _m_walker->_m_path))
+                                   .first->second);
 
-      bool print_path (bool before, bool result,
-                      const char *what, const die &there)
+         printf("pre_order context %p from %p",
+                _m_walker->_m_context, _m_old_context);
+         _m_walker->print_path (*_m_walker->_m_context, true, false, ":", here);
+
+         // Append this DIE to the path we'll record for its children.
+         _m_walker->_m_path.push_back (here);
+       }
+       inline ~step ()
+       {
+         printf("post_order context %p from %p\n",
+                _m_walker->_m_context, _m_old_context);
+         _m_walker->_m_context = _m_old_context;
+         _m_walker->_m_path.pop_back ();
+       }
+      };
+
+      static bool print_path (const die_path &path,
+                             bool before, bool result,
+                             const char *what, const die &there)
       {
-       return result;
        if (before)
          std::cout << what << std::hex
                    << "(" << there->offset () << ")";
        else
          std::cout << "after " << what << std::hex
                    << "(" << there->offset () << (result ? "=>T)" : "=>F)");
-       for (typename die_path::const_iterator it = _m_path.begin ();
-            it != _m_path.end ();
+       for (typename die_path::const_iterator it = path.begin ();
+            it != path.end ();
             ++it)
          std::cout << "->" << (*it)->offset ();
        std::cout << std::endl;
        return result;
       }
-#define W(w,r) (print_path(true,false,#w,a),print_path(false,w r,#w,a))
-
-      inline void pre_order (const die &a)
-      {
-       print_path(true,false, "pre_order", a);
-       // Record the path down from the CU to see this DIE.
-       _m_seen->insert (std::make_pair (a->identity (), _m_path));
-       // Append this DIE to the path we'll record for its children.
-       _m_path.push_back (a);
-      }
-
-      inline void post_order (const die &a)
-      {
-       _m_path.pop_back ();
-      }
+#define W(w,r) (print_path(_m_path,true,false,#w,a),print_path(_m_path,false,w r,#w,a))
 
       // Random access to a DIE, find the path of the walk that gets there.
       inline const die_path &path_to (const die &a)
@@ -205,24 +243,6 @@ namespace elfutils
                        there, cache);
       }
 
-      /* A step object does pre_order when constructed and post_order
-        when destroyed, so post_order always runs even for exceptions.
-        While this object lives, HERE is on the _m_path stack.  */
-      struct step
-      {
-       tracker *_m_walker;
-       const die &_m_here;
-       inline step (tracker *w, const die &here)
-         : _m_walker (w), _m_here (here)
-       {
-         _m_walker->pre_order (_m_here);
-       }
-       inline ~step ()
-       {
-         _m_walker->post_order (_m_here);
-       }
-      };
-
       bool walk_to (die it, const die &end,
                    const die &there, typename die_map::iterator &cache)
       {
@@ -232,7 +252,7 @@ namespace elfutils
              {
                // XXX is this iterator really still valid for erase/insert?
                // XXX note there may have been other insertions since
-       print_path(false,true, "walk_to", there);
+       print_path(_m_path,false,true, "walk_to", there);
 
                typename die_map::iterator x
                  = _m_seen->find (there->identity ());
@@ -241,6 +261,9 @@ namespace elfutils
                cache = _m_seen->insert (x,
                                         std::make_pair (there->identity (),
                                                         _m_path));
+               printf("walk_to %#x insert %p\n",
+                      there->offset(), &cache->second);
+
                return true;
              }
            else
@@ -386,34 +409,30 @@ namespace elfutils
       _m_right._m_seen->clear ();
     }
 
-    inline void start_walk (const cu1 &a, const cu2 &b)
+    struct walk
     {
-      _m_left.start_walk (a);
-      _m_right.start_walk (b);
-    }
+      typename tracker1::walk _m_left;
+      typename tracker2::walk _m_right;
 
-    inline void finish_walk (const cu1 &a, const cu2 &b)
-    {
-      _m_left.finish_walk (a);
-      _m_right.finish_walk (b);
-    }
+      inline walk (dwarf_ref_tracker *w, const cu1 &a, const cu2 &b)
+       : _m_left (&w->_m_left, a), _m_right (&w->_m_right, b)
+      {}
+    };
 
-    inline void pre_order (const die1 &a, const die2 &b)
+    struct step
     {
-      _m_left.pre_order (a);
-      _m_right.pre_order (b);
-    }
+      typename tracker1::step _m_left;
+      typename tracker2::step _m_right;
 
-    inline void post_order (const die1 &a, const die2 &b)
-    {
-      _m_left.post_order (a);
-      _m_right.post_order (b);
-    }
+      inline step (dwarf_ref_tracker *w, const die1 &a, const die2 &b)
+       : _m_left (&w->_m_left, a), _m_right (&w->_m_right, b)
+      {}
+    };
 
     typedef std::list<die1> left_context_type;
     inline const left_context_type &left_context ()
     {
-      return _m_left._m_path;
+      return *_m_left._m_context;
     }
 
     inline const left_context_type &left_context (const die1 &die)
@@ -424,7 +443,7 @@ namespace elfutils
     typedef std::list<die2> right_context_type;
     inline const right_context_type &right_context ()
     {
-      return _m_right._m_path;
+      return *_m_right._m_context;
     }
 
     inline const right_context_type &right_context (const die2 &die)
@@ -482,9 +501,17 @@ namespace elfutils
                       const left_context_type &lhs, const die1 &a,
                       const right_context_type &rhs, const die2 &b)
     {
+      if (&lhs) _m_left.print_path (lhs, true, false, "r_m lhs", a);
+      else puts("r_m lhs NULL!");
+      if (&rhs) _m_right.print_path (rhs, true, false, "r_m rhs", b);
+      else puts("r_m rhs NULL!");
       typename equiv_map::mapped_type *elt = &(*_m_equiv)[a->identity ()];
       if (elt->first == NULL)
        {
+         printf("r_m {%p, %#x} vs {%p, %#x}\n",
+                &lhs, a->offset (),
+                &rhs, b->offset ());
+
          /* Record that we have a walk in progress crossing A.
             When MATCHED goes out of scope in our caller, its
             destructor will reset ELT->first to clear this record.  */
@@ -495,6 +522,11 @@ namespace elfutils
          return elt->second.find (b->identity ()) != elt->second.end ();
        }
 
+      printf("r_m circ %p {%p, %#x} vs {%p, %#x}\n",
+            elt->first,
+            &lhs, a->offset (),
+            &rhs, b->offset ());
+
       /* We have a circularity.  We can tell because ELT->first remains
         set from an outer recursion still in progress.
 
index 927083ed0c3edcb6be9997925523f6b3c9a7e495..6f511444ea3fd5b65f18a9f9d53513f8e882c8e3 100755 (executable)
@@ -30,9 +30,13 @@ runtest()
 {
   for file; do
     if [ -f $file ]; then
-      { testrun ../src/dwarfcmp -q -i $file $file &&
+      {
+(set -x
+        testrun ../src/dwarfcmp -q -i $file $file &&
        testrun ../src/dwarfcmp -i $file $file &&
-       testrun ../src/dwarfcmp -T -q -i $file $file
+:
+#      testrun ../src/dwarfcmp -T -q -i $file $file
+) > dwarfcmp-${file//\//_}.out 2>&1
       } ||
       { echo "*** failure in $file"; status=1; }
     fi
@@ -41,6 +45,7 @@ runtest()
 
 runtest ../src/addr2line
 runtest ../src/dwarfcmp
+runtest ../src/dwarflint
 runtest ../src/elfcmp
 runtest ../src/elflint
 runtest ../src/findtextrel