public inbox for libabigail@sourceware.org
 help / color / mirror / Atom feed
From: dodji@redhat.com
To: libabigail@sourceware.org
Cc: dodji@redhat.com
Subject: [PATCH 16/17] abidw: Support the --abidiff option for Linux Kernel trees
Date: Tue, 16 Jul 2024 16:55:27 +0200	[thread overview]
Message-ID: <20240716145541.473065-17-dodji@redhat.com> (raw)
In-Reply-To: <20240716145541.473065-1-dodji@redhat.com>

From: Dodji Seketeli <dodji@redhat.com>

It turned out abidw --abidiff (self-comparison) doesn't work when
analyzing a Linux Kernel tree.  In other words, abidw cannot
self-compare a Linux Kernel tree.  Embarrassing.  Fixed thus.

	* include/abg-corpus.h (is_corpus_group): Declare ...
	* src/abg-corpus.cc (is_corpus_group): ... new function.
	* src/abg-ctf-reader.cc (create_reader): Support --debug-abidiff
	when the package is configured with --enable-debug-self-comparison.
	* tools/abidw.cc (load_corpus_and_write_abixml): Factorize self
	comparison code out into ...
	(perform_self_comparison): ... this.
	(load_kernel_corpus_group_and_write_abixml): Use the new
	perform_self_comparison to perform self comparison when the
	--abidiff option is provided.  Also, support --debug-abidiff when
	the package is configured with --enable-debug-self-comparison.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
---
 include/abg-corpus.h  |   2 +
 src/abg-corpus.cc     |  10 ++
 src/abg-ctf-reader.cc |   6 ++
 tools/abidw.cc        | 208 +++++++++++++++++++++++++-----------------
 4 files changed, 144 insertions(+), 82 deletions(-)

diff --git a/include/abg-corpus.h b/include/abg-corpus.h
index 37ff2879..cbadbdb2 100644
--- a/include/abg-corpus.h
+++ b/include/abg-corpus.h
@@ -444,6 +444,8 @@ public:
   operator==(const corpus_group&) const;
 }; // end class corpus_group
 
+corpus_group_sptr
+is_corpus_group(const corpus_sptr&);
 }// end namespace ir
 }//end namespace abigail
 #endif //__ABG_CORPUS_H__
diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc
index 994307fb..e9ba92ae 100644
--- a/src/abg-corpus.cc
+++ b/src/abg-corpus.cc
@@ -2247,6 +2247,16 @@ bool
 corpus_group::recording_types_reachable_from_public_interface_supported()
 {return !get_public_types_pretty_representations()->empty();}
 
+/// Test if a @ref corpus is a @ref corpus_group.
+///
+/// @param corpus the corpus to consider.
+///
+/// @return the @ref corpus_group is @p corpus is a corpus group, or
+/// nil.
+corpus_group_sptr
+is_corpus_group(const corpus_sptr& corpus)
+{return std::dynamic_pointer_cast<corpus_group>(corpus);}
+
 // </corpus_group stuff>
 
 }// end namespace ir
diff --git a/src/abg-ctf-reader.cc b/src/abg-ctf-reader.cc
index c36323cf..6879c6e0 100644
--- a/src/abg-ctf-reader.cc
+++ b/src/abg-ctf-reader.cc
@@ -1729,6 +1729,12 @@ create_reader(const std::string& elf_path,
   reader_sptr result(new reader(elf_path,
 				debug_info_root_paths,
 				env));
+
+#ifdef WITH_DEBUG_SELF_COMPARISON
+    if (env.self_comparison_debug_is_on())
+      env.set_self_comparison_debug_input(result->corpus());
+#endif
+
   return result;
 }
 
diff --git a/tools/abidw.cc b/tools/abidw.cc
index 14f2078c..6bb1ef55 100644
--- a/tools/abidw.cc
+++ b/tools/abidw.cc
@@ -624,6 +624,121 @@ set_generic_options(abigail::elf_based_reader& rdr, options& opts)
   rdr.options().load_undefined_interfaces = opts.load_undefined_interfaces;
 }
 
