]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarfcmp: Support four-argument usage to compare specific entries.
authorRoland McGrath <roland@redhat.com>
Wed, 30 Sep 2009 23:33:11 +0000 (16:33 -0700)
committerRoland McGrath <roland@redhat.com>
Wed, 30 Sep 2009 23:33:11 +0000 (16:33 -0700)
libdw/ChangeLog
libdw/c++/dwarf_tracker
src/ChangeLog
src/dwarfcmp.cc

index 1800a2950bb8c394c7901623d58fb152e110c358..0259370d9b22395b740eeaa0e8285aacb87dc32f 100644 (file)
@@ -1,5 +1,8 @@
 2009-09-30  Roland McGrath  <roland@redhat.com>
 
+       * c++/dwarf_tracker (dwarf_path_finder::walk::jump): New method.
+       (dwarf_ref_tracker::walk::jump): New method.
+
        * c++/dwarf (dwarf::debug_info_entry): Make constructor from file and
        offset public.
        (dwarf::debug_info_entry::compile_unit): New method.
index 06618e36b358931e34a359f73de4de492766c9cb..37055b935501d38d95ca90782a3335f9af718b29 100644 (file)
@@ -161,17 +161,29 @@ namespace elfutils
     struct walk
     {
       dwarf_path_finder *_m_tracker;
+      bool _m_jumped;
+
       inline walk (dwarf_path_finder *w, const cu &root)
-       : _m_tracker (w)
+       : _m_tracker (w), _m_jumped (false)
       {
        assert (_m_tracker->_m_path.empty ());
        _m_tracker->_m_root = root;
       }
+
       inline ~walk ()
       {
-       assert (_m_tracker->_m_path.empty ());
+       if (_m_jumped)
+         _m_tracker->_m_path.clear ();
+       else
+         assert (_m_tracker->_m_path.empty ());
        _m_tracker->_m_root = cu ();
       }
+
+      inline void jump (const typename dw::debug_info_entry &there)
+      {
+       _m_jumped = true;
+       _m_tracker->prime_path_to (there);
+      }
     };
 
     /* A step object does pre-order work when constructed and post-order
@@ -199,10 +211,38 @@ namespace elfutils
       }
     };
 
+    void prime_path_to (const typename dw::debug_info_entry &here,
+                       dwarf::debug_info_entry::identity_type id)
+    {
+      for (typename dw::debug_info_entry::children_type::const_iterator i
+            = here.children ().begin ();
+          i != here.children ().end ();
+          ++i)
+       {
+         step into (this, i);
+         if ((*i).identity () == id)
+           break;
+         prime_path_to (*i, id);
+       }
+    }
+
+    inline void prime_path_to (const typename dw::debug_info_entry &there)
+    {
+      assert (_m_path.empty ());
+      prime_path_to (*_m_root, there.identity ());
+      assert (_m_path.empty ());
+      _m_path = (*_m_seen)[there.identity ()];
+    }
+
     // Random access to a DIE, find the path of the walk that gets there.
     inline const die_path &path_to (const die &a)
     {
-      const dwarf::debug_info_entry::identity_type id = (*a).identity ();
+      return path_to (*a);
+    }
+
+    inline const die_path &path_to (const typename dw::debug_info_entry &a)
+    {
+      const dwarf::debug_info_entry::identity_type id = a.identity ();
       std::pair<typename die_map::iterator, bool> found
        = _m_seen->insert (std::make_pair (id, bad_die_path ()));
       if (found.second
@@ -462,6 +502,14 @@ namespace elfutils
       inline walk (dwarf_ref_tracker *w, const cu1 &a, const cu2 &b)
        : _m_left (&w->_m_left, a), _m_right (&w->_m_right, b)
       {}
+
+      // Wind forward to cache everything up through A and B.
+      inline void jump (const typename dwarf1::debug_info_entry &a,
+                       const typename dwarf2::debug_info_entry &b)
+      {
+       _m_left.jump (a);
+       _m_right.jump (b);
+      }
     };
 
     struct step
index 217143cbd6a63c20a55751d0fac224c5ba7c87ec..9d5a50a5ebb9c83a33d11706fb749007022da573 100644 (file)
@@ -1,3 +1,7 @@
+2009-09-30  Roland McGrath  <roland@redhat.com>
+
+       * dwarfcmp.cc: Support four-argument usage to compare specific entries.
+
 2009-09-15  Roland McGrath  <roland@redhat.com>
 
        * dwarfcmp.cc (talker, noisy_cmp): Describe context mismatch details
index 37cbb6c6a54226b6747e68ab6fc4a5fda28b9f00..aba8c86b7f3342a78db3cc83b5eb20d9d03b967c 100644 (file)
@@ -40,7 +40,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <cstdint>
+#include <cinttypes>
 #include "../libdw/libdwP.h"   // XXX
 
 #include "c++/dwarf"
@@ -80,10 +80,12 @@ static const struct argp_option options[] =
 
 /* Short description of program.  */
 static const char doc[] = N_("\
-Compare two DWARF files for semantic equality.");
+Compare two DWARF files for semantic equality.\n\
+In the second form, compare only the given pair of entries.");
 
 /* Strings for arguments in help texts.  */
