Bug 21730 - Make abipkgdiff compare Linux Kernel packages as expected
authorDodji Seketeli <dodji@redhat.com>
Mon, 10 Jul 2017 09:54:13 +0000 (11:54 +0200)
committerDodji Seketeli <dodji@redhat.com>
Mon, 17 Jul 2017 14:41:07 +0000 (16:41 +0200)
This is the initial patch that makes abipkgdiff recognize Linux kernel
packages passed in argument and do the right thing.

abipkgdiff gets the vmlinux binary from the debug info package,
considers the union of that vmlinux binary and the thousands of kernel
modules that we shall name "the Kernel".  It then compares ABI
(actually Kernel/Module Interface, a.k.a KMI) of the Kernel of the
first package against the KMI of the Kernel of the second package.

* include/abg-tools-utils.h (get_vmlinux_path_from_kernel_dist):
Declare new function.
(get_binary_paths_from_kernel_dist): Re-organize order of
parameters.
(file_is_kernel_package, file_is_kernel_debuginfo_package): Make
the file_path parameter be const.
(build_corpus_group_from_kernel_dist_under): Take an additional
debug_info_root parameter.
* src/abg-tools-utils.cc (file_is_kernel_package)
(file_is_kernel_debuginfo_package): Const-ify the file_name
parameter.
(find_vmlinux_path): Define new static function.
(get_binary_paths_from_kernel_dist): Re-organize the order of
parameters.  The debug_info_root_path parameter is now an input
parameter.
(get_vmlinux_path_from_kernel_dist): Define new function.
(get_binary_paths_from_kernel_dist): Adjust invocation of
get_binary_paths_from_kernel_dist.
(build_corpus_group_from_kernel_dist_under): Take an additional
debug_info_root parameter.
* tools/abidw.cc (load_kernel_corpus_group_and_write_abixml):
Adjust invocation to build_corpus_group_from_kernel_dist_under.
* tools/abipkgdiff.cc (create_maps_of_package_content):  Don't map
the content of a Linux Kernel package.
(compare_prepared_userspace_packages)
(compare_prepared_linux_kernel_packages, compare_prepared): Define
new functions.
(compare): Use the new functions above here.
* tools/kmidiff.cc (print_kernel_dist_binary_paths_under): Adjust
the invocation of get_binary_paths_from_kernel_dist.
(main): Adjust the invocation of
build_corpus_group_from_kernel_dist_under.  Make sure that a
kernel package is accompanied by a debug info package.

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

index fcbc3ad5f614a95b6f916a17e538ce36bd07b995..99c4f7aaee2ee997fdaa311e9b7c9a9d0b1f4153 100644 (file)
@@ -68,11 +68,15 @@ bool
 gen_suppr_spec_from_kernel_abi_whitelist(const string& abi_whitelist_path,
                                         suppr::suppressions_type& s);
 