+/// Given a corpus (or a corpus group), write it as ABIXML, read it
+/// back into another corpus and compare the resulting two corpora.
+///
+/// The result of the comparison should be the empty set.
+///
+/// @param write_ctxt the write context to use for writing the corpus
+/// to ABIXML.
+///
+/// @param corp the input corpus (or corpus group) to serialize to
+/// ABIXML.
+///
+/// @param env the environment used for computing.
+///
+/// @param t the timer to be used for the logs.
+///
+/// @param opts the options passed to the main program.
+///
+/// @param argv the vector of arguments of the main program.
+///
+/// @return 0 if the self comparison did yield the empty set, 1
+/// otherwise.  If the comparison does (wronly) yield a result, that
+/// result if emitted on std::cerr.
+static int
+perform_self_comparison(const write_context_sptr& write_ctxt,
+			const corpus_sptr& corp,
+			environment& env,
+			timer& t,
+			options& opts,
+			char* argv[])
+{
+  // Save the abi in abixml format in a temporary file, read
+  // it back, and compare the ABI of what we've read back
+  // against the ABI of the input ELF file.
+  temp_file_sptr tmp_file = temp_file::create();
+  set_ostream(*write_ctxt, tmp_file->get_stream());
+  corpus_group_sptr corp_group = is_corpus_group(corp);
+
+  if (corp_group)
+    write_corpus_group(*write_ctxt, corp_group, 0);
+  else
+    write_corpus(*write_ctxt, corp, 0);
+  tmp_file->get_stream().flush();
+
+#ifdef WITH_DEBUG_SELF_COMPARISON
+  if (opts.debug_abidiff)
+    {
+      opts.type_id_file_path = tmp_file->get_path() + string(".typeid");
+      write_canonical_type_ids(*write_ctxt, opts.type_id_file_path);
+    }
+#endif
+  fe_iface_sptr rdr = abixml::create_reader(tmp_file->get_path(), env);
+
+#ifdef WITH_DEBUG_SELF_COMPARISON
+  if (opts.debug_abidiff
+      && !opts.type_id_file_path.empty())
+    load_canonical_type_ids(*rdr, opts.type_id_file_path);
+#endif
+
+  t.start();
+  fe_iface::status sts;
+  corpus_sptr corp2;
+  corpus_group_sptr corp_group2;
+
+  if (corp_group)
+    corp_group2 = abixml::read_corpus_group_from_input(*rdr);
+  else
+    corp2 = rdr->read_corpus(sts);
+
+  t.stop();
+  if (opts.do_log)
+    emit_prefix(argv[0], cerr)
+      << "Read corpus in: " << t << "\n";
+
+#ifdef WITH_DEBUG_SELF_COMPARISON
+  if (opts.debug_abidiff
+      && !opts.type_id_file_path.empty())
+    remove(opts.type_id_file_path.c_str());
+#endif
+
+  if (!corp2 && !corp_group2)
+    {
+      emit_prefix(argv[0], cerr)
+	<< "Could not read temporary XML representation of "
+	"elf file back\n";
+      return 1;
+    }
+
+  diff_context_sptr ctxt(new diff_context);
+  set_diff_context(ctxt);
+  ctxt->show_locs(opts.show_locs);
+  t.start();
+  corpus_diff_sptr diff =
+    corp_group2
+    ? compute_diff(corp_group, corp_group2, ctxt)
+    : compute_diff(corp, corp2, ctxt);
+
+  t.stop();
+  if (opts.do_log)
+    emit_prefix(argv[0], cerr)
+      << "computed diff in: " << t << "\n";
+
+  bool has_error = diff->has_changes();
+  if (has_error)
+    {
+      t.start();
+      diff->report(cerr);
+      t.stop();
+      if (opts.do_log)
+	emit_prefix(argv[0], cerr)
+	  << "emitted report in: " << t << "\n";
+      return 1;
+    }
+  return 0;
+}
+
 /// Load an ABI @ref corpus (the internal representation of the ABI of
 /// a binary) and write it out as an abixml.
 ///
