]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Add dwarfcmp -l to show all differences.
authorRoland McGrath <roland@redhat.com>
Thu, 20 Aug 2009 08:19:17 +0000 (01:19 -0700)
committerRoland McGrath <roland@redhat.com>
Thu, 20 Aug 2009 08:19:17 +0000 (01:19 -0700)
libdw/ChangeLog
libdw/c++/dwarf_comparator
libdw/c++/dwarf_tracker
src/ChangeLog
src/dwarfcmp.cc

index 1b4125d535c5d7a43ecc60dc2f950f641bdd2887..b36935e237fd2c5d32ade2261817fbd2acd330c2 100644 (file)
@@ -1,3 +1,9 @@
+2009-08-20  Roland McGrath  <roland@redhat.com>
+
+       * c++/dwarf_comparator: Use tracker::subtracker for subcomparator.
+       Let mismatch hooks return bool that is true to keep comparing.
+       * c++/dwarf_tracker: Define subtracker.
+
 2009-08-19  Roland McGrath  <roland@redhat.com>
 
        * c++/dwarf_tracker: Revamp derived tracker logic.
index 7ba2475c3386b5f10e876bea2103f9533223b136..3e136639197334317ab3b3560f17a4464ec2a735 100644 (file)
@@ -96,19 +96,22 @@ namespace elfutils
     {
     }
 
-    inline void mismatch (const cu1 &, const cu1 &, // at, end
-                         const cu2 &, const cu2 &)
+    inline bool mismatch (cu1 &, const cu1 &, // at, end
+                         cu2 &, const cu2 &)
     {
+      return false;
     }
 
-    inline void mismatch (const die1 &, const die1 &, // at, end
-                         const die2 &, const die2 &)
+    inline bool mismatch (die1 &, const die1 &, // at, end
+                         die2 &, const die2 &)
     {
+      return false;
     }
 
-    inline void mismatch (const attr1 &, const attr1 &, // at, end
-                         const attr2 &, const attr2 &)
+    inline bool mismatch (attr1 &, const attr1 &, // at, end
+                         attr2 &, const attr2 &)
     {
+      return false;
     }
 
     struct left_context_type {};
@@ -159,6 +162,7 @@ namespace elfutils
     inline dwarf_tracker_base ()
     {}
 
+    typedef dwarf_tracker_base subtracker;
     inline dwarf_tracker_base (const dwarf_tracker_base &, reference_match &,
                               const left_context_type &,
                               const right_context_type &)
@@ -175,6 +179,9 @@ namespace elfutils
   private:
     tracker &_m_tracker;
 
+    typedef dwarf_comparator<dwarf1, dwarf2, false,
+                            typename tracker::subtracker> subcomparator;
+
     template<typename item1, typename item2>
     struct matcher : public std::binary_function<item1, item2, bool>
     {
@@ -207,10 +214,13 @@ namespace elfutils
       cu2_it it2 = b.begin ();
       const cu1_it end1 = a.end ();
       const cu2_it end2 = b.end ();
-      if (subr::container_equal
-         (it1, end1, it2, end2, MATCHER (compile_units)))
-       return true;
-      _m_tracker.mismatch (it1, end1, it2, end2);
+      do
+       {
+         if (subr::container_equal
+             (it1, end1, it2, end2, MATCHER (compile_units)))
+           return true;
+       }
+      while (_m_tracker.mismatch (it1, end1, it2, end2));
       return false;
     }
 
@@ -299,18 +309,21 @@ namespace elfutils
          // The set of attributes matches, in order.  Compare the values.
          it1 = a.begin ();
          it2 = b.begin ();
-         if (subr::container_equal (it1, end1, it2, end2, match_rhs (*this)))
-           return true;
-         _m_tracker.mismatch (it1, end1, it2, end2);
+         do
+           {
+             if (subr::container_equal (it1, end1, it2, end2,
+                                        match_rhs (*this)))
+               return true;
+           }
+         while (_m_tracker.mismatch (it1, end1, it2, end2));
          return false;
        }
 
       if (it1 != end1 && it2 != end2
          && !(attributes1::ordered () && attributes2::ordered ()))
        {
-         /* We have the same number of attributes, but the names don't match.
-
-          */
+         /* We have the same number of attributes, but the names don't
+            match.  Populate two sorted maps and compare those.  */
 
          ait1_map sorted1;
          populate (sorted1, a);
@@ -319,18 +332,18 @@ namespace elfutils
          populate (sorted2, b);
 
          std::pair<typename ait1_map::iterator,
-                   typename ait2_map::iterator> result
+           typename ait2_map::iterator> result
            = std::mismatch (sorted1.begin (), sorted1.end (),
                             sorted2.begin (), match_sorted (*this));
-         if (result.first == sorted1.end () && result.second == sorted2.end ())
+         if (result.first == sorted1.end ()
+             && result.second == sorted2.end ())
            return true;
 
          it1 = result.first->second;
          it2 = result.second->second;
        }
 
