From a1cee0760dceaeca52aff9498b144978537d5a16 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 15 Aug 2006 01:37:23 +0000 Subject: [PATCH] libdwfl/ 2006-08-14 Roland McGrath * linux-kernel-modules.c (try_kernel_name): If the call to dwfl_standard_find_debuginfo produces no results, try it again with NULL as DEBUGLINK_FILE to try *FNAME with .debug suffix. * find-debuginfo.c (DEFAULT_DEBUGINFO_PATH): Macro moved ... * libdwflP.h: ... to here. * linux-kernel-modules.c (try_kernel_name): Skip manual open if it repeats the first thing dwfl_standard_find_debuginfo will try. * linux-kernel-modules.c (MODULE_SECT_NAME_LEN): New macro. (dwfl_linux_kernel_module_section_address): If a /sys file is missing and the section name is >= MODULE_SECT_NAME_LEN, try truncating the section name. --- libdwfl/ChangeLog | 16 ++++++++++ libdwfl/find-debuginfo.c | 5 +-- libdwfl/libdwflP.h | 4 +++ libdwfl/linux-kernel-modules.c | 58 ++++++++++++++++++++++++++++++---- 4 files changed, 73 insertions(+), 10 deletions(-) diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index dafa98c85..0e3ac1367 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,19 @@ +2006-08-14 Roland McGrath + + * linux-kernel-modules.c (try_kernel_name): If the call to + dwfl_standard_find_debuginfo produces no results, try it again + with NULL as DEBUGLINK_FILE to try *FNAME with .debug suffix. + + * find-debuginfo.c (DEFAULT_DEBUGINFO_PATH): Macro moved ... + * libdwflP.h: ... to here. + * linux-kernel-modules.c (try_kernel_name): Skip manual open if it + repeats the first thing dwfl_standard_find_debuginfo will try. + + * linux-kernel-modules.c (MODULE_SECT_NAME_LEN): New macro. + (dwfl_linux_kernel_module_section_address): If a /sys file is missing + and the section name is >= MODULE_SECT_NAME_LEN, try truncating the + section name. + 2006-07-12 Ulrich Drepper * cu.c: Adjust for internal_function_def removal. diff --git a/libdwfl/find-debuginfo.c b/libdwfl/find-debuginfo.c index 4baf5fa87..a99fd1441 100644 --- a/libdwfl/find-debuginfo.c +++ b/libdwfl/find-debuginfo.c @@ -1,5 +1,5 @@ /* Standard find_debuginfo callback for libdwfl. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005, 2006 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -54,9 +54,6 @@ #include "system.h" -#define DEFAULT_DEBUGINFO_PATH ":.debug:/usr/lib/debug" - - /* Try to open64 [DIR/][SUBDIR/]DEBUGLINK, return file descriptor or -1. On success, *DEBUGINFO_FILE_NAME has the malloc'd name of the open file. */ static int diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index 949e0d7e1..31da938db 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -296,4 +296,8 @@ INTDECL (dwfl_module_relocate_address) #define CBFAIL (errno ? DWFL_E (ERRNO, errno) : DWFL_E_CB); +/* The default used by dwfl_standard_find_debuginfo. */ +#define DEFAULT_DEBUGINFO_PATH ":.debug:/usr/lib/debug" + + #endif /* libdwflP.h */ diff --git a/libdwfl/linux-kernel-modules.c b/libdwfl/linux-kernel-modules.c index a91d732c4..4d4194a5d 100644 --- a/libdwfl/linux-kernel-modules.c +++ b/libdwfl/linux-kernel-modules.c @@ -1,5 +1,5 @@ /* Standard libdwfl callbacks for debugging the running Linux kernel. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005, 2006 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -66,7 +66,8 @@ #define MODULEDIRFMT "/lib/modules/%s" #define MODULELIST "/proc/modules" -#define SECADDRFMT "/sys/module/%s/sections/%s" +#define SECADDRDIRFMT "/sys/module/%s/sections/" +#define MODULE_SECT_NAME_LEN 32 /* Minimum any linux/module.h has had. */ /* Try to open the given file as it is or under the debuginfo directory. */ @@ -76,14 +77,27 @@ try_kernel_name (Dwfl *dwfl, char **fname) if (*fname == NULL) return -1; - int fd = TEMP_FAILURE_RETRY (open64 (*fname, O_RDONLY)); + /* Don't bother trying *FNAME itself here if the path will cause it to be + tried because we give its own basename as DEBUGLINK_FILE. */ + int fd = ((((dwfl->callbacks->debuginfo_path + ? *dwfl->callbacks->debuginfo_path : NULL) + ?: DEFAULT_DEBUGINFO_PATH)[0] == ':') ? -1 + : TEMP_FAILURE_RETRY (open64 (*fname, O_RDONLY))); if (fd < 0) { 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) + /* Next, let the call use 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); free (*fname); *fname = debugfname; } @@ -404,7 +418,7 @@ dwfl_linux_kernel_module_section_address Dwarf_Addr *addr) { char *sysfile = NULL; - asprintf (&sysfile, SECADDRFMT, modname, secname); + asprintf (&sysfile, SECADDRDIRFMT "%s", modname, secname); if (sysfile == NULL) return ENOMEM; @@ -436,10 +450,11 @@ dwfl_linux_kernel_module_section_address behavior, and this cruft leaks out into the /sys information. The file name for ".init*" may actually look like "_init*". */ - if (!strncmp (secname, ".init", 5)) + const bool is_init = !strncmp (secname, ".init", 5); + if (is_init) { sysfile = NULL; - asprintf (&sysfile, SECADDRFMT "%s", modname, "_", &secname[1]); + asprintf (&sysfile, SECADDRDIRFMT "_%s", modname, &secname[1]); if (sysfile == NULL) return ENOMEM; f = fopen (sysfile, "r"); @@ -447,6 +462,37 @@ dwfl_linux_kernel_module_section_address if (f != NULL) goto ok; } + + /* The kernel truncates section names to MODULE_SECT_NAME_LEN - 1. + In case that size increases in the future, look for longer + truncated names first. */ + size_t namelen = strlen (secname); + if (namelen >= MODULE_SECT_NAME_LEN) + { + sysfile = NULL; + int len = asprintf (&sysfile, SECADDRDIRFMT "%s", + modname, secname); + if (sysfile == NULL) + return ENOMEM; + char *end = sysfile + len; + do + { + *--end = '\0'; + f = fopen (sysfile, "r"); + if (is_init && f == NULL && errno == ENOENT) + { + sysfile[len - namelen] = '_'; + f = fopen (sysfile, "r"); + sysfile[len - namelen] = '.'; + } + } + while (f == NULL && errno == ENOENT + && end - &sysfile[len - namelen] >= MODULE_SECT_NAME_LEN); + free (sysfile); + + if (f != NULL) + goto ok; + } } return DWARF_CB_ABORT; -- 2.47.2