+bool
+get_vmlinux_path_from_kernel_dist(const string&        from,
+                                 string&               vmlinux_path);
+
 bool
 get_binary_paths_from_kernel_dist(const string&        dist_root,
+                                 const string& debug_info_root_path,
                                  string&               vmlinux_path,
-                                 vector<string>&       module_paths,
-                                 string&               debug_info_root_path);
+                                 vector<string>&       module_paths);
 
 bool
 get_binary_paths_from_kernel_dist(const string&        dist_root,
@@ -240,11 +244,11 @@ bool
 get_deb_name(const string& str, string& name);
 
 bool
-file_is_kernel_package(string& file_path,
+file_is_kernel_package(const string& file_path,
                       file_type file_type);
 
 bool
-file_is_kernel_debuginfo_package(string& file_path,
+file_is_kernel_debuginfo_package(const string& file_path,
                                 file_type file_type);
 
 std::tr1::shared_ptr<char>
@@ -252,6 +256,7 @@ make_path_absolute(const char*p);
 
 corpus_group_sptr
 build_corpus_group_from_kernel_dist_under(const string&        root,
+                                         const string          debug_info_root,
                                          const string& vmlinux_path,
                                          vector<string>&       suppr_paths,
                                          vector<string>&       kabi_wl_paths,
index a66a5fd2e1a9425b431b09af2f67c8c5003591f6..d6a89b6906f071c847b7d2e8513a3bfd165805c3 100644 (file)
@@ -1013,7 +1013,7 @@ get_rpm_arch(const string& str, string& arch)
 /// @return true iff @p file_name of kind @p file_type designates a
 /// kernel package.
 bool
-file_is_kernel_package(string& file_name, file_type file_type)
+file_is_kernel_package(const string& file_name, file_type file_type)
 {
   bool result = false;
   string package_name;
@@ -1043,7 +1043,7 @@ file_is_kernel_package(string& file_name, file_type file_type)
 /// @return true iff @p file_name of kind @p file_type designates a
 /// kernel debuginfo package.
 bool
-file_is_kernel_debuginfo_package(string& file_name, file_type file_type)
+file_is_kernel_debuginfo_package(const string& file_name, file_type file_type)
 {
   bool result = false;
   string package_name;
@@ -1501,27 +1501,67 @@ find_vmlinux_and_module_paths(const string&     from,
   return found_vmlinux;
 }
 
+/// Find a vmlinux binary in a given directory tree.
+///
+/// @param from the directory tree to start looking from.
+///
+/// @param vmlinux_path output parameter
+///
+/// return true iff the vmlinux binary was found
+static bool
+find_vmlinux_path(const string&        from,
+                 string                &vmlinux_path)
+{
+  char* path[] = {const_cast<char*>(from.c_str()), 0};
+
+  FTS *file_hierarchy = fts_open(path, FTS_PHYSICAL|FTS_NOCHDIR|FTS_XDEV, 0);
+  if (!file_hierarchy)
+    return false;
+
+  bool found_vmlinux = false;
+  FTSENT *entry;
+  while ((entry = fts_read(file_hierarchy)))
+    {
+      // Skip descendents of symbolic links.
+      if (entry->fts_info == FTS_SL || entry->fts_info == FTS_SLNONE)
+       {
+         fts_set(file_hierarchy, entry, FTS_SKIP);
+         continue;
+       }
+
+      if (!found_vmlinux && is_vmlinux(entry))
+       {
+         vmlinux_path = entry->fts_path;
+         found_vmlinux = true;
+         break;
+       }
+    }
+
+  fts_close(file_hierarchy);
+
+  return found_vmlinux;
+}
+
 /// Get the paths of the vmlinux and kernel module binaries under
 /// given directory.
 ///
 /// @param dist_root the directory under which to look for.
 ///
+/// @param debug_info_root_path the path to the directory under which
+/// debug info is going to be found for binaries under @p dist_root.
+///
 /// @param vmlinux_path output parameter.  The path of the vmlinux
 /// binary that was found.
 ///
 /// @param module_paths output parameter.  The paths of the kernel
 /// module binaries that were found.
 ///
-/// @param debug_info_root_path output parameter. If a debug info
-/// sub-directory is found under @p dist_root, it's set to this
-/// parameter.
-///
 /// @return true if at least the path to the vmlinux binary was found.
 bool
 get_binary_paths_from_kernel_dist(const string&        dist_root,
+                                 const string& debug_info_root_path,
                                  string&               vmlinux_path,
-                                 vector<string>&       module_paths,
-                                 string&               debug_info_root_path)
+                                 vector<string>&       module_paths)
 {
   if (!dir_exists(dist_root))
     return false;
@@ -1531,26 +1571,62 @@ get_binary_paths_from_kernel_dist(const string& dist_root,
   //
   // We also take into account split debug info package for these.  In
   // this case, the content split debug info package is installed
-  // under the 'dist_root' directory as well, and its content is
-  // accessible from <dist_root>/usr/lib/debug directory.
+  // under the 'debug_info_root_path' directory and its content is
+  // accessible from <debug_info_root_path>/usr/lib/debug directory.
 
   string kernel_modules_root;
   string debug_info_root;
   if (dir_exists(dist_root + "/lib/modules"))
     {
       dist_root + "/lib/modules";
-      debug_info_root = dist_root + "/usr/lib/debug";
+      debug_info_root = debug_info_root_path.empty()
+       ? dist_root
+       : debug_info_root_path;
+      debug_info_root += "/usr/lib/debug";
     }
 
   if (dir_is_empty(debug_info_root))
     debug_info_root.clear();
 
   bool found = false;
-  string from = !debug_info_root.empty() ? debug_info_root : dist_root;
+  string from = dist_root;
   if (find_vmlinux_and_module_paths(from, vmlinux_path, module_paths))
     found = true;
 
-  debug_info_root_path = debug_info_root;
+  return found;
+}
+
+/// Get the path of the vmlinux binary under the given directory, that
+/// must have been generated either from extracting a package.
+///
+/// @param from the directory under which to look for.
+///
+/// @param vmlinux_path output parameter.  The path of the vmlinux
+/// binary that was found.
+///
+/// @return true if the path to the vmlinux binary was found.
+bool
+get_vmlinux_path_from_kernel_dist(const string&        from,
+                                 string&               vmlinux_path)
+{
+    if (!dir_exists(from))
+    return false;
+
+  // For now, we assume either an Enterprise Linux or a Fedora kernel
+  // distribution directory.
+  //
+  // We also take into account split debug info package for these.  In
+  // this case, the content split debug info package is installed
+  // under the 'dist_root' directory as well, and its content is
+  // accessible from <dist_root>/usr/lib/debug directory.
+
+    string dist_root = from;
+  if (dir_exists(dist_root + "/lib/modules"))
+    dist_root + "/lib/modules";
+
+  bool found = false;
+  if (find_vmlinux_path(dist_root, vmlinux_path))
+    found = true;
 
   return found;
 }
@@ -1574,9 +1650,9 @@ get_binary_paths_from_kernel_dist(const string&   dist_root,
 {
   string debug_info_root_path;
   return get_binary_paths_from_kernel_dist(dist_root,
+                                          debug_info_root_path,
                                           vmlinux_path,
-                                          module_paths,
-                                          debug_info_root_path);
+                                          module_paths);
 }
 
 /// Walk a given directory and build an instance of @ref corpus_group
@@ -1591,6 +1667,9 @@ get_binary_paths_from_kernel_dist(const string&   dist_root,
 /// somewhere under that directory, but if it's not in there, its path
 /// can be set to the @p vmlinux_path parameter.
 ///
+/// @param debug_info_root the directory under which debug info is to
+/// be found for binaries under director @p root.
+///
 /// @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
@@ -1612,6 +1691,7 @@ get_binary_paths_from_kernel_dist(const string&   dist_root,
 /// @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          debug_info_root,
                                          const string& vmlinux_path,
                                          vector<string>&       suppr_paths,
                                          vector<string>&       kabi_wl_paths,
@@ -1622,15 +1702,13 @@ build_corpus_group_from_kernel_dist_under(const string& root,
   string vmlinux = vmlinux_path;
   corpus_group_sptr result;
   vector<string> modules;
-  string debug_info_root_path;
 
   if (verbose)
     std::cout << "Analysing kernel dist root '"
              << root << "' ... " << std::flush;
 
   bool got_binary_paths =
-    get_binary_paths_from_kernel_dist(root, vmlinux, modules,
-                                     debug_info_root_path);
+    get_binary_paths_from_kernel_dist(root, debug_info_root, vmlinux, modules);
 
   if (verbose)
     std::cout << "DONE\n";
@@ -1639,7 +1717,7 @@ build_corpus_group_from_kernel_dist_under(const string&   root,
   if (got_binary_paths)
     {
       shared_ptr<char> di_root =
-       make_path_absolute(debug_info_root_path.c_str());
+       make_path_absolute(debug_info_root.c_str());
       char *di_root_ptr = di_root.get();
       abigail::dwarf_reader::status status = abigail::dwarf_reader::STATUS_OK;
       corpus_group_sptr group;
index 1cb80a03108cb8a4e46689b41bc60097194d289e..b24d0317bdaf4fc4df7914ba520cafb170013537 100644 (file)
@@ -511,6 +511,7 @@ load_kernel_corpus_group_and_write_abixml(char* argv[],
   suppressions_type supprs;
   corpus_group_sptr group =
     build_corpus_group_from_kernel_dist_under(opts.in_file_path,
+                                             /*debug_info_root=*/"",
                                              opts.vmlinux,
                                              opts.suppression_paths,
                                              opts.kabi_whitelist_paths,
index a632c055d492e1c4f3cbbaa9dfbdadde247593b0..f20c46cc63722e16f314ecf3343c7ec3c4b5b5ed 100644 (file)
@@ -109,10 +109,13 @@ using abigail::tools_utils::gen_suppr_spec_from_headers;
 using abigail::tools_utils::gen_suppr_spec_from_kernel_abi_whitelist;
 using abigail::tools_utils::get_default_system_suppression_file_path;
 using abigail::tools_utils::get_default_user_suppression_file_path;
+using abigail::tools_utils::get_vmlinux_path_from_kernel_dist;
+using abigail::tools_utils::build_corpus_group_from_kernel_dist_under;
 using abigail::tools_utils::load_default_system_suppressions;
 using abigail::tools_utils::load_default_user_suppressions;
 using abigail::tools_utils::abidiff_status;
 using abigail::ir::corpus_sptr;
+using abigail::ir::corpus_group_sptr;
 using abigail::comparison::diff_context;
 using abigail::comparison::diff_context_sptr;
 using abigail::comparison::compute_diff;
@@ -1657,10 +1660,16 @@ create_maps_of_package_content(package& package, options& opts)
   bool is_linux_kernel_package = file_is_kernel_package(pkg_name,
                                                        package.type());
   if (is_linux_kernel_package)
-    if (package_sptr debuginfo_pkg = package.debug_info_package())
-      is_ok =
-       get_interesting_files_under_dir(debuginfo_pkg->extracted_dir_path(),
-                                       "vmlinux", opts, elf_file_paths);
+    {
+      // For a linux kernel package, no analysis is done.  It'll be
+      // done later at comparison time by
+      // compare_prepared_linux_kernel_packages
+      is_ok = true;
+      if (opts.verbose)
+       emit_prefix("abipkgdiff", cerr)
+         << " Analysis of " << package.path() << " DONE\n";
+      return is_ok;
+    }
 
   is_ok &= get_interesting_files_under_dir(package.extracted_dir_path(),
                                           /*file_name_to_look_for=*/"",
@@ -1930,7 +1939,11 @@ maybe_erase_temp_dirs(package& first_package, package& second_package,
   erase_created_temporary_directories_parent(opts);
 }
 
-/// Compare the ABI of two packages
+/// Compare the ABI of two prepared packages that contain userspace
+/// binaries.
+///
+/// A prepared package is a package which content has been extracted
+/// and mapped.
 ///
 /// @param first_package the first package to consider.
 ///
@@ -1946,23 +1959,13 @@ maybe_erase_temp_dirs(package& first_package, package& second_package,
 ///
 /// @return the status of the comparison.
 static abidiff_status
-compare(package& first_package, package& second_package,
-       abi_diff& diff, options& opts)
+compare_prepared_userspace_packages(package& first_package,
+                                   package& second_package,
+                                   abi_diff& diff, options& opts)
 {
-  // Prepare (extract and analyze the contents) the packages and their
-  // ancillary packages.
-  //
-  // Note that the package preparations happens in parallel.
-  if (!prepare_packages(first_package, second_package, opts))
-    {
-      maybe_erase_temp_dirs(first_package, second_package, opts);
-      return abigail::tools_utils::ABIDIFF_ERROR;
-    }
-
+  abidiff_status status = abigail::tools_utils::ABIDIFF_OK;
+  abigail::workers::queue::tasks_type compare_tasks;
   string pkg_name = first_package.base_name();
-  bool is_linux_kernel_package =
-    abigail::tools_utils::file_is_kernel_package(pkg_name,
-                                                first_package.type());
 
   // Setting debug-info path of libraries
   string debug_dir1, debug_dir2, relative_debug_path = "/usr/lib/debug/";
@@ -1978,20 +1981,6 @@ compare(package& first_package, package& second_package,
          relative_debug_path;
     }
 
-  abidiff_status status = abigail::tools_utils::ABIDIFF_OK;
-
-  abigail::workers::queue::tasks_type compare_tasks;
-
-  if (is_linux_kernel_package)
-    {
-      opts.show_symbols_not_referenced_by_debug_info = false;
-      for (vector<string>::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_suppressions);
-    }
-
   for (map<string, elf_file_sptr>::iterator it =
         first_package.path_elf_file_sptr_map().begin();
        it != first_package.path_elf_file_sptr_map().end();
@@ -2004,14 +1993,9 @@ compare(package& first_package, package& second_package,
          && (iter->second->type == abigail::dwarf_reader::ELF_TYPE_DSO
              || iter->second->type == abigail::dwarf_reader::ELF_TYPE_EXEC
               || iter->second->type == abigail::dwarf_reader::ELF_TYPE_PI_EXEC
-             || iter->second->type
-             == abigail::dwarf_reader::ELF_TYPE_RELOCATABLE))
+             || iter->second->type == abigail::dwarf_reader::ELF_TYPE_RELOCATABLE))
        {
-         if ((((iter->second->type
-                == abigail::dwarf_reader::ELF_TYPE_RELOCATABLE)
-               && is_linux_kernel_package)
-              || (iter->second->type
-                  != abigail::dwarf_reader::ELF_TYPE_RELOCATABLE)))
+         if (iter->second->type != abigail::dwarf_reader::ELF_TYPE_RELOCATABLE)
            {
              compare_args_sptr args
                (new compare_args(*it->second,
@@ -2021,7 +2005,6 @@ compare(package& first_package, package& second_package,
                                  debug_dir2,
                                  second_package.private_types_suppressions(),
                                  opts));
-
              compare_task_sptr t(new compare_task(args));
              compare_tasks.push_back(t);
            }
@@ -2125,6 +2108,182 @@ compare(package& first_package, package& second_package,
   return status;
 }
 
+/// Compare the ABI of two prepared packages that contain linux kernel
+/// binaries.
+///
+/// A prepared package is a package which content has been extracted
+/// and mapped.
+///
+/// @param first_package the first package to consider.
+///
+/// @param second_package the second package to consider.
+///
+/// @param options the options the current program has been called
+/// with.
+///
+/// @param diff out parameter.  If this function returns true, then
+/// this parameter is set to the result of the comparison.
+///
+/// @param opts the options of the current program.
+///
+/// @return the status of the comparison.
+static abidiff_status
+compare_prepared_linux_kernel_packages(package& first_package,
+                                      package& second_package,
+                                      options& opts)
+{
+  abidiff_status status = abigail::tools_utils::ABIDIFF_OK;
+  string pkg_name = first_package.base_name();
+
+  // Setting debug-info path of binaries
+  string debug_dir1, debug_dir2, relative_debug_path = "/usr/lib/debug/";
+  if (first_package.debug_info_package()
+      && second_package.debug_info_package())
+    {
+      debug_dir1 =
+       first_package.debug_info_package()->extracted_dir_path() +
+       relative_debug_path;
+      if (second_package.debug_info_package())
+       debug_dir2 =
+         second_package.debug_info_package()->extracted_dir_path() +
+         relative_debug_path;
+    }
+
+  string vmlinux_path1, vmlinux_path2;
+
+  if (!get_vmlinux_path_from_kernel_dist(debug_dir1, vmlinux_path1))
+    return abigail::tools_utils::ABIDIFF_ERROR;
+
+  if (!get_vmlinux_path_from_kernel_dist(debug_dir2, vmlinux_path2))
+    return abigail::tools_utils::ABIDIFF_ERROR;
+
+  string dist_root1 = first_package.extracted_dir_path();
+  string dist_root2 = second_package.extracted_dir_path();
+
+  abigail::ir::environment_sptr env(new abigail::ir::environment);
+  suppressions_type supprs;
+  corpus_group_sptr corpus1, corpus2;
+  corpus1 = build_corpus_group_from_kernel_dist_under(dist_root1,
+                                                     debug_dir1,
+                                                     vmlinux_path1,
+                                                     opts.suppression_paths,
+                                                     opts.kabi_whitelist_paths,
+                                                     supprs,
+                                                     opts.verbose,
+                                                     env);
+
+  if (!corpus1)
+    return abigail::tools_utils::ABIDIFF_ERROR;
+
+  corpus2 = build_corpus_group_from_kernel_dist_under(dist_root2,
+                                                     debug_dir2,
+                                                     vmlinux_path2,
+                                                     opts.suppression_paths,
+                                                     opts.kabi_whitelist_paths,
+                                                     supprs,
+                                                     opts.verbose,
+                                                     env);
+
+  if (!corpus2)
+    return abigail::tools_utils::ABIDIFF_ERROR;
+
+  diff_context_sptr diff_ctxt(new diff_context);
+  set_diff_context_from_opts(diff_ctxt, opts);
+
+  corpus_diff_sptr diff = compute_diff(corpus1, corpus2, diff_ctxt);
+
+  if (diff->has_net_changes())
+    status |= abigail::tools_utils::ABIDIFF_ABI_CHANGE;
+  if (diff->has_incompatible_changes())
+    status |= abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE;
+
+  if (status & abigail::tools_utils::ABIDIFF_ABI_CHANGE)
+    {
+      cout << "== Kernel ABI changes between packages '"
+          << first_package.path() << "' and '"
+          << second_package.path() << "' are: ===\n";
+      diff->report(cout);
+      cout << "== End of kernel ABI changes between packages '"
+          << first_package.path()
+          << "' and '"
+          << second_package.path() << "' ===\n\n";
+    }
+
+  return status;
+}
+
+/// Compare the ABI of two prepared packages.
+///
+/// A prepared package is a package which content has been extracted
+/// and mapped.
+///
+/// @param first_package the first package to consider.
+///
+/// @param second_package the second package to consider.
+///
+/// @param options the options the current program has been called
+/// with.
+///
+/// @param diff out parameter.  If this function returns true, then
+/// this parameter is set to the result of the comparison.
+///
+/// @param opts the options of the current program.
+///
+/// @return the status of the comparison.
+static abidiff_status
+compare_prepared_package(package& first_package, package& second_package,
+                        abi_diff& diff, options& opts)
+{
+  abidiff_status status = abigail::tools_utils::ABIDIFF_OK;
+
+  if (abigail::tools_utils::file_is_kernel_package(first_package.base_name(),
+                                                  first_package.type()))
+    {
+      opts.show_symbols_not_referenced_by_debug_info = false;
+      status = compare_prepared_linux_kernel_packages(first_package,
+                                                     second_package,
+                                                     opts);
+    }
+  else
+    status = compare_prepared_userspace_packages(first_package,
+                                                second_package,
+                                                diff, opts);
+
+  return status;
+}
+
+/// Compare the ABI of two packages
+///
+/// @param first_package the first package to consider.
+///
+/// @param second_package the second package to consider.
+///
+/// @param options the options the current program has been called
+/// with.
+///
+/// @param diff out parameter.  If this function returns true, then
+/// this parameter is set to the result of the comparison.
+///
+/// @param opts the options of the current program.
+///
+/// @return the status of the comparison.
+static abidiff_status
+compare(package& first_package, package& second_package,
+       abi_diff& diff, options& opts)
+{
+  // Prepare (extract and analyze the contents) the packages and their
+  // ancillary packages.
+  //
+  // Note that the package preparations happens in parallel.
+  if (!prepare_packages(first_package, second_package, opts))
+    {
+      maybe_erase_temp_dirs(first_package, second_package, opts);
+      return abigail::tools_utils::ABIDIFF_ERROR;
+    }
+
+  return compare_prepared_package(first_package, second_package, diff, opts);
+}
+
 /// Compare the ABI of two packages.
 ///
 /// @param first_package the first package to consider.
@@ -2475,6 +2634,35 @@ main(int argc, char* argv[])
          return (abigail::tools_utils::ABIDIFF_USAGE_ERROR
                  | abigail::tools_utils::ABIDIFF_ERROR);
        }
+
+      if (file_is_kernel_package(first_package->base_name(),
+                                abigail::tools_utils::FILE_TYPE_RPM)
+         || file_is_kernel_package(second_package->base_name(),
+                                   abigail::tools_utils::FILE_TYPE_RPM))
+       {
+         if (file_is_kernel_package(first_package->base_name(),
+                                    abigail::tools_utils::FILE_TYPE_RPM)
+             != file_is_kernel_package(second_package->base_name(),
+                                       abigail::tools_utils::FILE_TYPE_RPM))
+           {
+             emit_prefix("abipkgdiff", cerr)
+               << "a Linux kernel package can only be compared to another "
+               "Linux kernel package\n";
+             return (abigail::tools_utils::ABIDIFF_USAGE_ERROR
+                     | abigail::tools_utils::ABIDIFF_ERROR);
+           }
+
+         if (!first_package->debug_info_package()
+             || !second_package->debug_info_package())
+           {
+             emit_prefix("abipkgdiff", cerr)
+               << "a Linux Kernel package must be accompanied with its "
+               "debug info package\n";
+             return (abigail::tools_utils::ABIDIFF_USAGE_ERROR
+                     | abigail::tools_utils::ABIDIFF_ERROR);
+           }
+       }
+
       break;
 
     case abigail::tools_utils::FILE_TYPE_DEB:
index 8da1c17141e9974ccabcd65119f4c7a7a3e061cb..3a7510d505c58f698b076638b7b60e60a1382612 100644 (file)
@@ -279,7 +279,8 @@ print_kernel_dist_binary_paths_under(const string& root, const options &opts)
   vector<string> modules;
 
   if (opts.verbose)
-    if (get_binary_paths_from_kernel_dist(root, vmlinux, modules))
+    if (get_binary_paths_from_kernel_dist(root, /*debug_info_root_path*/"",
+                                         vmlinux, modules))
        {
         cout << "Found kernel binaries under: '" << root << "'\n";
         if (!vmlinux.empty())
@@ -346,6 +347,7 @@ main(int argc, char* argv[])
        {
          group1 =
            build_corpus_group_from_kernel_dist_under(opts.kernel_dist_root1,
+                                                     /*debug_info_root=*/"",
                                                      opts.vmlinux1,
                                                      opts.suppression_paths,
                                                      opts.kabi_whitelist_paths,
@@ -368,6 +370,7 @@ main(int argc, char* argv[])
        {
          group2 =
            build_corpus_group_from_kernel_dist_under(opts.kernel_dist_root2,
+                                                     /*debug_info_root=*/"",
                                                      opts.vmlinux2,
                                                      opts.suppression_paths,
                                                      opts.kabi_whitelist_paths,