Support symbol_name_not_regexp in [suppress_{function, variable}]

In the suppress_function and suppress_variable directives of the
suppression specification language, we lack the
'symbol_name_not_regexp' properties, that would allow users to specify
which (function/variable) symbols to *keep* as opposed to specifying
which symbols to suppress.

This patch adds that feature.  That will later allow us to make the
linux kernel symbol white lists[1] functionality use this feature;
that is, upon analysing the content of a kernel symbol whitelist which
lists a symbol named "foo", Libabigail would automatically generate a
suppression specification which contains, e.g a 'suppress_function"
directive that has this new 'symbol_name_not_regexp' property which
value is set to "foo".

Note that the patch makes sure that feature is supported when
analyzing both abixml and DWARF formats.

[1]: You can learn about what a Linux Kernel symbols white list is by
reading about it at
https://sourceware.org/libabigail/manual/kmidiff.html#environment.

	* doc/manuals/libabigail-concepts.rst: Document the new
	symbol_name_not_regexp properties for the
	suppress_{function,variable} directives.
	* include/abg-suppression.h
	({function,variable}_suppression::{g,s}et_symbol_name_not_regex_str):
	Declare new member functions.
	* src/abg-dwarf-reader.cc
	(read_context::is_elf_symbol_suppressed): Define new member functions.
	(read_context::{load_symbol_maps_from_symtab_section,
	populate_symbol_map_from_ksymtab,
	populate_symbol_map_from_ksymtab_reloc}): Drop suppressed symbols
	when reading symbol tables.
	({function,variable}_is_suppressed): Consider that in C, the
	linkage name is _by default_ the same as the function/variable
	name. Remove local variable.
	* include/abg-ir.h (elf_symbol_is_{function,variable}): Add ...
	* src/abg-ir.cc (elf_symbol_is_{function,variable}): ... new
	functions.
	* src/abg-reader.cc (build_elf_symbol): Take an additional boolean
	to detect and drop suppressed symbols.
	(build_elf_symbol_db): Adjust the call to build_elf_symbol to make
	it detect and drop suppressed symbols.
	(read_corpus_from_input): Be mindful that the set of symbols for a
	given corpus can be empty because of suppression specifications.
	* src/abg-suppression-priv.h
	({function,variable}_suppression::priv::symbol_name_not_regex[_str_]):
	Add new data members.
	(function,variable}_suppression::priv::get_symbol_name_not_regex):
	Add new member functions.
	({function,variable}_is_suppressed): Guard against empty name.
	(is_elf_symbol_suppressed): Define new function template.
	* src/abg-suppression.cc
	({function,variable}_suppression::{g,s}et_symbol_name_not_regex_str):
	Define new member functions.
	({function,variable}_suppression::suppresses_function)
	(suppression_matches_{function,variable}_sym_name)
	(read_{function,variable}_suppression): Support the new
	"symbol_name_not_regex" property.
	* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-1.txt:
	New test reference report.
	* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-2.txt:
	Likewise.
	* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v{0,1}.c:
	Sources of the new test input.
	* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v{0,1}.o:
	New test input binaries.
	* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v{0,1}.o.abi:
	New test input abixml files.
	* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp.suppr.txt:
	Next test suppression specification.
	* tests/data/Makefile.am: Add the new test material above to
	source distribution.
	* tests/test-diff-suppr.cc (in_out_specs): Add the input tests
	above to the test harness.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2019-10-18 10:13:41 +02:00
parent e0484f7c19
commit b00976517f
19 changed files with 450 additions and 25 deletions

View File

