From 55022c76a3b0ec70504401bbee7f027c9a23f9ff Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Tue, 23 Feb 2016 02:27:35 -0600 Subject: [PATCH] libdwfl: Check for kernel debuginfo file without .debug extension as well 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. Backported from: https://git.fedorahosted.org/cgit/elfutils.git/patch/?id= 7802e6e57d48189e339b4ab40189eb44d8123559 Backported for: Ubuntu 14.04.4 (elfutils 0.158-0ubuntu5.2) Signed-off-by: Ravi Bangoria Signed-off-by: Mark Wielaard --- libdwfl/find-debuginfo.c | 15 ++++++++++++++- libdwfl/linux-kernel-modules.c | 20 ++++++++++++-------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/libdwfl/find-debuginfo.c b/libdwfl/find-debuginfo.c index 21db91a..c624694 100644 --- a/libdwfl/find-debuginfo.c +++ b/libdwfl/find-debuginfo.c @@ -122,7 +122,11 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name, bool cancheck = debuglink_crc != (GElf_Word) 0; const char *file_basename = file_name == NULL ? NULL : basename (file_name); - 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) { if (file_basename == NULL) { @@ -174,6 +178,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; switch (p[0]) { @@ -181,6 +189,7 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name, /* An empty entry says to try the main file's directory. */ dir = file_dirname; subdir = NULL; + try_file_basename = false; break; case '/': /* An absolute path says to look there for a subdirectory @@ -190,17 +199,21 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name, continue; dir = p; subdir = file_dirname + 1; + try_file_basename = debuglink_null; break; default: /* A relative path says to try a subdirectory of that name in the main file's directory. */ dir = file_dirname; subdir = p; + try_file_basename = debuglink_null; break; } char *fname = NULL; int fd = try_open (&main_stat, dir, subdir, debuglink_file, &fname); + if (fd < 0 && try_file_basename) + fd = try_open (&main_stat, dir, subdir, file_basename, &fname); if (fd < 0) switch (errno) { diff --git a/libdwfl/linux-kernel-modules.c b/libdwfl/linux-kernel-modules.c index 5307518..7dd7dcf 100644 --- a/libdwfl/linux-kernel-modules.c +++ b/libdwfl/linux-kernel-modules.c @@ -90,17 +90,21 @@ try_kernel_name (Dwfl *dwfl, char **fname, bool try_debug) { char *debugfname = NULL; 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, - &debugfname); - 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, &debugfname); + 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 (debugfname != NULL) { free (*fname); -- 1.9.1