2020-05-29 14:26:04 +00:00
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
// -*- Mode: C++ -*-
|
|
|
|
//
|
2023-01-01 17:14:26 +00:00
|
|
|
// Copyright (C) 2013-2023 Red Hat, Inc.
|
Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
//
|
|
|
|
// Author: Dodji Seketeli
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
#include <iostream>
|
|
|
|
#include "abg-comparison.h"
|
|
|
|
#include "abg-dwarf-reader.h"
|
|
|
|
|
|
|
|
using std::cout;
|
|
|
|
using std::cerr;
|
|
|
|
using std::ostream;
|
|
|
|
using std::string;
|
|
|
|
|
|
|
|
using abigail::comparison::diff;
|
|
|
|
using abigail::comparison::diff_sptr;
|
Introduce the concept of environment
There are resources needed by the type system and other artifacts of
libabigail. Today, when the life time of those resources need to be
greater than all of artifacts of Abigail, then said resources are made
global.
But then global resources are not great, if anything because they
complicate the future use of the library in concurrent computing
setups.
As I was in the need to add one resource to be used by the type
system, I decided to sit down and first overhaul how these long lived
resources needed to be handled.
And here comes the concept of "environment". An environment is a
place where one can put resources that need to live longer than all
the other artifacts of the Abigail system. And so, the code that
creates Abigail artifacts needs and environment of for said artifacts
to use. In other words, artifacts now use an environment.
This has interesting and strong implications. We can only compare two
artifacts if they use the same environment. This is quite a strong
requirement.
But then when this requirement is fulfilled, comparing two types
amounts to just comparing two pointer values; hash values for types
can also be cached. Now *that* is great for speed of comparison, is
it not?
This patch introduce the concept environment (which is basically a new
abigail::ir::environment type), removes the global variables and uses
the environment instead. Each ABI artifact (either type or decl) now
has a ::get_environment() member function to get its environment.
This patch also disables the caching of hash values because the
caching must happen only *after* all types have been canonicalized.
We were not respecting that requirement until now, and that introduces
wrong hash values. A subsequent patch is going to re-introduce hash
value caching again, once the infrastructure is in place to set a flag
in the environment (hah!) once type canonicalization is done, and then
later read that flag when some client code requests a hash value, to
know if we should look in the hash value cache or not.
The patch obviously changes the output of numerous regression tests
(if anything b/c it disables hash value caching) so 'make check'
yields regressions. But then, it's only the subsequent patch that
updates the tests.
* include/abg-ir.h: Adjust note about memory management.
(class environment): Declare new class.
(translation_unit::translation_unit): Take an environment in
parameter.
(translation_unit::{g,s}et_environment): Declare new member
functions.
(type_or_decl_base::{g,s}et_environment): Likewise.
(type_or_decl_base::{get_cached_hash_value,
set_cached_hash_value}): Change the name of
decl_base::peek_hash_value() and decl_base::set_hash() here into
these and move them here.
(type_or_decl_base::hashing_started): Move
decl_base::hashing_started() here.
({g,s}et_environment_for_artifact): Declare new functions.
(class decl_base): Move member functions hashing_started(),
peek_hash_value() and set_hash() on to the type_or_decl_base base
class.
(scope_decl::scope_decl): Initialize the virtual member
type_or_decl_base().
(type_decl::{get_void_type_decl,
get_variadic_parameter_type_decl}): Remove these static member
functions. They are now non-static member functions of the new
environment type.
* src/abg-ir.cc (class environment_setter): New internal class.
(get_canonical_types_map): Remove. This now becomes a member
function of the environment type.
(class usage_watchdog): Remove.
(usage_watchdog_{s,w}ptr): Remove these typedefs.
(get_usage_watchdog_wptr, ref_usage_watchdog)
(maybe_cleanup_type_system_data): Remove these functions.
(translation_unit::priv::usage_watchdog_): Remove data member.
(translation_unit::priv::env_): New data member.
(translation_unit::priv::priv): Take an environment and initialize
the new env_ data member. Do not initialize the removed
usage_watchdog_.
(translation_unit::translation_unit): Take an environment
parameter.
(translation_unit::get_global_scope): Set the environment of a new
global scope.
(translation_unit::{g,s}et_environment): New accessors.
(translation_unit::bind_function_type_life_time): Set the
environment of the function type.
(struct environment::priv): New class.
(environment::{environment, ~environment, get_canonical_types_map,
get_variadic_parameter_type_decl, canonicalization_is_done}): New
member functions.
(struct type_or_decl_base::priv): New class.
(type_or_decl_base::{type_or_decl_base, hashing_started,
get_cached_hash_value, set_cached_hash_value, set_environment,
get_environment, traverse}): New member functions.
({s,g}get_environment_for_artifact): New functions.
(decl_base::priv::{hash_, hashing_started}): Remove.
(decl_base::priv::priv): Adjust.
(decl_base::decl_base): In the copy constructor, initialize the
virtual base type_or_decl_base. Do not initialize hash_ and
hashing_started data member that got removed.
(decl_base::{hashing_started, peek_hash_value, set_hash}): Remove
member functions.
(strip_typedef): Set the environment of the new type which has its
typedefs stripped off. Adjust the call to type_or_void().
(scope_decl::{add, insert}_member_decl): Set the environment of
the new member decl to the environment of its scope.
(synthesize_type_from_translation_unit)
(synthesize_function_type_from_translation_unit): Set the
environment for the newly synthesized type. Adjust calls to
type_or_void().
(type_or_void): Take an environment in parameter. Get the void
type from the environment.
(get_canonical_types_map): Remove.
(type_base::get_canonical_type_for): Get the canonical types map
from the environment, not from a global variable.
(type_decl::{get_void_type_decl,
get_variadic_parameter_type_decl}): Remove.
(pointer_type_def::pointer_type_def): Adjust call to type_or_void.
(reference_type_def::reference_type_def): Likewise.
(function_decl::parameter::get_pretty_representation): Get the
variadic parameter type decl from the environment.
(class_decl::priv::classes_being_compared_): Remove static data
member.
(class_decl::priv::{mark_as_being_compared,
unmark_as_being_compared, comparison_started): Use the "classes
being compared" map from the environment.
(class_decl::base_spec::get_hash): Adjust.
(keep_type_alive): Get the alive types array from the environment)
not from a global variable anymore.
(get_next_string): Put the counter in thread-local storage.
* src/abg-hash.cc (scope_decl::hash::operator())
(function_decl::hash::operator()): Do not handle caching (here).
* include/abg-corpus.h (corpus::{g,s}et_environment): Declare new
accessors.
* src/abg-corpus.cc (corpus::priv::env): New data member.
(corpus::priv::priv): Initialize it.
(corpus::corpus): Take an environment in parameter.
(corpus::{g,s}et_environment): Define new member functions
(corpus::add): Set the environment of the newly added translation
unit, if it's not set already set. In any case, assert that the
translation unit must use the same environment as the corpus.
* include/abg-dwarf-reader.h (create_read_context)
(read_corpus_from_elf): Take an environment parameter.
({s,g}et_debug_info_root_path, {s,g}et_environment): Declare new
functions.
* src/abg-dwarf-reader.cc (read_context::{env_,
offline_callbacks_}): New data members.
(read_context::read_context): Initialize them.
(read_context::clear_per_translation_unit_data): Do not touch the
void type declaration, it doesn't belong to the translation unit.
(read_context::{env, offline_callbacks}): New accessors.
(read_context::{create_default_dwfl}): New member function.
(read_context::dwfl_handle): Add a setter overload.
({s,g}et_debug_info_root_path): Define new accessors.
(create_default_dwfl, create_dwfl_sptr, create_default_dwfl_sptr):
Remove these.
(build_translation_unit_and_add_to_ir): Adjust to pass the
environment to the newly created translation unit.
(build_function_decl): Adjust to pass the environment to the
created function and parameter types. Get variadic parameter type
node from the current environment, not from a global variable.
And do not try to canonicalize function types here.
(read_debug_info_into_corpus): Set the environment of the newly
created corpus.
(build_ir_node_for_void_type): Get the void type node from the
current environment, rather than from a global variable.
(create_read_context): Take the environment in parameter.
Create the default dwarf front end library handle using the new
member function of the read context. Set the current environment
used by the reader.
(read_corpus_from_elf): Take an environment in
parameter. Overhaul. This is now simpler.
(has_alt_debug_info): Adjust the call to create_read_context() to
make it pass an empty environment.
* include/abg-fwd.h (class environment): Forward declare.
* include/abg-reader.h (read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream)
(read_corpus_from_native_xml): Take an environment in parameter.
* src/abg-reader.cc (read_context::m_env): New data member.
(read_context::read_context): Initialize it.
(read_context::{get_environment, set_environment}): New data
member.
(read_translation_unit): Set environment of the new translation
unit.
(read_corpus_from_input): Set the environment of the new corpus.
(read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream, read_corpus_from_native_xml):
Take an environment in parameter.
(build_function_parameter): Get variadic parameter type from the environment.
* src/abg-comparison.cc (compute_diff): Add asserts in all the
overloads to ensure that the artifact being compared come from the
same environment.
* tests/print-diff-tree.cc (main): Create an env for the ABI
artifacts to use.
* tests/test-abidiff.cc (main): Likewise.
* tests/test-diff-dwarf.cc (main): Likewise.
* tests/test-ir-walker.cc (main): Likewise.
* tests/test-read-dwarf.cc (main): Likewise.
* tests/test-read-write.cc (main): Likewise.
* tools/abicompat.cc (main): Likewise.
* tools/abidiff.cc (main): Likewise.
* tools/abidw.cc (main): Likewise.
* tools/abilint.cc (main): Likewise.
* tools/abipkgdiff.cc (main): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-07 20:27:50 +00:00
|
|
|
using abigail::ir::environment;
|
|
|
|
using abigail::ir::environment_sptr;
|
Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
using abigail::comparison::corpus_diff_sptr;
|
|
|
|
using abigail::comparison::compute_diff;
|
|
|
|
using abigail::comparison::print_diff_tree;
|
|
|
|
using abigail::comparison::apply_filters;
|
|
|
|
using namespace abigail;
|
|
|
|
|
|
|
|
struct options
|
|
|
|
{
|
|
|
|
bool display_help;
|
|
|
|
bool categorize_redundancy;
|
|
|
|
bool apply_filters;
|
|
|
|
string elf1;
|
|
|
|
string elf2;
|
|
|
|
|
|
|
|
options()
|
|
|
|
: display_help(false),
|
|
|
|
categorize_redundancy(false),
|
|
|
|
apply_filters(false)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
display_help(const string& prog_name,
|
|
|
|
ostream& out)
|
|
|
|
{
|
|
|
|
out << prog_name << " [options] <elf lib1> <elf lib2>\n"
|
|
|
|
<< " where options can be:\n"
|
|
|
|
<< " --categorize-redundancy categorize diff node redundancy\n"
|
|
|
|
<< " --apply-filters apply the generic categorization filters\n"
|
|
|
|
<< " --help display this message\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
parse_command_line(int argc, char* argv[], options& opts)
|
|
|
|
{
|
|
|
|
if (argc < 2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (int i = 1; i < argc; ++i)
|
|
|
|
{
|
|
|
|
if (argv[i][0] != '-')
|
|
|
|
{
|
|
|
|
if (opts.elf1.empty())
|
|
|
|
opts.elf1 = argv[i];
|
|
|
|
else if (opts.elf2.empty())
|
|
|
|
opts.elf2 = argv[i];
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[i], "--help"))
|
|
|
|
opts.display_help = true;
|
|
|
|
else if (!strcmp(argv[i], "--categorize-redundancy"))
|
|
|
|
opts.categorize_redundancy = true;
|
|
|
|
else if (!strcmp(argv[i], "--apply-filters"))
|
|
|
|
opts.apply_filters = true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
options opts;
|
|
|
|
|
|
|
|
if (!parse_command_line(argc, argv, opts))
|
|
|
|
{
|
|
|
|
cerr << "unrecognized option\n"
|
|
|
|
"try the --help option for more information\n";
|
2019-04-15 17:05:14 +00:00
|
|
|
return 1;
|
Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (opts.display_help)
|
|
|
|
{
|
|
|
|
display_help(argv[0], cout);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!opts.elf1.empty() && !opts.elf2.empty())
|
|
|
|
{
|
Make Front Ends first class citizens
This patch is a reorganization of the code to better support the need
for having several different front-ends.
In the libabigail pipeline of operation, a front-end is the part of
the pipeline that analyses the input file. For instance, to analyse
an ELF file, there is going to be one front-end. To analyse an ABIXML
file, there is going to be another front-end.
The middle-end is the part of the pipeline that interacts with the
internal representation of ABIs. The middle-end knows how to analyse,
compare ABI corpora provide an internal representation of the
comparison result and analyse it as well.
The back-end would be the part of the front-end that knows how to
serialize internal representations of ABIs and ABI comparison results.
One could thus imagine a front-end that understands the DWARF debug
info format embedded in an ELF file. Another front-end would be
dedicated to the CTF debug info format, and so on.
Front-ends can share capabilities. For instance, DWARF and CTF
front-ends are ELF based front end. As such, they share capabilities
to understand the ELF format. They don't share much with the ABIXML
front-end, however, as it's based on XML, which has almost nothing in
common with ELF.
To support this organization of concepts, this patch introduces a new
hierarchy of types in the form of C++ classes.
All front-ends implements the "Front End Interface". As such, they
all inherit the abigail::fe_iface class.
That class provides properties and behaviours that are shared by all
front-ends that libabigail supports today. Namely, that class
provides access to some of the options that are relevant to operating
the front-end, to the ABI corpus or corpus group being constructed and
to the suppression specifications that are considered. It also
provides an abstract interface to perform the actual loading of the
ABI corpus. That abstract interface has to be implemented by every
single concrete front-end that is provided in libabigail.
Then, there is the "ELF Reader" front-end. Its class name is
abigail::elf::reader. It inherits the abigail::fe_iface class and
implements the fe_iface::load_corpus() so that the ELF properties of
the ELF file be loaded and exposed in the ABI corpus as returned by
the fe_iface::corpus() accessor. This ELF reader front-end also
provides lots of capabilities that are specific to accessing ELF
content.
Then, there is a common base class for ELF-based front-ends to come,
named abigail::elf_based_reader, which inherits the abigail::elf::reader
class. The purpose of this base class is to provide common properties
and behaviours that are necessary to implement things like a DWARF or
a CTF front-end, or any other front-end to support an ELF-based debug
info format.
Then, there is a CTF front-end which class is named
abigail::ctf::reader. It inherits the abigail::elf_based_reader class
and implements the fe_iface::load_corpus() interface to load and
analyse the CTF-specific properties of the ELF file. To do this,
abigail::ctf::reader::load_corpus() re-uses the abigail::elf::load_corpus() member
function to load the generic ELF parts of the ABI corpus. This reader
then constructs the internal representation of the ABI corpus and
passes it to the middle-end for further analysis.
Then, there is a DWARF front-end which class is named
abigail::dwarf::reader. It inherits the abigail::elf_based_reader
class and implements the fe_iface::load_corpus() interface to load and
analyse the DWARF-specific properties of the ELF file. To do this,
abigail::dwarf::reader re-uses the abigail::elf::load_corpus() member
function to load the generic ELF parts of the ABI corpus, just like
what the CTF front-end does. And then, just like the CTF front-end,
this reader then constructs the internal representation of the ABI
corpus and passes it to the middle-end for further analysis.
Lastly, there is an ABIXML front-end which class is named
abigail::abixml::reader. It inherits the abigail::fe_iface class
directly. Note that unlike the two previous front-ends, this one
doesn't inherit the elf_based_reader base class, for reasons that
should be obvious to the astute reader by now. So, this front-end
implements the abigail::fe_iface::load_corpus() abstract interface to
load the properties for the ABI corpus represented in the ABIXML
format, construct the internal representation and pass it to the
middle-end for further analysis.
The code of the tools got adapted to use these front-ends.
The support of CTF is still guarded by #ifdef WITH_CTF pre-processor
macros, but the one cool side effect is that the amount of guarded
code is reduced. Basically, it's only the creation of the CTF
front-end that is guarded. After its creation, what is returned is an
instance of abigail::elf_based_reader::reader, exactly like what is
returned by the creation of a DWARF front-end. Thus, the rest of the
code is exactly the same, regardless of the kind of front-end. I
believe this results in a more elegant and maintainable code.
As a proof-of-concept, this patch also provides the
create_best_elf_based_reader function. This function analyses the ELF
file and depending on the kind of debug info it provides, returns the
right front-end for it. Maybe at some point, all the #ifdef WITH_CTF
guard pre-processing macros will be constrained in a single function
like this one that will take the decision of instantiating the right
front-end. The rest of the code will be as generic as it gets.
The patch adjusts the reference abixml files produced by the CTF
front-end because it now emits the <elf-needed> XML element which was
not emitted before. This is done because the CTF front-end inherits
the elf-reader which reads the "elf-needed" property from the binary,
without explicit intervention from the CTF front-end.
The patch passes 'make distcheck' on all the supported platforms.
* include/abg-fwd.h (build_internal_underlying_enum_type_name):
Move this here from src/abg-dwarf-reader.cc.
* include/abg-elf-reader-common.h: Delete this file. Its content
is going to be put in the new include/abg-elf-reader.h.
* src/abg-elf-reader-common.cc: Likewise.
* include/abg-{elf-based-reader, elf-reader, fe-iface}.h: Add new
files.
* src/abg-fe-iface.cc: Likewise.
* include/Makefile.am: Add the new file abg-fe-iface.h,
abg-elf-based-reader.h and abg-elf-reader.h to source distribution
and remove include/abg-elf-reader-common.h from source
distribution.
* src/abg-ir.cc (build_internal_underlying_enum_type_name): Move
this here from abg-dwarf-reader.cc so that it can be used by other
readers.
* include/abg-reader.h (abigail::abixml::reader): Rename the
namespace abigail::xml_reader into this one.
(read_context, create_native_xml_read_context)
(read_context_get_path, read_corpus_from_native_xml)
(read_corpus_from_native_xml_file)
(read_corpus_group_from_native_xml)
(read_corpus_group_from_native_xml_file): Remove.
(read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream)
(read_translation_unit)
(consider_types_not_reachable_from_public_interfaces)
(get_types_from_type_id, get_artifact_used_by_relation_map)
(load_canonical_type_ids): Take an fe_iface&, not a read_context.
(create_reader): Declare new function that returns a
fe_iface_sptr.
(read_corpus_from_abixml, read_corpus_from_abixml_file)
(read_corpus_group_from_abixml)
(read_corpus_group_from_abixml_file): Declare new functions.
* src/abg-reader.cc (namespace abixml): Rename the
xml_reader namespace into this.
(abixml::reader_sptr): New typedef.
(abixml::reader): Rename read_context into this. Make it
inherit the fe_iface interface.
(abixml::reader::{m_path, m_env, m_corpus, m_corpus_group,
m_exported_decls_builder, m_supprs}): Remove these data members
that are now part of the fe_iface parent type.
(abixml::reader::{set_environment, get_corpus, set_corpus,
set_corpus_group, maybe_add_fn_to_exported_decls,
maybe_add_var_to_exported_decls,
maybe_check_abixml_canonical_type_stability,
suppression_matches_function_sym_name,
suppression_matches_variable_name,
suppression_matches_variable_sym_name}): Remove.
(read_corpus_from_input): Remove. Actually the code of this went
into abixml::reader::read_context().
(abixml::reader::get_libxml_reader): Rename the get_reader
member function into this.
(abixml::add_reader_suppressions): Rename
add_read_context_suppressions into this.
(abixml::reader::read_corpus): Implement this virtual
member function if the fe_iface parent interface.
(maybe_set_naming_typedef, advance_cursor)
(handle_version_attribute, walk_xml_node_to_map_type_ids)
(read_elf_needed_from_input, read_symbol_db_from_input)
(get_or_read_and_add_translation_unit, build_needed)
(read_elf_needed_from_input, add_read_context_suppressions)
(maybe_set_artificial_location, maybe_set_naming_typedef)
(build_namespace_decl, build_elf_symbol)
(build_elf_symbol_from_reference, build_elf_symbol_db)
(build_function_parameter, build_function_decl)
(build_function_decl_if_not_suppressed, function_is_suppressed)
(type_is_suppressed, build_var_decl_if_not_suppressed)
(variable_is_suppressed, variable_is_suppressed, build_var_decl)
(build_type_decl, build_qualified_type_decl)
(build_pointer_type_def, build_reference_type_def)
(build_function_type, build_subrange_type, build_array_type_def)
(build_enum_type_decl_if_not_suppressed, build_enum_type_decl)
(build_typedef_decl, build_class_decl_if_not_suppressed)
(build_union_decl_if_not_suppressed, build_class_decl)
(build_union_decl, build_function_tdecl, build_class_tdecl)
(build_type_tparameter, build_type_composition)
(build_non_type_tparameter, build_non_type_tparameter)
(build_template_tparameter, build_template_parameter, build_type)
(handle_type_decl, handle_namespace_decl)
(handle_qualified_type_decl, handle_pointer_type_def)
(handle_reference_type_def, handle_function_type)
(handle_array_type_def, handle_enum_type_decl)
(handle_typedef_decl, handle_var_decl, handle_function_decl)
(handle_class_decl, handle_union_decl, handle_function_tdecl)
(read_translation_unit_from_istream): Take or use an
abixml::reader rather than a read_context.
(read_translation_unit, read_translation_unit_from_input)
(consider_types_not_reachable_from_public_interfaces)
(get_types_from_type_id, get_artifact_used_by_relation_map)
(read_corpus_group_from_input, read_translation_unit)
(handle_element_node, read_location, read_artificial_location)
(load_canonical_type_ids) : Take an fe_iface&, not a read_context.
(create_abixml_reader): Rename create_native_xml_read_context
into this. Make it return a fe_iface_sptr.
(read_corpus_from_abixml): Rename read_corpus_from_abixml into
this.
(read_corpus_from_abixml_file): Rename
read_corpus_from_native_xml_file into this.
(read_context_get_path): Remove.
* include/abg-tools-utils.h
(abigail::tools_utils::{file_has_dwarf_debug_info,
file_has_ctf_debug_info}): Declare new functions.
(create_best_elf_based_reader): Declare new function.
* include/abg-corpus.h (corpus::add): Pass the translation unit by
reference.
(corpus::exported_decls_builder::maybe_add_{fn,var}_to_exported_fns):
Take a const parameter.
* src/abg-corpus-priv.h
(corpus::exported_decls_builder::priv::add_{fn,var}_to_exported):
Take a const parameter and adjust.
* src/abg-corpus.cc
(corpus::exported_decls_builder::maybe_add_{fn,var}_to_exported_fns):
Take a const parameter.
(corpus::add): Take a reference to translation_unit_sptr.
* include/abg-suppression.h (abigail::fe_iface): Forward-declare
this.
(abigail::{suppression_sptr, suppressions_type}): Declare these
types here.
(abigail::suppr::{suppression_can_match,
suppression_matches_function_name,
suppression_matches_function_sym_name,
suppression_matches_variable_name,
suppression_matches_variable_sym_name,
suppression_matches_type_name_or_location,
is_elf_symbol_suppressed, is_elf_symbol_suppressed,
is_function_suppressed, is_variable_suppressed,
is_type_suppressed}): Declare these functions here.
* src/abg-suppression-priv.h (function_is_suppressed)
(variable_is_suppressed, type_is_suppressed)
(is_elf_symbol_suppressed): Remove these template functions.
* src/abg-suppression.cc (suppression_matches_function_name)
(suppression_matches_function_sym_name): Remove.
(variable_is_suppressed, suppression_can_match)
(suppression_matches_function_name)
(suppression_matches_function_sym_name)
(suppression_matches_variable_name)
(suppression_matches_variable_sym_name)
(suppression_matches_type_name_or_location)
(is_elf_symbol_suppressed, is_elf_symbol_suppressed)
(is_function_suppressed, is_variable_suppressed)
(is_type_suppressed): New functions.
* include/abg-ctf-reader.h (abigail::ctf::{read_context,
create_read_context, read_corpus,
read_and_add_corpus_to_group_from_elf,
set_read_context_corpus_group, reset_read_context, dic_type_key}):
Remove.
(ctf::{create_reader, reset_reader}): Declare new
functions.
* src/abg-ctf-reader.cc (read_context): Remove.
(process_ctf_typedef, process_ctf_base_type)
(build_ir_node_for_variadic_parameter_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, fill_ctf_section)
(lookup_symbol_in_ctf_archive, dic_type_key): Forward-declare
these static functions.
(ctf::reader): New class that is the abstraction
of the CTF reader. It extends the abigail::elf_based_reader
class. This is a renaming of the
abigail::ctf::read_context class.
(ctf::reader::{elf_handler, elf_fd,
elf_handler_dbg, elf_fd_dbg, symtab, debug_info_root_paths_,
debug_info_root_paths_}): Remove these data members as they are
now properties of the abigail::elf_reader class, which is a parent
class of this abigail::ctf::reader class.
(ctf::reader::{exported_decls_builder,
maybe_add_fn_to_exported_decls, current_corpus_group,
has_corpus_group, main_corpus_from_current_group,
current_corpus_is_main_corpus_from_current_group,
should_reuse_type_from_corpus_group}): Remove these accessors
that can now be used from the parent classes abigail::{elf_reader,
elf_based_reader}.
(ctf::reader::reader): This now delegates to the constructor of
elf_based_reader. It doesn't pass any argument to initialize()
anymore.
(ctf::reader::initialize): Add an overload with no
parameter. In the other overload, do not take a pointer to an
environment as no new environment can be passed to the instance of
reader that is being reset. Adjust the code of the initializer to
reflect all the data members that got removed.
(ctf::{env, find_ctfa_file, slurp_elf_info,
process_ctf_archive, process_ctf_type, lookup_type, read_corpus,
~reader}): New member functions. Most of these were free-form
functions that took ctf::read_context as first parameter.
In read_corpus, do not set the corpus::LINUX_KERNEL_BINARY_ORIGIN
origin as that is now done by elf::reader when it reads the
binary.
(lookup_type): Remove. These are now member functions of the
ctf::reader class.
(process_ctf_typedef, process_ctf_base_type)
(build_ir_node_for_variadic_parameter_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): Take a
ctf::reader rather an ctf::read_context. Adjust the
content of the functions.
(process_ctf_type, lookup_type, process_ctf_archive): Remove these
and turn them into member functions of ctf::reader.
(open_elf_handler, close_elf_handler, find_alt_debuginfo): Remove
these ELF handling functions as ELF handling is now done by the
elf_reader parent class.
(fill_ctf_section): Take a const pointer to Elf_Scn.
(slurp_elf_info, find_ctfa_file): Remove this and make it be a
member of ctf::reader. Also, make it handle only CTF
reader specific pieces. slurp_elf_info now delegates the reading
of generic ELF properties to elf::reader by calling
elf::reader::read_corpus().
(create_read_context, read_corpus, set_read_context_corpus_group)
(read_and_add_corpus_to_group_from_elf): Remove these functions.
(create_reader, reset_reader): Create new functions
(dic_type_key): Make this static.
* include/abg-dwarf-reader.h (abigail::dwarf::elf_type):
Move this enum into the namespace abigail::elf_reader in the file
include/abg-elf-reader.h.
(abigail::dwarf::{read_context, read_context_sptr,
create_read_context, read_context_get_path, reset_read_context,
add_read_context_suppressions, set_read_context_corpus_group,
read_corpus_from_elf, read_and_add_corpus_to_group_from_elf,
read_and_add_corpus_to_group_from_elf,
add_read_context_suppressions, refers_to_alt_debug_info,
has_alt_debug_info, get_soname_of_elf_file, get_type_of_elf_file,
set_debug_info_root_path, get_debug_info_root_path,
get_show_stats, set_show_stats, set_drop_undefined_syms,
set_do_log, set_environment, get_environment}): Remove.
* src/abg-dwarf-reader.cc (struct dwfl_deleter, dwfl_sptr)
(addr_elf_symbol_sptr_map_type, address_set_type)
(address_set_sptr): Delete these types.
(read_context::options_type): Remove. The data members of this
type got moved to struct fe_iface::options_type.
(find_alt_debug_info_link, find_alt_debug_info_path)
(find_alt_debug_info, lookup_data_tag_from_dynamic_segment)
(elf_file_type, refers_to_alt_debug_info, has_alt_debug_info)
(get_soname_of_elf_file, get_type_of_elf_file) : Remove these ELF
specific functions from here; move them to the elf_reader
namespace.
(dwarf::reader): Create new class that extends
elf_based_reader. dwarf::read_context is renamed into this
type, actually.
(dwarf::reader::die_source_dependant_container_set::get_container):
Adjust.
(dwarf::reader::{supprs_, dwarf_version_,
offline_callbacks_, debug_info_root_paths_, handle_, dwarf_,
alt_fd_, alt_dwarf_, alt_debug_info_path_, elf_module_,
elf_handle_, elf_path_, symtab_section_, cur_corpus_group_,
cur_corpus_, dt_needed_, dt_soname_, elf_architecture_,
exported_decls_builder_, options_, drop_undefined_syms_}): Remove
these ELF-related data members to move them into the elf_reader
namespace.
(maybe_propagate_canonical_type)
(build_translation_unit_and_add_to_ir, build_ir_node_from_die)
(add_or_update_class_type, add_or_update_union_type)
(build_ir_node_for_void_type)
(build_ir_node_for_variadic_parameter_type, build_function_decl)
(function_is_suppressed, build_or_get_fn_decl_if_not_suppressed)
(build_var_decl, build_or_get_var_decl_if_not_suppressed)
(variable_is_suppressed)
(propagate_canonical_type)
(get_parent_die, get_scope_die, die_is_at_class_scope)
(die_location, die_qualified_type_name, die_qualified_name)
(die_qualified_type_name_empty)
(die_return_and_parm_names_from_fn_type_die)
(die_function_signature, die_function_type_is_method_type)
(die_pretty_print_type, die_pretty_print_decl, die_pretty_print)
(maybe_canonicalize_type, build_subrange_type)
(build_subranges_from_array_type_die, compare_dies, die_location)
(die_loc_and_name, die_is_effectively_public_decl)
(maybe_cache_type_comparison_result)
(get_cached_type_comparison_result)
(maybe_get_cached_type_comparison_result, die_is_at_class_scope)
(die_function_type_is_method_type, die_member_offset)
(die_qualified_type_name, die_qualified_decl_name)
(die_qualified_name, die_qualified_type_name_empty)
(die_return_and_parm_names_from_fn_type_die)
(die_function_signature, die_pretty_print_type)
(die_pretty_print_decl, die_pretty_print)
(at_least_one_decl_only_among_odr_relevant_dies)
(compare_as_type_dies, compare_as_decl_and_type_dies)
(fn_die_equal_by_linkage_name, try_canonical_die_comparison)
(maybe_propagate_canonical_type, propagate_canonical_type)
(compare_dies, compare_dies_during_canonicalization)
(find_import_unit_point_between_dies, get_parent_die)
(get_scope_die, find_lower_bound_in_imported_unit_points)
(build_translation_unit_and_add_to_ir)
(build_namespace_decl_and_add_to_ir, build_type_decl)
(build_enum_underlying_type, build_enum_type)
(finish_member_function_reading)
(maybe_finish_function_decl_reading)
(lookup_class_or_typedef_from_corpus)
(is_function_for_die_a_member_of_class)
(add_or_update_member_function, add_or_update_class_type)
(add_or_update_union_type, build_qualified_type)
(schedule_array_tree_for_late_canonicalization)
(maybe_strip_qualification, build_pointer_type_def)
(build_reference_type, build_function_type, build_subrange_type)
(build_subranges_from_array_type_die, build_array_type)
(build_typedef_type, build_or_get_var_decl_if_not_suppressed)
(build_var_decl, function_is_suppressed)
(build_or_get_fn_decl_if_not_suppressed, variable_is_suppressed)
(type_is_suppressed, type_is_suppressed)
(get_opaque_version_of_type, create_default_fn_sym)
(build_function_decl, maybe_canonicalize_type)
(build_ir_node_from_die)
(build_ir_node_for_variadic_parameter_type): Take a reference to
the new dwarf::reader rather than to the previous
read_context. Adjust the function body.
(return_comparison_result): Adjust.
(dwarf::reader::reader): Adjust this from
read_context::read_context.
(dwarf::reader::initialize): Adjust from
dwarf::read_context::initialize.
(dwarf::reader::create): New factory static member
function.
(dwarf::reader::~reader): This doesn't have to clear
anything for now.
(dwarf::reader::read_corpus): New virtual member function
which implements the fe_iface::read_corpus pure virtual interface.
This now delegates the reading of the generic ELF properties to
elf::reader by calling elf::reader::read_corpus().
Newer front-ends will be able to do the same.
(dwarf::reader::reset_corpus): New member function.
(dwarf::reader::read_debug_info_into_corpus): Adjust. This
is now a member function. Also, do not set the
corpus::LINUX_KERNEL_BINARY_ORIGIN here as it's now set by the
elf::reader when it loads the binary.
(dwarf::reader::{env, drop_undefined_syms,
drop_undefined_syms, dwarf_elf_handle, dwarf_per_die_source,
elf_path, compute_canonical_die_offset, get_die_source,
get_die_from_offset, get_die_qualified_name,
get_die_pretty_type_representation, get_die_qualified_type_name,
get_die_pretty_representation, odr_is_relevant,
set_canonical_die_offset, get_canonical_die_offset,
erase_canonical_die_offset, die_wip_classes_map,
die_wip_function_types_map, compare_before_canonicalisation,
resolve_declaration_only_classes, resolve_declaration_only_enums,
symbol_already_belongs_to_a_function,
fixup_functions_with_no_symbols, canonicalize_types_scheduled,
tu_die_imported_unit_points_map, die_parent_map,
find_symbol_table_section, get_variable_address,
exported_decls_builder, load_all_types, load_in_linux_kernel_mode,
show_stats, do_log, build_die_parent_maps): Adjust.
(offset_pairs_stack_type::rdr_): Changed the ctxt_ into this.
(offset_pairs_stack_type::offset_pairs_stack_type): Adjust.
(offset_pairs_stack_type::{erase_redundant_type_pair_entry,
cancel_canonical_propagated_type}): Adjust.
(dwarf::reader::{get_suppressions, offline_callbacks,
create_default_dwfl, dwfl_handle, elf_module, elf_handle,
add_debug_info_root_paths, add_debug_info_root_path,
find_alt_debug_info, dwarf, alt_dwarf, alt_debug_info_path,
current_corpus, reset_current_corpus, current_corpus_group,
has_corpus_group, main_corpus_from_current_group,
current_corpus_is_main_corpus_from_current_group,
should_reuse_type_from_corpus_group, function_symbol_is_exported,
variable_symbol_is_exported, symtab, dt_needed, dt_soname,
elf_architecture, is_elf_symbol_suppressed,
load_dt_soname_and_needed, load_elf_architecture,
load_elf_properties, maybe_add_fn_to_exported_decls,
maybe_add_var_to_exported_decls}): Remove these member functions
as they got moved into the elf_reader namespace or into the
fe_iface class.
(dwarf::read_context::{suppression_can_match,
suppression_matches_function_sym_name,
suppression_matches_function_name,
suppression_matches_variable_name,
suppression_matches_variable_sym_name,
suppression_matches_type_name_or_location}): Move these into the
suppr namespace. Make it take an additional parameter that is
reference fe_iface.
(dwarf::reader::load_debug_info): Remove. This became
merged into dwarf::read_debug_info_into_corpus.
(dwarf::{set_debug_info_root_path,
get_debug_info_root_path, get_show_stats, set_drop_undefined_syms,
set_do_log}): Remove.
(add_read_context_suppressions)
(set_read_context_corpus_group, read_corpus_from_elf): Remove.
(read_debug_info_into_corpus): This became a member function of
dwarf::reader.
(create_reader): Renamed create_read_context into this.
Make it return an elf_based_reader_sptr, like the other front-end
factory functions. Adjust.
(reset_dwarf_reader): Renamed reset_read_context into this.
Adjust.
(read_corpus_from_elf): Adjust.
* src/abg-elf-based-reader.cc: New file.
* src/abg-elf-helpers.h (struct dwfl_deleter, dwfl_sptr)
(addr_elf_symbol_sptr_map_type, address_set_sptr): Move these
types here from abg-dwarf-reader.cc
(initialize_dwfl_callbacks, lookup_data_tag_from_dynamic_segment):
* src/abg-elf-helpers.cc (lookup_data_tag_from_dynamic_segment)
(lookup_data_tag_from_dynamic_segment, initialize_dwfl_callbacks)
(create_new_dwfl_handle, get_soname_of_elf_file): New functions
that got moved here from the factorizing of abg-dwarf-reader.cc
and abg-ctf-reader.cc.
* src/abg-tools-utils.cc (file_has_dwarf_debug_info)
(file_has_ctf_debug_info): New functions.
(load_generate_apply_suppressions): Take an elf_based_reader, not
a dwarf::read_context.
(maybe_load_vmlinux_dwarf_corpus): Adjust the body to use the new
front-end types.
* src/Makefile.am: Add the new files src/abg-{fe-iface,
elf-based-reader, elf-reader}.cc to source distribution. Remove
src/abg-elf-reader-common.cc.
* tools/Makefile.am: Factorize linking to libabigail.so by using
LDADD.
* tools/abicompat.cc (read_corpus, main): Adjust.
* tools/abidiff.cc (set_suppressions)
(set_native_xml_reader_options, handle_error, main): Adjust.
* tools/abidw.cc (set_suppressions, load_corpus_and_write_abixml)
(load_kernel_corpus_group_and_write_abixml): Adjust.
* tools/abilint.cc (build_type_use_tree, show_how_type_is_used)
(set_suppressions, main): Adjust.
* tools/abipkgdiff.cc (elf_file::type, compare, compare_to_self)
(create_maps_of_package_content)
(compare_prepared_userspace_packages)
(self_compare_prepared_userspace_package): Adjust.
* tools/abisym.cc: Adjust invocation to
abigail::dwarf::lookup_symbol_from_elf, from
abigail::dwarf_reader::lookup_symbol_from_elf.
* tools/kmidiff.cc (main): Adjust.
* tests/print-diff-tree.cc (main): Adjust.
* tests/test-abidiff.cc (main): Likewise.
* tests/test-diff-dwarf.cc (main): Likewise.
* tests/test-ir-walker.cc (main): Likewise.
* tests/test-read-ctf.cc (test_task_ctf::perform): Likewise.
* tests/test-read-dwarf.cc: Remove the useless "using" statements.
* tests/test-read-write.cc: Likewise.
* tests/test-symtab.cc (read_corpus, TEST_CASE)
(assert_symbol_count): Adjust.
* tests/data/test-read-ctf/test0.abi: Adjust.
* tests/data/test-read-ctf/test0.hash.abi: Likewise.
* tests/data/test-read-ctf/test1.so.abi: Likewise.
* tests/data/test-read-ctf/test1.so.hash.abi: Likewise.
* tests/data/test-read-ctf/test2.so.abi: Likewise.
* tests/data/test-read-ctf/test2.so.hash.abi: Likewise.
* tests/data/test-read-ctf/test3.so.abi: Likewise.
* tests/data/test-read-ctf/test3.so.hash.abi: Likewise.
* tests/data/test-read-ctf/test4.so.abi: Likewise.
* tests/data/test-read-ctf/test4.so.hash.abi: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-15 16:26:37 +00:00
|
|
|
fe_iface::status c1_status, c2_status;
|
Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
corpus_sptr c1, c2;
|
|
|
|
|
Use environment by reference.
This patch simplifies how the environment is created and passed around
the functions that create front ends. With this change, the
environment can simply be allocated on the stack and passed by
reference to the libabigail pipeline.
At the core of this change, type_or_decl_base::priv now carries a
const reference to an environment rather than a pointer. The side
effect is that type_or_decl_base can no longer be copied. This is not
a problem because throughout the years I could see that the use case
to copy ABI artifacts is just not there. Similarly, elf_symbol::priv
carries a const reference to environment now, no more a pointer.
Getters, setters and code that use the environment from the ABI
artifacts are updated accordingly.
The DWARF front-end can now be created by code that looks like this,
for instance:
vector<char**> debug_info_paths;
abigail::ir::environment env;
abigail::ctf_reader::read_context_sptr reader =
abigail::dwarf_reader::create_read_context("elf/file/to/analyze",
debug_info_paths, env);
elf_reader::status reading_status;
corpus_sptr abi_corpus =
abigail::dwarf_reader::read_corpus_from_elf(reader, reading_status);
/* then do something with the resulting abi_corpus*/
Note how, you don't need to use the "new" operator to instantiate the
"env" object of type environment. It can sit on the stack and it's
passed to the read_corpus_from_elf function by reference.
In other words, the internal representation types have been changed to
refer to the environment by reference, rather than requiring a pointer
to it.
* include/abg-corpus.h (corpus::corpus)
(corpus_group::corpus_group): Take environment&, not environment*
as parameter.
(corpus::{get_environment, set_environment}): Take or return
environment&, not environment*.
* src/abg-corpus.cc (corpus::corpus): Likewise.
(corpus::{get_environment, set_environment}): Likewise.
(corpus::add): Don't update the environment of the translation
unit.
(corpus::{record_type_as_reachable_from_public_interfaces,
type_is_reachable_from_public_interfaces, init_format_version,
add_corpus}): Adjust for accessing a reference to environment,
rather than a pointer.
* include/abg-ctf-reader.h (create_read_context): Take or return
environment&, not environment*.
* src/abg-ctf-reader.cc (read_context::ir_env): Make this a
reference to environment, not pointer anymore.
(read_context::read_context): Initialize the reference to
environment.
(read_context::initialize): Do not re-set the environment.
(process_ctf_base_type)
(build_ir_node_for_variadic_parameter_type)
(process_ctf_enum_type, read_corpus): Adjust for accessing a
reference to environment, rather than a pointer.
(create_read_context, reset_read_context): Take environment&, not
environment*.
* include/abg-dwarf-reader.h (create_read_context)
(reset_read_context, read_corpus_from_elf)
(lookup_symbol_from_elf, lookup_public_function_symbol_from_elf):
Likewise.
* src/abg-dwarf-reader.cc (lookup_symbol_from_sysv_hash_tab)
(lookup_symbol_from_gnu_hash_tab)
(lookup_symbol_from_elf_hash_tab, lookup_symbol_from_symtab)
(lookup_symbol_from_elf, lookup_public_function_symbol_from_elf):
Likewise.
(read_context::options_type::env): Make this be a reference to
environment, not a pointer.
(read_context::options::options): Remove the default constructor.
Add a new one to initialize the environment data member.
(read_context::read_context): Take environment&, not environment*.
Initialize the options_ data member.
(read_context::initialize): Do not take or initialize an
environment anymore.
(read_context::env): Return or take environment&, not
environment*.
(read_context::{get_die_qualified_name,
get_die_qualified_type_name, get_die_pretty_type_representation,
get_die_pretty_representation, compare_before_canonicalisation})
(build_translation_unit_and_add_to_ir, build_function_type)
(build_typedef_type, read_debug_info_into_corpus)
(read_debug_info_into_corpus, build_ir_node_from_die)
(build_ir_node_for_variadic_parameter_type, has_alt_debug_info):
Adjust to use an environment&, not a pointer.
(create_default_fn_sym, create_read_context)
(read_corpus_from_elf, lookup_symbol_from_elf)
(lookup_public_function_symbol_from_elf): Take environment&, not
environment*.
(reset_read_context): Do not take or reset environment* anymore.
* include/abg-fwd.h (type_or_void): Likewise.
* include/abg-ir.h (translation_unit::translation_unit): Likewise.
(translation_unit::{get_environment, set_environment}): Likewise.
(elf_symbol::elf_symbol): Likewise.
(elf_symbol::create): Remove the overload that takes no
parameter. Then for overload that take parameters then take
environment&, not environment*.
(elf_symbol::get_environment): Take environment&, not
environment*.
(type_or_decl_base::type_or_decl_base): Make the copy constructor
and assignment operator private.
(type_or_decl_base::{s,g}et_environment): Take or return
environment& not environment*.
(type_or_decl_base::set_environment_for_artifact): Erase these
methods.
(decl_base::decl_base): Make copy constructor private. Take or
return environment&, not environment* for the other constructors.
(scope_decl::scope_decl): Take or return environment&, not
environment*.
(type_base::type_base): Likewise.
(scope_type_decl::scope_type_decl): Likewise.
(namespace_decl::namespace_decl): Likewise.
(qualified_type_def::qualified_type_def): Likewise.
(pointer_type_def::pointer_type_def): Likewise.
(reference_type_def::reference_type_def): Likewise.
(array_type_def::subrange_type::subrange_type): Likewise.
(enum_type_def::enumerator::enumerator): Likewise.
(enum_type_def::enumerator::{get_name, get_qualified_name}):
Return a string&, no more interned_string&. As the enumerator
don't have an enumerator anymore, there is no way to intern the
string anymore. Hopefully this won't incur a performance loss.
(typedef_decl::typedef_decl, function_type::function_type)
(method_type::method_type, template_decl::template_decl)
(function_tdecl::function_tdecl, class_tdecl::class_tdecl)
(class_or_union::class_or_union, class_decl::class_decl)
(union_decl::union_decl): Take or return environment&, not
environment*.
* include/abg-reader.h (read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream)
(create_native_xml_read_context, create_native_xml_read_context)
(read_corpus_from_native_xml, read_corpus_from_native_xml_file)
(read_corpus_group_from_native_xml)
(read_corpus_group_from_native_xml_file): Likewise.
* include/abg-tools-utils.h
(build_corpus_group_from_kernel_dist_under): Likewise.
* src/abg-tools-utils.cc (maybe_load_vmlinux_dwarf_corpus)
(maybe_load_vmlinux_ctf_corpus)
(build_corpus_group_from_kernel_dist_under): Likewise.
* include/abg-writer.h (create_write_context): Likewise.
* src/abg-writer.cc (id_manager::m_env, id_manager::id_manager)
(id_manager::get_environment, id_manager::get_id)
(id_manager::get_id_with_prefix): Adjust.
(write_context::m_env, write_context::write_context)
(write_context::get_environment, write_context::get_config)
(write_context::get_id_for_type, write_context::decl_is_emitted)
(write_context::record_decl_as_emitted, create_write_context)
(write_class_decl): Likewise.
* src/abg-comparison.cc (compute_diff): Stop ensuring that the two
artifacts being compare are in the same environment. Now that the
environment is passed by reference, the potential for
accendentally comparing artifacts coming from different
environments is very low, given how the API is used in practice.
This is in the overloads for decl_base_sptr, type_base_sptr,
var_decl_sptr, pointer_type_def_sptr, array_type_def_sptr,
reference_type_def_sptr, qualified_type_def_sptr,
enum_type_decl_sptr, class_decl_sptr, class_decl::base_spec_sptr,
union_decl_sptr, scope_decl_sptr, function_decl::parameter_sptr,
function_type_sptr, function_decl_sptr, type_decl_sptr,
typedef_decl_sptr, translation_unit_sptr, corpus_sptr.
* src/abg-corpus-priv.h (corpus::priv::env): Make this be a
reference to environments, not a pointer.
(corpus::priv::priv): Pass environment&, not environment*.
* src/abg-ir-priv.h (translation_unit::priv::env_): Make this an
environment&, not an environment* anymore.
(translation_unit::priv::priv): Take an environment&, not an
environment*.
(environment::priv::{confirm_ct_propagation_for_types_dependant_on,
confirm_ct_propagation,
cancel_ct_propagation_for_types_dependant_on,
mark_as_being_compared, unmark_as_being_compared,
comparison_started, mark_as_being_compared, comparison_started}):
Adjust to use an environment&, not a pointer.
* src/abg-ir.cc (class environment_setter): Remove this class.
(push_composite_type_comparison_operands)
(pop_composite_type_comparison_operands, try_canonical_compare)
(return_comparison_result, translation_unit::{get_global_scope,
bind_function_type_life_time}): Adjust.
(translation_unit::{translation_unit, get_environment}): Take or
get an environment&, not an environment*. Remove the getter that
returns an environment*.
(elf_symbol::priv::env_): Make this an environment&, not an
environment*.
(elf_symbol::priv::priv): Adjust.
(elf_symbol::elf_symbol): Remove the default constructor. Change
the one that takes an environment.
(elf_symbol::create): Remove the default one. Adjust the one that
takes an environment.
(elf_symbol::get_environment): Adjust.
(elf_symbol::set_environment_for_artifact): Remove.
(environment::{get_void_type, get_variadic_parameter_type}):
Adjust.
(type_or_decl_base::priv::env_): Make this be a const
environment&, not a const environment*.
(type_or_decl_base::priv::priv): Adjust.
(type_or_decl_base::type_or_decl_base): Remove the default and
copy constructor.
(type_or_decl_base::{set_environment, operator=})
(set_environment_for_artifact): Remove.
(type_or_decl_base::get_environment): Adjust.
(decl_base::{decl_base, set_name, set_naming_typedef,
set_linkage_name}): Adjust.
(get_decl_name_for_comparison, strip_typedef)
(strip_useless_const_qualification): Adjust.
(scope_decl::{scope_decl, add_member_decl, insert_member_decl}):
Adjust.
(get_generic_anonymous_internal_type_name, get_type_name)
(get_name_of_pointer_to_type, get_name_of_reference_to_type)
(get_name_of_qualified_type, get_function_type_name)
(get_method_type_name, is_void_pointer_type, lookup_basic_type)
(lookup_union_type, lookup_union_type_per_location)
(lookup_enum_type, lookup_typedef_type, lookup_pointer_type)
(lookup_type, lookup_basic_type_per_location)
(lookup_basic_type_per_location, lookup_basic_type)
(lookup_class_type, lookup_class_types)
(lookup_class_type_per_location, lookup_union_type)
(lookup_enum_type, lookup_enum_types)
(lookup_enum_type_per_location, lookup_typedef_type)
(lookup_typedef_type_per_location, maybe_update_types_lookup_map)
(maybe_update_types_lookup_map)
(synthesize_type_from_translation_unit)
(synthesize_function_type_from_translation_unit)
(demangle_cplus_mangled_name, type_or_void)
(types_defined_same_linux_kernel_corpus_public)
(compare_types_during_canonicalization)
(type_base::get_canonical_type_for, type_base::type_base)
(type_base::get_cached_pretty_representation)
(type_decl::type_decl, type_decl::get_qualified_name): Adjust.
(scope_type_decl::scope_type_decl)
(namespace_decl::namespace_decl, qualified_type_def::build_name)
(qualified_type_def::qualified_type_def)
(qualified_type_def::get_qualified_name)
(qualified_type_def::set_underlying_type)
(pointer_type_def::pointer_type_def)
(pointer_type_def::set_pointed_to_type)
(reference_type_def::reference_type_def)
(reference_type_def::set_pointed_to_type)
(array_type_def::subrange_type::subrange_type)
(array_type_def::array_type_def, array_type_def::update_size)
(array_type_def::set_element_type)
(array_type_def::append_subranges)
(array_type_def::get_qualified_name, enum_has_non_name_change):
Adjust.
(enum_type_decl::enumerator::priv::env_): Remove this pointer to
env. This is because the enumerator must be copy-able. As the
enumerator doesn't have an env anymore, it can't intern strings.
So the enumerator name and qualified name is not going to be
interned. If that incurs a performance hit, we'll reconsider this
decision. For now, it seems to work OK. As it simplifies things,
I am keeping this for now.
(enum_type_decl::enumerator::priv::{name, qualified_name}): Make
this be string, not interned_string.
(enum_type_decl::enumerator::get_environment): Remove.
(enum_type_decl::enumerator::priv::priv): Adjust.
(enum_type_decl::enumerator::enumerator)
(enum_type_decl::enumerator::operator=)
(enum_type_decl::enumerator::get_name)
(enum_type_decl::enumerator::get_qualified_name)
(enum_type_decl::enumerator::set_name): Likewise.
(typedef_decl::typedef_decl): Adjust.
(var_decl::get_id, var_decl::get_qualified_name): Adjust.
(function_type::function_type, method_type::method_type)
(function_decl::get_pretty_representation_of_declarator)
(function_decl::set_symbol): Likewise.
(function_decl::get_id, function_decl::parameter::get_type)
(function_decl::parameter::get_type_name)
(function_decl::parameter::get_type_pretty_representation)
(function_decl::parameter::get_name_id)
(class_or_union::class_or_union, class_decl::class_decl)
(class_decl::add_base_specifier, union_decl::union_decl)
(union_decl::union_decl, template_decl::template_decl)
(class_tdecl::class_tdecl)
(maybe_cancel_propagated_canonical_type)
(dump_classes_being_compared)
(dump_fn_types_being_compared, copy_member_function)
(maybe_propagate_canonical_type, keep_type_alive)
(is_non_canonicalized_type, qualified_name_setter::do_update):
Likewise.
(equals): Adjust the overloads for var_decl, function_type,
class_or_union, class_decl, union_decl.
* src/abg-reader.cc (read_context::m_env): Make this be an
environment&, not an environment*.
(read_context::read_context): Adjust
(read_context::set_environment): Remove.
(read_context::{get_environment,
maybe_check_abixml_canonical_type_stability}): Adjust.
(read_corpus_from_input, read_corpus_group_from_native_xml)
(read_corpus_group_from_native_xml_file)
(read_translation_unit_from_file)
(read_translation_unit_from_buffer, read_translation_unit)
(maybe_map_type_with_type_id, build_namespace_decl)
(build_elf_symbol, build_function_parameter, build_function_decl)
(build_function_type, build_enum_type_decl, build_class_decl)
(build_union_decl, build_function_tdecl, build_class_tdecl)
(build_type_tparameter, read_translation_unit_from_istream)
(create_native_xml_read_context, read_corpus_from_native_xml):
Likewise.
* src/abg-symtab-reader.h (symtab::load): Likewise.
* src/abg-symtab-reader.cc (symtab::load): Likewise.
* tests/print-diff-tree.cc (main): Likewise.
* tests/test-abidiff.cc (main): Likewise.
* tests/test-diff-dwarf.cc (main): Likewise.
* tests/test-ir-walker.cc (main): Likewise.
* tests/test-read-ctf.cc (test_task_ctf::perform): Likewise.
* tests/test-symtab.cc (read_corpus): Likewise.
* tools/abicompat.cc (read_corpus, main): Likewise.
* tools/abidiff.cc (main): Likewise.
* tools/abidw.cc (load_corpus_and_write_abixml)
(load_kernel_corpus_group_and_write_abixml, main): Likewise.
* tools/abilint.cc (main): Likewise.
* tools/abipkgdiff.cc (compare, compare_to_self)
(compare_prepared_linux_kernel_packages, compare_task::perform):
Likewise.
* tools/abisym.cc (main): Likewise.
* tools/kmidiff.cc (main): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-10 11:00:44 +00:00
|
|
|
environment env;
|
Support having several debuginfo search dirs for a binary
There are use cases where the split debuginfo file of a given binary
is under a given root directory and that the split debuginfo file
itself depends on an alternate debuginfo file that is under another
unrelated root directory.
In that case, the dwarf reader must be able to look for the debuginfo
files under several unrelated root directories. The tools abidiff and
abidw must thus support having several occurences of the option
--debug-info-dir1 (or --debug-info-dir2) meaning that the debuginfo
files for the binary must be looked for under several root
directories.
This is what this patch does.
* doc/manuals/abidiff.rst: Adjust doc for the
--debug-info-dir{1,2} that can now be provided several times.
* include/abg-dwarf-reader.h ({create, reset}_read_context)
(read_corpus_from_elf): Take a vector of debug info root dirs.
* include/abg-tools-utils.h (trim_leading_string)
(find_file_under_dir, make_path_absolute_to_be_freed)
(convert_char_stars_to_char_star_stars): Declare new functions.
* src/abg-dwarf-reader.cc (find_alt_debug_info_link): Renamed
find_alt_debug_info_location into this.
(find_alt_debug_info_path): Define new static function.
(find_alt_debug_info): Take a vector of debug info root dirs. Use
the new find_alt_debug_info_path to look into the debug info root
dirs for the alt debug info.
(read_context::debug_info_root_paths_): Define new data member.
(read_context::read_context): Take a vector of debug info root
dirs and initialize the new read_context::debug_info_root_paths_.
(read_context::{initialize, create_default_dwfl}): Take a vector
of debug info root dirs and adjust.
(read_context::{add_debug_info_root_paths,
add_debug_info_root_path, find_alt_debug_info}): Define new member
functions.
(read_context::load_debug_info): Look into the debug info roots
for split debug info files.
(create_read_context, read_corpus_from_elf): Take a vector of
debug info root dirs and adjust.
(has_alt_debug_info): Adjust.
* src/abg-tools-utils.cc (trim_leading_string)
(make_path_absolute_to_be_freed, find_file_under_dir)
(convert_char_stars_to_char_star_stars): Define new functions.
(entry_of_file_with_name): Define new static function.
(build_corpus_group_from_kernel_dist_under): Adjust.
* tests/print-diff-tree.cc (main): Adjust.
* tests/test-diff-dwarf.cc (main): Adjust.
* tests/test-ir-walker.cc (main): Adjust.
* tests/test-read-dwarf.cc (main): Adjust.
* tools/abicompat.cc (main): Adjust.
* tools/abidiff.cc (options::di_root_paths{1,2}): Changed
di_root_path{1,2} into this, change their types into vectors of
allocated char*.
(options::prepared_di_root_paths{1,2}): Define new data members.
(options::~options): Define new destructor.
(parse_command_line): Adjust.
(prepare_di_root_paths): Define new static function.
(handle_error): Remove arguments input_file_name,
debug_info_dir{1,2}. Now just take an instance of options
instead. Adjust.
(main): Adjust.
* tools/abidw.cc (options::dir_root_paths): Renamed dir_root_path
into this and make it be a vector of allocated char*.
(options::prepared_di_root_paths): Define new data member.
(options::~options): Free the allocated char* in
options::dir_root_paths.
(parse_command_line): Support several --debug-info-dir.
(load_corpus_and_write_abixml): Adjust.
(prepare_di_root_paths): Define static function.
(main): Adjust.
* tools/abilint.cc (main): Adjust.
* tools/abipkgdiff.cc (compare): Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2018-11-08 06:26:14 +00:00
|
|
|
vector<char**> di_roots;
|
Make Front Ends first class citizens
This patch is a reorganization of the code to better support the need
for having several different front-ends.
In the libabigail pipeline of operation, a front-end is the part of
the pipeline that analyses the input file. For instance, to analyse
an ELF file, there is going to be one front-end. To analyse an ABIXML
file, there is going to be another front-end.
The middle-end is the part of the pipeline that interacts with the
internal representation of ABIs. The middle-end knows how to analyse,
compare ABI corpora provide an internal representation of the
comparison result and analyse it as well.
The back-end would be the part of the front-end that knows how to
serialize internal representations of ABIs and ABI comparison results.
One could thus imagine a front-end that understands the DWARF debug
info format embedded in an ELF file. Another front-end would be
dedicated to the CTF debug info format, and so on.
Front-ends can share capabilities. For instance, DWARF and CTF
front-ends are ELF based front end. As such, they share capabilities
to understand the ELF format. They don't share much with the ABIXML
front-end, however, as it's based on XML, which has almost nothing in
common with ELF.
To support this organization of concepts, this patch introduces a new
hierarchy of types in the form of C++ classes.
All front-ends implements the "Front End Interface". As such, they
all inherit the abigail::fe_iface class.
That class provides properties and behaviours that are shared by all
front-ends that libabigail supports today. Namely, that class
provides access to some of the options that are relevant to operating
the front-end, to the ABI corpus or corpus group being constructed and
to the suppression specifications that are considered. It also
provides an abstract interface to perform the actual loading of the
ABI corpus. That abstract interface has to be implemented by every
single concrete front-end that is provided in libabigail.
Then, there is the "ELF Reader" front-end. Its class name is
abigail::elf::reader. It inherits the abigail::fe_iface class and
implements the fe_iface::load_corpus() so that the ELF properties of
the ELF file be loaded and exposed in the ABI corpus as returned by
the fe_iface::corpus() accessor. This ELF reader front-end also
provides lots of capabilities that are specific to accessing ELF
content.
Then, there is a common base class for ELF-based front-ends to come,
named abigail::elf_based_reader, which inherits the abigail::elf::reader
class. The purpose of this base class is to provide common properties
and behaviours that are necessary to implement things like a DWARF or
a CTF front-end, or any other front-end to support an ELF-based debug
info format.
Then, there is a CTF front-end which class is named
abigail::ctf::reader. It inherits the abigail::elf_based_reader class
and implements the fe_iface::load_corpus() interface to load and
analyse the CTF-specific properties of the ELF file. To do this,
abigail::ctf::reader::load_corpus() re-uses the abigail::elf::load_corpus() member
function to load the generic ELF parts of the ABI corpus. This reader
then constructs the internal representation of the ABI corpus and
passes it to the middle-end for further analysis.
Then, there is a DWARF front-end which class is named
abigail::dwarf::reader. It inherits the abigail::elf_based_reader
class and implements the fe_iface::load_corpus() interface to load and
analyse the DWARF-specific properties of the ELF file. To do this,
abigail::dwarf::reader re-uses the abigail::elf::load_corpus() member
function to load the generic ELF parts of the ABI corpus, just like
what the CTF front-end does. And then, just like the CTF front-end,
this reader then constructs the internal representation of the ABI
corpus and passes it to the middle-end for further analysis.
Lastly, there is an ABIXML front-end which class is named
abigail::abixml::reader. It inherits the abigail::fe_iface class
directly. Note that unlike the two previous front-ends, this one
doesn't inherit the elf_based_reader base class, for reasons that
should be obvious to the astute reader by now. So, this front-end
implements the abigail::fe_iface::load_corpus() abstract interface to
load the properties for the ABI corpus represented in the ABIXML
format, construct the internal representation and pass it to the
middle-end for further analysis.
The code of the tools got adapted to use these front-ends.
The support of CTF is still guarded by #ifdef WITH_CTF pre-processor
macros, but the one cool side effect is that the amount of guarded
code is reduced. Basically, it's only the creation of the CTF
front-end that is guarded. After its creation, what is returned is an
instance of abigail::elf_based_reader::reader, exactly like what is
returned by the creation of a DWARF front-end. Thus, the rest of the
code is exactly the same, regardless of the kind of front-end. I
believe this results in a more elegant and maintainable code.
As a proof-of-concept, this patch also provides the
create_best_elf_based_reader function. This function analyses the ELF
file and depending on the kind of debug info it provides, returns the
right front-end for it. Maybe at some point, all the #ifdef WITH_CTF
guard pre-processing macros will be constrained in a single function
like this one that will take the decision of instantiating the right
front-end. The rest of the code will be as generic as it gets.
The patch adjusts the reference abixml files produced by the CTF
front-end because it now emits the <elf-needed> XML element which was
not emitted before. This is done because the CTF front-end inherits
the elf-reader which reads the "elf-needed" property from the binary,
without explicit intervention from the CTF front-end.
The patch passes 'make distcheck' on all the supported platforms.
* include/abg-fwd.h (build_internal_underlying_enum_type_name):
Move this here from src/abg-dwarf-reader.cc.
* include/abg-elf-reader-common.h: Delete this file. Its content
is going to be put in the new include/abg-elf-reader.h.
* src/abg-elf-reader-common.cc: Likewise.
* include/abg-{elf-based-reader, elf-reader, fe-iface}.h: Add new
files.
* src/abg-fe-iface.cc: Likewise.
* include/Makefile.am: Add the new file abg-fe-iface.h,
abg-elf-based-reader.h and abg-elf-reader.h to source distribution
and remove include/abg-elf-reader-common.h from source
distribution.
* src/abg-ir.cc (build_internal_underlying_enum_type_name): Move
this here from abg-dwarf-reader.cc so that it can be used by other
readers.
* include/abg-reader.h (abigail::abixml::reader): Rename the
namespace abigail::xml_reader into this one.
(read_context, create_native_xml_read_context)
(read_context_get_path, read_corpus_from_native_xml)
(read_corpus_from_native_xml_file)
(read_corpus_group_from_native_xml)
(read_corpus_group_from_native_xml_file): Remove.
(read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream)
(read_translation_unit)
(consider_types_not_reachable_from_public_interfaces)
(get_types_from_type_id, get_artifact_used_by_relation_map)
(load_canonical_type_ids): Take an fe_iface&, not a read_context.
(create_reader): Declare new function that returns a
fe_iface_sptr.
(read_corpus_from_abixml, read_corpus_from_abixml_file)
(read_corpus_group_from_abixml)
(read_corpus_group_from_abixml_file): Declare new functions.
* src/abg-reader.cc (namespace abixml): Rename the
xml_reader namespace into this.
(abixml::reader_sptr): New typedef.
(abixml::reader): Rename read_context into this. Make it
inherit the fe_iface interface.
(abixml::reader::{m_path, m_env, m_corpus, m_corpus_group,
m_exported_decls_builder, m_supprs}): Remove these data members
that are now part of the fe_iface parent type.
(abixml::reader::{set_environment, get_corpus, set_corpus,
set_corpus_group, maybe_add_fn_to_exported_decls,
maybe_add_var_to_exported_decls,
maybe_check_abixml_canonical_type_stability,
suppression_matches_function_sym_name,
suppression_matches_variable_name,
suppression_matches_variable_sym_name}): Remove.
(read_corpus_from_input): Remove. Actually the code of this went
into abixml::reader::read_context().
(abixml::reader::get_libxml_reader): Rename the get_reader
member function into this.
(abixml::add_reader_suppressions): Rename
add_read_context_suppressions into this.
(abixml::reader::read_corpus): Implement this virtual
member function if the fe_iface parent interface.
(maybe_set_naming_typedef, advance_cursor)
(handle_version_attribute, walk_xml_node_to_map_type_ids)
(read_elf_needed_from_input, read_symbol_db_from_input)
(get_or_read_and_add_translation_unit, build_needed)
(read_elf_needed_from_input, add_read_context_suppressions)
(maybe_set_artificial_location, maybe_set_naming_typedef)
(build_namespace_decl, build_elf_symbol)
(build_elf_symbol_from_reference, build_elf_symbol_db)
(build_function_parameter, build_function_decl)
(build_function_decl_if_not_suppressed, function_is_suppressed)
(type_is_suppressed, build_var_decl_if_not_suppressed)
(variable_is_suppressed, variable_is_suppressed, build_var_decl)
(build_type_decl, build_qualified_type_decl)
(build_pointer_type_def, build_reference_type_def)
(build_function_type, build_subrange_type, build_array_type_def)
(build_enum_type_decl_if_not_suppressed, build_enum_type_decl)
(build_typedef_decl, build_class_decl_if_not_suppressed)
(build_union_decl_if_not_suppressed, build_class_decl)
(build_union_decl, build_function_tdecl, build_class_tdecl)
(build_type_tparameter, build_type_composition)
(build_non_type_tparameter, build_non_type_tparameter)
(build_template_tparameter, build_template_parameter, build_type)
(handle_type_decl, handle_namespace_decl)
(handle_qualified_type_decl, handle_pointer_type_def)
(handle_reference_type_def, handle_function_type)
(handle_array_type_def, handle_enum_type_decl)
(handle_typedef_decl, handle_var_decl, handle_function_decl)
(handle_class_decl, handle_union_decl, handle_function_tdecl)
(read_translation_unit_from_istream): Take or use an
abixml::reader rather than a read_context.
(read_translation_unit, read_translation_unit_from_input)
(consider_types_not_reachable_from_public_interfaces)
(get_types_from_type_id, get_artifact_used_by_relation_map)
(read_corpus_group_from_input, read_translation_unit)
(handle_element_node, read_location, read_artificial_location)
(load_canonical_type_ids) : Take an fe_iface&, not a read_context.
(create_abixml_reader): Rename create_native_xml_read_context
into this. Make it return a fe_iface_sptr.
(read_corpus_from_abixml): Rename read_corpus_from_abixml into
this.
(read_corpus_from_abixml_file): Rename
read_corpus_from_native_xml_file into this.
(read_context_get_path): Remove.
* include/abg-tools-utils.h
(abigail::tools_utils::{file_has_dwarf_debug_info,
file_has_ctf_debug_info}): Declare new functions.
(create_best_elf_based_reader): Declare new function.
* include/abg-corpus.h (corpus::add): Pass the translation unit by
reference.
(corpus::exported_decls_builder::maybe_add_{fn,var}_to_exported_fns):
Take a const parameter.
* src/abg-corpus-priv.h
(corpus::exported_decls_builder::priv::add_{fn,var}_to_exported):
Take a const parameter and adjust.
* src/abg-corpus.cc
(corpus::exported_decls_builder::maybe_add_{fn,var}_to_exported_fns):
Take a const parameter.
(corpus::add): Take a reference to translation_unit_sptr.
* include/abg-suppression.h (abigail::fe_iface): Forward-declare
this.
(abigail::{suppression_sptr, suppressions_type}): Declare these
types here.
(abigail::suppr::{suppression_can_match,
suppression_matches_function_name,
suppression_matches_function_sym_name,
suppression_matches_variable_name,
suppression_matches_variable_sym_name,
suppression_matches_type_name_or_location,
is_elf_symbol_suppressed, is_elf_symbol_suppressed,
is_function_suppressed, is_variable_suppressed,
is_type_suppressed}): Declare these functions here.
* src/abg-suppression-priv.h (function_is_suppressed)
(variable_is_suppressed, type_is_suppressed)
(is_elf_symbol_suppressed): Remove these template functions.
* src/abg-suppression.cc (suppression_matches_function_name)
(suppression_matches_function_sym_name): Remove.
(variable_is_suppressed, suppression_can_match)
(suppression_matches_function_name)
(suppression_matches_function_sym_name)
(suppression_matches_variable_name)
(suppression_matches_variable_sym_name)
(suppression_matches_type_name_or_location)
(is_elf_symbol_suppressed, is_elf_symbol_suppressed)
(is_function_suppressed, is_variable_suppressed)
(is_type_suppressed): New functions.
* include/abg-ctf-reader.h (abigail::ctf::{read_context,
create_read_context, read_corpus,
read_and_add_corpus_to_group_from_elf,
set_read_context_corpus_group, reset_read_context, dic_type_key}):
Remove.
(ctf::{create_reader, reset_reader}): Declare new
functions.
* src/abg-ctf-reader.cc (read_context): Remove.
(process_ctf_typedef, process_ctf_base_type)
(build_ir_node_for_variadic_parameter_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, fill_ctf_section)
(lookup_symbol_in_ctf_archive, dic_type_key): Forward-declare
these static functions.
(ctf::reader): New class that is the abstraction
of the CTF reader. It extends the abigail::elf_based_reader
class. This is a renaming of the
abigail::ctf::read_context class.
(ctf::reader::{elf_handler, elf_fd,
elf_handler_dbg, elf_fd_dbg, symtab, debug_info_root_paths_,
debug_info_root_paths_}): Remove these data members as they are
now properties of the abigail::elf_reader class, which is a parent
class of this abigail::ctf::reader class.
(ctf::reader::{exported_decls_builder,
maybe_add_fn_to_exported_decls, current_corpus_group,
has_corpus_group, main_corpus_from_current_group,
current_corpus_is_main_corpus_from_current_group,
should_reuse_type_from_corpus_group}): Remove these accessors
that can now be used from the parent classes abigail::{elf_reader,
elf_based_reader}.
(ctf::reader::reader): This now delegates to the constructor of
elf_based_reader. It doesn't pass any argument to initialize()
anymore.
(ctf::reader::initialize): Add an overload with no
parameter. In the other overload, do not take a pointer to an
environment as no new environment can be passed to the instance of
reader that is being reset. Adjust the code of the initializer to
reflect all the data members that got removed.
(ctf::{env, find_ctfa_file, slurp_elf_info,
process_ctf_archive, process_ctf_type, lookup_type, read_corpus,
~reader}): New member functions. Most of these were free-form
functions that took ctf::read_context as first parameter.
In read_corpus, do not set the corpus::LINUX_KERNEL_BINARY_ORIGIN
origin as that is now done by elf::reader when it reads the
binary.
(lookup_type): Remove. These are now member functions of the
ctf::reader class.
(process_ctf_typedef, process_ctf_base_type)
(build_ir_node_for_variadic_parameter_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): Take a
ctf::reader rather an ctf::read_context. Adjust the
content of the functions.
(process_ctf_type, lookup_type, process_ctf_archive): Remove these
and turn them into member functions of ctf::reader.
(open_elf_handler, close_elf_handler, find_alt_debuginfo): Remove
these ELF handling functions as ELF handling is now done by the
elf_reader parent class.
(fill_ctf_section): Take a const pointer to Elf_Scn.
(slurp_elf_info, find_ctfa_file): Remove this and make it be a
member of ctf::reader. Also, make it handle only CTF
reader specific pieces. slurp_elf_info now delegates the reading
of generic ELF properties to elf::reader by calling
elf::reader::read_corpus().
(create_read_context, read_corpus, set_read_context_corpus_group)
(read_and_add_corpus_to_group_from_elf): Remove these functions.
(create_reader, reset_reader): Create new functions
(dic_type_key): Make this static.
* include/abg-dwarf-reader.h (abigail::dwarf::elf_type):
Move this enum into the namespace abigail::elf_reader in the file
include/abg-elf-reader.h.
(abigail::dwarf::{read_context, read_context_sptr,
create_read_context, read_context_get_path, reset_read_context,
add_read_context_suppressions, set_read_context_corpus_group,
read_corpus_from_elf, read_and_add_corpus_to_group_from_elf,
read_and_add_corpus_to_group_from_elf,
add_read_context_suppressions, refers_to_alt_debug_info,
has_alt_debug_info, get_soname_of_elf_file, get_type_of_elf_file,
set_debug_info_root_path, get_debug_info_root_path,
get_show_stats, set_show_stats, set_drop_undefined_syms,
set_do_log, set_environment, get_environment}): Remove.
* src/abg-dwarf-reader.cc (struct dwfl_deleter, dwfl_sptr)
(addr_elf_symbol_sptr_map_type, address_set_type)
(address_set_sptr): Delete these types.
(read_context::options_type): Remove. The data members of this
type got moved to struct fe_iface::options_type.
(find_alt_debug_info_link, find_alt_debug_info_path)
(find_alt_debug_info, lookup_data_tag_from_dynamic_segment)
(elf_file_type, refers_to_alt_debug_info, has_alt_debug_info)
(get_soname_of_elf_file, get_type_of_elf_file) : Remove these ELF
specific functions from here; move them to the elf_reader
namespace.
(dwarf::reader): Create new class that extends
elf_based_reader. dwarf::read_context is renamed into this
type, actually.
(dwarf::reader::die_source_dependant_container_set::get_container):
Adjust.
(dwarf::reader::{supprs_, dwarf_version_,
offline_callbacks_, debug_info_root_paths_, handle_, dwarf_,
alt_fd_, alt_dwarf_, alt_debug_info_path_, elf_module_,
elf_handle_, elf_path_, symtab_section_, cur_corpus_group_,
cur_corpus_, dt_needed_, dt_soname_, elf_architecture_,
exported_decls_builder_, options_, drop_undefined_syms_}): Remove
these ELF-related data members to move them into the elf_reader
namespace.
(maybe_propagate_canonical_type)
(build_translation_unit_and_add_to_ir, build_ir_node_from_die)
(add_or_update_class_type, add_or_update_union_type)
(build_ir_node_for_void_type)
(build_ir_node_for_variadic_parameter_type, build_function_decl)
(function_is_suppressed, build_or_get_fn_decl_if_not_suppressed)
(build_var_decl, build_or_get_var_decl_if_not_suppressed)
(variable_is_suppressed)
(propagate_canonical_type)
(get_parent_die, get_scope_die, die_is_at_class_scope)
(die_location, die_qualified_type_name, die_qualified_name)
(die_qualified_type_name_empty)
(die_return_and_parm_names_from_fn_type_die)
(die_function_signature, die_function_type_is_method_type)
(die_pretty_print_type, die_pretty_print_decl, die_pretty_print)
(maybe_canonicalize_type, build_subrange_type)
(build_subranges_from_array_type_die, compare_dies, die_location)
(die_loc_and_name, die_is_effectively_public_decl)
(maybe_cache_type_comparison_result)
(get_cached_type_comparison_result)
(maybe_get_cached_type_comparison_result, die_is_at_class_scope)
(die_function_type_is_method_type, die_member_offset)
(die_qualified_type_name, die_qualified_decl_name)
(die_qualified_name, die_qualified_type_name_empty)
(die_return_and_parm_names_from_fn_type_die)
(die_function_signature, die_pretty_print_type)
(die_pretty_print_decl, die_pretty_print)
(at_least_one_decl_only_among_odr_relevant_dies)
(compare_as_type_dies, compare_as_decl_and_type_dies)
(fn_die_equal_by_linkage_name, try_canonical_die_comparison)
(maybe_propagate_canonical_type, propagate_canonical_type)
(compare_dies, compare_dies_during_canonicalization)
(find_import_unit_point_between_dies, get_parent_die)
(get_scope_die, find_lower_bound_in_imported_unit_points)
(build_translation_unit_and_add_to_ir)
(build_namespace_decl_and_add_to_ir, build_type_decl)
(build_enum_underlying_type, build_enum_type)
(finish_member_function_reading)
(maybe_finish_function_decl_reading)
(lookup_class_or_typedef_from_corpus)
(is_function_for_die_a_member_of_class)
(add_or_update_member_function, add_or_update_class_type)
(add_or_update_union_type, build_qualified_type)
(schedule_array_tree_for_late_canonicalization)
(maybe_strip_qualification, build_pointer_type_def)
(build_reference_type, build_function_type, build_subrange_type)
(build_subranges_from_array_type_die, build_array_type)
(build_typedef_type, build_or_get_var_decl_if_not_suppressed)
(build_var_decl, function_is_suppressed)
(build_or_get_fn_decl_if_not_suppressed, variable_is_suppressed)
(type_is_suppressed, type_is_suppressed)
(get_opaque_version_of_type, create_default_fn_sym)
(build_function_decl, maybe_canonicalize_type)
(build_ir_node_from_die)
(build_ir_node_for_variadic_parameter_type): Take a reference to
the new dwarf::reader rather than to the previous
read_context. Adjust the function body.
(return_comparison_result): Adjust.
(dwarf::reader::reader): Adjust this from
read_context::read_context.
(dwarf::reader::initialize): Adjust from
dwarf::read_context::initialize.
(dwarf::reader::create): New factory static member
function.
(dwarf::reader::~reader): This doesn't have to clear
anything for now.
(dwarf::reader::read_corpus): New virtual member function
which implements the fe_iface::read_corpus pure virtual interface.
This now delegates the reading of the generic ELF properties to
elf::reader by calling elf::reader::read_corpus().
Newer front-ends will be able to do the same.
(dwarf::reader::reset_corpus): New member function.
(dwarf::reader::read_debug_info_into_corpus): Adjust. This
is now a member function. Also, do not set the
corpus::LINUX_KERNEL_BINARY_ORIGIN here as it's now set by the
elf::reader when it loads the binary.
(dwarf::reader::{env, drop_undefined_syms,
drop_undefined_syms, dwarf_elf_handle, dwarf_per_die_source,
elf_path, compute_canonical_die_offset, get_die_source,
get_die_from_offset, get_die_qualified_name,
get_die_pretty_type_representation, get_die_qualified_type_name,
get_die_pretty_representation, odr_is_relevant,
set_canonical_die_offset, get_canonical_die_offset,
erase_canonical_die_offset, die_wip_classes_map,
die_wip_function_types_map, compare_before_canonicalisation,
resolve_declaration_only_classes, resolve_declaration_only_enums,
symbol_already_belongs_to_a_function,
fixup_functions_with_no_symbols, canonicalize_types_scheduled,
tu_die_imported_unit_points_map, die_parent_map,
find_symbol_table_section, get_variable_address,
exported_decls_builder, load_all_types, load_in_linux_kernel_mode,
show_stats, do_log, build_die_parent_maps): Adjust.
(offset_pairs_stack_type::rdr_): Changed the ctxt_ into this.
(offset_pairs_stack_type::offset_pairs_stack_type): Adjust.
(offset_pairs_stack_type::{erase_redundant_type_pair_entry,
cancel_canonical_propagated_type}): Adjust.
(dwarf::reader::{get_suppressions, offline_callbacks,
create_default_dwfl, dwfl_handle, elf_module, elf_handle,
add_debug_info_root_paths, add_debug_info_root_path,
find_alt_debug_info, dwarf, alt_dwarf, alt_debug_info_path,
current_corpus, reset_current_corpus, current_corpus_group,
has_corpus_group, main_corpus_from_current_group,
current_corpus_is_main_corpus_from_current_group,
should_reuse_type_from_corpus_group, function_symbol_is_exported,
variable_symbol_is_exported, symtab, dt_needed, dt_soname,
elf_architecture, is_elf_symbol_suppressed,
load_dt_soname_and_needed, load_elf_architecture,
load_elf_properties, maybe_add_fn_to_exported_decls,
maybe_add_var_to_exported_decls}): Remove these member functions
as they got moved into the elf_reader namespace or into the
fe_iface class.
(dwarf::read_context::{suppression_can_match,
suppression_matches_function_sym_name,
suppression_matches_function_name,
suppression_matches_variable_name,
suppression_matches_variable_sym_name,
suppression_matches_type_name_or_location}): Move these into the
suppr namespace. Make it take an additional parameter that is
reference fe_iface.
(dwarf::reader::load_debug_info): Remove. This became
merged into dwarf::read_debug_info_into_corpus.
(dwarf::{set_debug_info_root_path,
get_debug_info_root_path, get_show_stats, set_drop_undefined_syms,
set_do_log}): Remove.
(add_read_context_suppressions)
(set_read_context_corpus_group, read_corpus_from_elf): Remove.
(read_debug_info_into_corpus): This became a member function of
dwarf::reader.
(create_reader): Renamed create_read_context into this.
Make it return an elf_based_reader_sptr, like the other front-end
factory functions. Adjust.
(reset_dwarf_reader): Renamed reset_read_context into this.
Adjust.
(read_corpus_from_elf): Adjust.
* src/abg-elf-based-reader.cc: New file.
* src/abg-elf-helpers.h (struct dwfl_deleter, dwfl_sptr)
(addr_elf_symbol_sptr_map_type, address_set_sptr): Move these
types here from abg-dwarf-reader.cc
(initialize_dwfl_callbacks, lookup_data_tag_from_dynamic_segment):
* src/abg-elf-helpers.cc (lookup_data_tag_from_dynamic_segment)
(lookup_data_tag_from_dynamic_segment, initialize_dwfl_callbacks)
(create_new_dwfl_handle, get_soname_of_elf_file): New functions
that got moved here from the factorizing of abg-dwarf-reader.cc
and abg-ctf-reader.cc.
* src/abg-tools-utils.cc (file_has_dwarf_debug_info)
(file_has_ctf_debug_info): New functions.
(load_generate_apply_suppressions): Take an elf_based_reader, not
a dwarf::read_context.
(maybe_load_vmlinux_dwarf_corpus): Adjust the body to use the new
front-end types.
* src/Makefile.am: Add the new files src/abg-{fe-iface,
elf-based-reader, elf-reader}.cc to source distribution. Remove
src/abg-elf-reader-common.cc.
* tools/Makefile.am: Factorize linking to libabigail.so by using
LDADD.
* tools/abicompat.cc (read_corpus, main): Adjust.
* tools/abidiff.cc (set_suppressions)
(set_native_xml_reader_options, handle_error, main): Adjust.
* tools/abidw.cc (set_suppressions, load_corpus_and_write_abixml)
(load_kernel_corpus_group_and_write_abixml): Adjust.
* tools/abilint.cc (build_type_use_tree, show_how_type_is_used)
(set_suppressions, main): Adjust.
* tools/abipkgdiff.cc (elf_file::type, compare, compare_to_self)
(create_maps_of_package_content)
(compare_prepared_userspace_packages)
(self_compare_prepared_userspace_package): Adjust.
* tools/abisym.cc: Adjust invocation to
abigail::dwarf::lookup_symbol_from_elf, from
abigail::dwarf_reader::lookup_symbol_from_elf.
* tools/kmidiff.cc (main): Adjust.
* tests/print-diff-tree.cc (main): Adjust.
* tests/test-abidiff.cc (main): Likewise.
* tests/test-diff-dwarf.cc (main): Likewise.
* tests/test-ir-walker.cc (main): Likewise.
* tests/test-read-ctf.cc (test_task_ctf::perform): Likewise.
* tests/test-read-dwarf.cc: Remove the useless "using" statements.
* tests/test-read-write.cc: Likewise.
* tests/test-symtab.cc (read_corpus, TEST_CASE)
(assert_symbol_count): Adjust.
* tests/data/test-read-ctf/test0.abi: Adjust.
* tests/data/test-read-ctf/test0.hash.abi: Likewise.
* tests/data/test-read-ctf/test1.so.abi: Likewise.
* tests/data/test-read-ctf/test1.so.hash.abi: Likewise.
* tests/data/test-read-ctf/test2.so.abi: Likewise.
* tests/data/test-read-ctf/test2.so.hash.abi: Likewise.
* tests/data/test-read-ctf/test3.so.abi: Likewise.
* tests/data/test-read-ctf/test3.so.hash.abi: Likewise.
* tests/data/test-read-ctf/test4.so.abi: Likewise.
* tests/data/test-read-ctf/test4.so.hash.abi: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-15 16:26:37 +00:00
|
|
|
c1 = dwarf::read_corpus_from_elf(opts.elf1, di_roots, env,
|
|
|
|
/*load_all_types=*/false,
|
|
|
|
c1_status);
|
|
|
|
if (c1_status != fe_iface::STATUS_OK)
|
Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
{
|
|
|
|
cerr << "Failed to read elf file " << opts.elf1 << "\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
Make Front Ends first class citizens
This patch is a reorganization of the code to better support the need
for having several different front-ends.
In the libabigail pipeline of operation, a front-end is the part of
the pipeline that analyses the input file. For instance, to analyse
an ELF file, there is going to be one front-end. To analyse an ABIXML
file, there is going to be another front-end.
The middle-end is the part of the pipeline that interacts with the
internal representation of ABIs. The middle-end knows how to analyse,
compare ABI corpora provide an internal representation of the
comparison result and analyse it as well.
The back-end would be the part of the front-end that knows how to
serialize internal representations of ABIs and ABI comparison results.
One could thus imagine a front-end that understands the DWARF debug
info format embedded in an ELF file. Another front-end would be
dedicated to the CTF debug info format, and so on.
Front-ends can share capabilities. For instance, DWARF and CTF
front-ends are ELF based front end. As such, they share capabilities
to understand the ELF format. They don't share much with the ABIXML
front-end, however, as it's based on XML, which has almost nothing in
common with ELF.
To support this organization of concepts, this patch introduces a new
hierarchy of types in the form of C++ classes.
All front-ends implements the "Front End Interface". As such, they
all inherit the abigail::fe_iface class.
That class provides properties and behaviours that are shared by all
front-ends that libabigail supports today. Namely, that class
provides access to some of the options that are relevant to operating
the front-end, to the ABI corpus or corpus group being constructed and
to the suppression specifications that are considered. It also
provides an abstract interface to perform the actual loading of the
ABI corpus. That abstract interface has to be implemented by every
single concrete front-end that is provided in libabigail.
Then, there is the "ELF Reader" front-end. Its class name is
abigail::elf::reader. It inherits the abigail::fe_iface class and
implements the fe_iface::load_corpus() so that the ELF properties of
the ELF file be loaded and exposed in the ABI corpus as returned by
the fe_iface::corpus() accessor. This ELF reader front-end also
provides lots of capabilities that are specific to accessing ELF
content.
Then, there is a common base class for ELF-based front-ends to come,
named abigail::elf_based_reader, which inherits the abigail::elf::reader
class. The purpose of this base class is to provide common properties
and behaviours that are necessary to implement things like a DWARF or
a CTF front-end, or any other front-end to support an ELF-based debug
info format.
Then, there is a CTF front-end which class is named
abigail::ctf::reader. It inherits the abigail::elf_based_reader class
and implements the fe_iface::load_corpus() interface to load and
analyse the CTF-specific properties of the ELF file. To do this,
abigail::ctf::reader::load_corpus() re-uses the abigail::elf::load_corpus() member
function to load the generic ELF parts of the ABI corpus. This reader
then constructs the internal representation of the ABI corpus and
passes it to the middle-end for further analysis.
Then, there is a DWARF front-end which class is named
abigail::dwarf::reader. It inherits the abigail::elf_based_reader
class and implements the fe_iface::load_corpus() interface to load and
analyse the DWARF-specific properties of the ELF file. To do this,
abigail::dwarf::reader re-uses the abigail::elf::load_corpus() member
function to load the generic ELF parts of the ABI corpus, just like
what the CTF front-end does. And then, just like the CTF front-end,
this reader then constructs the internal representation of the ABI
corpus and passes it to the middle-end for further analysis.
Lastly, there is an ABIXML front-end which class is named
abigail::abixml::reader. It inherits the abigail::fe_iface class
directly. Note that unlike the two previous front-ends, this one
doesn't inherit the elf_based_reader base class, for reasons that
should be obvious to the astute reader by now. So, this front-end
implements the abigail::fe_iface::load_corpus() abstract interface to
load the properties for the ABI corpus represented in the ABIXML
format, construct the internal representation and pass it to the
middle-end for further analysis.
The code of the tools got adapted to use these front-ends.
The support of CTF is still guarded by #ifdef WITH_CTF pre-processor
macros, but the one cool side effect is that the amount of guarded
code is reduced. Basically, it's only the creation of the CTF
front-end that is guarded. After its creation, what is returned is an
instance of abigail::elf_based_reader::reader, exactly like what is
returned by the creation of a DWARF front-end. Thus, the rest of the
code is exactly the same, regardless of the kind of front-end. I
believe this results in a more elegant and maintainable code.
As a proof-of-concept, this patch also provides the
create_best_elf_based_reader function. This function analyses the ELF
file and depending on the kind of debug info it provides, returns the
right front-end for it. Maybe at some point, all the #ifdef WITH_CTF
guard pre-processing macros will be constrained in a single function
like this one that will take the decision of instantiating the right
front-end. The rest of the code will be as generic as it gets.
The patch adjusts the reference abixml files produced by the CTF
front-end because it now emits the <elf-needed> XML element which was
not emitted before. This is done because the CTF front-end inherits
the elf-reader which reads the "elf-needed" property from the binary,
without explicit intervention from the CTF front-end.
The patch passes 'make distcheck' on all the supported platforms.
* include/abg-fwd.h (build_internal_underlying_enum_type_name):
Move this here from src/abg-dwarf-reader.cc.
* include/abg-elf-reader-common.h: Delete this file. Its content
is going to be put in the new include/abg-elf-reader.h.
* src/abg-elf-reader-common.cc: Likewise.
* include/abg-{elf-based-reader, elf-reader, fe-iface}.h: Add new
files.
* src/abg-fe-iface.cc: Likewise.
* include/Makefile.am: Add the new file abg-fe-iface.h,
abg-elf-based-reader.h and abg-elf-reader.h to source distribution
and remove include/abg-elf-reader-common.h from source
distribution.
* src/abg-ir.cc (build_internal_underlying_enum_type_name): Move
this here from abg-dwarf-reader.cc so that it can be used by other
readers.
* include/abg-reader.h (abigail::abixml::reader): Rename the
namespace abigail::xml_reader into this one.
(read_context, create_native_xml_read_context)
(read_context_get_path, read_corpus_from_native_xml)
(read_corpus_from_native_xml_file)
(read_corpus_group_from_native_xml)
(read_corpus_group_from_native_xml_file): Remove.
(read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream)
(read_translation_unit)
(consider_types_not_reachable_from_public_interfaces)
(get_types_from_type_id, get_artifact_used_by_relation_map)
(load_canonical_type_ids): Take an fe_iface&, not a read_context.
(create_reader): Declare new function that returns a
fe_iface_sptr.
(read_corpus_from_abixml, read_corpus_from_abixml_file)
(read_corpus_group_from_abixml)
(read_corpus_group_from_abixml_file): Declare new functions.
* src/abg-reader.cc (namespace abixml): Rename the
xml_reader namespace into this.
(abixml::reader_sptr): New typedef.
(abixml::reader): Rename read_context into this. Make it
inherit the fe_iface interface.
(abixml::reader::{m_path, m_env, m_corpus, m_corpus_group,
m_exported_decls_builder, m_supprs}): Remove these data members
that are now part of the fe_iface parent type.
(abixml::reader::{set_environment, get_corpus, set_corpus,
set_corpus_group, maybe_add_fn_to_exported_decls,
maybe_add_var_to_exported_decls,
maybe_check_abixml_canonical_type_stability,
suppression_matches_function_sym_name,
suppression_matches_variable_name,
suppression_matches_variable_sym_name}): Remove.
(read_corpus_from_input): Remove. Actually the code of this went
into abixml::reader::read_context().
(abixml::reader::get_libxml_reader): Rename the get_reader
member function into this.
(abixml::add_reader_suppressions): Rename
add_read_context_suppressions into this.
(abixml::reader::read_corpus): Implement this virtual
member function if the fe_iface parent interface.
(maybe_set_naming_typedef, advance_cursor)
(handle_version_attribute, walk_xml_node_to_map_type_ids)
(read_elf_needed_from_input, read_symbol_db_from_input)
(get_or_read_and_add_translation_unit, build_needed)
(read_elf_needed_from_input, add_read_context_suppressions)
(maybe_set_artificial_location, maybe_set_naming_typedef)
(build_namespace_decl, build_elf_symbol)
(build_elf_symbol_from_reference, build_elf_symbol_db)
(build_function_parameter, build_function_decl)
(build_function_decl_if_not_suppressed, function_is_suppressed)
(type_is_suppressed, build_var_decl_if_not_suppressed)
(variable_is_suppressed, variable_is_suppressed, build_var_decl)
(build_type_decl, build_qualified_type_decl)
(build_pointer_type_def, build_reference_type_def)
(build_function_type, build_subrange_type, build_array_type_def)
(build_enum_type_decl_if_not_suppressed, build_enum_type_decl)
(build_typedef_decl, build_class_decl_if_not_suppressed)
(build_union_decl_if_not_suppressed, build_class_decl)
(build_union_decl, build_function_tdecl, build_class_tdecl)
(build_type_tparameter, build_type_composition)
(build_non_type_tparameter, build_non_type_tparameter)
(build_template_tparameter, build_template_parameter, build_type)
(handle_type_decl, handle_namespace_decl)
(handle_qualified_type_decl, handle_pointer_type_def)
(handle_reference_type_def, handle_function_type)
(handle_array_type_def, handle_enum_type_decl)
(handle_typedef_decl, handle_var_decl, handle_function_decl)
(handle_class_decl, handle_union_decl, handle_function_tdecl)
(read_translation_unit_from_istream): Take or use an
abixml::reader rather than a read_context.
(read_translation_unit, read_translation_unit_from_input)
(consider_types_not_reachable_from_public_interfaces)
(get_types_from_type_id, get_artifact_used_by_relation_map)
(read_corpus_group_from_input, read_translation_unit)
(handle_element_node, read_location, read_artificial_location)
(load_canonical_type_ids) : Take an fe_iface&, not a read_context.
(create_abixml_reader): Rename create_native_xml_read_context
into this. Make it return a fe_iface_sptr.
(read_corpus_from_abixml): Rename read_corpus_from_abixml into
this.
(read_corpus_from_abixml_file): Rename
read_corpus_from_native_xml_file into this.
(read_context_get_path): Remove.
* include/abg-tools-utils.h
(abigail::tools_utils::{file_has_dwarf_debug_info,
file_has_ctf_debug_info}): Declare new functions.
(create_best_elf_based_reader): Declare new function.
* include/abg-corpus.h (corpus::add): Pass the translation unit by
reference.
(corpus::exported_decls_builder::maybe_add_{fn,var}_to_exported_fns):
Take a const parameter.
* src/abg-corpus-priv.h
(corpus::exported_decls_builder::priv::add_{fn,var}_to_exported):
Take a const parameter and adjust.
* src/abg-corpus.cc
(corpus::exported_decls_builder::maybe_add_{fn,var}_to_exported_fns):
Take a const parameter.
(corpus::add): Take a reference to translation_unit_sptr.
* include/abg-suppression.h (abigail::fe_iface): Forward-declare
this.
(abigail::{suppression_sptr, suppressions_type}): Declare these
types here.
(abigail::suppr::{suppression_can_match,
suppression_matches_function_name,
suppression_matches_function_sym_name,
suppression_matches_variable_name,
suppression_matches_variable_sym_name,
suppression_matches_type_name_or_location,
is_elf_symbol_suppressed, is_elf_symbol_suppressed,
is_function_suppressed, is_variable_suppressed,
is_type_suppressed}): Declare these functions here.
* src/abg-suppression-priv.h (function_is_suppressed)
(variable_is_suppressed, type_is_suppressed)
(is_elf_symbol_suppressed): Remove these template functions.
* src/abg-suppression.cc (suppression_matches_function_name)
(suppression_matches_function_sym_name): Remove.
(variable_is_suppressed, suppression_can_match)
(suppression_matches_function_name)
(suppression_matches_function_sym_name)
(suppression_matches_variable_name)
(suppression_matches_variable_sym_name)
(suppression_matches_type_name_or_location)
(is_elf_symbol_suppressed, is_elf_symbol_suppressed)
(is_function_suppressed, is_variable_suppressed)
(is_type_suppressed): New functions.
* include/abg-ctf-reader.h (abigail::ctf::{read_context,
create_read_context, read_corpus,
read_and_add_corpus_to_group_from_elf,
set_read_context_corpus_group, reset_read_context, dic_type_key}):
Remove.
(ctf::{create_reader, reset_reader}): Declare new
functions.
* src/abg-ctf-reader.cc (read_context): Remove.
(process_ctf_typedef, process_ctf_base_type)
(build_ir_node_for_variadic_parameter_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, fill_ctf_section)
(lookup_symbol_in_ctf_archive, dic_type_key): Forward-declare
these static functions.
(ctf::reader): New class that is the abstraction
of the CTF reader. It extends the abigail::elf_based_reader
class. This is a renaming of the
abigail::ctf::read_context class.
(ctf::reader::{elf_handler, elf_fd,
elf_handler_dbg, elf_fd_dbg, symtab, debug_info_root_paths_,
debug_info_root_paths_}): Remove these data members as they are
now properties of the abigail::elf_reader class, which is a parent
class of this abigail::ctf::reader class.
(ctf::reader::{exported_decls_builder,
maybe_add_fn_to_exported_decls, current_corpus_group,
has_corpus_group, main_corpus_from_current_group,
current_corpus_is_main_corpus_from_current_group,
should_reuse_type_from_corpus_group}): Remove these accessors
that can now be used from the parent classes abigail::{elf_reader,
elf_based_reader}.
(ctf::reader::reader): This now delegates to the constructor of
elf_based_reader. It doesn't pass any argument to initialize()
anymore.
(ctf::reader::initialize): Add an overload with no
parameter. In the other overload, do not take a pointer to an
environment as no new environment can be passed to the instance of
reader that is being reset. Adjust the code of the initializer to
reflect all the data members that got removed.
(ctf::{env, find_ctfa_file, slurp_elf_info,
process_ctf_archive, process_ctf_type, lookup_type, read_corpus,
~reader}): New member functions. Most of these were free-form
functions that took ctf::read_context as first parameter.
In read_corpus, do not set the corpus::LINUX_KERNEL_BINARY_ORIGIN
origin as that is now done by elf::reader when it reads the
binary.
(lookup_type): Remove. These are now member functions of the
ctf::reader class.
(process_ctf_typedef, process_ctf_base_type)
(build_ir_node_for_variadic_parameter_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): Take a
ctf::reader rather an ctf::read_context. Adjust the
content of the functions.
(process_ctf_type, lookup_type, process_ctf_archive): Remove these
and turn them into member functions of ctf::reader.
(open_elf_handler, close_elf_handler, find_alt_debuginfo): Remove
these ELF handling functions as ELF handling is now done by the
elf_reader parent class.
(fill_ctf_section): Take a const pointer to Elf_Scn.
(slurp_elf_info, find_ctfa_file): Remove this and make it be a
member of ctf::reader. Also, make it handle only CTF
reader specific pieces. slurp_elf_info now delegates the reading
of generic ELF properties to elf::reader by calling
elf::reader::read_corpus().
(create_read_context, read_corpus, set_read_context_corpus_group)
(read_and_add_corpus_to_group_from_elf): Remove these functions.
(create_reader, reset_reader): Create new functions
(dic_type_key): Make this static.
* include/abg-dwarf-reader.h (abigail::dwarf::elf_type):
Move this enum into the namespace abigail::elf_reader in the file
include/abg-elf-reader.h.
(abigail::dwarf::{read_context, read_context_sptr,
create_read_context, read_context_get_path, reset_read_context,
add_read_context_suppressions, set_read_context_corpus_group,
read_corpus_from_elf, read_and_add_corpus_to_group_from_elf,
read_and_add_corpus_to_group_from_elf,
add_read_context_suppressions, refers_to_alt_debug_info,
has_alt_debug_info, get_soname_of_elf_file, get_type_of_elf_file,
set_debug_info_root_path, get_debug_info_root_path,
get_show_stats, set_show_stats, set_drop_undefined_syms,
set_do_log, set_environment, get_environment}): Remove.
* src/abg-dwarf-reader.cc (struct dwfl_deleter, dwfl_sptr)
(addr_elf_symbol_sptr_map_type, address_set_type)
(address_set_sptr): Delete these types.
(read_context::options_type): Remove. The data members of this
type got moved to struct fe_iface::options_type.
(find_alt_debug_info_link, find_alt_debug_info_path)
(find_alt_debug_info, lookup_data_tag_from_dynamic_segment)
(elf_file_type, refers_to_alt_debug_info, has_alt_debug_info)
(get_soname_of_elf_file, get_type_of_elf_file) : Remove these ELF
specific functions from here; move them to the elf_reader
namespace.
(dwarf::reader): Create new class that extends
elf_based_reader. dwarf::read_context is renamed into this
type, actually.
(dwarf::reader::die_source_dependant_container_set::get_container):
Adjust.
(dwarf::reader::{supprs_, dwarf_version_,
offline_callbacks_, debug_info_root_paths_, handle_, dwarf_,
alt_fd_, alt_dwarf_, alt_debug_info_path_, elf_module_,
elf_handle_, elf_path_, symtab_section_, cur_corpus_group_,
cur_corpus_, dt_needed_, dt_soname_, elf_architecture_,
exported_decls_builder_, options_, drop_undefined_syms_}): Remove
these ELF-related data members to move them into the elf_reader
namespace.
(maybe_propagate_canonical_type)
(build_translation_unit_and_add_to_ir, build_ir_node_from_die)
(add_or_update_class_type, add_or_update_union_type)
(build_ir_node_for_void_type)
(build_ir_node_for_variadic_parameter_type, build_function_decl)
(function_is_suppressed, build_or_get_fn_decl_if_not_suppressed)
(build_var_decl, build_or_get_var_decl_if_not_suppressed)
(variable_is_suppressed)
(propagate_canonical_type)
(get_parent_die, get_scope_die, die_is_at_class_scope)
(die_location, die_qualified_type_name, die_qualified_name)
(die_qualified_type_name_empty)
(die_return_and_parm_names_from_fn_type_die)
(die_function_signature, die_function_type_is_method_type)
(die_pretty_print_type, die_pretty_print_decl, die_pretty_print)
(maybe_canonicalize_type, build_subrange_type)
(build_subranges_from_array_type_die, compare_dies, die_location)
(die_loc_and_name, die_is_effectively_public_decl)
(maybe_cache_type_comparison_result)
(get_cached_type_comparison_result)
(maybe_get_cached_type_comparison_result, die_is_at_class_scope)
(die_function_type_is_method_type, die_member_offset)
(die_qualified_type_name, die_qualified_decl_name)
(die_qualified_name, die_qualified_type_name_empty)
(die_return_and_parm_names_from_fn_type_die)
(die_function_signature, die_pretty_print_type)
(die_pretty_print_decl, die_pretty_print)
(at_least_one_decl_only_among_odr_relevant_dies)
(compare_as_type_dies, compare_as_decl_and_type_dies)
(fn_die_equal_by_linkage_name, try_canonical_die_comparison)
(maybe_propagate_canonical_type, propagate_canonical_type)
(compare_dies, compare_dies_during_canonicalization)
(find_import_unit_point_between_dies, get_parent_die)
(get_scope_die, find_lower_bound_in_imported_unit_points)
(build_translation_unit_and_add_to_ir)
(build_namespace_decl_and_add_to_ir, build_type_decl)
(build_enum_underlying_type, build_enum_type)
(finish_member_function_reading)
(maybe_finish_function_decl_reading)
(lookup_class_or_typedef_from_corpus)
(is_function_for_die_a_member_of_class)
(add_or_update_member_function, add_or_update_class_type)
(add_or_update_union_type, build_qualified_type)
(schedule_array_tree_for_late_canonicalization)
(maybe_strip_qualification, build_pointer_type_def)
(build_reference_type, build_function_type, build_subrange_type)
(build_subranges_from_array_type_die, build_array_type)
(build_typedef_type, build_or_get_var_decl_if_not_suppressed)
(build_var_decl, function_is_suppressed)
(build_or_get_fn_decl_if_not_suppressed, variable_is_suppressed)
(type_is_suppressed, type_is_suppressed)
(get_opaque_version_of_type, create_default_fn_sym)
(build_function_decl, maybe_canonicalize_type)
(build_ir_node_from_die)
(build_ir_node_for_variadic_parameter_type): Take a reference to
the new dwarf::reader rather than to the previous
read_context. Adjust the function body.
(return_comparison_result): Adjust.
(dwarf::reader::reader): Adjust this from
read_context::read_context.
(dwarf::reader::initialize): Adjust from
dwarf::read_context::initialize.
(dwarf::reader::create): New factory static member
function.
(dwarf::reader::~reader): This doesn't have to clear
anything for now.
(dwarf::reader::read_corpus): New virtual member function
which implements the fe_iface::read_corpus pure virtual interface.
This now delegates the reading of the generic ELF properties to
elf::reader by calling elf::reader::read_corpus().
Newer front-ends will be able to do the same.
(dwarf::reader::reset_corpus): New member function.
(dwarf::reader::read_debug_info_into_corpus): Adjust. This
is now a member function. Also, do not set the
corpus::LINUX_KERNEL_BINARY_ORIGIN here as it's now set by the
elf::reader when it loads the binary.
(dwarf::reader::{env, drop_undefined_syms,
drop_undefined_syms, dwarf_elf_handle, dwarf_per_die_source,
elf_path, compute_canonical_die_offset, get_die_source,
get_die_from_offset, get_die_qualified_name,
get_die_pretty_type_representation, get_die_qualified_type_name,
get_die_pretty_representation, odr_is_relevant,
set_canonical_die_offset, get_canonical_die_offset,
erase_canonical_die_offset, die_wip_classes_map,
die_wip_function_types_map, compare_before_canonicalisation,
resolve_declaration_only_classes, resolve_declaration_only_enums,
symbol_already_belongs_to_a_function,
fixup_functions_with_no_symbols, canonicalize_types_scheduled,
tu_die_imported_unit_points_map, die_parent_map,
find_symbol_table_section, get_variable_address,
exported_decls_builder, load_all_types, load_in_linux_kernel_mode,
show_stats, do_log, build_die_parent_maps): Adjust.
(offset_pairs_stack_type::rdr_): Changed the ctxt_ into this.
(offset_pairs_stack_type::offset_pairs_stack_type): Adjust.
(offset_pairs_stack_type::{erase_redundant_type_pair_entry,
cancel_canonical_propagated_type}): Adjust.
(dwarf::reader::{get_suppressions, offline_callbacks,
create_default_dwfl, dwfl_handle, elf_module, elf_handle,
add_debug_info_root_paths, add_debug_info_root_path,
find_alt_debug_info, dwarf, alt_dwarf, alt_debug_info_path,
current_corpus, reset_current_corpus, current_corpus_group,
has_corpus_group, main_corpus_from_current_group,
current_corpus_is_main_corpus_from_current_group,
should_reuse_type_from_corpus_group, function_symbol_is_exported,
variable_symbol_is_exported, symtab, dt_needed, dt_soname,
elf_architecture, is_elf_symbol_suppressed,
load_dt_soname_and_needed, load_elf_architecture,
load_elf_properties, maybe_add_fn_to_exported_decls,
maybe_add_var_to_exported_decls}): Remove these member functions
as they got moved into the elf_reader namespace or into the
fe_iface class.
(dwarf::read_context::{suppression_can_match,
suppression_matches_function_sym_name,
suppression_matches_function_name,
suppression_matches_variable_name,
suppression_matches_variable_sym_name,
suppression_matches_type_name_or_location}): Move these into the
suppr namespace. Make it take an additional parameter that is
reference fe_iface.
(dwarf::reader::load_debug_info): Remove. This became
merged into dwarf::read_debug_info_into_corpus.
(dwarf::{set_debug_info_root_path,
get_debug_info_root_path, get_show_stats, set_drop_undefined_syms,
set_do_log}): Remove.
(add_read_context_suppressions)
(set_read_context_corpus_group, read_corpus_from_elf): Remove.
(read_debug_info_into_corpus): This became a member function of
dwarf::reader.
(create_reader): Renamed create_read_context into this.
Make it return an elf_based_reader_sptr, like the other front-end
factory functions. Adjust.
(reset_dwarf_reader): Renamed reset_read_context into this.
Adjust.
(read_corpus_from_elf): Adjust.
* src/abg-elf-based-reader.cc: New file.
* src/abg-elf-helpers.h (struct dwfl_deleter, dwfl_sptr)
(addr_elf_symbol_sptr_map_type, address_set_sptr): Move these
types here from abg-dwarf-reader.cc
(initialize_dwfl_callbacks, lookup_data_tag_from_dynamic_segment):
* src/abg-elf-helpers.cc (lookup_data_tag_from_dynamic_segment)
(lookup_data_tag_from_dynamic_segment, initialize_dwfl_callbacks)
(create_new_dwfl_handle, get_soname_of_elf_file): New functions
that got moved here from the factorizing of abg-dwarf-reader.cc
and abg-ctf-reader.cc.
* src/abg-tools-utils.cc (file_has_dwarf_debug_info)
(file_has_ctf_debug_info): New functions.
(load_generate_apply_suppressions): Take an elf_based_reader, not
a dwarf::read_context.
(maybe_load_vmlinux_dwarf_corpus): Adjust the body to use the new
front-end types.
* src/Makefile.am: Add the new files src/abg-{fe-iface,
elf-based-reader, elf-reader}.cc to source distribution. Remove
src/abg-elf-reader-common.cc.
* tools/Makefile.am: Factorize linking to libabigail.so by using
LDADD.
* tools/abicompat.cc (read_corpus, main): Adjust.
* tools/abidiff.cc (set_suppressions)
(set_native_xml_reader_options, handle_error, main): Adjust.
* tools/abidw.cc (set_suppressions, load_corpus_and_write_abixml)
(load_kernel_corpus_group_and_write_abixml): Adjust.
* tools/abilint.cc (build_type_use_tree, show_how_type_is_used)
(set_suppressions, main): Adjust.
* tools/abipkgdiff.cc (elf_file::type, compare, compare_to_self)
(create_maps_of_package_content)
(compare_prepared_userspace_packages)
(self_compare_prepared_userspace_package): Adjust.
* tools/abisym.cc: Adjust invocation to
abigail::dwarf::lookup_symbol_from_elf, from
abigail::dwarf_reader::lookup_symbol_from_elf.
* tools/kmidiff.cc (main): Adjust.
* tests/print-diff-tree.cc (main): Adjust.
* tests/test-abidiff.cc (main): Likewise.
* tests/test-diff-dwarf.cc (main): Likewise.
* tests/test-ir-walker.cc (main): Likewise.
* tests/test-read-ctf.cc (test_task_ctf::perform): Likewise.
* tests/test-read-dwarf.cc: Remove the useless "using" statements.
* tests/test-read-write.cc: Likewise.
* tests/test-symtab.cc (read_corpus, TEST_CASE)
(assert_symbol_count): Adjust.
* tests/data/test-read-ctf/test0.abi: Adjust.
* tests/data/test-read-ctf/test0.hash.abi: Likewise.
* tests/data/test-read-ctf/test1.so.abi: Likewise.
* tests/data/test-read-ctf/test1.so.hash.abi: Likewise.
* tests/data/test-read-ctf/test2.so.abi: Likewise.
* tests/data/test-read-ctf/test2.so.hash.abi: Likewise.
* tests/data/test-read-ctf/test3.so.abi: Likewise.
* tests/data/test-read-ctf/test3.so.hash.abi: Likewise.
* tests/data/test-read-ctf/test4.so.abi: Likewise.
* tests/data/test-read-ctf/test4.so.hash.abi: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-15 16:26:37 +00:00
|
|
|
c2 = dwarf::read_corpus_from_elf(opts.elf2, di_roots, env,
|
|
|
|
/*load_all_types=*/false,
|
|
|
|
c2_status);
|
|
|
|
if (c2_status != fe_iface::STATUS_OK)
|
Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
{
|
|
|
|
cerr << "Failed to read elf file " << opts.elf2 << "\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
corpus_diff_sptr diff = compute_diff(c1, c2);
|
|
|
|
if (!diff)
|
|
|
|
{
|
|
|
|
cerr << "Could not compute ABI diff between elf files "
|
|
|
|
<< opts.elf1 << " and " << opts.elf2;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts.categorize_redundancy)
|
|
|
|
categorize_redundancy(diff);
|
|
|
|
|
|
|
|
if (opts.apply_filters)
|
|
|
|
apply_filters(diff);
|
|
|
|
|
|
|
|
print_diff_tree(diff, cout);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
print_diff_tree(abigail::comparison::corpus_diff* diff_tree)
|
|
|
|
{
|
|
|
|
print_diff_tree(diff_tree, std::cout);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
print_diff_tree(abigail::comparison::corpus_diff_sptr diff_tree)
|
|
|
|
{
|
|
|
|
print_diff_tree(diff_tree, std::cout);
|
|
|
|
}
|