abidw: add support for CTF

Message ID 20211117073903.15773-1-jose.marchesi@oracle.com
State New
Headers
Series abidw: add support for CTF |

Commit Message

Jose E. Marchesi Nov. 17, 2021, 7:39 a.m. UTC
  This patch adds support for CTF to the abidw utility.  It depends on
the previous patch that makes abigail::ctf_reader::read_corpus to
return a status code.

Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com>

	* tools/abidw.cc: Conditionally include abg-ctf-reader.h.
	(load_corpus_and_write_abixml): Do not get a
	dwarf_reader::read_context as an argument.
	(main): Adjust call to load_corpus_and_write_abixml accordingly.
	(struct options): New option use_ctf.
	(options): ... and initialize it.
	(display_usage): Document --ctf.
	(parse_command_line): Handle --ctf.
	* doc/manuals/abidw.rst: Document --ctf.
---
 doc/manuals/abidw.rst |   5 +
 tools/abidw.cc        | 363 +++++++++++++++++++++++++++-----------------------
 2 files changed, 202 insertions(+), 166 deletions(-)
  

Comments

Dodji Seketeli Nov. 18, 2021, 10:29 a.m. UTC | #1
Hello,

"Jose E. Marchesi via Libabigail" <libabigail@sourceware.org> a écrit:

> This patch adds support for CTF to the abidw utility.  It depends on
> the previous patch that makes abigail::ctf_reader::read_corpus to
> return a status code.
>
> 	* tools/abidw.cc: Conditionally include abg-ctf-reader.h.
> 	(load_corpus_and_write_abixml): Do not get a
> 	dwarf_reader::read_context as an argument.
> 	(main): Adjust call to load_corpus_and_write_abixml accordingly.
> 	(struct options): New option use_ctf.
> 	(options): ... and initialize it.
> 	(display_usage): Document --ctf.
> 	(parse_command_line): Handle --ctf.
> 	* doc/manuals/abidw.rst: Document --ctf.
>
> Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com>

Applied to master.  Thanks!

[...]

Cheers,
  

Patch

diff --git a/doc/manuals/abidw.rst b/doc/manuals/abidw.rst
index fe4aafd8..bdd6204d 100644
--- a/doc/manuals/abidw.rst
+++ b/doc/manuals/abidw.rst
@@ -268,6 +268,11 @@  Options
     the --enable-debug-type-canonicalization option.
 
 
+  * ``--ctf``
+
+    Extract ABI information from CTF debug information, if present in
+    the given object.
+
   *  ``--annotate``
 
     Annotate the ABIXML output with comments above most elements.  The
diff --git a/tools/abidw.cc b/tools/abidw.cc
index 48f509a0..d2bc029b 100644
--- a/tools/abidw.cc
+++ b/tools/abidw.cc
@@ -26,6 +26,9 @@ 
 #include "abg-tools-utils.h"
 #include "abg-corpus.h"
 #include "abg-dwarf-reader.h"
+#ifdef WITH_CTF
+#include "abg-ctf-reader.h"
+#endif
 #include "abg-writer.h"
 #include "abg-reader.h"
 #include "abg-comparison.h"
@@ -64,10 +67,6 @@  using abigail::xml_writer::write_context_sptr;
 using abigail::xml_writer::write_corpus;
 using abigail::xml_reader::read_corpus_from_native_xml_file;
 using abigail::xml_reader::create_native_xml_read_context;
-using abigail::dwarf_reader::read_context;
-using abigail::dwarf_reader::read_context_sptr;
-using abigail::dwarf_reader::read_corpus_from_elf;
-using abigail::dwarf_reader::create_read_context;
 using namespace abigail;
 
 struct options
@@ -99,6 +98,9 @@  struct options
   bool			corpus_group_for_linux;
   bool			show_stats;
   bool			noout;
+#ifdef WITH_CTF
+  bool				use_ctf;
+#endif
   bool			show_locs;
   bool			abidiff;
 #ifdef WITH_DEBUG_SELF_COMPARISON
@@ -133,6 +135,9 @@  struct options
       corpus_group_for_linux(false),
       show_stats(),
       noout(),
