From c15eecc9a05310478aab8205dbcbe2032c6e80f8 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 4 Apr 2017 13:34:56 +0200 Subject: [PATCH] Make abidw support the --kmi-whitelist option When writting out the ABI of a Linux kernel binary we must be able to restrict it to the set of functions and global variables which ELF symbols have names defined in a white list. This patch adds that support, using the --kmi-whitelist option. * tools/abidw.cc (options::{kabi_whitelist_paths, kabi_whitelist_supprs}): New data members. (display_usage): Add a help string for the new --kmi-whitelist option. (parse_command_line): Parse the new --kmi-whitelist option. (maybe_check_suppression_files): Check the presence of the linux kernel abi white list passed by the option --kmi-whitelist. (main): Ignore loading the symbol table if the kernel abi white list is provided. * doc/manuals/abidw.rst: Add documentation for the new option. Signed-off-by: Dodji Seketeli --- doc/manuals/abidw.rst | 23 ++++++++++++++++++++--- tools/abidw.cc | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/doc/manuals/abidw.rst b/doc/manuals/abidw.rst index 1e9c3289..fd9299e1 100644 --- a/doc/manuals/abidw.rst +++ b/doc/manuals/abidw.rst @@ -1,6 +1,4 @@ -====== -abidw -====== +====== abidw ====== abidw reads a shared library in `ELF`_ format and emits an XML representation of its ABI to standard output. The emitted @@ -69,6 +67,25 @@ Options taken into account. ABI artifacts matched by the suppression specifications are suppressed from the output of this tool. + + * ``--kmi-whitelist | -kaw`` <*path-to-whitelist*> + + When analyzing a Linux kernel binary, this option points to the + white list of names of ELF symbols of functions and variables + which ABI must be written out. That white list is called a " + Kernel Module Interface white list". This is because for the + Kernel, we don't talk about the ABI; we rather talk about the + interface between the Kernel and its module. Hence the term + ``KMI`` rather than ``ABI`` + + Any other function or variable which ELF symbol are not present in + that white list will not be considered by the KMI writing process. + + If this option is not provided -- thus if no white list is + provided -- then the entire KMI, that is, all publicly defined and + exported functions and global variables by the Linux Kernel + binaries is emitted. + * ``--headers-dir | --hd`` Specifies where to find the public headers of the first shared diff --git a/tools/abidw.cc b/tools/abidw.cc index ebb2f1e3..863c7c0d 100644 --- a/tools/abidw.cc +++ b/tools/abidw.cc @@ -84,6 +84,8 @@ struct options shared_ptr di_root_path; string headers_dir; vector suppression_paths; + vector kabi_whitelist_paths; + suppressions_type kabi_whitelist_supprs; bool display_version; bool check_alt_debug_info_path; bool show_base_name_alt_debug_info_path; @@ -138,6 +140,8 @@ display_usage(const string& prog_name, ostream& out) "exported declarations\n" << " --no-linux-kernel-mode don't consider the input binary as " "a Linux Kernel binary\n" + << " --kmi-whitelist|-w path to a linux kernel " + "abi whitelist\n" << " --abidiff compare the loaded ABI against itself\n" << " --annotate annotate the ABI artifacts emitted in the output\n" << " --stats show statistics about various internal stuff\n" @@ -203,6 +207,15 @@ parse_command_line(int argc, char* argv[], options& opts) opts.suppression_paths.push_back(argv[j]); ++i; } + else if (!strcmp(argv[i], "--kmi-whitelist") + || !strcmp(argv[i], "-w")) + { + int j = i + 1; + if (j >= argc) + return false; + opts.kabi_whitelist_paths.push_back(argv[j]); + ++i; + } else if (!strcmp(argv[i], "--noout")) opts.noout = true; else if (!strcmp(argv[i], "--no-architecture")) @@ -279,7 +292,14 @@ maybe_check_suppression_files(const options& opts) for (vector::const_iterator i = opts.suppression_paths.begin(); i != opts.suppression_paths.end(); ++i) - if (!check_file(*i, cerr, "abidiff")) + if (!check_file(*i, cerr, "abidw")) + return false; + + for (vector::const_iterator i = + opts.kabi_whitelist_paths.begin(); + i != opts.kabi_whitelist_paths.end(); + ++i) + if (!check_file(*i, cerr, "abidw")) return false; return true; @@ -298,7 +318,7 @@ maybe_check_suppression_files(const options& opts) /// @param opts the options where to get the suppression /// specifications from. static void -set_suppressions(read_context& read_ctxt, const options& opts) +set_suppressions(read_context& read_ctxt, options& opts) { suppressions_type supprs; for (vector::const_iterator i = opts.suppression_paths.begin(); @@ -311,7 +331,15 @@ set_suppressions(read_context& read_ctxt, const options& opts) if (suppr) supprs.push_back(suppr); + using abigail::tools_utils::gen_suppr_spec_from_kernel_abi_whitelist; + for (vector::const_iterator i = + opts.kabi_whitelist_paths.begin(); + i != opts.kabi_whitelist_paths.end(); + ++i) + gen_suppr_spec_from_kernel_abi_whitelist(*i, opts.kabi_whitelist_supprs); + add_read_context_suppressions(read_ctxt, supprs); + add_read_context_suppressions(read_ctxt, opts.kabi_whitelist_supprs); } int @@ -367,6 +395,8 @@ main(int argc, char* argv[]) set_show_stats(ctxt, opts.show_stats); set_suppressions(ctxt, opts); abigail::dwarf_reader::set_do_log(ctxt, opts.do_log); + if (!opts.kabi_whitelist_supprs.empty()) + set_ignore_symbol_table(ctxt, true); if (opts.check_alt_debug_info_path) { @@ -374,7 +404,8 @@ main(int argc, char* argv[]) string alt_di_path; abigail::dwarf_reader::status status = abigail::dwarf_reader::has_alt_debug_info(ctxt, - has_alt_di, alt_di_path); + has_alt_di, + alt_di_path); if (status & abigail::dwarf_reader::STATUS_OK) { if (alt_di_path.empty()) -- 2.43.5