@ -601,7 +601,8 @@ one of the following properties must be provided:
``label``, ``file_name_regexp``, ``file_name_not_regexp``,
``soname_regexp``, ``soname_not_regexp``, ``name``, ``name_regexp``,
``name_not_regexp``, ``parameter``, ``return_type_name``,
``symbol_name``, ``symbol_name_regexp``, ``symbol_version``,
``symbol_name``, ``symbol_name_regexp``,
``symbol_name_not_regexp``,``symbol_version``,
``symbol_version_regexp``.
If none of the following properties are provided, then the
@ -830,6 +831,15 @@ The potential properties of this sections are:
the aliases of the function for the directive to actually suppress
the diff reports for said function.
* ``symbol_name_not_regexp``
Usage:
``symbol_name_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>
Suppresses change reports involving functions whose symbol name does
not match the regular expression specified as value of this property.
* ``symbol_version``
Usage:
@ -879,8 +889,8 @@ one of the following properties must be provided:
``label``, ``file_name_regexp``, ``file_name_not_regexp``,
``soname_regexp``, ``soname_not_regexp``, ``name``, ``name_regexp``,
``symbol_name``, ``symbol_name_regexp``, ``symbol_version``,
``symbol_version_regexp``.
``symbol_name``, ``symbol_name_regexp``, ``symbol_name_not_regexp``,
``symbol_version``, ``symbol_version_regexp``.
If none of the following properties are provided, then the
``[suppres_variable]`` directive is simply ignored.
@ -988,6 +998,15 @@ The potential properties of this sections are:
matches the regular expression specified as value of this property.
* ``symbol_name_not_regexp``
Usage:
``symbol_name_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>
Suppresses change reports involving variables whose symbol name does
not match the regular expression specified as value of this property.
* ``symbol_version``
Usage:

View File

@ -992,6 +992,12 @@ string_to_elf_symbol_binding(const string&, elf_symbol::binding&);
bool
string_to_elf_symbol_visibility(const string&, elf_symbol::visibility&);
bool
elf_symbol_is_function(elf_symbol::type);
bool
elf_symbol_is_variable(elf_symbol::type);
bool
operator==(const elf_symbol_sptr& lhs, const elf_symbol_sptr& rhs);

View File

@ -518,6 +518,12 @@ public:
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;
@ -707,6 +713,12 @@ public:
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;

View File