+#ifdef WITH_CTF
+      use_ctf(false),
+#endif
       show_locs(true),
       abidiff(),
 #ifdef WITH_DEBUG_SELF_COMPARISON
@@ -208,6 +213,9 @@  display_usage(const string& prog_name, ostream& out)
 #ifdef WITH_DEBUG_TYPE_CANONICALIZATION
     << "  --debug-tc  debug the type canonicalization process\n"
 #endif
+#ifdef WITH_CTF
+    << "  --ctf use CTF instead of DWARF in ELF files\n"
+#endif
     << "  --annotate  annotate the ABI artifacts emitted in the output\n"
     << "  --stats  show statistics about various internal stuff\n"
     << "  --verbose show verbose messages about internal stuff\n";
@@ -306,6 +314,10 @@  parse_command_line(int argc, char* argv[], options& opts)
 	}
       else if (!strcmp(argv[i], "--noout"))
 	opts.noout = true;
+#ifdef WITH_CTF
+        else if (!strcmp(argv[i], "--ctf"))
+          opts.use_ctf = true;
+#endif
       else if (!strcmp(argv[i], "--no-architecture"))
 	opts.write_architecture = false;
       else if (!strcmp(argv[i], "--no-corpus-path"))
@@ -462,7 +474,7 @@  maybe_check_header_files(const options& opts)
 /// @param opts the options where to get the suppression
 /// specifications from.
 static void