-      _m_tracker.mismatch (it1, end1, it2, end2);
-      return false;
+      return _m_tracker.mismatch (it1, end1, it2, end2);
     }
 
     typedef typename dwarf1::debug_info_entry::children_type children1;
@@ -368,10 +381,11 @@ namespace elfutils
       cit2 it2 = b.begin ();
       const cit1 end1 = a.end ();
       const cit2 end2 = b.end ();
-      if (subr::container_equal (it1, end1, it2, end2,
-                                MATCHER (debug_info_entry::children_type)))
-       return true;
-      _m_tracker.mismatch (it1, end1, it2, end2);
+      do
+       if (subr::container_equal (it1, end1, it2, end2,
+                                  MATCHER (debug_info_entry::children_type)))
+         return true;
+      while (_m_tracker.mismatch (it1, end1, it2, end2));
       return false;
     }
 
@@ -494,8 +508,8 @@ namespace elfutils
       bool result = !has_children;
       if (has_children)
        {
-         tracker t (_m_tracker, matched, lhs, rhs);
-         result = dwarf_comparator (t).match (a.children (), b.children ());
+         typename tracker::subtracker t (_m_tracker, matched, lhs, rhs);
+         result = subcomparator (t).equals (a.children (), b.children ());
        }
 
       // Let the tracker cache a result for its reference_matched.
index 23a8a6af2546301a84ab0f7054810ff447ccd226..acff400cd00bfd8975b55b2262cdcb15d312c422 100644 (file)
@@ -567,6 +567,8 @@ namespace elfutils
       return *elt->first == b;
     }
 
