Add --vmlinux{1,2} option to abidw and kmidiff
authorDodji Seketeli <dodji@redhat.com>
Wed, 31 May 2017 07:47:26 +0000 (09:47 +0200)
committerDodji Seketeli <dodji@redhat.com>
Mon, 3 Jul 2017 15:45:45 +0000 (17:45 +0200)
When using abidw to generate an abixml for a Linux Kernel build tree,
usually, people have to copy the vmlinux binary into the directory
where modules are, so that the tool can find it.  This --vmlinux
option helps to avoid doing that copy.

Simarly, when comparing two Linux Kernel build trees, --vmlinux1 and
--vmlinux2 are there to make the tool find the vmlinux binaries to
compare, independantly from the directories under which the modules
are to be found.

* include/abg-tools-utils.h
(build_corpus_group_from_kernel_dist_under): Add a new
vmlinux_path parameter.
* src/abg-tools-utils.cc (find_vmlinux_and_module_paths): Do not
try to find a vmlinux binary if we already have the path to one.
(build_corpus_group_from_kernel_dist_under): Add a new
vmlinux_path parameter.
* tools/abidw.cc (options::vmlinux): New data member.
(display_usage): Add a usage string for --vmlinux
(parse_command_line): Parse the new --vmlinux option.
(load_kernel_corpus_group_and_write_abixml): Fix some return code
when the function fails.  Verify the presence of the vmlinux
binary that was given.  Adjust.
* tools/kmidiff.cc (options::{vmlinux1, vmlinux2}): New data
members.
(display_usage): Add a usage string for --vmlinux1 and --vmlinux2.
(parse_command_line):  Parse the --vmlinux1 and --vmlinux2
options.
(main): Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
include/abg-tools-utils.h
src/abg-tools-utils.cc
tools/abidw.cc
tools/kmidiff.cc

index 703dd2aeff07776d809bad6b240208e129416efa..fcbc3ad5f614a95b6f916a17e538ce36bd07b995 100644 (file)
@@ -251,9 +251,10 @@ std::tr1::shared_ptr<char>
 make_path_absolute(const char*p);
 
 corpus_group_sptr
