mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-15 22:44:41 +00:00
abidw: add support for CTF
This patch adds support for CTF to the abidw utility. It depends on the previous patch that makes abigail::ctf_reader::read_corpus to return a status code. * tools/abidw.cc: Conditionally include abg-ctf-reader.h. (load_corpus_and_write_abixml): Do not get a dwarf_reader::read_context as an argument. (main): Adjust call to load_corpus_and_write_abixml accordingly. (struct options): New option use_ctf. (options): ... and initialize it. (display_usage): Document --ctf. (parse_command_line): Handle --ctf. * doc/manuals/abidw.rst: Document --ctf. Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com> Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
parent
8324a223df
commit
18569fc154
@ -268,6 +268,11 @@ Options
|
||||
the --enable-debug-type-canonicalization option.
|
||||
|
||||
|
||||
* ``--ctf``
|
||||
|
||||
Extract ABI information from CTF debug information, if present in
|
||||
the given object.
|
||||
|
||||
* ``--annotate``
|
||||
|
||||
Annotate the ABIXML output with comments above most elements. The
|
||||
|
385
tools/abidw.cc
385
tools/abidw.cc
@ -26,6 +26,9 @@
|
||||
#include "abg-tools-utils.h"
|
||||
#include "abg-corpus.h"
|
||||
#include "abg-dwarf-reader.h"
|
||||
#ifdef WITH_CTF
|
||||
#include "abg-ctf-reader.h"
|
||||
#endif
|
||||
#include "abg-writer.h"
|
||||
#include "abg-reader.h"
|
||||
#include "abg-comparison.h"
|
||||
@ -64,10 +67,6 @@ using abigail::xml_writer::write_context_sptr;
|
||||
using abigail::xml_writer::write_corpus;
|
||||
using abigail::xml_reader::read_corpus_from_native_xml_file;
|
||||
using abigail::xml_reader::create_native_xml_read_context;
|
||||
using abigail::dwarf_reader::read_context;
|
||||
using abigail::dwarf_reader::read_context_sptr;
|
||||
using abigail::dwarf_reader::read_corpus_from_elf;
|
||||
using abigail::dwarf_reader::create_read_context;
|
||||
using namespace abigail;
|
||||
|
||||
struct options
|
||||
@ -99,6 +98,9 @@ struct options
|
||||
bool corpus_group_for_linux;
|
||||
bool show_stats;
|
||||
bool noout;
|
||||
#ifdef WITH_CTF
|
||||
bool use_ctf;
|
||||
#endif
|
||||
bool show_locs;
|
||||
bool abidiff;
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
@ -133,6 +135,9 @@ struct options
|
||||
corpus_group_for_linux(false),
|
||||
show_stats(),
|
||||
noout(),
|
||||
#ifdef WITH_CTF
|
||||
use_ctf(false),
|
||||
#endif
|
||||
show_locs(true),
|
||||
abidiff(),
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
@ -207,6 +212,9 @@ display_usage(const string& prog_name, ostream& out)
|
||||
#endif
|
||||
#ifdef WITH_DEBUG_TYPE_CANONICALIZATION
|
||||
<< " --debug-tc debug the type canonicalization process\n"
|
||||
#endif
|
||||
#ifdef WITH_CTF
|
||||
<< " --ctf use CTF instead of DWARF in ELF files\n"
|
||||
#endif
|
||||
<< " --annotate annotate the ABI artifacts emitted in the output\n"
|
||||
<< " --stats show statistics about various internal stuff\n"
|
||||
@ -306,6 +314,10 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
}
|
||||
else if (!strcmp(argv[i], "--noout"))
|
||||
opts.noout = true;
|
||||
#ifdef WITH_CTF
|
||||
else if (!strcmp(argv[i], "--ctf"))
|
||||
opts.use_ctf = true;
|
||||
#endif
|
||||
else if (!strcmp(argv[i], "--no-architecture"))
|
||||
opts.write_architecture = false;
|
||||
else if (!strcmp(argv[i], "--no-corpus-path"))
|
||||
@ -462,7 +474,7 @@ maybe_check_header_files(const options& opts)
|
||||
/// @param opts the options where to get the suppression
|
||||
/// specifications from.
|
||||
static void
|
||||
set_suppressions(read_context& read_ctxt, options& opts)
|
||||
set_suppressions(dwarf_reader::read_context& read_ctxt, options& opts)
|
||||
{
|
||||
suppressions_type supprs;
|
||||
for (vector<string>::const_iterator i = opts.suppression_paths.begin();
|
||||
@ -498,8 +510,6 @@ set_suppressions(read_context& read_ctxt, options& opts)
|
||||
///
|
||||
/// @param env the environment the ABI artifacts are being created in.
|
||||
///
|
||||
/// @param context the context of the ELF reading.
|
||||
///
|
||||
/// @param opts the options of the program.
|
||||
///
|
||||
/// @return the exit code: 0 if everything went fine, non-zero
|
||||
@ -507,7 +517,6 @@ set_suppressions(read_context& read_ctxt, options& opts)
|
||||
static int
|
||||
load_corpus_and_write_abixml(char* argv[],
|
||||
environment_sptr& env,
|
||||
read_context_sptr& context,
|
||||
options& opts)
|
||||
{
|
||||
int exit_code = 0;
|
||||
@ -523,24 +532,90 @@ load_corpus_and_write_abixml(char* argv[],
|
||||
env->debug_type_canonicalization_is_on(true);
|
||||
#endif
|
||||
|
||||
read_context& ctxt = *context;
|
||||
// First of all, read a libabigail IR corpus from the file specified
|
||||
// in OPTS.
|
||||
corpus_sptr corp;
|
||||
elf_reader::status s = elf_reader::STATUS_UNKNOWN;
|
||||
t.start();
|
||||
corp = read_corpus_from_elf(ctxt, s);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "read corpus from elf file in: " << t << "\n";
|
||||
#ifdef WITH_CTF
|
||||
if (opts.use_ctf)
|
||||
{
|
||||
abigail::ctf_reader::read_context *ctxt
|
||||
= abigail::ctf_reader::create_read_context (opts.in_file_path,
|
||||
env.get());
|
||||
|
||||
t.start();
|
||||
context.reset();
|
||||
t.stop();
|
||||
assert (ctxt);
|
||||
t.start();
|
||||
corp = abigail::ctf_reader::read_corpus (ctxt, s);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "read corpus from elf file in: " << t << "\n";
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
dwarf_reader::read_context_sptr c
|
||||
= abigail::dwarf_reader::create_read_context(opts.in_file_path,
|
||||
opts.prepared_di_root_paths,
|
||||
env.get(),
|
||||
opts.load_all_types,
|
||||
opts.linux_kernel_mode);
|
||||
dwarf_reader::read_context& ctxt = *c;
|
||||
set_drop_undefined_syms(ctxt, opts.drop_undefined_syms);
|
||||
set_show_stats(ctxt, opts.show_stats);
|
||||
set_suppressions(ctxt, opts);
|
||||
abigail::dwarf_reader::set_do_log(ctxt, opts.do_log);
|
||||
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "reset read context in: " << t << "\n";
|
||||
if (opts.check_alt_debug_info_path)
|
||||
{
|
||||
bool has_alt_di = false;
|
||||
string alt_di_path;
|
||||
abigail::elf_reader::status status =
|
||||
abigail::dwarf_reader::has_alt_debug_info(ctxt,
|
||||
has_alt_di,
|
||||
alt_di_path);
|
||||
if (status & abigail::elf_reader::STATUS_OK)
|
||||
{
|
||||
if (alt_di_path.empty())
|
||||
;
|
||||
else
|
||||
{
|
||||
cout << "found the alternate debug info file";
|
||||
if (opts.show_base_name_alt_debug_info_path)
|
||||
{
|
||||
tools_utils::base_name(alt_di_path, alt_di_path);
|
||||
cout << " '" << alt_di_path << "'";
|
||||
}
|
||||
cout << "\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "could not find alternate debug info file\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
t.start();
|
||||
corp = dwarf_reader::read_corpus_from_elf(ctxt, s);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "read corpus from elf file in: " << t << "\n";
|
||||
|
||||
t.start();
|
||||
c.reset();
|
||||
t.stop();
|
||||
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "reset read context in: " << t << "\n";
|
||||
}
|
||||
|
||||
// If we couldn't create a corpus, emit some (hopefully) useful
|
||||
// diagnostics and return and error.
|
||||
if (!corp)
|
||||
{
|
||||
if (s == elf_reader::STATUS_DEBUG_INFO_NOT_FOUND)
|
||||
@ -580,122 +655,122 @@ load_corpus_and_write_abixml(char* argv[],
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Now create a write context and write out an ABI XML description
|
||||
// of the read corpus.
|
||||
t.start();
|
||||
const write_context_sptr& write_ctxt
|
||||
= create_write_context(corp->get_environment(), cout);
|
||||
set_common_options(*write_ctxt, opts);
|
||||
t.stop();
|
||||
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "created & initialized write context in: "
|
||||
<< t << "\n";
|
||||
|
||||
if (opts.abidiff)
|
||||
{
|
||||
// Save the abi in abixml format in a temporary file, read
|
||||
// it back, and compare the ABI of what we've read back
|
||||
// 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);
|
||||
tmp_file->get_stream().flush();
|
||||
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
if (opts.debug_abidiff)
|
||||
{
|
||||
opts.type_id_file_path = tmp_file->get_path() + string(".typeid");
|
||||
write_canonical_type_ids(*write_ctxt, opts.type_id_file_path);
|
||||
}
|
||||
#endif
|
||||
xml_reader::read_context_sptr read_ctxt =
|
||||
create_native_xml_read_context(tmp_file->get_path(), env.get());
|
||||
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
if (opts.debug_abidiff
|
||||
&& !opts.type_id_file_path.empty())
|
||||
load_canonical_type_ids(*read_ctxt, opts.type_id_file_path);
|
||||
#endif
|
||||
t.start();
|
||||
corpus_sptr corp2 =
|
||||
read_corpus_from_input(*read_ctxt);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "Read corpus in: " << t << "\n";
|
||||
|
||||
if (!corp2)
|
||||
{
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "Could not read temporary XML representation of "
|
||||
"elf file back\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
diff_context_sptr ctxt(new diff_context);
|
||||
set_diff_context(ctxt);
|
||||
ctxt->show_locs(opts.show_locs);
|
||||
t.start();
|
||||
corpus_diff_sptr diff = compute_diff(corp, corp2, ctxt);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "computed diff in: " << t << "\n";
|
||||
|
||||
bool has_error = diff->has_changes();
|
||||
if (has_error)
|
||||
{
|
||||
t.start();
|
||||
diff->report(cerr);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "emitted report in: " << t << "\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
if (opts.debug_abidiff
|
||||
&& !opts.type_id_file_path.empty())
|
||||
remove(opts.type_id_file_path.c_str());
|
||||
#endif
|
||||
|
||||
if (opts.noout)
|
||||
return 0;
|
||||
|
||||
if (!opts.out_file_path.empty())
|
||||
{
|
||||
ofstream of(opts.out_file_path.c_str(), std::ios_base::trunc);
|
||||
if (!of.is_open())
|
||||
{
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "could not open output file '"
|
||||
<< opts.out_file_path << "'\n";
|
||||
return 1;
|
||||
}
|
||||
set_ostream(*write_ctxt, of);
|
||||
t.start();
|
||||
write_corpus(*write_ctxt, corp, 0);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "emitted abixml output in: " << t << "\n";
|
||||
of.close();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
t.start();
|
||||
const write_context_sptr& write_ctxt
|
||||
= create_write_context(corp->get_environment(), cout);
|
||||
set_common_options(*write_ctxt, opts);
|
||||
exit_code = !write_corpus(*write_ctxt, corp, 0);
|
||||
t.stop();
|
||||
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "created & initialized write context in: "
|
||||
<< t << "\n";
|
||||
|
||||
if (opts.abidiff)
|
||||
{
|
||||
// Save the abi in abixml format in a temporary file, read
|
||||
// it back, and compare the ABI of what we've read back
|
||||
// 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);
|
||||
tmp_file->get_stream().flush();
|
||||
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
if (opts.debug_abidiff)
|
||||
{
|
||||
opts.type_id_file_path = tmp_file->get_path() + string(".typeid");
|
||||
write_canonical_type_ids(*write_ctxt, opts.type_id_file_path);
|
||||
}
|
||||
#endif
|
||||
xml_reader::read_context_sptr read_ctxt =
|
||||
create_native_xml_read_context(tmp_file->get_path(), env.get());
|
||||
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
if (opts.debug_abidiff
|
||||
&& !opts.type_id_file_path.empty())
|
||||
load_canonical_type_ids(*read_ctxt, opts.type_id_file_path);
|
||||
#endif
|
||||
t.start();
|
||||
corpus_sptr corp2 =
|
||||
read_corpus_from_input(*read_ctxt);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "Read corpus in: " << t << "\n";
|
||||
|
||||
if (!corp2)
|
||||
{
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "Could not read temporary XML representation of "
|
||||
"elf file back\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
diff_context_sptr ctxt(new diff_context);
|
||||
set_diff_context(ctxt);
|
||||
ctxt->show_locs(opts.show_locs);
|
||||
t.start();
|
||||
corpus_diff_sptr diff = compute_diff(corp, corp2, ctxt);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "computed diff in: " << t << "\n";
|
||||
|
||||
bool has_error = diff->has_changes();
|
||||
if (has_error)
|
||||
{
|
||||
t.start();
|
||||
diff->report(cerr);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "emitted report in: " << t << "\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
if (opts.debug_abidiff
|
||||
&& !opts.type_id_file_path.empty())
|
||||
remove(opts.type_id_file_path.c_str());
|
||||
#endif
|
||||
|
||||
if (opts.noout)
|
||||
return 0;
|
||||
|
||||
if (!opts.out_file_path.empty())
|
||||
{
|
||||
ofstream of(opts.out_file_path.c_str(), std::ios_base::trunc);
|
||||
if (!of.is_open())
|
||||
{
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "could not open output file '"
|
||||
<< opts.out_file_path << "'\n";
|
||||
return 1;
|
||||
}
|
||||
set_ostream(*write_ctxt, of);
|
||||
t.start();
|
||||
write_corpus(*write_ctxt, corp, 0);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "emitted abixml output in: " << t << "\n";
|
||||
of.close();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
t.start();
|
||||
exit_code = !write_corpus(*write_ctxt, corp, 0);
|
||||
t.stop();
|
||||
if (opts.do_log)
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "emitted abixml out in: " << t << "\n";
|
||||
}
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "emitted abixml out in: " << t << "\n";
|
||||
}
|
||||
|
||||
return exit_code;
|
||||
@ -884,51 +959,7 @@ main(int argc, char* argv[])
|
||||
int exit_code = 0;
|
||||
|
||||
if (tools_utils::is_regular_file(opts.in_file_path))
|
||||
{
|
||||
read_context_sptr c = create_read_context(opts.in_file_path,
|
||||
opts.prepared_di_root_paths,
|
||||
env.get(),
|
||||
opts.load_all_types,
|
||||
opts.linux_kernel_mode);
|
||||
read_context& ctxt = *c;
|
||||
set_drop_undefined_syms(ctxt, opts.drop_undefined_syms);
|
||||
set_show_stats(ctxt, opts.show_stats);
|
||||
set_suppressions(ctxt, opts);
|
||||
abigail::dwarf_reader::set_do_log(ctxt, opts.do_log);
|
||||
|
||||
if (opts.check_alt_debug_info_path)
|
||||
{
|
||||
bool has_alt_di = false;
|
||||
string alt_di_path;
|
||||
abigail::elf_reader::status status =
|
||||
abigail::dwarf_reader::has_alt_debug_info(ctxt,
|
||||
has_alt_di,
|
||||
alt_di_path);
|
||||
if (status & abigail::elf_reader::STATUS_OK)
|
||||
{
|
||||
if (alt_di_path.empty())
|
||||
;
|
||||
else
|
||||
{
|
||||
cout << "found the alternate debug info file";
|
||||
if (opts.show_base_name_alt_debug_info_path)
|
||||
{
|
||||
tools_utils::base_name(alt_di_path, alt_di_path);
|
||||
cout << " '" << alt_di_path << "'";
|
||||
}
|
||||
cout << "\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "could not find alternate debug info file\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
exit_code = load_corpus_and_write_abixml(argv, env, c, opts);
|
||||
}
|
||||
exit_code = load_corpus_and_write_abixml(argv, env, opts);
|
||||
else
|
||||
exit_code = load_kernel_corpus_group_and_write_abixml(argv, env, opts);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user