From bd0926a2b58f4c5546799154e8da1773d05d0d31 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Mon, 21 Sep 2015 15:14:26 +0200 Subject: [PATCH] Add a new --abidiff option to abidw This is a debugging and sanity check option. It saves the abi of the ELF binary to a temporary file, reads it back and compares the abis of the temporary file against the abi of the input ELF binary. * tools/abidw.cc (options::abidiff): New data member. (options::options): Initialize it. (display_usage): Add a usage string for the new --abidiff option. (parse_command): Parse the new --abidiff options. (main): Save the abi of the input elf in a temporary abixml file; read it back and compare both. Signed-off-by: Dodji Seketeli --- doc/manuals/abidw.rst | 11 ++++++++++ tools/abidw.cc | 48 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/doc/manuals/abidw.rst b/doc/manuals/abidw.rst index 8f13ff12..9a618354 100644 --- a/doc/manuals/abidw.rst +++ b/doc/manuals/abidw.rst @@ -76,6 +76,17 @@ Options makes ``abidw`` load *all* the types defined in the binaries, even those that are not reachable from public declarations. + * ``--abidiff`` + + Load the ABI of the ELF binary given in argument, save it in + libabigail's XML format in a temporary file; read the ABI from the + temporary XML file and compare the ABI that has been read back + against the ABI of the ELF binary given in argument. The ABIs + should compare equal. If they don't, the program emits a + diagnostic and exits with a non-zero code. + + This is a debugging and sanity check option. + * ``--stats`` Emit statistics about various internal things. diff --git a/tools/abidw.cc b/tools/abidw.cc index c81c7556..611106db 100644 --- a/tools/abidw.cc +++ b/tools/abidw.cc @@ -39,6 +39,8 @@ #include "abg-corpus.h" #include "abg-dwarf-reader.h" #include "abg-writer.h" +#include "abg-reader.h" +#include "abg-comparison.h" using std::string; using std::cerr; @@ -46,6 +48,15 @@ using std::cout; using std::ostream; using std::ofstream; using std::tr1::shared_ptr; +using abigail::tools_utils::temp_file; +using abigail::tools_utils::temp_file_sptr; +using abigail::comparison::corpus_diff; +using abigail::comparison::corpus_diff_sptr; +using abigail::comparison::compute_diff; +using abigail::comparison::diff_context_sptr; +using abigail::comparison::diff_context; +using abigail::xml_writer::write_corpus_to_native_xml; +using abigail::xml_reader::read_corpus_from_native_xml_file; struct options { @@ -58,6 +69,7 @@ struct options bool load_all_types; bool show_stats; bool noout; + bool abidiff; options() : check_alt_debug_info_path(), @@ -65,7 +77,8 @@ struct options write_architecture(true), load_all_types(), show_stats(), - noout() + noout(), + abidiff() {} }; @@ -85,6 +98,7 @@ display_usage(const string& prog_name, ostream& out) "debug info of , and show its base name\n" << " --load-all-types read all types including those not reachable from" "exported declarations\n" + << " --abidiff compare the loaded ABI against itself\n" << " --stats show statistics about various internal stuff\n"; ; } @@ -146,6 +160,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], "--abidiff")) + opts.abidiff = true; else if (!strcmp(argv[i], "--stats")) opts.show_stats = true; else if (!strcmp(argv[i], "--help") @@ -263,6 +279,36 @@ main(int argc, char* argv[]) } else { + 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(); + write_corpus_to_native_xml(corp, 0, tmp_file->get_stream()); + tmp_file->get_stream().flush(); + corpus_sptr corp2 = + read_corpus_from_native_xml_file(tmp_file->get_path(), + env.get()); + if (!corp2) + { + cerr << "Could not read temporary XML representation of " + "elf file back\n"; + return 1; + } + diff_context_sptr ctxt(new diff_context); + ctxt->default_output_stream(&cerr); + ctxt->error_output_stream(&cerr); + corpus_diff_sptr diff = compute_diff(corp, corp2, ctxt); + bool has_error = diff->has_changes(); + if (has_error) + { + diff->report(cerr); + return 1; + } + return 0; + } + if (opts.noout) return 0;