libdwfl: Check for kernel debuginfo file without .debug extension as well
authorRavi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Tue, 16 Feb 2016 16:21:35 +0000 (21:51 +0530)
committerMark Wielaard <mjw@redhat.com>
Mon, 22 Feb 2016 19:46:30 +0000 (20:46 +0100)
Elfutils, looking for kernel debuginfo file, tries to find it at
various places. If elfutils finds /boot/vmlinu*x* file, it checks
for debufginfo section. If debuginfo is not present, it saves it as
'main elf' and continue looking for debuginfo file having .debug
extension i.e. vmlinux-RELEASE.debug.

'Ubuntu on powerpc' installs kernel as /boot/vmlinux and installs
debuginfo without any extension as /usr/lib/debug/boot/vmlinux-RELEASE
and hence, elfutils is not able to find the debuginfo file.

Here is the launchpad bug for the same:
  https://bugs.launchpad.net/ubuntu/+source/systemtap/+bug/1537125

This patch adds functionality to search for a kernel or debuginfo file
both with and without .debug extension.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Signed-off-by: Mark Wielaard <mjw@redhat.com>
libdwfl/ChangeLog
libdwfl/find-debuginfo.c
libdwfl/linux-kernel-modules.c

index 69fd233..462a61d 100644 (file)
@@ -1,3 +1,13 @@
+2016-02-22  Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
+           Mark Wielaard  <mjw@redhat.com>
+
+       * find-debuginfo.c (find_debuginfo_in_path): Remember whether
+       debuglink_file is NULL. Try file basename (without .debug) ofr
+       absolute and relative path if debug_file was NULL.
+       * linux-kernel-modules.c (try_kernel_name): If try_debug is true call
+       dwfl_standard_find_debuginfo with NULL debuglink_file, otherwise with
+       basename of fname.
+
 2016-02-13  Mark Wielaard  <mjw@redhat.com>
 
        * linux-proc-maps.c (proc_maps_report): Free last_file when ENOEXEC.
index 72461bc..80515db 100644 (file)
@@ -163,7 +163,11 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
 
   const char *file_basename = file_name == NULL ? NULL : basename (file_name);
   char *localname = NULL;
-  if (debuglink_file == NULL)
+
+  /* We invent a debuglink .debug name if NULL, but then want to try the
+     basename too.  */
+  bool debuglink_null = debuglink_file == NULL;
+  if (debuglink_null)
     {
       /* For a alt debug multi file we need a name, for a separate debug
         name we may be able to fall back on file_basename.debug.  */
@@ -231,6 +235,10 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
        check = *p++ == '+';
       check = check && cancheck;
 
+      /* Try the basename too, if we made up the debuglink name and this
+        is not the main directory.  */
+      bool try_file_basename;
+
       const char *dir, *subdir, *file;
       switch (p[0])
        {
@@ -239,6 +247,7 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
          dir = file_dirname;
          subdir = NULL;
          file = debuglink_file;
+         try_file_basename = false;
          break;
        case '/':
          /* An absolute path says to look there for a subdirectory
@@ -268,6 +277,7 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
              subdir = NULL;
              file = basename (debuglink_file);
            }
+         try_file_basename = debuglink_null;
          break;
        default:
          /* A relative path says to try a subdirectory of that name
@@ -275,11 +285,14 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
          dir = file_dirname;
          subdir = p;
          file = debuglink_file;
+         try_file_basename = debuglink_null;
          break;
        }
 
       char *fname = NULL;
       int fd = try_open (&main_stat, dir, subdir, file, &fname);
+      if (fd < 0 && try_file_basename)
+       fd = try_open (&main_stat, dir, subdir, file_basename, &fname);
       if (fd < 0)
        switch (errno)
          {
index 79faf99..54c0b90 100644 (file)
@@ -92,17 +92,21 @@ try_kernel_name (Dwfl *dwfl, char **fname, bool try_debug)
   if (fd < 0)
     {
       Dwfl_Module fakemod = { .dwfl = dwfl };
-      /* First try the file's unadorned basename as DEBUGLINK_FILE,
-        to look for "vmlinux" files.  */
-      fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0,
-                                                *fname, basename (*fname), 0,
-                                                &fakemod.debug.name);
-      if (fd < 0 && try_debug)
-       /* Next, let the call use the default of basename + ".debug",
-          to look for "vmlinux.debug" files.  */
+
+      if (try_debug)
+       /* Passing NULL for DEBUGLINK_FILE searches for both the basenamer
+          "vmlinux" and the default of basename + ".debug", to look for
+          "vmlinux.debug" files.  */
        fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0,
                                                   *fname, NULL, 0,
                                                   &fakemod.debug.name);
+      else
+       /* Try the file's unadorned basename as DEBUGLINK_FILE,
+          to look only for "vmlinux" files.  */
+       fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0,
+                                                  *fname, basename (*fname),
+                                                  0, &fakemod.debug.name);
+
       if (fakemod.debug.name != NULL)
        {
          free (*fname);