Make test-ir-walker work on ELF binaries directly
authorDodji Seketeli <dodji@redhat.com>
Mon, 6 Aug 2018 08:28:06 +0000 (10:28 +0200)
committerDodji Seketeli <dodji@redhat.com>
Mon, 6 Aug 2018 08:28:06 +0000 (10:28 +0200)
The tests/test-ir-walker.cc example was working on abixml files
resulting from abidw.  This commit changes that to make it work on
ELF input files directly.  The commit also adds some comments to make
it easier to understand the concepts.

* test-ir-walker.cc (main): Load an ABI corpus from an elf file
and walk its translation units.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
tests/test-ir-walker.cc

index 147b8e4..8e434d6 100644 (file)
@@ -22,8 +22,7 @@
 #include <fstream>
 #include <iostream>
 #include <cstdlib>
-#include "abg-ir.h"
-#include "abg-reader.h"
+#include "abg-dwarf-reader.h"
 #include "test-utils.h"
 
 using std::string;
@@ -31,6 +30,37 @@ using std::ofstream;
 using std::cerr;
 using std::cout;
 
+///@file
+///
+/// This example shows how to walk the Internal Representation (IR)
+/// graph of the ABI of a binary (called an ABI Corpus) and perform
+/// actions on each node of the graph.
+///
+/// Basically, one has to define a "visitor" which carries member
+/// functions that are called during the traversal of the graph.
+///
+/// On the visitor, there is potentially one member function pair per
+/// type of node traversed.  Each time a given node is visited, the
+/// corresponding member function pair is called by the traversal
+/// machinery.  In other words, the visitor is notified each time a
+/// node is traversed.
+///
+/// To define a visitor, one has to create a type which implements
+/// (inherits) the abigail::ir_node_visitor interface.  The visitor
+/// must have a pair of node_begin() and node_end() function per type
+/// of node that we wish to be notified for.
+///
+///  Once the visitor is defined, we can load an elf file and build an
+///  ABI corpus out of it by using the
+///  libabigail::dwarf_reader::read_corpus_from_elf() function, for
+///  instance.
+///
+///  Then we enumerate the translation units comprised in
+///  that ABI corpus and we invoke their "traverse()" method, using
+///  and instance of the visitor that we just defined.
+///
+///  Enjoy!
+
 struct name_printing_visitor : public abigail::ir_node_visitor
 {
   unsigned level_;
@@ -137,14 +167,24 @@ main(int argc, char **argv)
   string file_name = argv[1];
 
   abigail::ir::environment_sptr env(new abigail::ir::environment);
-  abigail::translation_unit_sptr tu;
-  if (!(tu = abigail::xml_reader::read_translation_unit_from_file(file_name,
-                                                                 env.get())))
+  abigail::corpus_sptr c;
+  abigail::dwarf_reader::status status = abigail::dwarf_reader::STATUS_OK;
+  if (!(c = abigail::dwarf_reader::read_corpus_from_elf(file_name,
+                                                       /*debug_info_path=*/0,
+                                                       env.get(),
+                                                       /*load_all_type=*/false,
+                                                       status)))
     {
       cerr << "failed to read " << file_name << "\n";
       return 1;
     }
 
   name_printing_visitor v;
-  tu->traverse(v);
+  // Now traverse each translation unit of the corpus using our
+  // instance of name_printing_visitor
+  for (abigail::ir::translation_units::const_iterator tu_iterator =
+        c->get_translation_units().begin();
+       tu_iterator != c->get_translation_units().end();
+       ++tu_iterator)
+    (*tu_iterator)->traverse(v);
 }