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