-set_suppressions(read_context& read_ctxt, options& opts)
+set_suppressions(dwarf_reader::read_context& read_ctxt, options& opts)
 {
   suppressions_type supprs;
   for (vector<string>::const_iterator i = opts.suppression_paths.begin();
@@ -498,8 +510,6 @@  set_suppressions(read_context& read_ctxt, options& opts)
 ///
 /// @param env the environment the ABI artifacts are being created in.
 ///
-/// @param context the context of the ELF reading.
-///
 /// @param opts the options of the program.
 ///
 /// @return the exit code: 0 if everything went fine, non-zero
@@ -507,7 +517,6 @@  set_suppressions(read_context& read_ctxt, options& opts)
 static int
 load_corpus_and_write_abixml(char* argv[],
 			     environment_sptr& env,
-			     read_context_sptr& context,
 			     options& opts)
 {
   int exit_code = 0;
@@ -523,24 +532,90 @@  load_corpus_and_write_abixml(char* argv[],
     env->debug_type_canonicalization_is_on(true);
 #endif
 
-  read_context& ctxt = *context;
+  // First of all, read a libabigail IR corpus from the file specified
+  // in OPTS.
   corpus_sptr corp;
   elf_reader::status s = elf_reader::STATUS_UNKNOWN;
-  t.start();
-  corp = read_corpus_from_elf(ctxt, s);
-  t.stop();
-  if (opts.do_log)
-    emit_prefix(argv[0], cerr)
-      << "read corpus from elf file in: " << t << "\n";
+#ifdef WITH_CTF
+  if (opts.use_ctf)
+    {
+      abigail::ctf_reader::read_context *ctxt
+        = abigail::ctf_reader::create_read_context (opts.in_file_path,
+                                                    env.get());
 
-  t.start();
-  context.reset();
-  t.stop();
+      assert (ctxt);
+      t.start();
+      corp = abigail::ctf_reader::read_corpus (ctxt, s);
+      t.stop();
+      if (opts.do_log)
+        emit_prefix(argv[0], cerr)
+          << "read corpus from elf file in: " << t << "\n";
+    }
+  else
+#endif
+    {
+      dwarf_reader::read_context_sptr c
+        = abigail::dwarf_reader::create_read_context(opts.in_file_path,
+                                                     opts.prepared_di_root_paths,
+                                                     env.get(),
+                                                     opts.load_all_types,
+                                                     opts.linux_kernel_mode);
+      dwarf_reader::read_context& ctxt = *c;
+      set_drop_undefined_syms(ctxt, opts.drop_undefined_syms);
+      set_show_stats(ctxt, opts.show_stats);
+      set_suppressions(ctxt, opts);
+      abigail::dwarf_reader::set_do_log(ctxt, opts.do_log);
 
-  if (opts.do_log)
-    emit_prefix(argv[0], cerr)
-      << "reset read context in: " << t << "\n";
+      if (opts.check_alt_debug_info_path)
+        {
+          bool has_alt_di = false;
+          string alt_di_path;
+          abigail::elf_reader::status status =
+            abigail::dwarf_reader::has_alt_debug_info(ctxt,
+                                                      has_alt_di,
+                                                      alt_di_path);
+          if (status & abigail::elf_reader::STATUS_OK)
+            {
+              if (alt_di_path.empty())
+                ;
+              else
+                {
+                  cout << "found the alternate debug info file";
+                  if (opts.show_base_name_alt_debug_info_path)
+                    {
+                      tools_utils::base_name(alt_di_path, alt_di_path);
+                      cout << " '" << alt_di_path << "'";
+                    }
+                  cout << "\n";
+                }
+              return 0;
+            }
+          else
+            {
+              emit_prefix(argv[0], cerr)
+                << "could not find alternate debug info file\n";
+              return 1;
+            }
+        }
 
+      t.start();
+      corp = dwarf_reader::read_corpus_from_elf(ctxt, s);
+      t.stop();
+      if (opts.do_log)
+        emit_prefix(argv[0], cerr)
+          << "read corpus from elf file in: " << t << "\n";
+
+      t.start();
+      c.reset();
+      t.stop();
+
+      if (opts.do_log)
+        emit_prefix(argv[0], cerr)
+          << "reset read context in: " << t << "\n";
+    }
+
+  // If we couldn't create a corpus, emit some (hopefully) useful
+  // diagnostics and return and error.
   if (!corp)
     {
       if (s == elf_reader::STATUS_DEBUG_INFO_NOT_FOUND)
@@ -580,122 +655,122 @@  load_corpus_and_write_abixml(char* argv[],
 
       return 1;
     }
-  else
-    {
-      t.start();
-      const write_context_sptr& write_ctxt
-	  = create_write_context(corp->get_environment(), cout);
-      set_common_options(*write_ctxt, opts);
-      t.stop();
 
-      if (opts.do_log)
-	emit_prefix(argv[0], cerr)
-	  << "created & initialized write context in: "
-	  << t << "\n";
+  // Now create a write context and write out an ABI XML description
+  // of the read corpus.
+  t.start();
+  const write_context_sptr& write_ctxt
+    = create_write_context(corp->get_environment(), cout);
+  set_common_options(*write_ctxt, opts);
+  t.stop();
 
-      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());
-	  write_corpus(*write_ctxt, corp, 0);
-	  tmp_file->get_stream().flush();
+  if (opts.do_log)
+    emit_prefix(argv[0], cerr)
+      << "created & initialized write context in: "
+      << 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());
+      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);
-	    }
+      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
-	  xml_reader::read_context_sptr read_ctxt =
-	    create_native_xml_read_context(tmp_file->get_path(), env.get());
+      xml_reader::read_context_sptr read_ctxt =
+        create_native_xml_read_context(tmp_file->get_path(), env.get());
 
 #ifdef WITH_DEBUG_SELF_COMPARISON
-	  if (opts.debug_abidiff
-	      && !opts.type_id_file_path.empty())
-	    load_canonical_type_ids(*read_ctxt, opts.type_id_file_path);
+      if (opts.debug_abidiff
+          && !opts.type_id_file_path.empty())
+        load_canonical_type_ids(*read_ctxt, opts.type_id_file_path);
 #endif
-	  t.start();
-	  corpus_sptr corp2 =
-	    read_corpus_from_input(*read_ctxt);
-	  t.stop();
-	  if (opts.do_log)
-	    emit_prefix(argv[0], cerr)
-	      << "Read corpus in: " << t << "\n";
+      t.start();
+      corpus_sptr corp2 =
+        read_corpus_from_input(*read_ctxt);
+      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;
-	    }
+      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 = compute_diff(corp, corp2, ctxt);
-	  t.stop();
-	  if (opts.do_log)
-	    emit_prefix(argv[0], cerr)
-	      << "computed diff in: " << t << "\n";
+      diff_context_sptr ctxt(new diff_context);
+      set_diff_context(ctxt);
+      ctxt->show_locs(opts.show_locs);
+      t.start();
+      corpus_diff_sptr diff = 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;
-	}
+      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());
+  if (opts.debug_abidiff
+      && !opts.type_id_file_path.empty())
+    remove(opts.type_id_file_path.c_str());
 #endif
 
