libabigail/tests/test-read-common.h
Guillermo E. Martinez 8fd02e0a10 Use the CTF reader by default when applicable
At the moment, the tools abidw, abidiff, abipkgdiff and kmidiff all
use the DWARF front-end by default.  When the "--ctf" option is added
to the command line, they use the CTF front-end.

This patch changes that behaviour in the way described below.

If the "--ctf" command line option is passed to the tool and if the
binary to analyze contains CTF debug info, then the CTF front-end is
used.

If the binary contains ONLY CTF debug info, then the CTF front-end is
used, even if no "--ctf" option was provided.

In all the other cases, the DWARF front-end is used.

Of course, the CTF front-end is not used at all if the CTF
functionality hasn't been enabled at configure time.

This new behaviour is effective for user space and Linux kernel
binaries.

	* doc/manuals/abidiff.rst: Adjust.
	* doc/manuals/abidw.rst: Likewise.
	* doc/manuals/abipkgdiff.rst: Likewise.
	* doc/manuals/kmidiff.rst: Likewise.
	* include/abg-elf-based-reader.h (initialize): Add member function.
	* include/abg-elf-reader.h (has_{dwarf,ctf}_debug_info): Add predicate
	functions.
	* include/abg-tools-utils.h (create_best_elf_based_reader): Add arguments.
	* src/abg-ctf-reader.cc (process_ctf_typedef, process_ctf_base_type)
	(process_ctf_function_type, process_ctf_sou_members, process_ctf_forward_type)
	(process_ctf_struct_type, process_ctf_union_type, process_ctf_array_type)
	(process_ctf_qualified_type, process_ctf_pointer_type, process_ctf_enum_type):
	Remove arguments. Using getters to access required information instead.
	(reader::cur_tu_): Add data member.
	(initialize): Add arguments.
	(cur_transl_unit): Add {get,set)ter.
	(slurp_elf_info): Clear `STATUS_DEBUG_INFO_NOT_FOUND' if corpus is
	`LINUX_KERNEL_BINARY_ORIGIN'.
	(reader::lookup_type): Remove.
	(reader::build_type): New member function.
	* src/abg-elf-reader.cc (reader::reader): Locate ctf debug info
	from binary file.
	(reader::reader): Reset base `fe_iface' constructor.
	(reader::has_{dwarf,ctf}_debug_info): New definitions.
	(reader::read_corpus): Set `STATUS_DEBUG_INFO_NOT_FOUND' according
	to corpus::origin.
	* src/abg-tools-utils.cc (dir_contains_ctf_archive): Define new member.
	(file_has_ctf_debug_info): Looks for kernel ctf debug information archive.
	(maybe_load_vmlinux_{dwarf,ctf}_corpus): Remove.
	(load_vmlinux_corpus): Define function to load IR from kernel
	regardless of the corpus::origin.
	(build_corpus_group_from_kernel_dist_under): Use
	create_best_elf_based_reader to select the front-end.
	(create_best_elf_based_reader): Adjust to allow fallback behaviour
	for different front-ends.
	* tests/data/Makefile.am: Add tests.
	* tests/data/test-diff-pkg-ctf/dirpkg-3-report-2.txt: Adjust.
	* tests/data/test-read-ctf/test-fallback.abi: New test case.
	* tests/data/test-read-ctf/test-fallback.c: Likewise.
	* tests/data/test-read-ctf/test-fallback.o: Likewise.
	* tests/data/test-read-dwarf/test-fallback.abi: Likewise.
	* tests/data/test-read-dwarf/test-fallback.c: Likewise.
	* tests/data/test-read-dwarf/test-fallback.o: Likewise.
	* tests/test-diff-pkg.cc: Adjust.
	* tests/test-read-common.cc (test_task::run_abidw): Use the
	`options:option' field.
	* tests/test-read-common.h (InOutSpec): Add new member.
	* tests/test-read-ctf.cc (in_out_specs): Add option field to test
	suite.  Add new test case.
	* tests/test-read-dwarf.cc: Likewise.
	* tools/abidiff.cc (main): Use create_best_elf_based_reader.
	* tools/abidw.cc: Likewise.
	* tools/abipkgdiff.cc: Likewise.

Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-28 16:52:33 +01:00

185 lines
4.5 KiB
C++

// -*- Mode: C++ -*-
//
/// @file
///
/// This file declares the common functionality for tests in
/// CTF and DWARF readers, it declares abstractions for `act` test
/// stage.
#ifndef __TEST_READ_COMMON_H__
#define __TEST_READ_COMMON_H__
#include <string>
#include "abg-ir.h"
#include "abg-corpus.h"
#include "abg-workers.h"
#include "abg-writer.h"
#include "test-utils.h"
#include "abg-tools-utils.h"
using std::string;
using abigail::xml_writer::type_id_style_kind;
using abigail::ir::corpus_sptr;
namespace abigail
{
namespace tests
{
namespace read_common
{
/// This is an aggregate that specifies where a test shall get its
/// input from, and where it shall write its output to.
struct InOutSpec
{
const char* in_elf_path;
const char* in_suppr_spec_path;
const char* in_public_headers_path;
type_id_style_kind type_id_style;
const char* in_abi_path;
const char* out_abi_path;
const char* options;
};// end struct InOutSpec
/// The task that performs the tests.
struct test_task : public abigail::workers::task
{
bool is_ok;
InOutSpec spec;
string error_message;
string out_abi_base;
string in_elf_base;
string in_abi_base;
string in_elf_path;
string in_abi_path;
string in_suppr_spec_path;
string in_public_headers_path;
string out_abi_path;
/// A setter for `in_elf_path` field.
/// The `in_elf_path` is the full path for input object
/// in the tests container @ref
/// abigail::tests::read_common::InOutSpec.
void
set_in_elf_path()
{
in_elf_path = in_elf_base + spec.in_elf_path;
}
/// A setter for `in_suppr_spec_path` field.
/// The `in_suppr_spec_path` is the full path for suppression
/// entry in the tests container @ref
/// abigail::tests::read_common::InOutSpec.
void
set_in_suppr_spec_path()
{
if (spec.in_suppr_spec_path)
in_suppr_spec_path = in_elf_base + spec.in_suppr_spec_path;
else
in_suppr_spec_path.clear();
}
/// A setter for `in_public_headers_path` field.
/// The `in_public_headers_path` is the full path for headers
/// entry in the tests container @ref
/// abigail::tests::read_common::InOutSpec.
void
set_in_public_headers_path()
{
if (spec.in_public_headers_path)
in_public_headers_path = spec.in_public_headers_path;
if (!in_public_headers_path.empty())
in_public_headers_path = in_elf_base + spec.in_public_headers_path;
}
/// A setter for `out_abi_path` field.
/// The `out_abi_path` is the full path for output of abixml file.
/// @return true if `out_abi_path` is a valid directory.
bool
set_out_abi_path()
{
if (!spec.out_abi_path)
// No output abi path was specified in the spec, so get out.
return false;
out_abi_path = out_abi_base + spec.out_abi_path;
if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
{
error_message =
string("Could not create parent directory for ") + out_abi_path;
return false;
}
return true;
}
/// A setter for `in_abi_path` field.
/// The `in_abi_path` is the full path for the expected abixml file.
void
set_in_abi_path()
{
in_abi_path = in_abi_base + spec.in_abi_path;
}
test_task(const InOutSpec &s,
string& a_out_abi_base,
string& a_in_elf_base,
string& a_in_abi_base);
bool
serialize_corpus(const string& out_abi_path,
corpus_sptr corp);
bool
run_abidw(const string& extargs = "");
bool
run_diff();
virtual
~test_task()
{}
}; // end struct test_task
typedef shared_ptr<test_task> test_task_sptr;
/// An abstraction for valid test options.
struct options
{
// saves a wrong option string passed to test-harness.
string wrong_option;
// parallel test execution.
bool parallel;
options()
: parallel(true)
{}
~options()
{
}
}; // end struct options
void
display_usage(const string& prog_name, ostream& out);
bool
parse_command_line(int argc, char* argv[], options& opts);
/// A convenience typedef for a callback to create_new_test
/// instances.
typedef test_task* (*create_new_test)(const InOutSpec* s,
string& a_out_abi_base,
string& a_in_elf_base,
string& a_in_abi_base);
bool
run_tests(const size_t num_test, const InOutSpec* specs,
const options& opts, create_new_test new_test);
}//end namespace read_common
}//end namespace tests
}//end namespace abigail
#endif //__TEST_READ_COMMON_H__