@ -7385,6 +7385,10 @@ public:
ABG_ASSERT(symbol);
ABG_ASSERT(symbol->is_function());
// If the symbol was suppressed by a suppression
// specification then drop it on the floor.
if (is_elf_symbol_suppressed(symbol))
continue;
if (load_fun_map && symbol->is_public())
{
@ -7850,6 +7854,21 @@ public:
return nb_ksymtab_gpl_entries_;
}
/// Test if a given ELF symbol was suppressed by a suppression
/// specification.
///
/// @param symbol the ELF symbol to consider.
///
/// @return true iff @p symbol is suppressed.
bool
is_elf_symbol_suppressed(const elf_symbol_sptr& symbol) const
{
return (symbol
&& suppr::is_elf_symbol_suppressed(*this,
symbol->get_name(),
symbol->get_type()));
}
/// Populate the symbol map by reading exported symbols from the
/// ksymtab directly.
///
@ -7939,6 +7958,11 @@ public:
continue;
}
// If the symbol was suppressed by a suppression
// specification then drop it on the floor.
if (is_elf_symbol_suppressed(symbol))
continue;
address_set_sptr set;
if (symbol->is_function())
{
@ -8031,6 +8055,11 @@ public:
continue;
}
// If the symbol was suppressed by a suppression
// specification then drop it on the floor.
if (is_elf_symbol_suppressed(symbol))
continue;
// If we are looking at an ET_REL (relocatable) binary, then
// the symbol value of native_symbol is relative to the
// section that symbol is defined in. We need to translate it
@ -16477,13 +16506,14 @@ function_is_suppressed(const read_context& ctxt,
string fname = die_string_attribute(function_die, DW_AT_name);
string flinkage_name = die_linkage_name(function_die);
if (flinkage_name.empty() && ctxt.die_is_in_c(function_die))
flinkage_name = fname;
string qualified_name = build_qualified_name(scope, fname);
// A non-member function which symbol is not exported is suppressed.
if (!is_class_type(scope) && !die_is_declaration_only(function_die))
{
Dwarf_Addr fn_addr;
elf_symbol_sptr fn_sym;
if (!ctxt.get_function_address(function_die, fn_addr))
return true;
if (!get_ignore_symbol_table(ctxt))
@ -16583,6 +16613,8 @@ variable_is_suppressed(const read_context& ctxt,
string name = die_string_attribute(variable_die, DW_AT_name);
string linkage_name = die_linkage_name(variable_die);
if (linkage_name.empty() && ctxt.die_is_in_c(variable_die))
linkage_name = name;
string qualified_name = build_qualified_name(scope, name);
// If a non member variable that is a declaration (has no exported
@ -16597,7 +16629,6 @@ variable_is_suppressed(const read_context& ctxt,
if (!is_class_type(scope) && !is_required_decl_spec)
{
Dwarf_Addr var_addr = 0;
elf_symbol_sptr var_sym;
if (!ctxt.get_variable_address(variable_die, var_addr))
return true;
if (!get_ignore_symbol_table(ctxt))

View File

@ -2314,6 +2314,26 @@ string_to_elf_symbol_visibility(const string& s, elf_symbol::visibility& v)
return true;
}
/// Test if the type of an ELF symbol denotes a function symbol.
///
/// @param t the type of the ELF symbol.
///
/// @return true iff elf symbol type @p t denotes a function symbol
/// type.
bool
elf_symbol_is_function(elf_symbol::type t)
{return t == elf_symbol::FUNC_TYPE;}
/// Test if the type of an ELF symbol denotes a function symbol.
///
/// @param t the type of the ELF symbol.
///
/// @return true iff elf symbol type @p t denotes a function symbol
/// type.
bool
elf_symbol_is_variable(elf_symbol::type t)
{return t == elf_symbol::OBJECT_TYPE;}
// <elf_symbol::version stuff>
struct elf_symbol::version::priv

View File

@ -1093,7 +1093,7 @@ build_namespace_decl(read_context&, const xmlNodePtr, bool);
// below.
static elf_symbol_sptr
build_elf_symbol(read_context&, const xmlNodePtr);
build_elf_symbol(read_context&, const xmlNodePtr, bool);
static elf_symbol_sptr
build_elf_symbol_from_reference(read_context&, const xmlNodePtr,
@ -1882,7 +1882,9 @@ read_corpus_from_input(read_context& ctxt)
bool is_ok = read_symbol_db_from_input(ctxt, fn_sym_db, var_sym_db);
if (is_ok)
{
ABG_ASSERT(fn_sym_db || var_sym_db);
// Note that it's possible that both fn_sym_db and var_sym_db
// are nil, due to potential suppression specifications. That's
// fine.
if (fn_sym_db)
{
corp.set_fun_symbol_map(fn_sym_db);
@ -2592,9 +2594,13 @@ build_namespace_decl(read_context& ctxt,
///
/// @param node the XML node to read.
///
/// @param drop_if_suppressed if the elf symbol was suppressed by a
/// suppression specification then do not build it.
///
/// @return the @ref elf_symbol built, or nil if it couldn't be built.
static elf_symbol_sptr
build_elf_symbol(read_context& ctxt, const xmlNodePtr node)
build_elf_symbol(read_context& ctxt, const xmlNodePtr node,
bool drop_if_suppressed)
{
elf_symbol_sptr nil;
@ -2657,6 +2663,9 @@ build_elf_symbol(read_context& ctxt, const xmlNodePtr node)
elf_symbol::version version(version_string, is_default_version);
if (drop_if_suppressed && suppr::is_elf_symbol_suppressed(ctxt, name, type))
return elf_symbol_sptr();
const environment* env = ctxt.get_environment();
elf_symbol_sptr e = elf_symbol::create(env, /*index=*/0,
size, name, type, binding,
@ -2758,7 +2767,7 @@ build_elf_symbol_db(read_context& ctxt,
elf_symbol_sptr sym;
for (xmlNodePtr n = node->children; n; n = n->next)
{
if ((sym = build_elf_symbol(ctxt, n)))
if ((sym = build_elf_symbol(ctxt, n, /*drop_if_suppress=*/true)))
{
id_sym_map[sym->get_id_string()] = sym;
xml_node_ptr_elf_symbol_map[n] = sym;

View File

@ -272,6 +272,8 @@ struct function_suppression::priv
string symbol_name_;
string symbol_name_regex_str_;
mutable sptr_utils::regex_t_sptr symbol_name_regex_;
string symbol_name_not_regex_str_;
mutable sptr_utils::regex_t_sptr symbol_name_not_regex_;
string symbol_version_;
string symbol_version_regex_str_;
mutable sptr_utils::regex_t_sptr symbol_version_regex_;
@ -397,6 +399,29 @@ struct function_suppression::priv
return symbol_name_regex_;
}
/// Getter for a pointer to a regular expression object built from
/// the regular expression string
/// function_suppression::priv::symbol_name_not_regex_str_.
///
/// If that string is empty, then an empty regular expression object
/// pointer is returned.
///
/// @return a pointer to the regular expression object of
/// function_suppression::priv::symbol_name_not_regex_str_.
const sptr_utils::regex_t_sptr
get_symbol_name_not_regex() const
{
if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
{
sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
if (regcomp(r.get(),
symbol_name_not_regex_str_.c_str(),
REG_EXTENDED) == 0)
symbol_name_not_regex_ = r;
}
return symbol_name_not_regex_;
}
/// Getter for a pointer to a regular expression object built from
/// the regular expression string
/// function_suppression::priv::symbol_version_regex_str_.
@ -474,10 +499,12 @@ function_is_suppressed(const ReadContextType& ctxt,
{
if (require_drop_property && !(*i)->get_drops_artifact_from_ir())
continue;
if (ctxt.suppression_matches_function_name(*suppr, fn_name))
if (!fn_name.empty()
&& ctxt.suppression_matches_function_name(*suppr, fn_name))
return true;
if (ctxt.suppression_matches_function_sym_name(*suppr,
fn_linkage_name))
if (!fn_linkage_name.empty()
&& ctxt.suppression_matches_function_sym_name(*suppr,
fn_linkage_name))
return true;
}
return false;
@ -500,6 +527,8 @@ struct variable_suppression::priv
string symbol_name_;
string symbol_name_regex_str_;
mutable sptr_utils::regex_t_sptr symbol_name_regex_;
string symbol_name_not_regex_str_;
mutable sptr_utils::regex_t_sptr symbol_name_not_regex_;
string symbol_version_;
string symbol_version_regex_str_;
mutable sptr_utils::regex_t_sptr symbol_version_regex_;
@ -595,6 +624,28 @@ struct variable_suppression::priv
return symbol_name_regex_;
}
/// Getter for a pointer to a regular expression object built from
/// the regular expression string
/// variable_suppression::priv::symbol_name_not_regex_str_.
///
/// If that string is empty, then an empty regular expression object
/// pointer is returned.
///
/// @return a pointer to the regular expression object of
/// variable_suppression::priv::symbol_name_not_regex_str_.
const sptr_utils::regex_t_sptr
get_symbol_name_not_regex() const
{
if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
{
sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
if (regcomp(r.get(), symbol_name_not_regex_str_.c_str(),
REG_EXTENDED == 0) == 0)
symbol_name_not_regex_ = r;
}
return symbol_name_not_regex_;
}
/// Getter for a pointer to a regular expression object built from
/// the regular expression string
/// variable_suppression::priv::symbol_version_regex_str_.
@ -657,10 +708,12 @@ variable_is_suppressed(const ReadContextType& ctxt,
{
if (require_drop_property && !(*i)->get_drops_artifact_from_ir())
continue;
if (ctxt.suppression_matches_variable_name(*suppr, var_name))
if (!var_name.empty()
&& ctxt.suppression_matches_variable_name(*suppr, var_name))
return true;
if (ctxt.suppression_matches_variable_sym_name(*suppr,
var_linkage_name))
if (!var_linkage_name.empty()
&& ctxt.suppression_matches_variable_sym_name(*suppr,
var_linkage_name))
return true;
}
return false;
@ -915,6 +968,33 @@ type_is_suppressed(const ReadContextType& ctxt,
return false;
}
/// Test if a given ELF symbol is suppressed by a suppression
/// specification.
///
/// @param ctxt the read context to use.
///
/// @param sym_name the name of the symbol to consider.
///
/// @param sym_type the type of the symbol to consider.
///
/// @return true iff the elf symbol denoted by @p sym_name and @p
/// sym_type is suppressed.
template<typename ReadContextType>
bool
is_elf_symbol_suppressed(const ReadContextType& ctxt,
const string& sym_name,
elf_symbol::type sym_type)
{
if (elf_symbol_is_function(sym_type))
return suppr::function_is_suppressed(ctxt, /*fn_name=*/"",
/*symbol_name=*/sym_name);
else if (elf_symbol_is_variable(sym_type))
return suppr::variable_is_suppressed(ctxt, /*var_name=*/"",
/*symbol_name=*/sym_name);
return false;
}
// </type_suppression stuff>
}// end namespace suppr

View File

@ -2265,6 +2265,45 @@ void
function_suppression::set_symbol_name_regex_str(const string& r)
{priv_->symbol_name_regex_str_ = r;}
/// Getter for a regular expression for a family of names of symbols
/// of functions the user wants this specification to designate.
///
/// If a symbol name is matched by this regular expression, then the
/// suppression specification will *NOT* suppress the symbol.
///
/// If the symbol name as returned by
/// function_suppression::get_symbol_name() is not empty, then this
/// property is ignored at specification evaluation time.
///
/// This property might be empty, in which case it's ignored at
/// evaluation time.
///
/// @return the regular expression string for a family of names of
/// symbols that is to be *NOT* suppressed by this suppression specification.
const string&
function_suppression::get_symbol_name_not_regex_str() const
{return priv_->symbol_name_not_regex_str_;}
/// Setter for a regular expression for a family of names of symbols
/// of functions the user wants this specification to designate.
///
/// If a symbol name is matched by this regular expression, then the
/// suppression specification will *NOT* suppress the symbol.
///
/// If the symbol name as returned by
/// function_suppression::get_symbol_name() is not empty, then this
/// property is ignored at specification evaluation time.
///
/// This property might be empty, in which case it's ignored at
/// evaluation time.
///
/// @param the new regular expression string for a family of names of
/// symbols that is to be *NOT* suppressed by this suppression
/// specification.
void
function_suppression::set_symbol_name_not_regex_str(const string& r)
{priv_->symbol_name_not_regex_str_ = r;}
/// Getter for the name of the version of the symbol of the function
/// the user wants this specification to designate.
///
@ -2522,8 +2561,8 @@ function_suppression::suppresses_function(const function_decl* fn,
return false;
}
// Check if the "symbol_name" and "symbol_name_regexp" properties
// match.
// Check if the "symbol_name", "symbol_name_regexp", and
// "symbol_name_not_regexp" properties match.
string fn_sym_name, fn_sym_version;
elf_symbol_sptr sym = fn->get_symbol();
if (sym)
@ -2562,6 +2601,14 @@ function_suppression::suppresses_function(const function_decl* fn,
0, NULL, 0) != 0))
return false;
const sptr_utils::regex_t_sptr symbol_name_not_regex =
priv_->get_symbol_name_not_regex();
if (symbol_name_not_regex
&& (regexec(symbol_name_not_regex.get(),
fn_sym_name.c_str(),
0, NULL, 0) == 0))
return false;
if (get_allow_other_aliases())
{
// In this case, we want to allow the suppression of change
@ -2572,11 +2619,19 @@ function_suppression::suppresses_function(const function_decl* fn,
for (elf_symbol_sptr a = sym->get_next_alias();
a && !a->is_main_symbol();
a = a->get_next_alias())
if (symbol_name_regex
&& (regexec(symbol_name_regex.get(),
a->get_name().c_str(),
0, NULL, 0) != 0))
return false;
{
if (symbol_name_regex
&& (regexec(symbol_name_regex.get(),
a->get_name().c_str(),
0, NULL, 0) != 0))
return false;
if (symbol_name_not_regex
&& (regexec(symbol_name_not_regex.get(),
a->get_name().c_str(),
0, NULL, 0) == 0))
return false;
}
}
}
}
@ -2875,6 +2930,11 @@ suppression_matches_function_sym_name(const suppr::function_suppression& s,
if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) != 0)
return false;
}
else if (sptr_utils::regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
{
if (regexec(regexp.get(), fn_linkage_name.c_str(), 0, NULL, 0) == 0)
return false;
}
else if (s.priv_->symbol_name_.empty())
return false;
else // if (!s.priv_->symbol_name_.empty())
@ -2937,6 +2997,12 @@ suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) != 0)
return false;
}
else if (sptr_utils::regex_t_sptr regexp =
s.priv_->get_symbol_name_not_regex())
{
if (regexec(regexp.get(), var_linkage_name.c_str(), 0, NULL, 0) == 0)
return false;
}
else if (s.priv_->symbol_name_.empty())
return false;
else // if (!s.priv_->symbol_name_.empty())
@ -3149,6 +3215,12 @@ read_function_suppression(const ini::config::section& section)
? sym_name_regex_prop->get_value()->as_string()
: "";
ini::simple_property_sptr sym_name_not_regex_prop =
is_simple_property(section.find_property("symbol_name_not_regexp"));
string sym_name_not_regex_str = sym_name_not_regex_prop
? sym_name_not_regex_prop->get_value()->as_string()
: "";
ini::simple_property_sptr sym_ver_prop =
is_simple_property(section.find_property("symbol_version"));
string sym_version = sym_ver_prop
@ -3195,6 +3267,7 @@ read_function_suppression(const ini::config::section& section)
|| !return_type_regex_str.empty()
|| !sym_name.empty()
|| !sym_name_regex_str.empty()
|| !sym_name_not_regex_str.empty()
|| !sym_version.empty()
|| !sym_ver_regex_str.empty()
|| !parms.empty())
@ -3213,7 +3286,8 @@ read_function_suppression(const ini::config::section& section)
|| !name_regex_str.empty()
|| !name_not_regex_str.empty()
|| !sym_name.empty()
|| !sym_name_regex_str.empty()))
|| !sym_name_regex_str.empty()
|| !sym_name_not_regex_str.empty()))
result->set_drops_artifact_from_ir(true);
if (result && !change_kind_str.empty())
@ -3227,6 +3301,9 @@ read_function_suppression(const ini::config::section& section)
if (!name_not_regex_str.empty())
result->set_name_not_regex_str(name_not_regex_str);
if (!sym_name_not_regex_str.empty())
result->set_symbol_name_not_regex_str(sym_name_not_regex_str);
if (!file_name_regex_str.empty())
result->set_file_name_regex_str(file_name_regex_str);
@ -3458,6 +3535,45 @@ void
variable_suppression::set_symbol_name_regex_str(const string& r)
{priv_->symbol_name_regex_str_ = r;}
/// Getter for a regular expression for a family of names of symbols
/// of variables the user wants this specification to designate.
///
/// If a symbol name is matched by this regular expression, then the
/// suppression specification will *NOT* suppress the symbol.
///
/// If the symbol name as returned by
/// variable_suppression::get_symbol_name() is not empty, then this
/// property is ignored at specification evaluation time.
///
/// This property might be empty, in which case it's ignored at
/// evaluation time.
///
/// @return the regular expression string for a family of names of
/// symbols that is to be *NOT* suppressed by this suppression specification.
const string&
variable_suppression::get_symbol_name_not_regex_str() const
{return priv_->symbol_name_not_regex_str_;}
/// Setter for a regular expression for a family of names of symbols
/// of variables the user wants this specification to designate.
///
/// If a symbol name is matched by this regular expression, then the
/// suppression specification will *NOT* suppress the symbol.
///
/// If the symbol name as returned by
/// variable_suppression::get_symbol_name() is not empty, then this
/// property is ignored at specification evaluation time.
///
/// This property might be empty, in which case it's ignored at
/// evaluation time.
///
/// @param the new regular expression string for a family of names of
/// symbols that is to be *NOT* suppressed by this suppression
/// specification.
void
variable_suppression::set_symbol_name_not_regex_str(const string& r)
{priv_->symbol_name_not_regex_str_ = r;}
/// Getter for the version of the symbol of the variable the user
/// wants the current specification to designate. This property might
/// be empty, in which case it's ignored at evaluation time.
@ -3637,7 +3753,8 @@ variable_suppression::suppresses_variable(const var_decl* var,
}
}
// Check for the symbol_name property match.
// Check for the symbol_name, symbol_name_regex and
// symbol_name_not_regex property match.
string var_sym_name = var->get_symbol() ? var->get_symbol()->get_name() : "";
if (!get_symbol_name().empty())
{
@ -3652,6 +3769,13 @@ variable_suppression::suppresses_variable(const var_decl* var,
&& (regexec(sym_name_regex.get(), var_sym_name.c_str(),
0, NULL, 0) != 0))
return false;
const sptr_utils::regex_t_sptr sym_name_not_regex =
priv_->get_symbol_name_not_regex();
if (sym_name_not_regex
&& (regexec(sym_name_not_regex.get(), var_sym_name.c_str(),
0, NULL, 0) == 0))
return false;
}
// Check for symbol_version and symbol_version_regexp property match
@ -3965,6 +4089,12 @@ read_variable_suppression(const ini::config::section& section)
? sym_name_regex_prop->get_value()->as_string()
: "";
ini::simple_property_sptr sym_name_not_regex_prop =
is_simple_property(section.find_property("symbol_name_not_regexp"));
string symbol_name_not_regex_str = sym_name_not_regex_prop
? sym_name_not_regex_prop->get_value()->as_string()
: "";
ini::simple_property_sptr sym_version_prop =
is_simple_property(section.find_property("symbol_version"));
string symbol_version = sym_version_prop
@ -3999,6 +4129,7 @@ read_variable_suppression(const ini::config::section& section)
&& soname_not_regex_str.empty()
&& symbol_name.empty()
&& symbol_name_regex_str.empty()
&& symbol_name_not_regex_str.empty()
&& symbol_version.empty()
&& symbol_version_regex_str.empty()
&& type_name_str.empty()
@ -4015,12 +4146,16 @@ read_variable_suppression(const ini::config::section& section)
|| !name_regex_str.empty()
|| !name_not_regex_str.empty()
|| !symbol_name.empty()
|| !symbol_name_regex_str.empty()))
|| !symbol_name_regex_str.empty()
|| !symbol_name_not_regex_str.empty()))
result->set_drops_artifact_from_ir(true);
if (!name_not_regex_str.empty())
result->set_name_not_regex_str(name_not_regex_str);
if (!symbol_name_not_regex_str.empty())
result->set_symbol_name_not_regex_str(symbol_name_not_regex_str);
if (result && !change_kind_str.empty())
result->set_change_kind
(variable_suppression::parse_change_kind(change_kind_str));

