mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-14 22:14:35 +00:00
Support Linux Kernel ABI whitelist files
Enterprise Linux (at least) kernels come with ABI whitelist files that list the names of the set of functions to be considered when looking at the ABI exposed by the kernel to its modules. This patch adds a new --linux-kernel-abi-whitelist option to abidiff so that it drops changes that relate to functions that are *NOT* defined in the whitelist. The patch reads the whitelist file and generates one or several instances of function_suppression that are applied when the two binaries are loaded. * include/abg-suppression.h (function_suppression::function_suppression): Make the declaration of the default constructor public. * src/abg-suppression-priv.h (function_suppression::priv::priv): Declare a default constructor. * src/abg-suppression.cc (function_suppression::function_suppression): Define default constructor. * include/abg-tools-utils.h (gen_suppr_spec_from_kernel_abi_whitelist): Declare new function. * src/abg-tools-utils.cc (gen_suppr_spec_from_kernel_abi_whitelist): Define new function. * tools/abidiff.cc (options::kernel_abi_whitelist_paths): (display_usage): Display a help string for the new --linux-kernel-abi-whitelist option. (parse_command_line): Parse the --linux-kernel-abi-whitelist from the command line. (maybe_check_suppression_files): Check the presence of the kernel abi whitelist files. (set_suppressions): Generate suppression specifications from the whitelist files. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
parent
fadfa1a6f6
commit
08e760221b
@ -401,9 +401,6 @@ class function_suppression : public suppression_base
|
|||||||
struct priv;
|
struct priv;
|
||||||
typedef shared_ptr<priv> priv_sptr;
|
typedef shared_ptr<priv> priv_sptr;
|
||||||
|
|
||||||
// Forbid this.
|
|
||||||
function_suppression();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
priv_sptr priv_;
|
priv_sptr priv_;
|
||||||
@ -435,6 +432,8 @@ public:
|
|||||||
| DELETED_FUNCTION_CHANGE_KIND)
|
| DELETED_FUNCTION_CHANGE_KIND)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function_suppression();
|
||||||
|
|
||||||
function_suppression(const string& label,
|
function_suppression(const string& label,
|
||||||
const string& name,
|
const string& name,
|
||||||
const string& name_regex,
|
const string& name_regex,
|
||||||
|
@ -60,6 +60,10 @@ bool string_is_ascii_identifier(const string&);
|
|||||||
suppr::type_suppression_sptr
|
suppr::type_suppression_sptr
|
||||||
gen_suppr_spec_from_headers(const string& hdrs_root_dir);
|
gen_suppr_spec_from_headers(const string& hdrs_root_dir);
|
||||||
|
|
||||||
|
bool
|
||||||
|
gen_suppr_spec_from_kernel_abi_whitelist(const string& abi_whitelist_path,
|
||||||
|
suppr::suppressions_type& s);
|
||||||
|
|
||||||
string
|
string
|
||||||
get_default_system_suppression_file_path();
|
get_default_system_suppression_file_path();
|
||||||
|
|
||||||
|
@ -277,6 +277,11 @@ struct function_suppression::priv
|
|||||||
mutable sptr_utils::regex_t_sptr symbol_version_regex_;
|
mutable sptr_utils::regex_t_sptr symbol_version_regex_;
|
||||||
bool allow_other_aliases_;
|
bool allow_other_aliases_;
|
||||||
|
|
||||||
|
priv():
|
||||||
|
change_kind_(ALL_CHANGE_KIND),
|
||||||
|
allow_other_aliases_(true)
|
||||||
|
{}
|
||||||
|
|
||||||
priv(const string& name,
|
priv(const string& name,
|
||||||
const string& name_regex_str,
|
const string& name_regex_str,
|
||||||
const string& return_type_name,
|
const string& return_type_name,
|
||||||
|
@ -1816,6 +1816,15 @@ function_suppression::parameter_spec::set_parameter_type_name_regex_str
|
|||||||
(const string& type_name_regex_str)
|
(const string& type_name_regex_str)
|
||||||
{priv_->type_name_regex_str_ = type_name_regex_str;}
|
{priv_->type_name_regex_str_ = type_name_regex_str;}
|
||||||
|
|
||||||
|
/// Default constructor for the @ref function_suppression type.
|
||||||
|
///
|
||||||
|
/// It defines no suppression for now. Suppressions have to be
|
||||||
|
/// specified by using the various accessors of the @ref
|
||||||
|
/// function_suppression type.
|
||||||
|
function_suppression::function_suppression()
|
||||||
|
: suppression_base(/*label=*/""), priv_(new priv)
|
||||||
|
{}
|
||||||
|
|
||||||
/// Constructor for the @ref function_suppression type.
|
/// Constructor for the @ref function_suppression type.
|
||||||
///
|
///
|
||||||
/// @param label an informative text string that the evalution code
|
/// @param label an informative text string that the evalution code
|
||||||
|
@ -50,6 +50,7 @@ namespace abigail
|
|||||||
{
|
{
|
||||||
|
|
||||||
using namespace abigail::suppr;
|
using namespace abigail::suppr;
|
||||||
|
using namespace abigail::ini;
|
||||||
|
|
||||||
/// @brief Namespace for a set of utility function used by tools based
|
/// @brief Namespace for a set of utility function used by tools based
|
||||||
/// on libabigail.
|
/// on libabigail.
|
||||||
@ -888,6 +889,84 @@ gen_suppr_spec_from_headers(const string& headers_root_dir)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate a suppression specification from kernel abi whitelist
|
||||||
|
/// files.
|
||||||
|
///
|
||||||
|
/// A kernel ABI whitelist file is an INI file that usually has only
|
||||||
|
/// one section. The name of the section is a string that ends up
|
||||||
|
/// with the sub-string "whitelist". For instance
|
||||||
|
/// RHEL7_x86_64_whitelist.
|
||||||
|
///
|
||||||
|
/// Then the content of the section is a set of function names, one
|
||||||
|
/// name per line. Each function names is the name of a function
|
||||||
|
/// whose changes are to be keept.
|
||||||
|
///
|
||||||
|
/// This function reads the white list and generate
|
||||||
|
/// function_suppression_sptr (or several, if there are more than one
|
||||||
|
/// section) that is added to a vector of suppressions.
|
||||||
|
///
|
||||||
|
/// @param abi_whitelist_path the path to the Kernel ABI whitelist.
|
||||||
|
///
|
||||||
|
/// @param supprs the resulting vector of suppressions to which the
|
||||||
|
/// new function suppressions resulting from reading the whitelist are
|
||||||
|
/// added. This vector is updated iff the function returns true.
|
||||||
|
///
|
||||||
|
/// @return true iff the abi whitelist file was read and function
|
||||||
|
/// suppressions could be generated as a result.
|
||||||
|
bool
|
||||||
|
gen_suppr_spec_from_kernel_abi_whitelist(const string& abi_whitelist_path,
|
||||||
|
suppressions_type& supprs)
|
||||||
|
{
|
||||||
|
config whitelist;
|
||||||
|
if (!read_config(abi_whitelist_path, whitelist))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool created_a_suppr = false;
|
||||||
|
|
||||||
|
const config::sections_type &whitelist_sections = whitelist.get_sections();
|
||||||
|
for (config::sections_type::const_iterator s =
|
||||||
|
whitelist_sections.begin();
|
||||||
|
s != whitelist_sections.end();
|
||||||
|
++s)
|
||||||
|
{
|
||||||
|
string section_name = (*s)->get_name();
|
||||||
|
if (!string_ends_with(section_name, "whitelist"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
function_suppression_sptr suppr;
|
||||||
|
string function_names_regexp;
|
||||||
|
for (config::properties_type::const_iterator p =
|
||||||
|
(*s)->get_properties().begin();
|
||||||
|
p != (*s)->get_properties().end();
|
||||||
|
++p)
|
||||||
|
{
|
||||||
|
if (simple_property_sptr prop = is_simple_property(*p))
|
||||||
|
if (prop->has_empty_value())
|
||||||
|
{
|
||||||
|
const string &function_name = prop->get_name();
|
||||||
|
if (!function_name.empty())
|
||||||
|
{
|
||||||
|
if (!function_names_regexp.empty())
|
||||||
|
function_names_regexp += "|";
|
||||||
|
function_names_regexp += "^" + function_name + "$";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_names_regexp.empty())
|
||||||
|
{
|
||||||
|
suppr.reset(new function_suppression);
|
||||||
|
suppr->set_label(section_name);
|
||||||
|
suppr->set_name_not_regex_str(function_names_regexp);
|
||||||
|
suppr->set_drops_artifact_from_ir(true);
|
||||||
|
supprs.push_back(suppr);
|
||||||
|
created_a_suppr = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return created_a_suppr;
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the path to the default system suppression file.
|
/// Get the path to the default system suppression file.
|
||||||
///
|
///
|
||||||
/// @return a copy of the default system suppression file.
|
/// @return a copy of the default system suppression file.
|
||||||
|
@ -56,6 +56,7 @@ using abigail::tools_utils::emit_prefix;
|
|||||||
using abigail::tools_utils::check_file;
|
using abigail::tools_utils::check_file;
|
||||||
using abigail::tools_utils::guess_file_type;
|
using abigail::tools_utils::guess_file_type;
|
||||||
using abigail::tools_utils::gen_suppr_spec_from_headers;
|
using abigail::tools_utils::gen_suppr_spec_from_headers;
|
||||||
|
using abigail::tools_utils::gen_suppr_spec_from_kernel_abi_whitelist;
|
||||||
using abigail::tools_utils::load_default_system_suppressions;
|
using abigail::tools_utils::load_default_system_suppressions;
|
||||||
using abigail::tools_utils::load_default_user_suppressions;
|
using abigail::tools_utils::load_default_user_suppressions;
|
||||||
using abigail::tools_utils::abidiff_status;
|
using abigail::tools_utils::abidiff_status;
|
||||||
@ -69,6 +70,7 @@ struct options
|
|||||||
string file1;
|
string file1;
|
||||||
string file2;
|
string file2;
|
||||||
vector<string> suppression_paths;
|
vector<string> suppression_paths;
|
||||||
|
vector<string> kernel_abi_whitelist_paths;
|
||||||
vector<string> drop_fn_regex_patterns;
|
vector<string> drop_fn_regex_patterns;
|
||||||
vector<string> drop_var_regex_patterns;
|
vector<string> drop_var_regex_patterns;
|
||||||
vector<string> keep_fn_regex_patterns;
|
vector<string> keep_fn_regex_patterns;
|
||||||
@ -151,6 +153,8 @@ display_usage(const string& prog_name, ostream& out)
|
|||||||
"internal representation\n"
|
"internal representation\n"
|
||||||
<< " --no-linux-kernel-mode don't consider the input binaries as "
|
<< " --no-linux-kernel-mode don't consider the input binaries as "
|
||||||
"linux kernel binaries\n"
|
"linux kernel binaries\n"
|
||||||
|
<< " --linux-kernel-abi-whitelist|--lkaw path to a "
|
||||||
|
"linux kernel abi whitelist\n"
|
||||||
<< " --stat only display the diff stats\n"
|
<< " --stat only display the diff stats\n"
|
||||||
<< " --symtabs only display the symbol tables of the corpora\n"
|
<< " --symtabs only display the symbol tables of the corpora\n"
|
||||||
<< " --no-default-suppression don't load any "
|
<< " --no-default-suppression don't load any "
|
||||||
@ -280,8 +284,19 @@ parse_command_line(int argc, char* argv[], options& opts)
|
|||||||
opts.headers_dir2 = argv[j];
|
opts.headers_dir2 = argv[j];
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else if (!strcmp(argv[i], "--no-linux-kernel-mode"))
|
else if (!strcmp(argv[i], "--linux-kernel-abi-whitelist")
|
||||||
opts.linux_kernel_mode = false;
|
|| !strcmp(argv[i], "--lkaw"))
|
||||||
|
{
|
||||||
|
int j = i + 1;
|
||||||
|
if (j >= argc)
|
||||||
|
{
|
||||||
|
opts.missing_operand = true;
|
||||||
|
opts.wrong_option = argv[i];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
opts.kernel_abi_whitelist_paths.push_back(argv[j]);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
else if (!strcmp(argv[i], "--stat"))
|
else if (!strcmp(argv[i], "--stat"))
|
||||||
opts.show_stats_only = true;
|
opts.show_stats_only = true;
|
||||||
else if (!strcmp(argv[i], "--symtabs"))
|
else if (!strcmp(argv[i], "--symtabs"))
|
||||||
@ -533,6 +548,13 @@ maybe_check_suppression_files(const options& opts)
|
|||||||
if (!check_file(*i, cerr, "abidiff"))
|
if (!check_file(*i, cerr, "abidiff"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
for (vector<string>::const_iterator i =
|
||||||
|
opts.kernel_abi_whitelist_paths.begin();
|
||||||
|
i != opts.kernel_abi_whitelist_paths.end();
|
||||||
|
++i)
|
||||||
|
if (!check_file(*i, cerr, "abidiff"))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -673,7 +695,13 @@ set_suppressions(ReadContextType& read_ctxt, const options& opts)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add_read_context_suppressions(read_ctxt, supprs);
|
for (vector<string>::const_iterator i =
|
||||||
|
opts.kernel_abi_whitelist_paths.begin();
|
||||||
|
i != opts.kernel_abi_whitelist_paths.end();
|
||||||
|
++i)
|
||||||
|
gen_suppr_spec_from_kernel_abi_whitelist(*i, supprs);
|
||||||
|
|
||||||
|
add_read_context_suppressions(read_ctxt, supprs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the regex patterns describing the functions to drop from the
|
/// Set the regex patterns describing the functions to drop from the
|
||||||
|
Loading…
Reference in New Issue
Block a user