1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2013-2020 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7 
8 #include <cstring>
9 #include <iostream>
10 #include "abg-comparison.h"
11 #include "abg-dwarf-reader.h"
12 
13 using std::cout;
14 using std::cerr;
15 using std::ostream;
16 using std::string;
17 
18 using abigail::comparison::diff;
19 using abigail::comparison::diff_sptr;
20 using abigail::ir::environment;
21 using abigail::ir::environment_sptr;
22 using abigail::comparison::corpus_diff_sptr;
23 using abigail::comparison::compute_diff;
24 using abigail::comparison::print_diff_tree;
25 using abigail::comparison::apply_filters;
26 using namespace abigail;
27 using namespace abigail::dwarf_reader;
28 
29 struct options
30 {
31   bool display_help;
32   bool categorize_redundancy;
33   bool apply_filters;
34   string elf1;
35   string elf2;
36 
optionsoptions37   options()
38     : display_help(false),
39       categorize_redundancy(false),
40       apply_filters(false)
41   {}
42 };
43 
44 static void
display_help(const string & prog_name,ostream & out)45 display_help(const string& prog_name,
46 	     ostream& out)
47 {
48   out << prog_name << " [options] <elf lib1> <elf lib2>\n"
49       << " where options can be:\n"
50       << " --categorize-redundancy  categorize diff node redundancy\n"
51       << " --apply-filters  apply the generic categorization filters\n"
52       << " --help  display this message\n";
53 }
54 
55 static bool
parse_command_line(int argc,char * argv[],options & opts)56 parse_command_line(int argc, char* argv[], options& opts)
57 {
58     if (argc < 2)
59     return false;
60 
61   for (int i = 1; i < argc; ++i)
62     {
63       if (argv[i][0] != '-')
64 	{
65 	  if (opts.elf1.empty())
66 	    opts.elf1 = argv[i];
67 	  else if (opts.elf2.empty())
68 	    opts.elf2 = argv[i];
69 	  else
70 	    return false;
71 	}
72       else if (!strcmp(argv[i], "--help"))
73 	opts.display_help = true;
74       else if (!strcmp(argv[i], "--categorize-redundancy"))
75 	opts.categorize_redundancy = true;
76       else if (!strcmp(argv[i], "--apply-filters"))
77 	opts.apply_filters = true;
78       else
79 	return false;
80     }
81   return true;
82 }
83 
84 int
main(int argc,char * argv[])85 main(int argc, char* argv[])
86 {
87   options opts;
88 
89   if (!parse_command_line(argc, argv, opts))
90     {
91       cerr << "unrecognized option\n"
92 	"try the --help option for more information\n";
93       return 1;
94     }
95 
96   if (opts.display_help)
97     {
98       display_help(argv[0], cout);
99       return 0;
100     }
101 
102   if (!opts.elf1.empty() && !opts.elf2.empty())
103     {
104       dwarf_reader::status c1_status, c2_status;
105       corpus_sptr c1, c2;
106 
107       environment_sptr env(new environment);
108       vector<char**> di_roots;
109       c1 = dwarf_reader::read_corpus_from_elf(opts.elf1, di_roots, env.get(),
110 					      /*load_all_types=*/false,
111 					      c1_status);
112       if (c1_status != dwarf_reader::STATUS_OK)
113 	{
114 	  cerr << "Failed to read elf file " << opts.elf1 << "\n";
115 	  return 1;
116 	}
117 
118       c2 = dwarf_reader::read_corpus_from_elf(opts.elf2, di_roots, env.get(),
119 					      /*load_all_types=*/false,
120 					      c2_status);
121       if (c2_status != dwarf_reader::STATUS_OK)
122 	{
123 	  cerr << "Failed to read elf file " << opts.elf2 << "\n";
124 	  return 1;
125 	}
126 
127       corpus_diff_sptr diff = compute_diff(c1, c2);
128       if (!diff)
129 	{
130 	  cerr << "Could not compute ABI diff between elf files "
131 	       << opts.elf1 << " and " << opts.elf2;
132 	  return 1;
133 	}
134 
135       if (opts.categorize_redundancy)
136 	categorize_redundancy(diff);
137 
138       if (opts.apply_filters)
139 	apply_filters(diff);
140 
141       print_diff_tree(diff, cout);
142       return 0;
143     }
144   return 1;
145 }
146 
147 void
print_diff_tree(abigail::comparison::corpus_diff * diff_tree)148 print_diff_tree(abigail::comparison::corpus_diff* diff_tree)
149 {
150   print_diff_tree(diff_tree, std::cout);
151 }
152 
153 void
print_diff_tree(abigail::comparison::corpus_diff_sptr diff_tree)154 print_diff_tree(abigail::comparison::corpus_diff_sptr diff_tree)
155 {
156   print_diff_tree(diff_tree, std::cout);
157 }
158