]> sourceware.org Git - libabigail.git/commitdiff
Add a --stats to abidiff and abidw
authorDodji Seketeli <dodji@redhat.com>
Thu, 20 Aug 2015 10:28:38 +0000 (12:28 +0200)
committerDodji Seketeli <dodji@redhat.com>
Thu, 20 Aug 2015 11:25:42 +0000 (13:25 +0200)
For now, this new --stats emits diagnostics about the number of types
canonicalized at the very end of building the ABI corpus as well as
the number of types that were scheduled for late canonicalizing and
that couldn't be canonicalized.

* include/abg-dwarf-reader.h (get_show_stats)
(set_show_stats): New accessors for a new "show_stats" property of
the dwarf reader context.
* src/abg-dwarf-reader.cc: Include iostream to use std::cerr.
(dwarf_reader::show_stats_): New data member.
(dwarf_reader::dwarf_reader): Initialize it.
(dwarf_reader::show_stats)
(get_show_stats)
(set_show_stats): Define new accessors.
(dwarf_reader::die_type_map): Add const overload to this accessor.
(dwarf_reader::lookup_type_from_die_offset): Make this accessor
const.
(dwarf_reader::add_late_canonicalized_types_stats): New member
function.
(dwarf_reader::perform_late_type_canonicalizing): Emit the
statistics about late-canonicalized types if the user asked for
it.
* tools/abidiff.cc (options::show_stats): New data member.
(options::options): Initialize it.
(display_usage): Document it.
(parse_command_line): Parse the new --stats option.
(main): Create a dwarf reader context, set the show_stats to it
and then use that context to read the corpora before diffing them.
* tools/abidw.cc (options::show_stats): New data member.
(options::options): Initialize it.
(display_usage): Document it.
(parse_command_line): Parse the new --stats option.
(main): Set the show_stats to the dwarf reader context before
using it.
* doc/manuals/abidiff.rst: Update the manual.
* doc/manuals/abidw.rst: Update the manual.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
doc/manuals/abidiff.rst
doc/manuals/abidw.rst
include/abg-dwarf-reader.h
src/abg-dwarf-reader.cc
tools/abidiff.cc
tools/abidw.cc

index 1dc93df73ca477b57e512ff27cbaca9768028b8b..1b7d3479d21d24efe0d9467c318f1e6a4c90bf0b 100644 (file)
@@ -208,6 +208,10 @@ Options
     changes.  Added or removed functions and variables do not have any
     diff nodes tree associated to them.
 
+  * ``--stats``
+
+    Emit statistics about various internal things.
+
 .. _abidiff_return_value_label:
 
 Return values
index 11785a0f9ecf564adb1da205738503519ba85f84..67c2008d091f7c664e47b182a12de25d918c939b 100644 (file)
@@ -69,6 +69,10 @@ Options
     makes ``abidw`` load *all* the types defined in the binaries, even
     those that are not reachable from public declarations.
 
+  * ``--stats``
+
+    Emit statistics about various internal things.
+
 Notes
 =====
 
index dfa408c9d004f8ed374a5c76ce1d5d9605b9b5d8..bdc71fe9c1f8ba2844c7b5427b6a07db5ba3378b 100644 (file)
@@ -128,6 +128,14 @@ get_soname_of_elf_file(const string& path, string& soname);
 bool
 get_type_of_elf_file(const string& path, elf_type& type);
 
+
+bool
+get_show_stats(read_context_sptr& ctxt);
+
+void
+set_show_stats(read_context_sptr& ctxt,
+                                   bool f);
+
 }// end namespace dwarf_reader
 
 }// end namespace abigail
index cab4490a98f0c6989197de61953c75a2eda6f5db..c54e02dd9fbd19c4293b6887092bcb477cf266e7 100644 (file)
@@ -37,6 +37,7 @@
 #include <cmath>
 #include <elfutils/libdwfl.h>
 #include <dwarf.h>
+#include <iostream>
 #include <tr1/unordered_map>
 #include <stack>
 #include <deque>