-static const char args_doc[] = N_("FILE1 FILE2");
+static const char args_doc[] = N_("FILE1 FILE2\n\
+FILE1 FILE2 OFFSET1 OFFSET2");
 
 /* Prototype for option handler.  */
 static error_t parse_opt (int key, char *arg, struct argp_state *state);
@@ -196,7 +198,8 @@ struct talker : public dwarf_ref_tracker<dwarf1, dwarf2>
     if (!visiting_result_)
       location () << dwarf::tags::name (a.tag ())
                  << " vs "
-                 << dwarf::tags::name (b.tag ());
+                 << dwarf::tags::name (b.tag ())
+                 << endl;
   }
 
   inline bool keep_going ()
@@ -376,6 +379,24 @@ struct talker : public dwarf_ref_tracker<dwarf1, dwarf2>
   }
 };
 
+template<class dw>
+static inline typename dw::compile_units::const_iterator
+find_cu (const dw &file, const typename dw::debug_info_entry &entry)
+{
+  dwarf::debug_info_entry::identity_type id = entry.compile_unit ().identity ();
+
+  for (typename dw::compile_units::const_iterator cu
+        = file.compile_units ().begin ();
+       cu != file.compile_units ().end ();
+       ++cu)
+    {
+      if ((*cu).identity () == id)
+       return cu;
+    }
+
+  throw std::logic_error ("cannot find compile_unit for debug_info_entry!");
+}
+
 template<class dwarf1, class dwarf2, class tracker>
 struct cmp
   : public dwarf_comparator<dwarf1, dwarf2, false, tracker>
@@ -390,7 +411,24 @@ struct cmp
 template<class dwarf1, class dwarf2>
 struct quiet_cmp
   : public cmp<dwarf1, dwarf2, dwarf_ref_tracker<dwarf1, dwarf2> >
-{};
+{
+  typedef dwarf_ref_tracker<dwarf1, dwarf2> my_tracker;
+
+  inline bool operator () (const dwarf1 &a, const dwarf2 &b)
+  {
+    return equals (a, b);
+  }
+
+  inline bool operator () (const dwarf1 &file1, const dwarf2 &file2,
+                          const typename dwarf1::debug_info_entry &a,
+                          const typename dwarf2::debug_info_entry &b)
+  {
+    typename my_tracker::walk in (&this->_m_tracker,
+                                 find_cu (file1, a), find_cu (file2, b));
+    in.jump (a, b);
+    return equals (a, b);
+  }
+};
 
 template<class dwarf1, class dwarf2>
 static inline bool
@@ -399,12 +437,25 @@ quiet_compare (const dwarf1 &a, const dwarf2 &b)
   return quiet_cmp<dwarf1, dwarf2> () (a, b);
 }
 
