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
next prev 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).