View File

@ -1224,6 +1224,15 @@ test-diff-suppr/test43-suppr-direct-fn-subtype-v0.o \
test-diff-suppr/test43-suppr-direct-fn-subtype-v1.cc \
test-diff-suppr/test43-suppr-direct-fn-subtype-v1.o \
test-diff-suppr/test43-suppr-direct-fn-subtype-report-1.txt \
test-diff-suppr/test44-suppr-sym-name-not-regexp-report-1.txt \
test-diff-suppr/test44-suppr-sym-name-not-regexp-report-2.txt \
test-diff-suppr/test44-suppr-sym-name-not-regexp-v0.c \
test-diff-suppr/test44-suppr-sym-name-not-regexp-v0.o \
test-diff-suppr/test44-suppr-sym-name-not-regexp-v0.o.abi \
test-diff-suppr/test44-suppr-sym-name-not-regexp-v1.c \
test-diff-suppr/test44-suppr-sym-name-not-regexp-v1.o \
test-diff-suppr/test44-suppr-sym-name-not-regexp-v1.o.abi \
test-diff-suppr/test44-suppr-sym-name-not-regexp.suppr.txt \
\
test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1 \
test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1.abi \

View File

@ -0,0 +1,11 @@
Functions changes summary: 1 Removed, 0 Changed, 0 Added function
Variables changes summary: 1 Removed, 0 Changed, 0 Added variable
1 Removed function:
'function void test2()' {test2}
1 Removed variable:
'char test2_variable' {test2_variable}