+    typedef dwarf_ref_tracker subtracker;
+
     // Share the _m_seen maps with the prototype tracker,
     // but start a fresh walk from the given starting point.
     inline dwarf_ref_tracker (const dwarf_ref_tracker &proto, reference_match &,
index feecbf29737e9f6c6ecec1f583f30142e80f6f79..dd71bf43ee3c9c06996286ea9aad0b35b195fe6e 100644 (file)
@@ -1,3 +1,9 @@
+2009-08-20  Roland McGrath  <roland@redhat.com>
+
+       * dwarfcmp.cc (verbose): New variable.
+       (options, parse_opt): Add --verbose/-l to set it.
+       (talker): Keep going after mismatches when verbose.
+
 2009-08-19  Roland McGrath  <roland@redhat.com>
 
        Diagnose reference mismatches with more detail.
index d62a2edeea758da922b331d19d8d06248e47e4f0..14f0b118c79c9299d00c2988215675121e7d96b0 100644 (file)
@@ -68,6 +68,7 @@ static const struct argp_option options[] =
 {
   { NULL, 0, NULL, 0, N_("Control options:"), 0 },
   { "quiet", 'q', NULL, 0, N_("Output nothing; yield exit status only"), 0 },
+  { "verbose", 'l', NULL, 0, N_("Output all differences"), 0 },
   { "ignore-missing", 'i', NULL, 0,
     N_("Don't complain if both files have no DWARF at all"), 0 },
 
@@ -99,6 +100,9 @@ static bool quiet;
 /* Nonzero if missing DWARF is equal DWARF.  */
 static bool missing_ok;
 
+/* True if we should print all differences.  */
+static bool verbose;
+
 /* Nonzero to test writer classes.  */
 static int test_writer;
 
@@ -130,7 +134,7 @@ template<class dwarf1, class dwarf2>
 struct talker : public dwarf_ref_tracker<dwarf1, dwarf2>
 {
   typedef dwarf_tracker_base<dwarf1, dwarf2> _base;
-  typedef dwarf_ref_tracker<dwarf1, dwarf2> _tracker;
+  typedef dwarf_ref_tracker<dwarf1, dwarf2> subtracker;
   typedef typename _base::cu1 cu1;
   typedef typename _base::cu2 cu2;
   typedef typename _base::die1 die1;
@@ -140,19 +144,26 @@ struct talker : public dwarf_ref_tracker<dwarf1, dwarf2>
 
   const typename dwarf1::debug_info_entry *a_;
   const typename dwarf2::debug_info_entry *b_;
+  bool result_;
 
   inline talker ()
-    : a_ (NULL), b_ (NULL)
+    : a_ (NULL), b_ (NULL), result_ (true)
   {}
 
-  inline talker (const talker &proto, typename _tracker::reference_match &m,
-                const typename _tracker::left_context_type &l,
-                const typename _tracker::right_context_type &r)
-    : _tracker (static_cast<const _tracker &> (proto), m, l, r),
+  inline talker (const talker &proto, typename subtracker::reference_match &m,
+                const typename subtracker::left_context_type &l,
+                const typename subtracker::right_context_type &r)
+    : subtracker (static_cast<const subtracker &> (proto), m, l, r),
       a_ (NULL), b_ (NULL)
   {
   }
 
+  inline bool keep_going ()
+  {
+    result_ = false;
+    return verbose;
+  }
+
   inline ostream &location () const
   {
     return cout << hex << a_->offset () << " vs " << b_->offset () << ": ";
@@ -169,43 +180,67 @@ struct talker : public dwarf_ref_tracker<dwarf1, dwarf2>
                  << dwarf::tags::name (b.tag ());
   }
 
-  inline void mismatch (const cu1 &it1, const cu1 &end1,
-                       const cu2 &it2, const cu2 &end2)
+  inline bool mismatch (cu1 &it1, const cu1 &end1,
+                       cu2 &it2, const cu2 &end2)
   {
     if (it1 == end1)           // a lacks some of b's CUs.
-      cout << "files differ: "
-          << dec << subr::length (it2, end2)
-          << " extra compilation units "
-          << endl;
+      {
+       cout << "files differ: "
+            << dec << subr::length (it2, end2)
+            << " extra compilation units "
+            << endl;
+       it2 = end2;
+      }
     else if (it2 == end2)      // b lacks some of a's CUs.
-      cout << "files differ: "
-          << dec << subr::length (it1, end1)
-          << " compilation units missing "
-          << endl;
-    // Otherwise the differing CU will have announced itself.
+      {
+       cout << "files differ: "
+            << dec << subr::length (it1, end1)
+            << " compilation units missing "
+            << endl;
+       it1 = end1;
+      }
+    else
+      // Otherwise the differing CU will have announced itself.
+      ++it1, ++it2;
+    return keep_going ();
   }
 
-  inline void mismatch (const die1 &it1, const die1 &end1,
-                       const die2 &it2, const die2 &end2)
+  inline bool mismatch (die1 &it1, const die1 &end1,
+                       die2 &it2, const die2 &end2)
   {
     if (it1 == end1)           // a_ lacks some of b_'s children.
-      location () << dec << subr::length (it2, end2)
-                 << " extra children " << endl;
+      {
+       location () << dec << subr::length (it2, end2)
+                   << " extra children " << endl;
+       it2 = end2;
+      }
     else if (it2 == end2)      // b_ lacks some of a_'s children.
-      location () << dec << subr::length (it1, end1)
-                 << " children missing " << endl;
-    // Otherwise the differing child will have announced itself.
+      {
+       location () << dec << subr::length (it1, end1)
+                   << " children missing " << endl;
+       it1 = end1;
+      }
+    else
+      // Otherwise the differing child will have announced itself.
+      ++it1, ++it2;
+    return keep_going ();
   }
 
-  inline void mismatch (attr1 it1, const attr1 &end1,
-                       attr2 it2, const attr2 &end2)
+  inline bool mismatch (attr1 &it1, const attr1 &end1,
+                       attr2 &it2, const attr2 &end2)
   {
     if (it1 == end1)           // a_ lacks some of b_'s attrs.
-      for (location () << " extra attributes:"; it2 != end2; ++it2)
-       cout << " " << to_string (*it2);
+      {
+       for (location () << " extra attributes:"; it2 != end2; ++it2)
+         cout << " " << to_string (*it2);
+       it2 = end2;
+      }
     else if (it2 == end2)      // b_ lacks some of a_'s attrs.
-      for (location () << " missing attributes:"; it1 != end1; ++it1)
-       cout << " " << to_string (*it1);
+      {
+       for (location () << " missing attributes:"; it1 != end1; ++it1)
+         cout << " " << to_string (*it1);
+       it1 = end1;
+      }
     else
       {
        location () << to_string (*it1) << " vs " << to_string (*it2);
@@ -213,14 +248,20 @@ struct talker : public dwarf_ref_tracker<dwarf1, dwarf2>
            && (*it2).second.what_space () == dwarf::VS_reference)
          reference_mismatch ((*it1).second.reference (),
                              (*it2).second.reference ());
+       ++it1;
+       ++it2;
       }
     cout << endl;
+    return keep_going ();
   }
 
   inline void reference_mismatch (const die1 &ref1, const die2 &ref2)
   {
-    dwarf_comparator<dwarf1, dwarf2, false, _tracker> cmp (*(_tracker *) this);
-    if (cmp.equals (*ref1, *ref2))
+    dwarf_comparator<
+      dwarf1, dwarf2, false, subtracker> cmp (*(subtracker *) this);
+    if (cmp.equals (ref1, ref2))
+      cout << " (XXX refs now equal again!)";
+    else if (cmp.equals (*ref1, *ref2))
       cout << " (identical but contexts mismatch)";
     else
       {
@@ -256,7 +297,12 @@ struct quiet_cmp
 template<class dwarf1, class dwarf2>
 struct noisy_cmp
   : public cmp<dwarf1, dwarf2, talker<dwarf1, dwarf2> >
-{};
+{
+  inline bool operator () (const dwarf1 &a, const dwarf2 &b)
+  {
+    return equals (a, b) && this->_m_tracker.result_;
+  }
+};
 
 
 // Test that one comparison works as expected.
@@ -417,6 +463,10 @@ parse_opt (int key, char *, struct argp_state *)
       quiet = true;
       break;
 
+    case 'l':
+      verbose = true;
+      break;
+
     case 'i':
       missing_ok = true;
       break;