@@ -841,88 +956,9 @@ load_corpus_and_write_abixml(char* argv[],
       << t << "\n";
 
   if (opts.abidiff)
-    {
-      // Save the abi in abixml format in a temporary file, read
-      // it back, and compare the ABI of what we've read back
-      // against the ABI of the input ELF file.
-      temp_file_sptr tmp_file = temp_file::create();
-      set_ostream(*write_ctxt, tmp_file->get_stream());
-      if (corp_group)
-	write_corpus_group(*write_ctxt, corp_group, 0);
-      else
-	write_corpus(*write_ctxt, corp, 0);
-      tmp_file->get_stream().flush();
-
-#ifdef WITH_DEBUG_SELF_COMPARISON
-      if (opts.debug_abidiff)
-        {
-          opts.type_id_file_path = tmp_file->get_path() + string(".typeid");
-          write_canonical_type_ids(*write_ctxt, opts.type_id_file_path);
-        }
-#endif
-      fe_iface_sptr rdr = abixml::create_reader(tmp_file->get_path(), env);
-
-#ifdef WITH_DEBUG_SELF_COMPARISON
-      if (opts.debug_abidiff
-          && !opts.type_id_file_path.empty())
-        load_canonical_type_ids(*rdr, opts.type_id_file_path);
-#endif
-      t.start();
-      fe_iface::status sts;
-      corpus_sptr corp2;
-      corpus_group_sptr corp_group2;
-
-      if (corp_group)
-	corp_group2 = abixml::read_corpus_group_from_input(*rdr);
-      else
-	corp2 = rdr->read_corpus(sts);
-
-      t.stop();
-      if (opts.do_log)
-        emit_prefix(argv[0], cerr)
-          << "Read corpus in: " << t << "\n";
-
-      if (!corp2)
-        {
-          emit_prefix(argv[0], cerr)
-            << "Could not read temporary XML representation of "
-            "elf file back\n";
-          return 1;
-        }
-
-      diff_context_sptr ctxt(new diff_context);
-      set_diff_context(ctxt);
-      ctxt->show_locs(opts.show_locs);
-      t.start();
-      corpus_diff_sptr diff =
-	corp_group2
-	? compute_diff(corp_group, corp_group2, ctxt)
-	: compute_diff(corp, corp2, ctxt);
-
-      t.stop();
-      if (opts.do_log)
-        emit_prefix(argv[0], cerr)
-          << "computed diff in: " << t << "\n";
-
-      bool has_error = diff->has_changes();
-      if (has_error)
-        {
-          t.start();
-          diff->report(cerr);
-          t.stop();
-          if (opts.do_log)
-            emit_prefix(argv[0], cerr)
-              << "emitted report in: " << t << "\n";
-          return 1;
-        }
-      return 0;
-    }
-
-#ifdef WITH_DEBUG_SELF_COMPARISON
-  if (opts.debug_abidiff
-      && !opts.type_id_file_path.empty())
-    remove(opts.type_id_file_path.c_str());
-#endif
+    return perform_self_comparison(write_ctxt,
+				   corp_group ? corp_group : corp,
+				   env, t, opts, argv);
 
   if (opts.noout)
     return 0;
@@ -992,6 +1028,11 @@ load_kernel_corpus_group_and_write_abixml(char* argv[],
     if (!abigail::tools_utils::check_file(opts.vmlinux, cerr, argv[0]))
       return 1;
 
+#ifdef WITH_DEBUG_SELF_COMPARISON
+  if (opts.debug_abidiff)
+    env.self_comparison_debug_is_on(true);
+#endif
+
   timer t, global_timer;
   suppressions_type supprs;
 
@@ -1038,6 +1079,9 @@ load_kernel_corpus_group_and_write_abixml(char* argv[],
 	  = xml_writer::create_write_context(env, cout);
       set_common_options(*ctxt, opts);
 
+      if (opts.abidiff)
+	return perform_self_comparison(ctxt, group, env, t, opts, argv);
+
       if (!opts.out_file_path.empty())
 	{
 	  ofstream of(opts.out_file_path.c_str(), std::ios_base::trunc);
-- 
2.43.5


  parent reply	other threads:[~2024-07-16 14:55 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-16 14:55 [PATCH 00/17] Support self comparison of vmlinux & modules using BTF/CTF dodji
2024-07-16 14:55 ` [PATCH 01/17] ir: Fix a potential crash in canonicalize_types dodji
2024-07-16 14:55 ` [PATCH 02/17] elf-based-reader: Clean up logic of elf_based_reader::read_and_add_corpus_to_group dodji
2024-07-16 14:55 ` [PATCH 03/17] tools-utils,btf-reader: Take modules into account for corpus group dodji
2024-07-16 14:55 ` [PATCH 04/17] corpus: Support adding translation units with empty path dodji
2024-07-16 14:55 ` [PATCH 05/17] ctf-reader: Do not set data member offsets for unions dodji
2024-07-16 14:55 ` [PATCH 06/17] ctf-reader: During re-initialization, only clear canonicalize-able types dodji
2024-07-16 14:55 ` [PATCH 07/17] ctf-reader: Fix analyzing single kernel binaries dodji
2024-07-16 14:55 ` [PATCH 08/17] reader: Fix corpus group reading dodji
2024-07-16 14:55 ` [PATCH 09/17] reader: Simplify type canonicalization invocation dodji
2024-07-16 14:55 ` [PATCH 10/17] reader: Simplify logic of get_or_read_and_add_translation_unit dodji
2024-07-16 14:55 ` [PATCH 11/17] reader: Fix building of void and void pointer types dodji
2024-07-16 14:55 ` [PATCH 12/17] reader: Fix building of variadic parameter type dodji
2024-07-16 14:55 ` [PATCH 13/17] ir: Don't strip typedefs from parms and return type when comparing fns dodji
2024-07-16 14:55 ` [PATCH 14/17] ir: Rename integral_type into real_type dodji
2024-07-16 14:55 ` [PATCH 15/17] ir,comparison,default-reporter: Consider sub-ranges in array diffs dodji
2024-07-16 14:55 ` dodji [this message]
2024-07-16 14:55 ` [PATCH 17/17] configure: Support the optional 'big-tests' sub-directory dodji

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240716145541.473065-17-dodji@redhat.com \
    --to=dodji@redhat.com \
    --cc=libabigail@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).