-build_corpus_group_from_kernel_dist_under(const string&                root,
-                                         vector<string>&               suppr_paths,
-                                         vector<string>&               kabi_wl_paths,
+build_corpus_group_from_kernel_dist_under(const string&        root,
+                                         const string& vmlinux_path,
+                                         vector<string>&       suppr_paths,
+                                         vector<string>&       kabi_wl_paths,
                                          suppr::suppressions_type&     supprs,
                                          bool                          verbose,
                                          environment_sptr&             env);
index 6b45dafdc01476fed7cbfe6a8042c365110c1dd6..a452bdf5b8f817a2ce0e6bd26eab51847ae08ab8 100644 (file)
@@ -1459,7 +1459,7 @@ is_kernel_module(const FTSENT *entry)
 ///
 /// @param vmlinux_path output parameter.  This is set to the path
 /// where the vmlinux binary is found.  This is set iff the returns
-/// true.
+/// true and if this argument was empty to begin with.
 ///
 /// @param module_paths output parameter.  This is set to the paths of
 /// the linux kernel module binaries.
@@ -1476,7 +1476,7 @@ find_vmlinux_and_module_paths(const string&       from,
   if (!file_hierarchy)
     return false;
 
-  bool found_vmlinux = false;
+  bool found_vmlinux = !vmlinux_path.empty();
   FTSENT *entry;
   while ((entry = fts_read(file_hierarchy)))
     {
@@ -1586,22 +1586,41 @@ get_binary_paths_from_kernel_dist(const string& dist_root,
 /// The main corpus of the @ref corpus_group is made of the vmlinux
 /// binary.  The other corpora are made of the linux kernel binaries.
 ///
-/// @param root the path of the directory under which vmlinux and its
-/// kernel modules are to be found.
+/// @param root the path of the directory under which the kernel
+/// kernel modules are to be found.  The vmlinux can also be found
+/// somewhere under that directory, but if it's not in there, its path
+/// can be set to the @p vmlinux_path parameter.
 ///
-/// @param opts the options to use during the search.
+/// @param vmlinux_path the path to the vmlinux binary, if that binary
+/// is not under the @p root directory.  If this is empty, then it
+/// means the vmlinux binary is to be found under the @p root
+/// directory.
+///
+/// @param suppr_paths the paths to the suppression specifications to
+/// apply while loading the binaries.
+///
+/// @param kabi_wl_path the paths to the kabi whitelist files to take
+/// into account while loading the binaries.
+///
+/// @param supprs the suppressions resulting from parsing the
+/// suppression specifications at @p suppr_paths.  This is set by this
+/// function.
+///
+/// @param verbose true if the function has to emit some verbose
+/// messages.
 ///
 /// @param env the environment to create the corpus_group in.
 corpus_group_sptr
 build_corpus_group_from_kernel_dist_under(const string&        root,
+                                         const string& vmlinux_path,
                                          vector<string>&       suppr_paths,
                                          vector<string>&       kabi_wl_paths,
                                          suppressions_type&    supprs,
                                          bool                  verbose,
                                          environment_sptr&     env)
 {
+  string vmlinux = vmlinux_path;
   corpus_group_sptr result;
-  string vmlinux;
   vector<string> modules;
   string debug_info_root_path;
 
index e6b137b18e99a96b46d742ee46e8cce24772beee..1cb80a03108cb8a4e46689b41bc60097194d289e 100644 (file)
@@ -84,6 +84,7 @@ struct options
   string               out_file_path;
   shared_ptr<char>     di_root_path;
   string               headers_dir;
+  string               vmlinux;
   vector<string>       suppression_paths;
   vector<string>       kabi_whitelist_paths;
   suppressions_type    kabi_whitelist_supprs;
@@ -147,6 +148,8 @@ display_usage(const string& prog_name, ostream& out)
     "abi whitelist\n"
     << "  --linux-tree|--lt  emit the ABI for the union of a "
     "vmlinux and its modules\n"
+    << "  --vmlinux <path>  the path to the vmlinux binary to consider to emit "
+       "the ABI of the union of vmlinux and its modules\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"
@@ -224,6 +227,14 @@ parse_command_line(int argc, char* argv[], options& opts)
       else if (!strcmp(argv[i], "--linux-tree")
               || !strcmp(argv[i], "--lt"))
        opts.corpus_group_for_linux = true;
+      else if (!strcmp(argv[i], "--vmlinux"))
+       {
+         int j = i + 1;
+         if (j >= argc)
+           return false;
+         opts.vmlinux = argv[j];
+         ++i;
+       }
       else if (!strcmp(argv[i], "--noout"))
        opts.noout = true;
       else if (!strcmp(argv[i], "--no-architecture"))
@@ -489,39 +500,49 @@ load_kernel_corpus_group_and_write_abixml(char* argv[],
                                          options& opts)
 {
   if (!(tools_utils::is_dir(opts.in_file_path) && opts.corpus_group_for_linux))
-    return 0;
+    return 1;
 
   int exit_code = 0;
 
+  if (!opts.vmlinux.empty())
+    if (!abigail::tools_utils::check_file(opts.vmlinux, cerr, argv[0]))
+      return 1;
+
   suppressions_type supprs;
   corpus_group_sptr group =
     build_corpus_group_from_kernel_dist_under(opts.in_file_path,
+                                             opts.vmlinux,
                                              opts.suppression_paths,
                                              opts.kabi_whitelist_paths,
                                              supprs, opts.do_log, env);
 
   if (!group)
-    return exit_code;
+    return 1;
 
   if (!opts.write_architecture)
     group->set_architecture_name("");
   if (!opts.write_corpus_path)
     group->set_path("");
 
-  if (!opts.out_file_path.empty())
+  if (!opts.noout)
     {
-      ofstream of(opts.out_file_path.c_str(), std::ios_base::trunc);
-      if (!of.is_open())
+      if (!opts.out_file_path.empty())
        {
-         emit_prefix(argv[0], cerr)
-           << "could not open output file '"
-           << opts.out_file_path << "'\n";
-         return 1;
+         ofstream of(opts.out_file_path.c_str(), std::ios_base::trunc);
+         if (!of.is_open())
+           {
+             emit_prefix(argv[0], cerr)
+               << "could not open output file '"
+               << opts.out_file_path << "'\n";
+             return 1;
+           }
+         exit_code = !xml_writer::write_corpus_group(group, 0, of,
+                                                     opts.annotate);
        }
-      exit_code = !xml_writer::write_corpus_group(group, 0, of, opts.annotate);
+      else
+       exit_code = !xml_writer::write_corpus_group(group, 0, cout,
+                                                   opts.annotate);
     }
-  else
-    exit_code = !xml_writer::write_corpus_group(group, 0, cout, opts.annotate);
 
   return exit_code;
 }
index 94f458fa2135a2cec4e21c4ae0245bd158705fcc..8da1c17141e9974ccabcd65119f4c7a7a3e061cb 100644 (file)
@@ -75,6 +75,8 @@ struct options
   string       wrong_option;
   string       kernel_dist_root1;
   string       kernel_dist_root2;
+  string       vmlinux1;
+  string       vmlinux2;
   vector<string> kabi_whitelist_paths;
   vector<string> suppression_paths;
   suppressions_type read_time_supprs;
@@ -97,11 +99,13 @@ static void
 display_usage(const string& prog_name, ostream& out)
 {
   emit_prefix(prog_name, out)
-    << "usage: " << prog_name << " [options] kernel-package1 kernel-package2\n"
+    << "usage: " << prog_name << " [options] kernel-modules-dir1 kernel-modules-dir2\n"
     << " where options can be:\n"
     << " --help|-h  display this message\n"
     << " --version|-v  display program version information and exit\n"
     << " --verbose  display verbose messages\n"
+    << " --vmlinux1|--l1 <path>  the path to the first vmlinux"
+    << " --vmlinux2|--l2 <path>  the path to the second vmlinux"
     << " --suppressions|--suppr <path>  specify a suppression file\n"
     << " --kmi-whitelist|-w <path>  path to a kernel module interface "
     "whitelist\n";
@@ -149,6 +153,32 @@ parse_command_line(int argc, char* argv[], options& opts)
          opts.display_usage = true;
          return true;
        }
+      else if (!strcmp(argv[i], "--vmlinux1")
+              || !strcmp(argv[i], "--l1"))
+       {
+         int j = i + 1;
+         if (j >= argc)
+           {
+             opts.missing_operand = true;
+             opts.wrong_option = argv[i];
+             return false;
+           }
+         opts.vmlinux1 = argv[j];
+         ++i;
+       }
+      else if (!strcmp(argv[i], "--vmlinux2")
+              || !strcmp(argv[i], "--l2"))
+       {
+         int j = i + 1;
+         if (j >= argc)
+           {
+             opts.missing_operand = true;
+             opts.wrong_option = argv[i];
+             return false;
+           }
+         opts.vmlinux2 = argv[j];
+         ++i;
+       }
       else if (!strcmp(argv[i], "--kmi-whitelist")
               || !strcmp(argv[i], "-w"))
        {
@@ -316,6 +346,7 @@ main(int argc, char* argv[])
        {
          group1 =
            build_corpus_group_from_kernel_dist_under(opts.kernel_dist_root1,
+                                                     opts.vmlinux1,
                                                      opts.suppression_paths,
                                                      opts.kabi_whitelist_paths,
                                                      opts.read_time_supprs,
@@ -337,6 +368,7 @@ main(int argc, char* argv[])
        {
          group2 =
            build_corpus_group_from_kernel_dist_under(opts.kernel_dist_root2,
+                                                     opts.vmlinux2,
                                                      opts.suppression_paths,
                                                      opts.kabi_whitelist_paths,
                                                      opts.read_time_supprs,