View File

@ -0,0 +1,3 @@
Functions changes summary: 0 Removed (1 filtered out), 0 Changed, 0 Added function
Variables changes summary: 0 Removed (1 filtered out), 0 Changed, 0 Added variable

View File

@ -0,0 +1,4 @@
int test1_variable = 0;
char test2_variable = 0;
void test1(){};
void test2(){};

View File

@ -0,0 +1,23 @@
<abi-corpus path='test44-suppr-sym-name-not-regexp-v0.o' architecture='elf-amd-x86_64'>
<elf-function-symbols>
<elf-symbol name='test1' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='test2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
<elf-variable-symbols>
<elf-symbol name='test1_variable' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='test2_variable' size='1' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-variable-symbols>
<abi-instr version='1.0' address-size='64' path='test44-suppr-sym-name-not-regexp-v0.c' comp-dir-path='/home/dodji/git/libabigail/PR25095/tests/data/test-diff-suppr' language='LANG_C99'>
<type-decl name='char' size-in-bits='8' id='type-id-1'/>
<type-decl name='int' size-in-bits='32' id='type-id-2'/>
<type-decl name='void' id='type-id-3'/>
<var-decl name='test1_variable' type-id='type-id-2' mangled-name='test1_variable' visibility='default' filepath='/home/dodji/git/libabigail/PR25095/tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v0.c' line='1' column='1' elf-symbol-id='test1_variable'/>
<var-decl name='test2_variable' type-id='type-id-1' mangled-name='test2_variable' visibility='default' filepath='/home/dodji/git/libabigail/PR25095/tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v0.c' line='2' column='1' elf-symbol-id='test2_variable'/>
<function-decl name='test2' mangled-name='test2' filepath='/home/dodji/git/libabigail/PR25095/tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v0.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='test2'>
<return type-id='type-id-3'/>
</function-decl>
<function-decl name='test1' mangled-name='test1' filepath='/home/dodji/git/libabigail/PR25095/tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v0.c' line='3' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='test1'>
<return type-id='type-id-3'/>
</function-decl>
</abi-instr>
</abi-corpus>

