abidw: Add --{follow,list}-dependencies & --add-binaries support
This implements the --follow-dependencies , --list-dependencies, --add-binaries <foo,bar,...> and --added-binaries-dir options for the abidw command, as documented in the README-ABIDIFF-BINARIES-SET-SUPPORT.md file. * tools/abidw.cc (options::{added_bins_dirs, added_bins, follow_dependencies, list_dependencies}): Add new data members. (options::options): Initialize follow_dependencies and list_dependencies. (display_usage): Add usage strings for --add-binaries, --follow-dependencies, --list-dependencies, --added-binaries-dir. (parse_command_line): Parse options --add-binaries, --follow-dependencies, --list-dependencies, --added-binaries-dir. (load_corpus_and_write_abixml): Implement the --list-dependencies, --follow-dependencies and --add-binaries sub-commands. * doc/manuals/abidw.rst: Document the --add-binaries, --follow-dependencies, --list-dependencies, --added-binaries-dir options. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
parent
a30a3146b5
commit
3e568fef6b
|
@ -44,14 +44,49 @@ Options
|
|||
|
||||
Display a short help about the command and exit.
|
||||
|
||||
* `--version | -v`
|
||||
* ``--version | -v``
|
||||
|
||||
Display the version of the program and exit.
|
||||
|
||||
* `--abixml-version`
|
||||
* ``--abixml-version``
|
||||
|
||||
Display the version of the ABIXML format emitted by this program and exit.
|
||||
|
||||
* ``--add-binaries`` <*bin1,bin2,...*>
|
||||
|
||||
For each of the comma-separated binaries given in argument to this
|
||||
option, if the binary is found in the directory specified by the
|
||||
`--added-binaries-dir` option, then load the ABI corpus of the
|
||||
binary and add it to a set of ABI corpora (called a ABI Corpus
|
||||
Group) made of the binary denoted by the Argument of
|
||||
``abidw``. That corpus group is then serialized out.
|
||||
|
||||
* ``--follow-dependencies``
|
||||
|
||||
For each dependency of the input binary of ``abidw``, if it is
|
||||
found in the directory specified by the ``--added-binaries-dir``
|
||||
option, then construct an ABI corpus out of the dependency and add
|
||||
it to a set of ABI corpora (called an ABI Corpus Group) along with
|
||||
the ABI corpus of the input binary of the program. The ABI Corpus
|
||||
Group is then serialized out.
|
||||
|
||||
* ``--list-dependencies``
|
||||
|
||||
For each dependency of the input binary of``abidw``, if it's found
|
||||
in the directory specified by the ``--added-binaries-dir`` option,
|
||||
then the name of the dependency is printed out.
|
||||
|
||||
* ``--added-binaries-dir | --abd`` <*dir-path*>
|
||||
|
||||
This option is to be used in conjunction with the
|
||||
``--add-binaries``, the ``--follow-dependencies`` or the
|
||||
``--list-dependencies`` option. Binaries listed as arguments of
|
||||
the ``--add-binaries`` option or being dependencies of the input
|
||||
binary in the case of the ``--follow-dependencies`` option and
|
||||
found in the directory <*dir-path*> are going to be loaded as ABI
|
||||
corpus and added to the set of ABI corpora (called an ABI corpus
|
||||
group) built and serialized.
|
||||
|
||||
* ``--debug-info-dir | -d`` <*dir-path*>
|
||||
|
||||
In cases where the debug info for *path-to-elf-file* is in a
|
||||
|
@ -368,6 +403,39 @@ Options
|
|||
Emit verbose logs about the progress of miscellaneous internal
|
||||
things.
|
||||
|
||||
Usage examples
|
||||
==============
|
||||
|
||||
1. Emitting an ``ABIXML`` representation of a binary: ::
|
||||
|
||||
$ abidw binary > binary.abi
|
||||
|
||||
|
||||
2. Emitting an ``ABIXML`` representation of a set of binaries
|
||||
specified on the command line: ::
|
||||
|
||||
$ abidw --added-binaries=bin1,bin2,bin3 \
|
||||
--added-binaries-dir /some/where \
|
||||
binary > binaries.abi
|
||||
|
||||
Note that the binaries bin1, bin2 and bin3 are to be found in the
|
||||
directory ``/some/where``. A representation of the ABI of the
|
||||
set of binaries ``binary, bin1, bin2`` and ``bin3`` called an
|
||||
``ABI corpus group`` is serialized in the file binaries.abi.
|
||||
|
||||
3. Emitting an ``ABIXML`` representation of a binary and its
|
||||
dependencies: ::
|
||||
|
||||
$ abidw --follow-dependencies \
|
||||
--added-binaries-dir /some/where \
|
||||
binary > binary.abi
|
||||
|
||||
Note that only the dependencies that are found in the directory
|
||||
``/some/where`` are analysed. Their ABIs, along with the ABI the
|
||||
binary named ``binary`` are represented as an ABI corpus group
|
||||
and serialized in the file ``binary.abi``, in the ABIXML format.
|
||||
|
||||
|
||||
Notes
|
||||
=====
|
||||
|
||||
|
|
125
tools/abidw.cc
125
tools/abidw.cc
|
@ -22,6 +22,7 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "abg-config.h"
|
||||
#include "abg-tools-utils.h"
|
||||
#include "abg-corpus.h"
|
||||
|
@ -43,7 +44,9 @@ using std::cout;
|
|||
using std::ostream;
|
||||
using std::ofstream;
|
||||
using std::vector;
|
||||
using std::set;
|
||||
using std::shared_ptr;
|
||||
using std::static_pointer_cast;
|
||||
using abg_compat::optional;
|
||||
using abigail::tools_utils::emit_prefix;
|
||||
using abigail::tools_utils::temp_file;
|
||||
|
@ -52,6 +55,9 @@ using abigail::tools_utils::check_file;
|
|||
using abigail::tools_utils::build_corpus_group_from_kernel_dist_under;
|
||||
using abigail::tools_utils::timer;
|
||||
using abigail::tools_utils::create_best_elf_based_reader;
|
||||
using abigail::tools_utils::stick_corpus_and_dependencies_into_corpus_group;
|
||||
using abigail::tools_utils::stick_corpus_and_binaries_into_corpus_group;
|
||||
using abigail::tools_utils::add_dependencies_into_corpus_group;
|
||||
using abigail::ir::environment_sptr;
|
||||
using abigail::ir::environment;
|
||||
using abigail::corpus;
|
||||
|
@ -71,6 +77,7 @@ using abigail::xml_writer::create_write_context;
|
|||
using abigail::xml_writer::type_id_style_kind;
|
||||
using abigail::xml_writer::write_context_sptr;
|
||||
using abigail::xml_writer::write_corpus;
|
||||
using abigail::xml_writer::write_corpus_group;
|
||||
using abigail::abixml::read_corpus_from_abixml_file;
|
||||
|
||||
using namespace abigail;
|
||||
|
@ -84,6 +91,8 @@ struct options
|
|||
vector<char**> prepared_di_root_paths;
|
||||
vector<string> headers_dirs;
|
||||
vector<string> header_files;
|
||||
vector<string> added_bins_dirs;
|
||||
vector<string> added_bins;
|
||||
string vmlinux;
|
||||
vector<string> suppression_paths;
|
||||
vector<string> kabi_whitelist_paths;
|
||||
|
@ -104,6 +113,8 @@ struct options
|
|||
bool corpus_group_for_linux;
|
||||
bool show_stats;
|
||||
bool noout;
|
||||
bool follow_dependencies;
|
||||
bool list_dependencies;
|
||||
#ifdef WITH_CTF
|
||||
bool use_ctf;
|
||||
#endif
|
||||
|
@ -148,6 +159,8 @@ struct options
|
|||
corpus_group_for_linux(false),
|
||||
show_stats(),
|
||||
noout(),
|
||||
follow_dependencies(),
|
||||
list_dependencies(),
|
||||
#ifdef WITH_CTF
|
||||
use_ctf(false),
|
||||
#endif
|
||||
|
@ -229,6 +242,12 @@ display_usage(const string& prog_name, ostream& out)
|
|||
<< " --vmlinux <path> the path to the vmlinux binary to consider to emit "
|
||||
"the ABI of the union of vmlinux and its modules\n"
|
||||
<< " --abidiff compare the loaded ABI against itself\n"
|
||||
<< " --add-binaries <bin1,bin2,...> build a corpus group with "
|
||||
"the added inaries\n"
|
||||
<< " --follow-dependencies build a corpus group with the dependencies\n"
|
||||
<< " --list-dependencies list the dependencies of a given binary\n"
|
||||
<< " --added-binaries-dir|--abd <dir-of-deps> where to look for dependencies "
|
||||
"or added binaries\n"
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
<< " --debug-abidiff debug the process of comparing the loaded ABI against itself\n"
|
||||
#endif
|
||||
|
@ -294,6 +313,15 @@ parse_command_line(int argc, char* argv[], options& opts)
|
|||
opts.headers_dirs.push_back(argv[j]);
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--added-binaries-dir")
|
||||
|| !strcmp(argv[i], "--abd"))
|
||||
{
|
||||
int j = i + 1;
|
||||
if (j >= argc)
|
||||
return false;
|
||||
opts.added_bins_dirs.push_back(argv[j]);
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--header-file")
|
||||
|| !strcmp(argv[i], "--hf"))
|
||||
{
|
||||
|
@ -344,6 +372,28 @@ parse_command_line(int argc, char* argv[], options& opts)
|
|||
}
|
||||
else if (!strcmp(argv[i], "--noout"))
|
||||
opts.noout = true;
|
||||
else if (!strcmp(argv[i], "--follow-dependencies"))
|
||||
opts.follow_dependencies = true;
|
||||
else if (!strcmp(argv[i], "--list-dependencies"))
|
||||
opts.list_dependencies = true;
|
||||
else if (!strncmp(argv[i], "--add-binaries=",
|
||||
strlen("--add-binaries=")))
|
||||
tools_utils::get_comma_separated_args_of_option(argv[i],
|
||||
"--add-binaries=",
|
||||
opts.added_bins);
|
||||
else if (!strcmp(argv[i], "--add-binaries"))
|
||||
{
|
||||
int j = i + 1;
|
||||
if (j >= argc)
|
||||
return false;
|
||||
|
||||
string s = argv[j];
|
||||
if (s.find(','))
|
||||
tools_utils::split_string(s, ",", opts.added_bins);
|
||||
else
|
||||
opts.added_bins.push_back(s);
|
||||
++i;
|
||||
}
|
||||
#ifdef WITH_CTF
|
||||
else if (!strcmp(argv[i], "--ctf"))
|
||||
opts.use_ctf = true;
|
||||
|
@ -598,6 +648,7 @@ load_corpus_and_write_abixml(char* argv[],
|
|||
#endif
|
||||
|
||||
corpus_sptr corp;
|
||||
corpus_group_sptr corp_group;
|
||||
fe_iface::status s = fe_iface::STATUS_UNKNOWN;
|
||||
corpus::origin requested_fe_kind = corpus::DWARF_ORIGIN;
|
||||
#ifdef WITH_CTF
|
||||
|
@ -720,6 +771,50 @@ load_corpus_and_write_abixml(char* argv[],
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (opts.list_dependencies)
|
||||
{
|
||||
// Show the dependencies of the corpus and display them.
|
||||
set<string> dependencies;
|
||||
if (tools_utils::get_dependencies(*corp, opts.added_bins_dirs,
|
||||
dependencies))
|
||||
{
|
||||
cout << "Dependencies of '" << corp->get_path()
|
||||
<< "':\n\t";
|
||||
int n = 0;
|
||||
for (const auto& dep : dependencies)
|
||||
{
|
||||
if (n)
|
||||
cout << ", ";
|
||||
cout << dep;
|
||||
++n;
|
||||
}
|
||||
cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!opts.added_bins.empty())
|
||||
corp_group =
|
||||
stick_corpus_and_binaries_into_corpus_group(reader, corp,
|
||||
opts.added_bins,
|
||||
opts.added_bins_dirs);
|
||||
|
||||
if (opts.follow_dependencies)
|
||||
{
|
||||
// load the dependencies of the corpus and put them all into a
|
||||
// corpus group.
|
||||
|
||||
// If a corpus_group already exists, use that one ...
|
||||
if (!corp_group->is_empty())
|
||||
add_dependencies_into_corpus_group(reader, *corp,
|
||||
opts.added_bins_dirs,
|
||||
*corp_group);
|
||||
else
|
||||
// .. otherwise, create a new corpus group.
|
||||
corp_group =
|
||||
stick_corpus_and_dependencies_into_corpus_group(reader, corp,
|
||||
opts.added_bins_dirs);
|
||||
}
|
||||
|
||||
// Clear some resources to gain back some space.
|
||||
t.start();
|
||||
reader.reset();
|
||||
|
@ -744,7 +839,10 @@ load_corpus_and_write_abixml(char* argv[],
|
|||
// 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);
|
||||
if (corp_group)
|
||||
write_corpus_group(*write_ctxt, corp_group, 0);
|
||||
else
|
||||
write_corpus(*write_ctxt, corp, 0);
|
||||
tmp_file->get_stream().flush();
|
||||
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
|
@ -763,7 +861,14 @@ load_corpus_and_write_abixml(char* argv[],
|
|||
#endif
|
||||
t.start();
|
||||
fe_iface::status sts;
|
||||
corpus_sptr corp2 = rdr->read_corpus(sts);
|
||||
corpus_sptr corp2;
|
||||
corpus_group_sptr corp_group2;
|
||||
|
||||
if (corp_group)
|
||||
corp_group2 = abixml::read_corpus_group_from_input(*rdr);
|
||||
else
|
||||
corp2 = rdr->read_corpus(sts);
|
||||
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
|
@ -781,7 +886,11 @@ load_corpus_and_write_abixml(char* argv[],
|
|||
set_diff_context(ctxt);
|
||||
ctxt->show_locs(opts.show_locs);
|
||||
t.start();
|
||||
corpus_diff_sptr diff = compute_diff(corp, corp2, ctxt);
|
||||
corpus_diff_sptr diff =
|
||||
corp_group2
|
||||
? compute_diff(corp_group, corp_group2, ctxt)
|
||||
: compute_diff(corp, corp2, ctxt);
|
||||
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
|
@ -822,7 +931,10 @@ load_corpus_and_write_abixml(char* argv[],
|
|||
}
|
||||
set_ostream(*write_ctxt, of);
|
||||
t.start();
|
||||
write_corpus(*write_ctxt, corp, 0);
|
||||
if (corp_group)
|
||||
write_corpus_group(*write_ctxt, corp_group, 0);
|
||||
else
|
||||
write_corpus(*write_ctxt, corp, 0);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
|
@ -833,7 +945,10 @@ load_corpus_and_write_abixml(char* argv[],
|
|||
else
|
||||
{
|
||||
t.start();
|
||||
exit_code = !write_corpus(*write_ctxt, corp, 0);
|
||||
exit_code =
|
||||
corp_group
|
||||
? !write_corpus_group(*write_ctxt, corp_group, 0)
|
||||
: !write_corpus(*write_ctxt, corp, 0);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
|
|
Loading…
Reference in New Issue