mirror of
git://sourceware.org/git/libabigail.git
synced 2025-01-18 07:11:03 +00:00
dbae53ec30
By default, using abidw --abidiff on the binary /usr/lib64/libwebkit2gtk-4.0.so.37 on the ppc64le platform takes more than 50GB of RAM and ooms on my system. That is why a number of suppression specifications have been put in place in the default.abignore file that is installed by default on the system. With that suppression specification however, abidw --abidiff hits an assert and crashes. That is because the suppression specification rule below is too eager and thus removes parameters from some function's signature, in the final internal representation: [suppress_type] soname_regexp = libwebkit2?gtk-.*\\.so.* name_regexp = (^std::.*|WebCore::.*|WebKit::.*) drop = true An example of function signature that got changed (in the IR) because of this suppression specification is: This function signature: WebKitAuthenticationScheme webkit_authentication_request_get_scheme(WebKitAuthenticationRequest*) becomes (after applying the suppression specification above): void webkit_authentication_request_get_scheme() Woops. That is not good. To address that problem, this patch changes that suppression specification to make libabigail transform those types into opaque types. An opaque struct, class or enum is essentially a declaration-only type of the same kind and name. So the suppression specification above becomes: [suppress_type] # Drop all standard c++ types on the floor like before. soname_regexp = libwebkit2?gtk-.*\\.so.* name_regexp = ^std::.* drop = true [suppress_type] # Transform all C++ types in the WebCore and WebKit namespaces into # opaque types. These are essentially internal types of libwebkit2 # anyway. This greatly reduces the size of the in-memory working set. label = libabigail::OPAQUE_TYPE_LABEL soname_regexp = libwebkit2?gtk-.*\\.so.* name_regexp = (WebCore::.*|WebKit::.*) drop = true Notice the introduction of the new special label "libabigail::OPAQUE_TYPE_LABEL". This new special label is what makes the suppression engine of libabigail transform a type (that matches that suppression specification) into an opaque type, rather than dropping it on the floor. The patch then adapts the code of the suppression engine to detect this special label for the purpose of transforming types into opaque types. The patch normalizes the use of the term "opaque type" instead of "private type" that was used previously in the code. The patch fixes a bug in the code of get_opaque_version_of_type that prevents this function from working on types with no location information. While working on this, I have noticed that the abipkgdiff has a bug that was making it ignore suppression specifications provided via the --suppression option. The patch fixes that. I have noticed that abipkgdiff --self-check completely ignores all suppression specifications provided either via --suppression or indirectly via devel packages. The patch fixes that. Last but not least, fedabipkgdiff --self-compare completely ignores suppression specifications too! The patch fixes that as well. With all those fixes, the system now takes around 7GB of RAM and ~ 30 minutes to complete the analysis of the webkit2gtk3 package, using a non-optimized libabigail build. The command I use is: $ time tools/fedabipkgdiff --debug --self-compare --abipkgdiff build/tools/abipkgdiff --suppressions default.abignore -a --from fc39 webkit2gtk3 [...] [DEBUG] Result from run_abipkgdiff: 0, in: 0:29:00.088735 [DEBUG] Result from self_compare_rpms_from_distro: 0, in: 0:29:20.721748 real 29m20,846s user 29m4,561s sys 2m41,611s $ The culprit package was webkit2gtk3-2.40.1-1.fc36.ppc64le.rpm. To reproduce the issue on that package, I do: $ time ~/git/libabigail/rhbz2273891/build/tools/abipkgdiff --self-check --suppr ~/git/libabigail/rhbz2273891/default.abignore --d1 webkit2gtk3-debuginfo-2.40.1-1.fc36.ppc64le.rpm --devel1 webkit2gtk3-devel-2.40.1-1.fc36.ppc64le.rpm webkit2gtk3-2.40.1-1.fc36.ppc64le.rpm ==== SELF CHECK SUCCEEDED for 'libwebkit2gtk-4.0.so.37.63.2' ==== ==== SELF CHECK SUCCEEDED for 'WebKitWebDriver' ==== ==== SELF CHECK SUCCEEDED for 'WebKitNetworkProcess' ==== ==== SELF CHECK SUCCEEDED for 'WebKitWebProcess' ==== real 8m25,895s user 8m46,433s sys 0m15,683s $ * default.abignore: Split the libwebkit2gtk suppression specification for types whose names match the regexp ^std::.*|WebCore::.*|WebKit::.* into two. One that drops type with names being ^std::.* and another one that turns type being WebCore::.*|WebKit::.* into opaque types. * doc/manuals/libabigail-concepts.rst: Add documentation for the new special label libabigail::OPAQUE_TYPE_LABEL that transforms types matching a [suppress_type] into opaque types. * include/abg-suppression.h (is_opaque_type_suppr_spec): Renamed is_private_type_suppr_spec into this. (get_opaque_types_suppr_spec_label): Renamed get_private_types_suppr_spec_label. * src/abg-comparison.cc (diff::is_suppressed): Adjust. * src/abg-dwarf-reader.cc (type_is_suppressed): Adjust. Change the name of the type_is_private parameter into type_is_opaque. (get_opaque_version_of_type): Do not return early if the type has no associated location. What was I thinking. (build_ir_node_from_die): For enums, struct and classes adjust call to type_is_suppressed. * src/abg-suppression.cc (type_suppression::suppresses_diff): Adjust to using is_opaque_type_suppr_spec and get_opaque_version_of_type in lieu of is_private_type_suppr_spec and get_private_types_suppr_spec_label. (get_opaque_types_suppr_spec_label): Rename get_private_types_suppr_spec_label into this. Also, rename the name of the special label that specifies opaque types from "Artificial private types suppression specification" to "libabigail::OPAQUE_TYPE_LABEL". (is_opaque_type_suppr_spec): Rename is_private_type_suppr_spec into this. (is_type_suppressed): Rename the "type_is_private" parameter into "type_is_opaque". * src/abg-tools-utils.cc (handle_file_entry): Adjust to using get_opaque_types_suppr_spec_label rather than get_private_types_suppr_spec_label. * tools/abipkgdiff.cc (compare): Use the supprs variable where all the suppression specifications got accumulated, not just the priv_types_supprs1. (compare_to_self): Add a suppression specifications variable for private types. Add those private types specs to the user-provided ones. * tools/fedabipkgdiff (abipkgdiff): In the self comparison mode, take into account devel packages and suppression specifications. Pass those to the abipkgdiff tool's invocation. * tests/data/test-diff-suppr/PR31646/test-PR31646-result-[1-3].txt: New reference test output files. * tests/data/test-diff-suppr/PR31646/test-PR31646-v{0,1}.cc: Source code of binary inputs below. * tests/data/test-diff-suppr/PR31646/test-PR31646-v{0,1}.o: Binary input files. * tests/data/test-diff-suppr/PR31646/test-PR31646.2.abignore: Suppression specification file. * tests/data/test-diff-suppr/PR31646/test-PR31646.abignore: Likewise. * tests/data/Makefile.am: Add the new test material above to source distribution. * tests/test-diff-suppr.cc (in_out_specs): Add the new test input to this harness. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
1029 lines
25 KiB
C++
1029 lines
25 KiB
C++
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
// -*- Mode: C++ -*-
|
|
//
|
|
// Copyright (C) 2016-2023 Red Hat, Inc.
|
|
//
|
|
// Author: Dodji Seketeli
|
|
|
|
#ifndef __ABG_SUPPRESSION_H__
|
|
#define __ABG_SUPPRESSION_H__
|
|
|
|
#include <unordered_set>
|
|
|
|
#include "abg-ini.h"
|
|
#include "abg-ir.h"
|
|
|
|
namespace abigail
|
|
{
|
|
|
|
class fe_iface;
|
|
|
|
/// @brief an engine to suppress the parts of the result of comparing
|
|
/// two sets of ABI artifacts.
|
|
///
|
|
/// The user specifies the kind of changes between ABI artefact she
|
|
/// wants to see suppressed. That suppression specification is done
|
|
/// in an INI format.
|
|
///
|
|
/// That INI file is parsed and represented internally using the types
|
|
/// that are defined in this namespace.
|
|
namespace suppr
|
|
{
|
|
using std::unordered_set;
|
|
using std::string;
|
|
using std::shared_ptr;
|
|
using std::vector;
|
|
using comparison::diff;
|
|
using comparison::diff_context_sptr;
|
|
|
|
/// Base type of a direct suppression specifications types.
|
|
///
|
|
/// This abstracts a suppression specification. It's a way to specify
|
|
/// how to drop reports about a particular diff node on the floor, if
|
|
/// it matches the supppression specification.
|
|
///
|
|
/// Note that a direct suppression specification suppresses (for
|
|
/// reporting purposes) the diff node that it matches. A negated
|
|
/// suppression specification, however, suppresses a diff node that it
|
|
/// DOES NOT match. A Negated suppression specification is abstracted
|
|
/// by the class @ref negated_suppression_base.
|
|
class suppression_base
|
|
{
|
|
public:
|
|
class priv; // declare publicly to allow subclasses to reuse the priv
|
|
private:
|
|
// Forbid default constructor
|
|
suppression_base();
|
|
|
|
public:
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
suppression_base(const string& label);
|
|
|
|
suppression_base(const string& label,
|
|
const string& file_name_regex_str,
|
|
const string& file_name_not_regex_str);
|
|
|
|
bool
|
|
get_drops_artifact_from_ir() const;
|
|
|
|
void
|
|
set_drops_artifact_from_ir(bool);
|
|
|
|
bool
|
|
get_is_artificial() const;
|
|
|
|
void
|
|
set_is_artificial(bool);
|
|
|
|
const string
|
|
get_label() const;
|
|
|
|
void
|
|
set_label(const string&);
|
|
|
|
void
|
|
set_file_name_regex_str(const string& regexp);
|
|
|
|
const string&
|
|
get_file_name_regex_str() const;
|
|
|
|
void
|
|
set_file_name_not_regex_str(const string& regexp);
|
|
|
|
const string&
|
|
get_file_name_not_regex_str() const;
|
|
|
|
bool
|
|
has_file_name_related_property() const;
|
|
|
|
void
|
|
set_soname_regex_str(const string& regexp);
|
|
|
|
const string&
|
|
get_soname_regex_str() const;
|
|
|
|
void
|
|
set_soname_not_regex_str(const string& regexp);
|
|
|
|
const string&
|
|
get_soname_not_regex_str() const;
|
|
|
|
bool
|
|
has_soname_related_property() const;
|
|
|
|
virtual bool
|
|
suppresses_diff(const diff*) const = 0;
|
|
|
|
virtual ~suppression_base();
|
|
|
|
friend bool
|
|
suppression_matches_soname(const string& soname,
|
|
const suppression_base& suppr);
|
|
|
|
friend bool
|
|
suppression_matches_soname_or_filename(const string& soname,
|
|
const string& filename,
|
|
const suppression_base& suppr);
|
|
}; // end class suppression_base
|
|
|
|
/// Convenience typedef for a shared pointer to a @ref suppression.
|
|
typedef shared_ptr<suppression_base> suppression_sptr;
|
|
|
|
/// Convenience typedef for a vector of @ref suppression_sptr
|
|
typedef vector<suppression_sptr> suppressions_type;
|
|
|
|
void
|
|
read_suppressions(std::istream& input,
|
|
suppressions_type& suppressions);
|
|
|
|
void
|
|
read_suppressions(const string& file_path,
|
|
suppressions_type& suppressions);
|
|
|
|
class type_suppression;
|
|
|
|
/// Convenience typedef for a shared pointer to type_suppression.
|
|
typedef shared_ptr<type_suppression> type_suppression_sptr;
|
|
|
|
/// Convenience typedef for vector of @ref type_suppression_sptr.
|
|
typedef vector<type_suppression_sptr> type_suppressions_type;
|
|
|
|
/// The base class of suppression specifications that are defined by
|
|
/// the negation of matching clauses.
|
|
///
|
|
/// A direct suppression specification suppresses (for reporting
|
|
/// purposes) the diff node that it matches. A negated suppression
|
|
/// specification suppresses a diff node that it DOES NOT match.
|
|
class negated_suppression_base
|
|
{
|
|
public:
|
|
negated_suppression_base();
|
|
|
|
virtual ~negated_suppression_base();
|
|
}; // end class negated_suppression_base.
|
|
|
|
/// A convenience typedef for a shared pointer to @ref
|
|
/// negated_suppression_base.
|
|
typedef shared_ptr<negated_suppression_base> negated_suppression_sptr;
|
|
|
|
/// Convenience typedef for a vector of @ref negated_suppression_sptr
|
|
typedef vector<negated_suppression_sptr> negated_suppressions_type;
|
|
|
|
bool
|
|
is_negated_suppression(const suppression_base&);
|
|
|
|
const negated_suppression_base*
|
|
is_negated_suppression(const suppression_base*);
|
|
|
|
negated_suppression_sptr
|
|
is_negated_suppression(const suppression_sptr&);
|
|
|
|
/// Abstraction of a type suppression specification.
|
|
///
|
|
/// Specifies under which condition reports about a type diff node
|
|
/// should be dropped on the floor.
|
|
class type_suppression : public suppression_base
|
|
{
|
|
class priv;
|
|
|
|
// Forbid this;
|
|
type_suppression();
|
|
|
|
public:
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
/// The kind of the type the current type suppression is supposed to
|
|
/// be about.
|
|
enum type_kind
|
|
{
|
|
UNKNOWN_TYPE_KIND,
|
|
CLASS_TYPE_KIND,
|
|
STRUCT_TYPE_KIND,
|
|
UNION_TYPE_KIND,
|
|
ENUM_TYPE_KIND,
|
|
ARRAY_TYPE_KIND,
|
|
TYPEDEF_TYPE_KIND,
|
|
BUILTIN_TYPE_KIND
|
|
}; // end enum type_kind
|
|
|
|
/// The different ways through which the type diff has been reached.
|
|
enum reach_kind
|
|
{
|
|
/// The type diff has been reached (from a function or variable
|
|
/// change) directly.
|
|
DIRECT_REACH_KIND = 0,
|
|
|
|
/// The type diff has been reached (from a function or variable
|
|
/// change) through a pointer.
|
|
POINTER_REACH_KIND,
|
|
|
|
/// The type diff has been reached (from a function or variable
|
|
/// change) through a reference; you know, like a c++ reference..
|
|
REFERENCE_REACH_KIND,
|
|
|
|
/// The type diff has been reached (from a function or variable
|
|
/// change) through either a reference or a pointer.
|
|
REFERENCE_OR_POINTER_REACH_KIND
|
|
}; // end enum reach_kind
|
|
|
|
class insertion_range;
|
|
/// A convenience typedef for a shared pointer to @ref
|
|
/// insertion_range.
|
|
typedef shared_ptr<insertion_range> insertion_range_sptr;
|
|
/// A convenience typedef for a vector of @ref insertion_range_sptr.
|
|
typedef vector<insertion_range_sptr> insertion_ranges;
|
|
|
|
type_suppression(const string& label,
|
|
const string& type_name_regexp,
|
|
const string& type_name);
|
|
|
|
virtual ~type_suppression();
|
|
|
|
void
|
|
set_type_name_regex_str(const string& name_regex_str);
|
|
|
|
const string&
|
|
get_type_name_regex_str() const;
|
|
|
|
void
|
|
set_type_name_not_regex_str(const string& name_regex_str);
|
|
|
|
const string&
|
|
get_type_name_not_regex_str() const;
|
|
|
|
void
|
|
set_type_name(const string& name);
|
|
|
|
const string&
|
|
get_type_name() const;
|
|
|
|
bool
|
|
get_consider_type_kind() const;
|
|
|
|
void
|
|
set_consider_type_kind(bool f);
|
|
|
|
void
|
|
set_type_kind(type_kind k);
|
|
|
|
type_kind
|
|
get_type_kind() const;
|
|
|
|
bool
|
|
get_consider_reach_kind() const;
|
|
|
|
void
|
|
set_consider_reach_kind(bool f);
|
|
|
|
reach_kind
|
|
get_reach_kind() const;
|
|
|
|
void
|
|
set_reach_kind(reach_kind k);
|
|
|
|
bool
|
|
get_has_size_change() const;
|
|
|
|
void
|
|
set_has_size_change(bool flag);
|
|
|
|
const string_set_type&
|
|
get_potential_data_member_names() const;
|
|
|
|
void
|
|
set_potential_data_member_names(const string_set_type&) const;
|
|
|
|
const string&
|
|
get_potential_data_member_names_regex_str() const;
|
|
|
|
void
|
|
set_potential_data_member_names_regex_str(const string&) const;
|
|
|
|
void
|
|
set_data_member_insertion_ranges(const insertion_ranges& r);
|
|
|
|
const insertion_ranges&
|
|
get_data_member_insertion_ranges() const;
|
|
|
|
insertion_ranges&
|
|
get_data_member_insertion_ranges();
|
|
|
|
const unordered_set<string>&
|
|
get_source_locations_to_keep() const;
|
|
|
|
unordered_set<string>&
|
|
get_source_locations_to_keep();
|
|
|
|
void
|
|
set_source_locations_to_keep(const unordered_set<string>&);
|
|
|
|
const string&
|
|
get_source_location_to_keep_regex_str() const;
|
|
|
|
void
|
|
set_source_location_to_keep_regex_str(const string&);
|
|
|
|
const vector<string>&
|
|
get_changed_enumerator_names() const;
|
|
|
|
void
|
|
set_changed_enumerator_names(const vector<string>&);
|
|
|
|
const vector<regex::regex_t_sptr>&
|
|
get_changed_enumerators_regexp() const;
|
|
|
|
void
|
|
set_changed_enumerators_regexp(const vector<regex::regex_t_sptr>&);
|
|
|
|
bool
|
|
has_strict_fam_conversion () const;
|
|
|
|
void
|
|
set_has_strict_fam_conversion(bool);
|
|
|
|
virtual bool
|
|
suppresses_diff(const diff* diff) const;
|
|
|
|
bool
|
|
suppresses_type(const type_base_sptr& type,
|
|
const diff_context_sptr& ctxt) const;
|
|
|
|
bool
|
|
suppresses_type(const type_base_sptr& type) const;
|
|
|
|
bool
|
|
suppresses_type(const type_base_sptr& type,
|
|
const scope_decl* type_scope) const;
|
|
}; // end type_suppression
|
|
|
|
type_suppression_sptr
|
|
is_type_suppression(const suppression_sptr);
|
|
|
|
/// The abstraction of a range of offsets in which a member of a type
|
|
/// might get inserted.
|
|
class type_suppression::insertion_range
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
public:
|
|
|
|
class boundary;
|
|
class integer_boundary;
|
|
class fn_call_expr_boundary;
|
|
class named_boundary;
|
|
|
|
/// Convenience typedef for a shared_ptr to @ref boundary
|
|
typedef shared_ptr<boundary> boundary_sptr;
|
|
|
|
/// Convenience typedef for a shared_ptr to a @ref integer_boundary
|
|
typedef shared_ptr<integer_boundary> integer_boundary_sptr;
|
|
|
|
/// Convenience typedef for a shared_ptr to a @ref
|
|
/// fn_call_expr_boundary
|
|
typedef shared_ptr<fn_call_expr_boundary> fn_call_expr_boundary_sptr;
|
|
|
|
/// Convenience typedef for a shared_ptr to a @ref
|
|
/// named_boundary
|
|
typedef shared_ptr<named_boundary> named_boundary_sptr;
|
|
|
|
insertion_range();
|
|
|
|
insertion_range(boundary_sptr begin, boundary_sptr end);
|
|
|
|
boundary_sptr
|
|
begin() const;
|
|
|
|
boundary_sptr
|
|
end() const;
|
|
|
|
static insertion_range::integer_boundary_sptr
|
|
create_integer_boundary(int value);
|
|
|
|
static insertion_range::fn_call_expr_boundary_sptr
|
|
create_fn_call_expr_boundary(ini::function_call_expr_sptr);
|
|
|
|
static insertion_range::fn_call_expr_boundary_sptr
|
|
create_fn_call_expr_boundary(const string&);
|
|
|
|
static insertion_range::named_boundary_sptr
|
|
create_named_boundary(const string&);
|
|
|
|
static bool
|
|
eval_boundary(const boundary_sptr boundary,
|
|
const class_or_union* context,
|
|
uint64_t& value);
|
|
|
|
static bool
|
|
boundary_value_is_end(uint64_t value);
|
|
}; // end class insertion_range
|
|
|
|
type_suppression::insertion_range::integer_boundary_sptr
|
|
is_integer_boundary(type_suppression::insertion_range::boundary_sptr);
|
|
|
|
type_suppression::insertion_range::fn_call_expr_boundary_sptr
|
|
is_fn_call_expr_boundary(type_suppression::insertion_range::boundary_sptr);
|
|
|
|
type_suppression::insertion_range::named_boundary_sptr
|
|
is_named_boundary(type_suppression::insertion_range::boundary_sptr);
|
|
|
|
/// The abstraction of the boundary of an @ref insertion_range, in the
|
|
/// context of a @ref type_suppression
|
|
class type_suppression::insertion_range::boundary
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
public:
|
|
boundary();
|
|
virtual ~boundary();
|
|
};// end class type_suppression::insertion_range::boundary
|
|
|
|
/// An @ref insertion_range boundary that is expressed as an integer
|
|
/// value. That integer value is usually a bit offset.
|
|
class type_suppression::insertion_range::integer_boundary
|
|
: public type_suppression::insertion_range::boundary
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
integer_boundary();
|
|
|
|
public:
|
|
integer_boundary(uint64_t value);
|
|
uint64_t as_integer() const;
|
|
operator uint64_t () const;
|
|
~integer_boundary();
|
|
}; //end class type_suppression::insertion_range::integer_boundary
|
|
|
|
/// An @ref insertion_range boundary that is expressed as function
|
|
/// call expression. The (integer) value of that expression is
|
|
/// usually a bit offset.
|
|
class type_suppression::insertion_range::fn_call_expr_boundary
|
|
: public type_suppression::insertion_range::boundary
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
fn_call_expr_boundary();
|
|
|
|
public:
|
|
fn_call_expr_boundary(ini::function_call_expr_sptr expr);
|
|
ini::function_call_expr_sptr as_function_call_expr() const;
|
|
operator ini::function_call_expr_sptr () const;
|
|
~fn_call_expr_boundary();
|
|
}; //end class type_suppression::insertion_range::fn_call_expr_boundary
|
|
|
|
/// An @ref insertion_range boundary that is expressed as a named
|
|
/// constant that is to be evaluated later in the context of a given
|
|
/// type and resolved to a bit offset.
|
|
class type_suppression::insertion_range::named_boundary
|
|
: public type_suppression::insertion_range::boundary
|
|
{
|
|
struct priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
named_boundary();
|
|
|
|
public:
|
|
named_boundary(const string& name);
|
|
const string& get_name() const;
|
|
}; //end class type_suppression::insertion_range::named_boundary
|
|
|
|
/// Abstraction of a negated type suppression specification.
|
|
///
|
|
/// A negated type suppression suppresses a type if the negation of
|
|
/// the equivalent propositions for a @ref type_suppression are valid.
|
|
class negated_type_suppression : virtual public type_suppression,
|
|
virtual public negated_suppression_base
|
|
{
|
|
|
|
public:
|
|
|
|
negated_type_suppression(const string& label,
|
|
const string& type_name_regexp,
|
|
const string& type_name);
|
|
|
|
virtual bool
|
|
suppresses_diff(const diff* diff) const;
|
|
|
|
bool
|
|
suppresses_type(const type_base_sptr& type,
|
|
const diff_context_sptr& ctxt) const;
|
|
|
|
bool
|
|
suppresses_type(const type_base_sptr& type) const;
|
|
|
|
bool
|
|
suppresses_type(const type_base_sptr& type,
|
|
const scope_decl* type_scope) const;
|
|
|
|
virtual ~negated_type_suppression();
|
|
};// end class negated_type_suppression
|
|
|
|
class function_suppression;
|
|
|
|
/// Convenience typedef for a shared pointer to function_suppression.
|
|
typedef shared_ptr<function_suppression> function_suppression_sptr;
|
|
|
|
/// Convenience typedef for a vector of @ref function_suppression_sptr.
|
|
typedef vector<function_suppression_sptr> function_suppressions_type;
|
|
|
|
/// Abstraction of a function suppression specification.
|
|
///
|
|
/// Specifies under which condition reports about a @ref
|
|
/// function_decl_diff diff node should be dropped on the floor for
|
|
/// the purpose of reporting.
|
|
class function_suppression : public suppression_base
|
|
{
|
|
struct priv;
|
|
|
|
public:
|
|
|
|
std::unique_ptr<priv> priv_;
|
|
class parameter_spec;
|
|
|
|
/// Convenience typedef for shared_ptr of @ref parameter_spec.
|
|
typedef shared_ptr<parameter_spec> parameter_spec_sptr;
|
|
|
|
/// Convenience typedef for vector of @ref parameter_spec_sptr.
|
|
typedef vector<parameter_spec_sptr> parameter_specs_type;
|
|
|
|
/// The kind of change the current function suppression should apply
|
|
/// to.
|
|
enum change_kind
|
|
{
|
|
UNDEFINED_CHANGE_KIND,
|
|
/// A change in a sub-type of the function.
|
|
FUNCTION_SUBTYPE_CHANGE_KIND = 1,
|
|
/// The function was added to the second subject of the diff.
|
|
ADDED_FUNCTION_CHANGE_KIND = 1 << 1,
|
|
/// The function was deleted from the second subject of the diff.
|
|
DELETED_FUNCTION_CHANGE_KIND = 1 << 2,
|
|
/// This represents all the changes possibly described by this
|
|
/// enum. It's a logical 'OR' of all the change enumerators
|
|
/// above.
|
|
ALL_CHANGE_KIND = (FUNCTION_SUBTYPE_CHANGE_KIND
|
|
| ADDED_FUNCTION_CHANGE_KIND
|
|
| DELETED_FUNCTION_CHANGE_KIND)
|
|
};
|
|
|
|
function_suppression();
|
|
|
|
function_suppression(const string& label,
|
|
const string& name,
|
|
const string& name_regex,
|
|
const string& return_type_name,
|
|
const string& return_type_regex,
|
|
parameter_specs_type& parm_specs,
|
|
const string& symbol_name,
|
|
const string& symbol_name_regex,
|
|
const string& symbol_version,
|
|
const string& symbol_version_regex_str);
|
|
|
|
virtual ~function_suppression();
|
|
|
|
static change_kind
|
|
parse_change_kind(const string&);
|
|
|
|
change_kind
|
|
get_change_kind() const;
|
|
|
|
void
|
|
set_change_kind(change_kind k);
|
|
|
|
const string&
|
|
get_name() const;
|
|
|
|
void
|
|
set_name(const string&);
|
|
|
|
const string&
|
|
get_name_regex_str() const;
|
|
|
|
void
|
|
set_name_regex_str(const string&);
|
|
|
|
const string&
|
|
get_name_not_regex_str() const;
|
|
|
|
void
|
|
set_name_not_regex_str(const string&);
|
|
|
|
const string&
|
|
get_return_type_name() const;
|
|
|
|
void
|
|
set_return_type_name(const string&);
|
|
|
|
const string&
|
|
get_return_type_regex_str() const;
|
|
|
|
void
|
|
set_return_type_regex_str(const string& r);
|
|
|
|
const parameter_specs_type&
|
|
get_parameter_specs() const;
|
|
|
|
void
|
|
set_parameter_specs(parameter_specs_type&);
|
|
|
|
void
|
|
append_parameter_specs(const parameter_spec_sptr);
|
|
|
|
const string&
|
|
get_symbol_name() const;
|
|
|
|
void
|
|
set_symbol_name(const string& n);
|
|
|
|
const string&
|
|
get_symbol_name_regex_str() const;
|
|
|
|
void
|
|
set_symbol_name_regex_str(const string&);
|
|
|
|
const string&
|
|
get_symbol_name_not_regex_str() const;
|
|
|
|
void
|
|
set_symbol_name_not_regex_str(const string&);
|
|
|
|
const string&
|
|
get_symbol_version() const;
|
|
|
|
void
|
|
set_symbol_version(const string&);
|
|
|
|
const string&
|
|
get_symbol_version_regex_str() const;
|
|
|
|
void
|
|
set_symbol_version_regex_str(const string&);
|
|
|
|
bool
|
|
get_allow_other_aliases() const;
|
|
|
|
void
|
|
set_allow_other_aliases(bool f);
|
|
|
|
virtual bool
|
|
suppresses_diff(const diff* diff) const;
|
|
|
|
bool
|
|
suppresses_function(const function_decl* fn,
|
|
change_kind k,
|
|
const diff_context_sptr ctxt) const;
|
|
|
|
bool
|
|
suppresses_function(const function_decl_sptr fn,
|
|
change_kind k,
|
|
const diff_context_sptr ctxt) const;
|
|
|
|
bool
|
|
suppresses_function_symbol(const elf_symbol* sym,
|
|
change_kind k,
|
|
const diff_context_sptr ctxt);
|
|
|
|
bool
|
|
suppresses_function_symbol(const elf_symbol_sptr sym,
|
|
change_kind k,
|
|
const diff_context_sptr ctxt);
|
|
}; // end class function_suppression.
|
|
|
|
function_suppression_sptr
|
|
is_function_suppression(const suppression_sptr);
|
|
|
|
function_suppression::change_kind
|
|
operator&(function_suppression::change_kind l,
|
|
function_suppression::change_kind r);
|
|
|
|
function_suppression::change_kind
|
|
operator|(function_suppression::change_kind l,
|
|
function_suppression::change_kind r);
|
|
|
|
/// Abstraction of the specification of a function parameter in a
|
|
/// function suppression specification.
|
|
class function_suppression::parameter_spec
|
|
{
|
|
friend class function_suppression;
|
|
|
|
class priv;
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
// Forbid this.
|
|
parameter_spec();
|
|
|
|
public:
|
|
parameter_spec(size_t index,
|
|
const string& type_name,
|
|
const string& type_name_regex);
|
|
|
|
size_t
|
|
get_index() const;
|
|
|
|
void
|
|
set_index(size_t);
|
|
|
|
const string&
|
|
get_parameter_type_name() const;
|
|
|
|
void
|
|
set_parameter_type_name(const string&);
|
|
|
|
const string&
|
|
get_parameter_type_name_regex_str() const;
|
|
|
|
void
|
|
set_parameter_type_name_regex_str(const string&);
|
|
};// end class function_suppression::parameter_spec
|
|
|
|
class variable_suppression;
|
|
|
|
/// A convenience typedef for a shared pointer to @ref
|
|
/// variable_suppression.
|
|
typedef shared_ptr<variable_suppression> variable_suppression_sptr;
|
|
|
|
/// A convenience typedef for a vector of @ref
|
|
/// variable_suppression_sptr.
|
|
typedef vector<variable_suppression_sptr> variable_suppressions_type;
|
|
|
|
/// The abstraction of a variable suppression specification.
|
|
///
|
|
/// It specifies under which condition reports about a @ref var_diff
|
|
/// diff node should be dropped on the floor for the purpose of
|
|
/// reporting.
|
|
class variable_suppression : public suppression_base
|
|
{
|
|
public:
|
|
|
|
/// The kind of change the current variable suppression should apply
|
|
/// to.
|
|
enum change_kind
|
|
{
|
|
UNDEFINED_CHANGE_KIND,
|
|
/// A change in a sub-type of the variable.
|
|
VARIABLE_SUBTYPE_CHANGE_KIND = 1,
|
|
/// The variable was added to the second second subject of the
|
|
/// diff.
|
|
ADDED_VARIABLE_CHANGE_KIND = 1 << 1,
|
|
/// The variable was deleted from the second subject of the diff.
|
|
DELETED_VARIABLE_CHANGE_KIND = 1 << 2,
|
|
/// This represents all the changes possibly described by this
|
|
/// enum. It's a logical 'OR' of all the change enumerators
|
|
/// above.
|
|
ALL_CHANGE_KIND = (VARIABLE_SUBTYPE_CHANGE_KIND
|
|
| ADDED_VARIABLE_CHANGE_KIND
|
|
| DELETED_VARIABLE_CHANGE_KIND)
|
|
};
|
|
|
|
private:
|
|
struct priv;
|
|
|
|
public:
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
variable_suppression(const string& label = "",
|
|
const string& name = "",
|
|
const string& name_regex_str = "",
|
|
const string& symbol_name = "",
|
|
const string& symbol_name_regex_str = "",
|
|
const string& symbol_version = "",
|
|
const string& symbol_version_regex_str = "",
|
|
const string& type_name = "",
|
|
const string& type_name_regex_str = "");
|
|
|
|
virtual ~variable_suppression();
|
|
|
|
static change_kind
|
|
parse_change_kind(const string&);
|
|
|
|
change_kind
|
|
get_change_kind() const;
|
|
|
|
void
|
|
set_change_kind(change_kind k);
|
|
|
|
const string&
|
|
get_name() const;
|
|
|
|
void
|
|
set_name(const string&);
|
|
|
|
const string&
|
|
get_name_regex_str() const;
|
|
|
|
void
|
|
set_name_regex_str(const string&);
|
|
|
|
const string&
|
|
get_name_not_regex_str() const;
|
|
|
|
void
|
|
set_name_not_regex_str(const string&);
|
|
|
|
const string&
|
|
get_symbol_name() const;
|
|
|
|
void
|
|
set_symbol_name(const string&);
|
|
|
|
const string&
|
|
get_symbol_name_regex_str() const;
|
|
|
|
void
|
|
set_symbol_name_regex_str(const string&);
|
|
|
|
const string&
|
|
get_symbol_name_not_regex_str() const;
|
|
|
|
void
|
|
set_symbol_name_not_regex_str(const string&);
|
|
|
|
const string&
|
|
get_symbol_version() const;
|
|
|
|
void
|
|
set_symbol_version(const string&);
|
|
|
|
const string&
|
|
get_symbol_version_regex_str() const;
|
|
|
|
void
|
|
set_symbol_version_regex_str(const string&);
|
|
|
|
const string&
|
|
get_type_name() const;
|
|
|
|
void
|
|
set_type_name(const string&);
|
|
|
|
const string&
|
|
get_type_name_regex_str() const;
|
|
|
|
void
|
|
set_type_name_regex_str(const string&);
|
|
|
|
bool
|
|
suppresses_diff(const diff* d) const;
|
|
|
|
bool
|
|
suppresses_variable(const var_decl* var,
|
|
change_kind k,
|
|
const diff_context_sptr cxt) const;
|
|
|
|
bool
|
|
suppresses_variable(const var_decl_sptr var,
|
|
change_kind k,
|
|
const diff_context_sptr cxt) const;
|
|
|
|
bool
|
|
suppresses_variable_symbol(const elf_symbol* sym,
|
|
change_kind k,
|
|
const diff_context_sptr cxt) const;
|
|
|
|
bool
|
|
suppresses_variable_symbol(const elf_symbol_sptr fn,
|
|
change_kind k,
|
|
const diff_context_sptr cxt) const;
|
|
}; // end class variable_suppression
|
|
|
|
variable_suppression_sptr
|
|
is_variable_suppression(const suppression_sptr);
|
|
|
|
variable_suppression::change_kind
|
|
operator&(variable_suppression::change_kind l,
|
|
variable_suppression::change_kind r);
|
|
|
|
variable_suppression::change_kind
|
|
operator|(variable_suppression::change_kind l,
|
|
variable_suppression::change_kind r);
|
|
|
|
class file_suppression;
|
|
|
|
/// A convenience typedef for a shared_ptr to @ref file_suppression
|
|
typedef shared_ptr<file_suppression> file_suppression_sptr;
|
|
|
|
/// Abstraction of a suppression specification to avoid loading a
|
|
/// file.
|
|
///
|
|
/// This can be used by a tool that loads (binary) files, to know
|
|
/// which file it has to avoid loading.
|
|
class file_suppression: public suppression_base
|
|
{
|
|
std::unique_ptr<priv> priv_;
|
|
|
|
// Forbid this
|
|
file_suppression();
|
|
|
|
public:
|
|
|
|
file_suppression(const string& label,
|
|
const string& file_name_regex,
|
|
const string& file_name_not_regex);
|
|
|
|
virtual bool
|
|
suppresses_diff(const diff* diff) const;
|
|
|
|
bool
|
|
suppresses_file(const string& file_path);
|
|
|
|
virtual ~file_suppression();
|
|
}; // end file_suppression
|
|
|
|
file_suppression_sptr
|
|
is_file_suppression(const suppression_sptr);
|
|
|
|
file_suppression_sptr
|
|
file_is_suppressed(const string& file_path,
|
|
const suppressions_type& suppressions);
|
|
|
|
bool
|
|
suppression_matches_soname(const string& soname,
|
|
const suppression_base& suppr);
|
|
|
|
bool
|
|
suppression_matches_soname_or_filename(const string& soname,
|
|
const string& filename,
|
|
const suppression_base& suppr);
|
|
|
|
const char*
|
|
get_opaque_types_suppr_spec_label();
|
|
|
|
bool
|
|
is_opaque_type_suppr_spec(const type_suppression&);
|
|
|
|
bool
|
|
is_opaque_type_suppr_spec(const suppression_sptr& s);
|
|
|
|
bool
|
|
suppression_can_match(const fe_iface&,
|
|
const suppression_base&);
|
|
|
|
bool
|
|
suppression_matches_function_name(const fe_iface&,
|
|
const suppr::function_suppression&,
|
|
const string&);
|
|
|
|
bool
|
|
suppression_matches_function_sym_name(const fe_iface&,
|
|
const suppr::function_suppression& s,
|
|
const string& fn_linkage_name);
|
|
|
|
bool
|
|
suppression_matches_variable_name(const fe_iface&,
|
|
const suppr::variable_suppression& s,
|
|
const string& var_name);
|
|
|
|
bool
|
|
suppression_matches_variable_sym_name(const fe_iface&,
|
|
const suppr::variable_suppression&,
|
|
const string&);
|
|
|
|
bool
|
|
suppression_matches_type_name_or_location(const fe_iface&,
|
|
const suppr::type_suppression&,
|
|
const string&,
|
|
const location&);
|
|
|
|
bool
|
|
is_elf_symbol_suppressed(const fe_iface&,
|
|
const elf_symbol_sptr& symbol);
|
|
|
|
bool
|
|
is_elf_symbol_suppressed(const fe_iface&,
|
|
const string& sym_name,
|
|
elf_symbol::type sym_type);
|
|
|
|
bool
|
|
is_function_suppressed(const fe_iface& fe,
|
|
const string& fn_name,
|
|
const string& fn_linkage_name,
|
|
bool require_drop_property = false);
|
|
|
|
bool
|
|
is_variable_suppressed(const fe_iface& fe,
|
|
const string& var_name,
|
|
const string& var_linkage_name,
|
|
bool require_drop_property = false);
|
|
|
|
bool
|
|
is_type_suppressed(const fe_iface& fe,
|
|
const string& type_name,
|
|
const location& type_location,
|
|
bool& type_is_private,
|
|
bool require_drop_property = false);
|
|
|
|
bool
|
|
is_data_member_offset_in_range(const var_decl_sptr&,
|
|
const type_suppression::insertion_range_sptr&,
|
|
const class_or_union*);
|
|
|
|
} // end namespace suppr
|
|
|
|
|
|
} // end namespace abigail
|
|
|
|
#endif //__ABG_SUPPRESSION_H__
|