+template<class dwarf1, class dwarf2>
+static inline bool
+quiet_compare (const dwarf1 &file1, const dwarf2 &file2,
+              const typename dwarf1::debug_info_entry &a,
+              const typename dwarf2::debug_info_entry &b)
+
+{
+  return quiet_cmp<dwarf1, dwarf2> () (file1, file2, a, b);
+}
+
 // To be noisy, the talker wraps the standard tracker with verbosity hooks.
 template<class dwarf1, class dwarf2, bool print_all>
 struct noisy_cmp
   : public cmp<dwarf1, dwarf2, talker<dwarf1, dwarf2, print_all> >
 {
-  inline bool operator () (const dwarf1 &a, const dwarf2 &b)
+  typedef talker<dwarf1, dwarf2, print_all> my_tracker;
+
+  template<typename item1, typename item2>
+  inline bool compare (const item1 &a, const item2 &b)
   {
     if (equals (a, b) && this->_m_tracker.result_)
       {
@@ -414,6 +465,21 @@ struct noisy_cmp
     this->_m_tracker.print_bad_context ();
     return false;
   }
+
+  inline bool operator () (const dwarf1 &a, const dwarf2 &b)
+  {
+    return compare (a, b);
+  }
+
+  inline bool operator () (const dwarf1 &file1, const dwarf2 &file2,
+                          const typename dwarf1::debug_info_entry &a,
+                          const typename dwarf2::debug_info_entry &b)
+  {
+    typename my_tracker::walk in (&this->_m_tracker,
+                                 find_cu (file1, a), find_cu (file2, b));
+    in.jump (a, b);
+    return compare (a, b);
+  }
 };
 
 template<class dwarf1, class dwarf2>
@@ -425,6 +491,18 @@ noisy_compare (const dwarf1 &a, const dwarf2 &b, bool print_all)
          : noisy_cmp<dwarf1, dwarf2, false> () (a, b));
 }
 
+template<class dwarf1, class dwarf2>
+static inline bool
+noisy_compare (const dwarf1 &file1, const dwarf2 &file2,
+              const typename dwarf1::debug_info_entry &a,
+              const typename dwarf2::debug_info_entry &b,
+              bool print_all)
+{
+  return (print_all
+         ? noisy_cmp<dwarf1, dwarf2, true> () (file1, file2, a, b)
+         : noisy_cmp<dwarf1, dwarf2, false> () (file1, file2, a, b));
+}
+
 
 #ifdef TEST
 
@@ -514,6 +592,31 @@ static inline void do_writer_test (dwarf &, dwarf &, bool) {}
 #endif // TEST
 
 
+static inline const dwarf::debug_info_entry
+parse_offset (const char *name, dwarf &file, const char *arg)
+{
+  char *end = NULL;
+  Dwarf_Off offset = strtoull (arg, &end, 16);
+  if (end == NULL || *end != '\0')
+    {
+      fputs (gettext ("Invalid offset parameter (use hex).\n"),
+            stderr);
+      argp_help (&argp, stderr, ARGP_HELP_SEE,
+                program_invocation_short_name);
+      exit (1);
+    }
+  try
+    {
+      return dwarf::debug_info_entry (file, offset);
+    }
+  catch (std::runtime_error x)
+    {
+      fprintf (stderr, gettext ("%s: offset %#" PRIx64 ": %s\n"),
+              name, offset, x.what ());
+      exit (1);
+    }
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -531,17 +634,18 @@ main (int argc, char *argv[])
   (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
 
   /* We expect exactly two non-option parameters.  */
-  if (unlikely (remaining + 2 != argc))
+  if (unlikely (remaining + 2 != argc)
+      && unlikely (remaining + 4 != argc))
     {
       fputs (gettext ("Invalid number of parameters.\n"), stderr);
       argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name);
       exit (1);
     }
-  const char *const fname1 = argv[remaining];
+  const char *const fname1 = argv[remaining++];
   int fd1;
   Dwarf *dw1 = open_file (fname1, &fd1);
 
-  const char *const fname2 = argv[remaining + 1];
+  const char *const fname2 = argv[remaining++];
   int fd2;
   Dwarf *dw2 = open_file (fname2, &fd2);
 
@@ -563,13 +667,29 @@ main (int argc, char *argv[])
       dwarf file1 (dw1);
       dwarf file2 (dw2);
 
-      bool same = (quiet
-                  ? quiet_compare (file1, file2)
-                  : noisy_compare (file1, file2, verbose));
+      if (remaining < argc)
+       {
+         const dwarf::debug_info_entry a = parse_offset (fname1, file1,
+                                                         argv[remaining++]);
+         const dwarf::debug_info_entry b = parse_offset (fname2, file2,
+                                                         argv[remaining++]);
+
+         bool same = (quiet
+                      ? quiet_compare (file1, file2, a, b)
+                      : noisy_compare (file1, file2, a, b, verbose));
+
+         result = !same;
+       }
+      else
+       {
+         bool same = (quiet
+                      ? quiet_compare (file1, file2)
+                      : noisy_compare (file1, file2, verbose));
 
-      do_writer_test (file1, file2, same);
+         do_writer_test (file1, file2, same);
 
-      result = !same;
+         result = !same;
+       }
     }
 
   dwarf_end (dw1);