@@ -51,6 +52,8 @@ using std::string;
 namespace abigail
 {
 
+using std::cerr;
+
 /// The namespace for the DWARF reader.
 namespace dwarf_reader
 {
@@ -1780,6 +1783,7 @@ class read_context
   string                       elf_architecture_;
   corpus::exported_decls_builder* exported_decls_builder_;
   bool                         load_all_types_;
+  bool                         show_stats_;
 
   read_context();
 
@@ -1801,7 +1805,8 @@ public:
       verdef_section_(),
       verneed_section_(),
       exported_decls_builder_(),
-      load_all_types_()
+      load_all_types_(),
+      show_stats_()
   {}
 
   /// Clear the data that is relevant only for the current translation
@@ -2129,6 +2134,19 @@ public:
     return die_type_map_;
   }
 
+  /// Return the map that associates DIEs to the type they represent.
+  ///
+  /// @param in_alt_die true iff the DIE is in the alternate debug info section.
+  ///
+  /// @return return the map that associated DIEs to the type they represent.
+  const die_type_map_type&
+  die_type_map(bool in_alt_die) const
+  {
+    if (in_alt_die)
+      return alternate_die_type_map_;
+    return die_type_map_;
+  }
+
   /// Associated a DIE (representing a type) at a given offset to the
   /// type that it represents.
   ///
@@ -2165,11 +2183,11 @@ public:
   /// or NULL if no type is associated to the DIE.
   type_base_sptr
   lookup_type_from_die_offset(size_t die_offset,
-                             bool in_alt_die)
+                             bool in_alt_die) const
   {
     type_base_sptr result;
-    die_type_map_type& m = die_type_map(in_alt_die);
-    die_type_map_type::iterator i = m.find(die_offset);
+    const die_type_map_type& m = die_type_map(in_alt_die);
+    die_type_map_type::const_iterator i = m.find(die_offset);
 
     if (i != m.end())
       result = i->second;
@@ -2489,6 +2507,59 @@ public:
       }
   }
 
+  /// Compute the number of canonicalized and missed types in the late
+  /// canonicalization phase.
+  ///
+  /// @param in_alt_di if set to yes, this means to look for types in
+  /// the alternate debug info.  If set to no, this means to look for
+  /// the main debug info.
+  ///
+  /// @param canonicalized the number of types that got canonicalized
+  /// is added to the value already present in this parameter.
+  ///
+  /// @param missed the number of types scheduled for late
+  /// canonicalization and which couldn't be canonicalized (for a
+  /// reason) is added to the value already present in this parameter.
+  void
+  add_late_canonicalized_types_stats(bool in_alt_di,
+                                    size_t& canonicalized,
+                                    size_t& missed) const
+  {
+    for (vector<Dwarf_Off>::const_iterator i =
+          types_to_canonicalize(in_alt_di).begin();
+        i != types_to_canonicalize(in_alt_di).end();
+        ++i)
+      {
+        type_base_sptr t = lookup_type_from_die_offset(*i, in_alt_di);
+       if (t->get_canonical_type())
+         ++canonicalized;
+       else
+         ++missed;
+      }
+  }
+
+  /// Compute the number of canonicalized and missed types in the late
+  /// canonicalization phase.
+  ///
+  /// @param canonicalized the number of types that got canonicalized
+  /// is added to the value already present in this parameter.
+  ///
+  /// @param missed the number of types scheduled for late
+  /// canonicalization and which couldn't be canonicalized (for a
+  /// reason) is added to the value already present in this parameter.
+  void
+  add_late_canonicalized_types_stats(size_t& canonicalized,
+                                    size_t& missed) const
+  {
+    add_late_canonicalized_types_stats(/*in_alt_di=*/true,
+                                      canonicalized,
+                                      missed);
+
+      add_late_canonicalized_types_stats(/*in_alt_di=*/false,
+                                        canonicalized,
+                                        missed);
+  }
+
   // Look at the types that need to be canonicalized after the
   // translation unit has been constructed and canonicalize them.
   void
