Check for kconfig.h presence, not just build dir (#3588)
authorWGH <wgh@torlan.ru>
Tue, 14 Sep 2021 01:00:23 +0000 (04:00 +0300)
committerGitHub <noreply@github.com>
Tue, 14 Sep 2021 01:00:23 +0000 (18:00 -0700)
This is a better check than just checking the presence of the build dir.

In Gentoo Linux, when you remove the kernel source package, the leftover
build directory is intentionally left in place. Which means the
/lib/modules/$(uname -r)/build symlink still remains valid, but there's
no kconfig.h there anymore[1]. This prevents bcc from using the kheaders
(/sys/kernel/kheaders.tar.xz) fallback, instead making it fail later on:

    <built-in>:1:10: fatal error: './include/linux/kconfig.h' file not found
    #include "./include/linux/kconfig.h"
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    1 error generated.

[1] https://bugs.gentoo.org/809347

Signed-off-by: WGH <wgh@torlan.ru>
src/cc/frontends/clang/loader.cc

index 240569793e3b61b5964aef3f4fb211c362e95c39..4f9914a2cfa9379943add59b38cc4dcf9a433a70 100644 (file)
@@ -115,6 +115,16 @@ bool is_dir(const string& path)
   return S_ISDIR(buf.st_mode);
 }
 
+bool is_file(const string& path)
+{
+  struct stat buf;
+
+  if (::stat (path.c_str (), &buf) < 0)
+    return false;
+
+  return S_ISREG(buf.st_mode);
+}
+
 std::pair<bool, string> get_kernel_path_info(const string kdir)
 {
   if (is_dir(kdir + "/build") && is_dir(kdir + "/source"))
@@ -170,7 +180,10 @@ int ClangLoader::parse(unique_ptr<llvm::Module> *mod, TableStorage &ts,
   }
 
   // If all attempts to obtain kheaders fail, check for kheaders.tar.xz in sysfs
-  if (!is_dir(kpath)) {
+  // Checking just for kpath existence is unsufficient, since it can refer to
+  // leftover build directory without headers present anymore.
+  // See https://github.com/iovisor/bcc/pull/3588 for more details.
+  if (!is_file(kpath + "/include/linux/kconfig.h")) {
     int ret = get_proc_kheaders(tmpdir);
     if (!ret) {
       kpath = tmpdir;