View File

@ -0,0 +1,2 @@
int test1_variable = 0;
void test1(){};

View File

@ -0,0 +1,16 @@
<abi-corpus path='test44-suppr-sym-name-not-regexp-v1.o' architecture='elf-amd-x86_64'>
<elf-function-symbols>
<elf-symbol name='test1' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
<elf-variable-symbols>
<elf-symbol name='test1_variable' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-variable-symbols>
<abi-instr version='1.0' address-size='64' path='test44-suppr-sym-name-not-regexp-v1.c' comp-dir-path='/home/dodji/git/libabigail/PR25095/tests/data/test-diff-suppr' language='LANG_C99'>
<type-decl name='int' size-in-bits='32' id='type-id-1'/>
<type-decl name='void' id='type-id-2'/>
<var-decl name='test1_variable' type-id='type-id-1' mangled-name='test1_variable' visibility='default' filepath='/home/dodji/git/libabigail/PR25095/tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v1.c' line='1' column='1' elf-symbol-id='test1_variable'/>
<function-decl name='test1' mangled-name='test1' filepath='/home/dodji/git/libabigail/PR25095/tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v1.c' line='2' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='test1'>
<return type-id='type-id-2'/>
</function-decl>
</abi-instr>
</abi-corpus>

View File

@ -0,0 +1,5 @@
[suppress_function]
symbol_name_not_regexp = test1
[suppress_variable]
symbol_name_not_regexp = test1_variable

View File

@ -1778,6 +1778,46 @@ InOutSpec in_out_specs[] =
"data/test-diff-suppr/test43-suppr-direct-fn-subtype-report-1.txt",
"output/test-diff-suppr/test43-suppr-direct-fn-subtype-report-1.txt"
},
{
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v0.o",
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v1.o",
"",
"",
"",
"--no-default-suppression",
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-1.txt",
"output/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-1.txt"
},
{
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v0.o",
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v1.o",
"",
"",
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp.suppr.txt",
"--no-default-suppression",
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-2.txt",
"output/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-2.txt"
},
{
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v0.o.abi",
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v1.o.abi",
"",
"",
"",
"--no-default-suppression",
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-1.txt",
"output/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-1.txt"
},
{
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v0.o.abi",
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v1.o.abi",
"",
"",
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp.suppr.txt",
"--no-default-suppression",
"data/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-2.txt",
"output/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-2.txt"
},
// This should be the last entry
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
};