@@ -2496,6 +2567,24 @@ public:
   {
     canonicalize_types_scheduled(/*in_alt_di=*/false);
     canonicalize_types_scheduled(/*in_alt_di=*/true);
+
+    if (show_stats())
+      {
+       size_t num_canonicalized = 0, num_missed = 0, total = 0;
+       add_late_canonicalized_types_stats(num_canonicalized,
+                                          num_missed);
+       total = num_canonicalized + num_missed;
+       cerr << "binary: "
+            << elf_path()
+            << "\n";
+       cerr << "    # late canonicalized types: "
+            << num_canonicalized
+            << " (" << num_canonicalized * 100 / total << "%)\n"
+            << "    # missed canonicalization opportunities: "
+            << num_missed
+            << " (" << num_missed * 100 / total << "%)\n";
+      }
+
   }
 
   const die_tu_map_type&
@@ -3647,6 +3736,26 @@ public:
   load_all_types(bool f)
   {load_all_types_ = f;}
 
+  /// Getter of the "show_stats" flag.
+  ///
+  /// This flag tells if we should emit statistics about various
+  /// internal stuff.
+  ///
+  /// @return the value of the flag.
+  bool
+  show_stats() const
+  {return show_stats_;}
+
+  /// Setter of the "show_stats" flag.
+  ///
+  /// This flag tells if we should emit statistics about various
+  /// internal stuff.
+  ///
+  /// @param f the value of the flag.
+  void
+  show_stats(bool f)
+  {show_stats_ = f;}
+
   /// If a given function decl is suitable for the set of exported
   /// functions of the current corpus, this function adds it to that
   /// set.
@@ -3706,6 +3815,38 @@ finish_member_function_reading(Dwarf_Die*                die,
                               function_decl_sptr       f,
                               class_decl_sptr          klass);
 
+/// Getter of the "show_stats" flag.
+///
+/// This flag tells if we should emit statistics about various
+/// internal stuff.
+///
+/// @param ctx the read context to consider for this flag.
+///
+/// @return the value of the flag.
+bool
+get_show_stats(read_context_sptr& ctxt)
+{
+  if(!ctxt)
+    return false;
+  return ctxt->show_stats();
+}
+
+/// Setter of the "show_stats" flag.
+///
+/// This flag tells if we should emit statistics about various
+/// internal stuff.
+///
+/// @param ctxt the read context to consider for this flag.
+///
+/// @param f the value of the flag.
+void
+set_show_stats(read_context_sptr& ctxt,
+              bool f)
+{
+  if (ctxt)
+    ctxt->show_stats(f);
+}
+
 /// Constructor for a default Dwfl handle that knows how to load debug
 /// info from a library or executable elf file.
 ///
index 9c706b5bab94a016111662d3d71e17020105ba32..9e9221e6b7da330172f2f21faca7545f03d84db3 100644 (file)
@@ -79,6 +79,7 @@ struct options
   bool                 show_redundant_changes;
   bool                 show_symbols_not_referenced_by_debug_info;
   bool                 dump_diff_tree;
+  bool                 show_stats;
   shared_ptr<char>     di_root_path1;
   shared_ptr<char>     di_root_path2;
 
@@ -100,7 +101,8 @@ struct options
       show_harmless_changes(false),
       show_redundant_changes(false),
       show_symbols_not_referenced_by_debug_info(true),
-      dump_diff_tree()
+      dump_diff_tree(),
+      show_stats()
   {}
 };//end struct options;
 
@@ -111,6 +113,7 @@ display_usage(const string& prog_name, ostream& out)
       << " where options can be:\n"
       << " --debug-info-dir1|--d1 <path> the root for the debug info of file1\n"
       << " --debug-info-dir2|--d2 <path> the root for the debug info of file2\n"
+      << " --help|-h  display this message\n "
       << " --stat  only display the diff stats\n"
       << " --symtabs  only display the symbol tables of the corpora\n"
       << " --deleted-fns  display deleted public functions\n"
@@ -138,7 +141,7 @@ display_usage(const string& prog_name, ostream& out)
          "(this is the default)\n"
       << " --dump-diff-tree  emit a debug dump of the internal diff tree to "
          "the error output stream\n"
-      << " --help|-h display this message\n";
+      <<  " --stats  show statistics about various internal stuff\n";
 }
 
 /// Parse the command line and set the options accordingly.
