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