-      if (opts.noout)
-	return 0;
+  if (opts.noout)
+    return 0;
 
-      if (!opts.out_file_path.empty())
-	{
-	  ofstream of(opts.out_file_path.c_str(), std::ios_base::trunc);
-	  if (!of.is_open())
-	    {
-	      emit_prefix(argv[0], cerr)
-		<< "could not open output file '"
-		<< opts.out_file_path << "'\n";
-	      return 1;
-	    }
-	  set_ostream(*write_ctxt, of);
-	  t.start();
-	  write_corpus(*write_ctxt, corp, 0);
-	  t.stop();
-	  if (opts.do_log)
-	    emit_prefix(argv[0], cerr)
-	      << "emitted abixml output in: " << t << "\n";
-	  of.close();
-	  return 0;
-	}
-      else
-	{
-	  t.start();
-	  exit_code = !write_corpus(*write_ctxt, corp, 0);
-	  t.stop();
-	  if (opts.do_log)
-	    emit_prefix(argv[0], cerr)
-	      << "emitted abixml out in: " << t << "\n";
-	}
+  if (!opts.out_file_path.empty())
+    {
+      ofstream of(opts.out_file_path.c_str(), std::ios_base::trunc);
+      if (!of.is_open())
+        {
+          emit_prefix(argv[0], cerr)
+            << "could not open output file '"
+            << opts.out_file_path << "'\n";
+          return 1;
+        }
+      set_ostream(*write_ctxt, of);
+      t.start();
+      write_corpus(*write_ctxt, corp, 0);
+      t.stop();
+      if (opts.do_log)
+        emit_prefix(argv[0], cerr)
+          << "emitted abixml output in: " << t << "\n";
+      of.close();
+      return 0;
+    }
+  else
+    {
+      t.start();
+      exit_code = !write_corpus(*write_ctxt, corp, 0);
+      t.stop();
+      if (opts.do_log)
+        emit_prefix(argv[0], cerr)
+          << "emitted abixml out in: " << t << "\n";
     }
 
   return exit_code;
@@ -884,51 +959,7 @@  main(int argc, char* argv[])
   int exit_code = 0;
 
   if (tools_utils::is_regular_file(opts.in_file_path))
-    {
-      read_context_sptr c = create_read_context(opts.in_file_path,
-						opts.prepared_di_root_paths,
-						env.get(),
-						opts.load_all_types,
-						opts.linux_kernel_mode);
-      read_context& ctxt = *c;
-      set_drop_undefined_syms(ctxt, opts.drop_undefined_syms);
-      set_show_stats(ctxt, opts.show_stats);
-      set_suppressions(ctxt, opts);
-      abigail::dwarf_reader::set_do_log(ctxt, opts.do_log);
-
-      if (opts.check_alt_debug_info_path)
-	{
-	  bool has_alt_di = false;
-	  string alt_di_path;
-	  abigail::elf_reader::status status =
-	    abigail::dwarf_reader::has_alt_debug_info(ctxt,
-						      has_alt_di,
-						      alt_di_path);
-	  if (status & abigail::elf_reader::STATUS_OK)
-	    {
-	      if (alt_di_path.empty())
-		;
-	      else
-		{
-		  cout << "found the alternate debug info file";
-		  if (opts.show_base_name_alt_debug_info_path)
-		    {
-		      tools_utils::base_name(alt_di_path, alt_di_path);
-		      cout << " '" << alt_di_path << "'";
-		    }
-		  cout << "\n";
-		}
-	      return 0;
-	    }
-	  else
-	    {
-	      emit_prefix(argv[0], cerr)
-		<< "could not find alternate debug info file\n";
-	      return 1;
-	    }
-	}
-      exit_code = load_corpus_and_write_abixml(argv, env, c, opts);
-    }
+    exit_code = load_corpus_and_write_abixml(argv, env, opts);
   else
     exit_code = load_kernel_corpus_group_and_write_abixml(argv, env, opts);