@@ -331,6 +334,8 @@ parse_command_line(int argc, char* argv[], options& opts)
        opts.show_redundant_changes = false;
       else if (!strcmp(argv[i], "--dump-diff-tree"))
        opts.dump_diff_tree = true;
+      else if (!strcmp(argv[i], "--stats"))
+       opts.show_stats = true;
       else
        return false;
     }
@@ -532,11 +537,18 @@ main(int argc, char* argv[])
          break;
        case abigail::tools_utils::FILE_TYPE_ELF:
        case abigail::tools_utils::FILE_TYPE_AR:
-         di_dir1 = opts.di_root_path1.get();
-         c1 = abigail::dwarf_reader::read_corpus_from_elf(opts.file1,
-                                                          &di_dir1,
-                                                          /*load_all_types=*/false,
-                                                          c1_status);
+         {
+           di_dir1 = opts.di_root_path1.get();
+           abigail::dwarf_reader::read_context_sptr ctxt =
+             abigail::dwarf_reader::create_read_context(opts.file1,
+                                                        &di_dir1,
+                                                        /*read_all_types=*/false);
+           assert(ctxt);
+           abigail::dwarf_reader::set_show_stats
+             (ctxt, opts.show_stats);
+
+           c1 = abigail::dwarf_reader::read_corpus_from_elf(*ctxt, c1_status);
+         }
          break;
        case abigail::tools_utils::FILE_TYPE_XML_CORPUS:
          c1 =
@@ -566,11 +578,17 @@ main(int argc, char* argv[])
          break;
        case abigail::tools_utils::FILE_TYPE_ELF:
        case abigail::tools_utils::FILE_TYPE_AR:
-         di_dir2 = opts.di_root_path2.get();
-         c2 = abigail::dwarf_reader::read_corpus_from_elf(opts.file2,
-                                                          &di_dir2,
-                                                          /*load_all_types=*/false,
-                                                          c2_status);
+         {
+           di_dir2 = opts.di_root_path2.get();
+           abigail::dwarf_reader::read_context_sptr ctxt =
+             abigail::dwarf_reader::create_read_context(opts.file2,
+                                                        &di_dir2,
+                                                        /*read_all_types=*/false);
+           assert(ctxt);
+           abigail::dwarf_reader::set_show_stats
+             (ctxt, opts.show_stats);
+           c2 = abigail::dwarf_reader::read_corpus_from_elf(*ctxt, c2_status);
+         }
          break;
        case abigail::tools_utils::FILE_TYPE_XML_CORPUS:
          c2 =
index 77a1cb6fc350fffdee4bf099841f344b6ea6000b..3f988a519983911812f01be279cfca301eba7b15 100644 (file)
@@ -56,12 +56,14 @@ struct options
   bool                 show_base_name_alt_debug_info_path;
   bool                 write_architecture;
   bool                 load_all_types;
+  bool                 show_stats;
 
   options()
     : check_alt_debug_info_path(),
       show_base_name_alt_debug_info_path(),
       write_architecture(true),
-      load_all_types()
+      load_all_types(),
+      show_stats()
   {}
 };
 
@@ -80,6 +82,7 @@ display_usage(const string& prog_name, ostream& out)
     "debug info of <elf-path>, and show its base name\n"
       << "  --load-all-types read all types including those not reachable from"
          "exported declarations\n"
+      << "  --stats  show statistics about various internal stuff\n";
     ;
 }
 
@@ -138,6 +141,8 @@ parse_command_line(int argc, char* argv[], options& opts)
        }
       else if (!strcmp(argv[i], "--load-all-types"))
        opts.load_all_types = true;
+      else if (!strcmp(argv[i], "--stats"))
+       opts.show_stats = true;
       else if (!strcmp(argv[i], "--help")
               || !strcmp(argv[i], "--h"))
        return false;
@@ -185,6 +190,7 @@ main(int argc, char* argv[])
   corpus_sptr corp;
   read_context_sptr c = create_read_context(opts.in_file_path, &p,
                                            opts.load_all_types);
+  set_show_stats(c, opts.show_stats);
   read_context& ctxt = *c;
 
   if (opts.check_alt_debug_info_path)
This page took 0.053701 seconds and 5 git commands to generate.