Home | History | Annotate | Download | only in libdwfl
      1 /* Standard libdwfl callbacks for debugging the running Linux kernel.
      2    Copyright (C) 2005-2011 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4 
      5    Red Hat elfutils is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by the
      7    Free Software Foundation; version 2 of the License.
      8 
      9    Red Hat elfutils is distributed in the hope that it will be useful, but
     10    WITHOUT ANY WARRANTY; without even the implied warranty of
     11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12    General Public License for more details.
     13 
     14    You should have received a copy of the GNU General Public License along
     15    with Red Hat elfutils; if not, write to the Free Software Foundation,
     16    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     17 
     18    In addition, as a special exception, Red Hat, Inc. gives You the
     19    additional right to link the code of Red Hat elfutils with code licensed
     20    under any Open Source Initiative certified open source license
     21    (http://www.opensource.org/licenses/index.php) which requires the
     22    distribution of source code with any binary distribution and to
     23    distribute linked combinations of the two.  Non-GPL Code permitted under
     24    this exception must only link to the code of Red Hat elfutils through
     25    those well defined interfaces identified in the file named EXCEPTION
     26    found in the source code files (the "Approved Interfaces").  The files
     27    of Non-GPL Code may instantiate templates or use macros or inline
     28    functions from the Approved Interfaces without causing the resulting
     29    work to be covered by the GNU General Public License.  Only Red Hat,
     30    Inc. may make changes or additions to the list of Approved Interfaces.
     31    Red Hat's grant of this exception is conditioned upon your not adding
     32    any new exceptions.  If you wish to add a new Approved Interface or
     33    exception, please contact Red Hat.  You must obey the GNU General Public
     34    License in all respects for all of the Red Hat elfutils code and other
     35    code used in conjunction with Red Hat elfutils except the Non-GPL Code
     36    covered by this exception.  If you modify this file, you may extend this
     37    exception to your version of the file, but you are not obligated to do
     38    so.  If you do not wish to provide this exception without modification,
     39    you must delete this exception statement from your version and license
     40    this file solely under the GPL without exception.
     41 
     42    Red Hat elfutils is an included package of the Open Invention Network.
     43    An included package of the Open Invention Network is a package for which
     44    Open Invention Network licensees cross-license their patents.  No patent
     45    license is granted, either expressly or impliedly, by designation as an
     46    included package.  Should you wish to participate in the Open Invention
     47    Network licensing program, please visit www.openinventionnetwork.com
     48    <http://www.openinventionnetwork.com>.  */
     49 
     50 /* We include this before config.h because it can't handle _FILE_OFFSET_BITS.
     51    Everything we need here is fine if its declarations just come first.  */
     52 
     53 /* TODO ANDROID - defined in AndroidConfig.h. */
     54 #undef _FILE_OFFSET_BITS
     55 
     56 #include <fts.h>
     57 
     58 #include <config.h>
     59 
     60 #include "libdwflP.h"
     61 #include <inttypes.h>
     62 #include <errno.h>
     63 #include <stdio.h>
     64 #include <stdio_ext.h>
     65 #include <string.h>
     66 #include <stdlib.h>
     67 #include <sys/utsname.h>
     68 #include <fcntl.h>
     69 #include <unistd.h>
     70 
     71 
     72 #define KERNEL_MODNAME	"kernel"
     73 
     74 #define MODULEDIRFMT	"/lib/modules/%s"
     75 
     76 #define KNOTESFILE	"/sys/kernel/notes"
     77 #define	MODNOTESFMT	"/sys/module/%s/notes"
     78 #define KSYMSFILE	"/proc/kallsyms"
     79 #define MODULELIST	"/proc/modules"
     80 #define	SECADDRDIRFMT	"/sys/module/%s/sections/"
     81 #define MODULE_SECT_NAME_LEN 32	/* Minimum any linux/module.h has had.  */
     82 
     83 
     84 #if defined (USE_ZLIB) || defined (USE_BZLIB) || defined (USE_LZMA)
     85 static const char *vmlinux_suffixes[] =
     86   {
     87 #ifdef USE_ZLIB
     88     ".gz",
     89 #endif
     90 #ifdef USE_BZLIB
     91     ".bz2",
     92 #endif
     93 #ifdef USE_LZMA
     94     ".xz",
     95 #endif
     96   };
     97 #endif
     98 
     99 /* Try to open the given file as it is or under the debuginfo directory.  */
    100 static int
    101 try_kernel_name (Dwfl *dwfl, char **fname, bool try_debug)
    102 {
    103   if (*fname == NULL)
    104     return -1;
    105 
    106   /* Don't bother trying *FNAME itself here if the path will cause it to be
    107      tried because we give its own basename as DEBUGLINK_FILE.  */
    108   int fd = ((((dwfl->callbacks->debuginfo_path
    109 	       ? *dwfl->callbacks->debuginfo_path : NULL)
    110 	      ?: DEFAULT_DEBUGINFO_PATH)[0] == ':') ? -1
    111 	    : TEMP_FAILURE_RETRY (open64 (*fname, O_RDONLY)));
    112 
    113   if (fd < 0)
    114     {
    115       char *debugfname = NULL;
    116       Dwfl_Module fakemod = { .dwfl = dwfl };
    117       /* First try the file's unadorned basename as DEBUGLINK_FILE,
    118 	 to look for "vmlinux" files.  */
    119       fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0,
    120 						 *fname, basename (*fname), 0,
    121 						 &debugfname);
    122       if (fd < 0 && try_debug)
    123 	/* Next, let the call use the default of basename + ".debug",
    124 	   to look for "vmlinux.debug" files.  */
    125 	fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0,
    126 						   *fname, NULL, 0,
    127 						   &debugfname);
    128       if (debugfname != NULL)
    129 	{
    130 	  free (*fname);
    131 	  *fname = debugfname;
    132 	}
    133     }
    134 
    135 #if defined (USE_ZLIB) || defined (USE_BZLIB) || defined (USE_LZMA)
    136   if (fd < 0)
    137     for (size_t i = 0;
    138 	 i < sizeof vmlinux_suffixes / sizeof vmlinux_suffixes[0];
    139 	 ++i)
    140       {
    141 	char *zname;
    142 	if (asprintf (&zname, "%s%s", *fname, vmlinux_suffixes[i]) > 0)
    143 	  {
    144 	    fd = TEMP_FAILURE_RETRY (open64 (zname, O_RDONLY));
    145 	    if (fd < 0)
    146 	      free (zname);
    147 	    else
    148 	      {
    149 		free (*fname);
    150 		*fname = zname;
    151 	      }
    152 	  }
    153       }
    154 #endif
    155 
    156   if (fd < 0)
    157     {
    158       free (*fname);
    159       *fname = NULL;
    160     }
    161 
    162   return fd;
    163 }
    164 
    165 static inline const char *
    166 kernel_release (void)
    167 {
    168   /* Cache the `uname -r` string we'll use.  */
    169   static struct utsname utsname;
    170   if (utsname.release[0] == '\0' && uname (&utsname) != 0)
    171     return NULL;
    172   return utsname.release;
    173 }
    174 
    175 static int
    176 find_kernel_elf (Dwfl *dwfl, const char *release, char **fname)
    177 {
    178   if ((release[0] == '/'
    179        ? asprintf (fname, "%s/vmlinux", release)
    180        : asprintf (fname, "/boot/vmlinux-%s", release)) < 0)
    181     return -1;
    182 
    183   int fd = try_kernel_name (dwfl, fname, true);
    184   if (fd < 0 && release[0] != '/')
    185     {
    186       free (*fname);
    187       if (asprintf (fname, MODULEDIRFMT "/vmlinux", release) < 0)
    188 	return -1;
    189       fd = try_kernel_name (dwfl, fname, true);
    190     }
    191 
    192   return fd;
    193 }
    194 
    195 static int
    196 get_release (Dwfl *dwfl, const char **release)
    197 {
    198   if (dwfl == NULL)
    199     return -1;
    200 
    201   const char *release_string = release == NULL ? NULL : *release;
    202   if (release_string == NULL)
    203     {
    204       release_string = kernel_release ();
    205       if (release_string == NULL)
    206 	return errno;
    207       if (release != NULL)
    208 	*release = release_string;
    209     }
    210 
    211   return 0;
    212 }
    213 
    214 static int
    215 report_kernel (Dwfl *dwfl, const char **release,
    216 	       int (*predicate) (const char *module, const char *file))
    217 {
    218   int result = get_release (dwfl, release);
    219   if (unlikely (result != 0))
    220     return result;
    221 
    222   char *fname;
    223   int fd = find_kernel_elf (dwfl, *release, &fname);
    224 
    225   if (fd < 0)
    226     result = ((predicate != NULL && !(*predicate) (KERNEL_MODNAME, NULL))
    227 	      ? 0 : errno ?: ENOENT);
    228   else
    229     {
    230       bool report = true;
    231 
    232       if (predicate != NULL)
    233 	{
    234 	  /* Let the predicate decide whether to use this one.  */
    235 	  int want = (*predicate) (KERNEL_MODNAME, fname);
    236 	  if (want < 0)
    237 	    result = errno;
    238 	  report = want > 0;
    239 	}
    240 
    241       if (report)
    242 	{
    243 	  Dwfl_Module *mod = INTUSE(dwfl_report_elf) (dwfl, KERNEL_MODNAME,
    244 						      fname, fd, 0);
    245 	  if (mod == NULL)
    246 	    result = -1;
    247 	  else
    248 	    /* The kernel is ET_EXEC, but always treat it as relocatable.  */
    249 	    mod->e_type = ET_DYN;
    250 	}
    251 
    252       if (!report || result < 0)
    253 	close (fd);
    254     }
    255 
    256   free (fname);
    257 
    258   return result;
    259 }
    260 
    261 /* Look for a kernel debug archive.  If we find one, report all its modules.
    262    If not, return ENOENT.  */
    263 static int
    264 report_kernel_archive (Dwfl *dwfl, const char **release,
    265 		       int (*predicate) (const char *module, const char *file))
    266 {
    267   int result = get_release (dwfl, release);
    268   if (unlikely (result != 0))
    269     return result;
    270 
    271   char *archive;
    272   if (unlikely ((*release)[0] == '/'
    273 		? asprintf (&archive, "%s/debug.a", *release)
    274 		: asprintf (&archive, MODULEDIRFMT "/debug.a", *release)) < 0)
    275     return ENOMEM;
    276 
    277   int fd = try_kernel_name (dwfl, &archive, false);
    278   if (fd < 0)
    279     result = errno ?: ENOENT;
    280   else
    281     {
    282       /* We have the archive file open!  */
    283       Dwfl_Module *last = __libdwfl_report_offline (dwfl, NULL, archive, fd,
    284 						    true, predicate);
    285       if (unlikely (last == NULL))
    286 	result = -1;
    287       else
    288 	{
    289 	  /* Find the kernel and move it to the head of the list.  */
    290 	  Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp;
    291 	  for (Dwfl_Module *m = *prevp; m != NULL; m = *(prevp = &m->next))
    292 	    if (!m->gc && m->e_type != ET_REL && !strcmp (m->name, "kernel"))
    293 	      {
    294 		*prevp = m->next;
    295 		m->next = *tailp;
    296 		*tailp = m;
    297 		break;
    298 	      }
    299 	}
    300     }
    301 
    302   free (archive);
    303   return result;
    304 }
    305 
    306 static size_t
    307 check_suffix (const FTSENT *f, size_t namelen)
    308 {
    309 #define TRY(sfx)							\
    310   if ((namelen ? f->fts_namelen == namelen + sizeof sfx - 1		\
    311        : f->fts_namelen >= sizeof sfx)					\
    312       && !memcmp (f->fts_name + f->fts_namelen - (sizeof sfx - 1),	\
    313 		  sfx, sizeof sfx))					\
    314     return sizeof sfx - 1
    315 
    316   TRY (".ko");
    317 #if USE_ZLIB
    318   TRY (".ko.gz");
    319 #endif
    320 #if USE_BZLIB
    321   TRY (".ko.bz2");
    322 #endif
    323 
    324   return 0;
    325 
    326 #undef	TRY
    327 }
    328 
    329 /* Report a kernel and all its modules found on disk, for offline use.
    330    If RELEASE starts with '/', it names a directory to look in;
    331    if not, it names a directory to find under /lib/modules/;
    332    if null, /lib/modules/`uname -r` is used.
    333    Returns zero on success, -1 if dwfl_report_module failed,
    334    or an errno code if finding the files on disk failed.  */
    335 int
    336 dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char *release,
    337 				  int (*predicate) (const char *module,
    338 						    const char *file))
    339 {
    340   int result = report_kernel_archive (dwfl, &release, predicate);
    341   if (result != ENOENT)
    342     return result;
    343 
    344   /* First report the kernel.  */
    345   result = report_kernel (dwfl, &release, predicate);
    346   if (result == 0)
    347     {
    348       /* Do "find /lib/modules/RELEASE -name *.ko".  */
    349 
    350       char *modulesdir[] = { NULL, NULL };
    351       if (release[0] == '/')
    352 	modulesdir[0] = (char *) release;
    353       else
    354 	{
    355 	  if (asprintf (&modulesdir[0], MODULEDIRFMT, release) < 0)
    356 	    return errno;
    357 	}
    358 
    359       FTS *fts = fts_open (modulesdir, FTS_NOSTAT | FTS_LOGICAL, NULL);
    360       if (modulesdir[0] == (char *) release)
    361 	modulesdir[0] = NULL;
    362       if (fts == NULL)
    363 	{
    364 	  free (modulesdir[0]);
    365 	  return errno;
    366 	}
    367 
    368       FTSENT *f;
    369       while ((f = fts_read (fts)) != NULL)
    370 	{
    371 	  /* Skip a "source" subtree, which tends to be large.
    372 	     This insane hard-coding of names is what depmod does too.  */
    373 	  if (f->fts_namelen == sizeof "source" - 1
    374 	      && !strcmp (f->fts_name, "source"))
    375 	    {
    376 	      fts_set (fts, f, FTS_SKIP);
    377 	      continue;
    378 	    }
    379 
    380 	  switch (f->fts_info)
    381 	    {
    382 	    case FTS_F:
    383 	    case FTS_SL:
    384 	    case FTS_NSOK:;
    385 	      /* See if this file name matches "*.ko".  */
    386 	      const size_t suffix = check_suffix (f, 0);
    387 	      if (suffix)
    388 		{
    389 		  /* We have a .ko file to report.  Following the algorithm
    390 		     by which the kernel makefiles set KBUILD_MODNAME, we
    391 		     replace all ',' or '-' with '_' in the file name and
    392 		     call that the module name.  Modules could well be
    393 		     built using different embedded names than their file
    394 		     names.  To handle that, we would have to look at the
    395 		     __this_module.name contents in the module's text.  */
    396 
    397 		  char name[f->fts_namelen - suffix + 1];
    398 		  for (size_t i = 0; i < f->fts_namelen - 3U; ++i)
    399 		    if (f->fts_name[i] == '-' || f->fts_name[i] == ',')
    400 		      name[i] = '_';
    401 		    else
    402 		      name[i] = f->fts_name[i];
    403 		  name[f->fts_namelen - suffix] = '\0';
    404 
    405 		  if (predicate != NULL)
    406 		    {
    407 		      /* Let the predicate decide whether to use this one.  */
    408 		      int want = (*predicate) (name, f->fts_path);
    409 		      if (want < 0)
    410 			{
    411 			  result = -1;
    412 			  break;
    413 			}
    414 		      if (!want)
    415 			continue;
    416 		    }
    417 
    418 		  if (dwfl_report_offline (dwfl, name, f->fts_path, -1) == NULL)
    419 		    {
    420 		      result = -1;
    421 		      break;
    422 		    }
    423 		}
    424 	      continue;
    425 
    426 	    case FTS_ERR:
    427 	    case FTS_DNR:
    428 	    case FTS_NS:
    429 	      result = f->fts_errno;
    430 	      break;
    431 
    432 	    case FTS_SLNONE:
    433 	    default:
    434 	      continue;
    435 	    }
    436 
    437 	  /* We only get here in error cases.  */
    438 	  break;
    439 	}
    440       fts_close (fts);
    441       free (modulesdir[0]);
    442     }
    443 
    444   return result;
    445 }
    446 INTDEF (dwfl_linux_kernel_report_offline)
    447 
    448 
    449 /* Grovel around to guess the bounds of the runtime kernel image.  */
    450 static int
    451 intuit_kernel_bounds (Dwarf_Addr *start, Dwarf_Addr *end, Dwarf_Addr *notes)
    452 {
    453   FILE *f = fopen (KSYMSFILE, "r");
    454   if (f == NULL)
    455     return errno;
    456 
    457   (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
    458 
    459   *notes = 0;
    460 
    461   char *line = NULL;
    462   size_t linesz = 0;
    463   size_t n;
    464   char *p = NULL;
    465   const char *type;
    466 
    467   inline bool read_address (Dwarf_Addr *addr)
    468   {
    469     if ((n = getline (&line, &linesz, f)) < 1 || line[n - 2] == ']')
    470       return false;
    471     *addr = strtoull (line, &p, 16);
    472     p += strspn (p, " \t");
    473     type = strsep (&p, " \t\n");
    474     if (type == NULL)
    475       return false;
    476     return p != NULL && p != line;
    477   }
    478 
    479   int result;
    480   do
    481     result = read_address (start) ? 0 : -1;
    482   while (result == 0 && strchr ("TtRr", *type) == NULL);
    483 
    484   if (result == 0)
    485     {
    486       *end = *start;
    487       while (read_address (end))
    488 	if (*notes == 0 && !strcmp (p, "__start_notes\n"))
    489 	  *notes = *end;
    490 
    491       Dwarf_Addr round_kernel = sysconf (_SC_PAGE_SIZE);
    492       *start &= -(Dwarf_Addr) round_kernel;
    493       *end += round_kernel - 1;
    494       *end &= -(Dwarf_Addr) round_kernel;
    495       if (*start >= *end || *end - *start < round_kernel)
    496 	result = -1;
    497     }
    498   free (line);
    499 
    500   if (result == -1)
    501     result = ferror_unlocked (f) ? errno : ENOEXEC;
    502 
    503   fclose (f);
    504 
    505   return result;
    506 }
    507 
    508 
    509 /* Look for a build ID note in NOTESFILE and associate the ID with MOD.  */
    510 static int
    511 check_notes (Dwfl_Module *mod, const char *notesfile,
    512 	     Dwarf_Addr vaddr, const char *secname)
    513 {
    514   int fd = open64 (notesfile, O_RDONLY);
    515   if (fd < 0)
    516     return 1;
    517 
    518   assert (sizeof (Elf32_Nhdr) == sizeof (GElf_Nhdr));
    519   assert (sizeof (Elf64_Nhdr) == sizeof (GElf_Nhdr));
    520   union
    521   {
    522     GElf_Nhdr nhdr;
    523     unsigned char data[8192];
    524   } buf;
    525 
    526   ssize_t n = read (fd, buf.data, sizeof buf);
    527   close (fd);
    528 
    529   if (n <= 0)
    530     return 1;
    531 
    532   unsigned char *p = buf.data;
    533   while (p < &buf.data[n])
    534     {
    535       /* No translation required since we are reading the native kernel.  */
    536       GElf_Nhdr *nhdr = (void *) p;
    537       p += sizeof *nhdr;
    538       unsigned char *name = p;
    539       p += (nhdr->n_namesz + 3) & -4U;
    540       unsigned char *bits = p;
    541       p += (nhdr->n_descsz + 3) & -4U;
    542 
    543       if (p <= &buf.data[n]
    544 	  && nhdr->n_type == NT_GNU_BUILD_ID
    545 	  && nhdr->n_namesz == sizeof "GNU"
    546 	  && !memcmp (name, "GNU", sizeof "GNU"))
    547 	{
    548 	  /* Found it.  For a module we must figure out its VADDR now.  */
    549 
    550 	  if (secname != NULL
    551 	      && (INTUSE(dwfl_linux_kernel_module_section_address)
    552 		  (mod, NULL, mod->name, 0, secname, 0, NULL, &vaddr) != 0
    553 		  || vaddr == (GElf_Addr) -1l))
    554 	    vaddr = 0;
    555 
    556 	  if (vaddr != 0)
    557 	    vaddr += bits - buf.data;
    558 	  return INTUSE(dwfl_module_report_build_id) (mod, bits,
    559 						      nhdr->n_descsz, vaddr);
    560 	}
    561     }
    562 
    563   return 0;
    564 }
    565 
    566 /* Look for a build ID for the kernel.  */
    567 static int
    568 check_kernel_notes (Dwfl_Module *kernelmod, GElf_Addr vaddr)
    569 {
    570   return check_notes (kernelmod, KNOTESFILE, vaddr, NULL) < 0 ? -1 : 0;
    571 }
    572 
    573 /* Look for a build ID for a loaded kernel module.  */
    574 static int
    575 check_module_notes (Dwfl_Module *mod)
    576 {
    577   char *dirs[2] = { NULL, NULL };
    578   if (asprintf (&dirs[0], MODNOTESFMT, mod->name) < 0)
    579     return ENOMEM;
    580 
    581   FTS *fts = fts_open (dirs, FTS_NOSTAT | FTS_LOGICAL, NULL);
    582   if (fts == NULL)
    583     {
    584       free (dirs[0]);
    585       return 0;
    586     }
    587 
    588   int result = 0;
    589   FTSENT *f;
    590   while ((f = fts_read (fts)) != NULL)
    591     {
    592       switch (f->fts_info)
    593 	{
    594 	case FTS_F:
    595 	case FTS_SL:
    596 	case FTS_NSOK:
    597 	  result = check_notes (mod, f->fts_accpath, 0, f->fts_name);
    598 	  if (result > 0)	/* Nothing found.  */
    599 	    {
    600 	      result = 0;
    601 	      continue;
    602 	    }
    603 	  break;
    604 
    605 	case FTS_ERR:
    606 	case FTS_DNR:
    607 	  result = f->fts_errno;
    608 	  break;
    609 
    610 	case FTS_NS:
    611 	case FTS_SLNONE:
    612 	default:
    613 	  continue;
    614 	}
    615 
    616       /* We only get here when finished or in error cases.  */
    617       break;
    618     }
    619   fts_close (fts);
    620   free (dirs[0]);
    621 
    622   return result;
    623 }
    624 
    625 int
    626 dwfl_linux_kernel_report_kernel (Dwfl *dwfl)
    627 {
    628   Dwarf_Addr start;
    629   Dwarf_Addr end;
    630   inline Dwfl_Module *report (void)
    631     {
    632       return INTUSE(dwfl_report_module) (dwfl, KERNEL_MODNAME, start, end);
    633     }
    634 
    635   /* This is a bit of a kludge.  If we already reported the kernel,
    636      don't bother figuring it out again--it never changes.  */
    637   for (Dwfl_Module *m = dwfl->modulelist; m != NULL; m = m->next)
    638     if (!strcmp (m->name, KERNEL_MODNAME))
    639       {
    640 	start = m->low_addr;
    641 	end = m->high_addr;
    642 	return report () == NULL ? -1 : 0;
    643       }
    644 
    645   /* Try to figure out the bounds of the kernel image without
    646      looking for any vmlinux file.  */
    647   Dwarf_Addr notes;
    648   /* The compiler cannot deduce that if intuit_kernel_bounds returns
    649      zero NOTES will be initialized.  Fake the initialization.  */
    650   asm ("" : "=m" (notes));
    651   int result = intuit_kernel_bounds (&start, &end, &notes);
    652   if (result == 0)
    653     {
    654       Dwfl_Module *mod = report ();
    655       return unlikely (mod == NULL) ? -1 : check_kernel_notes (mod, notes);
    656     }
    657   if (result != ENOENT)
    658     return result;
    659 
    660   /* Find the ELF file for the running kernel and dwfl_report_elf it.  */
    661   return report_kernel (dwfl, NULL, NULL);
    662 }
    663 INTDEF (dwfl_linux_kernel_report_kernel)
    664 
    665 
    666 /* Dwfl_Callbacks.find_elf for the running Linux kernel and its modules.  */
    667 
    668 int
    669 dwfl_linux_kernel_find_elf (Dwfl_Module *mod,
    670 			    void **userdata __attribute__ ((unused)),
    671 			    const char *module_name,
    672 			    Dwarf_Addr base __attribute__ ((unused)),
    673 			    char **file_name, Elf **elfp)
    674 {
    675   if (mod->build_id_len > 0)
    676     {
    677       int fd = INTUSE(dwfl_build_id_find_elf) (mod, NULL, NULL, 0,
    678 					       file_name, elfp);
    679       if (fd >= 0 || mod->main.elf != NULL || errno != 0)
    680 	return fd;
    681     }
    682 
    683   const char *release = kernel_release ();
    684   if (release == NULL)
    685     return errno;
    686 
    687   if (!strcmp (module_name, KERNEL_MODNAME))
    688     return find_kernel_elf (mod->dwfl, release, file_name);
    689 
    690   /* Do "find /lib/modules/`uname -r` -name MODULE_NAME.ko".  */
    691 
    692   char *modulesdir[] = { NULL, NULL };
    693   if (asprintf (&modulesdir[0], MODULEDIRFMT, release) < 0)
    694     return -1;
    695 
    696   FTS *fts = fts_open (modulesdir, FTS_NOSTAT | FTS_LOGICAL, NULL);
    697   if (fts == NULL)
    698     {
    699       free (modulesdir[0]);
    700       return -1;
    701     }
    702 
    703   size_t namelen = strlen (module_name);
    704 
    705   /* This is a kludge.  There is no actual necessary relationship between
    706      the name of the .ko file installed and the module name the kernel
    707      knows it by when it's loaded.  The kernel's only idea of the module
    708      name comes from the name embedded in the object's magic
    709      .gnu.linkonce.this_module section.
    710 
    711      In practice, these module names match the .ko file names except for
    712      some using '_' and some using '-'.  So our cheap kludge is to look for
    713      two files when either a '_' or '-' appears in a module name, one using
    714      only '_' and one only using '-'.  */
    715 
    716   char alternate_name[namelen + 1];
    717   inline bool subst_name (char from, char to)
    718     {
    719       const char *n = memchr (module_name, from, namelen);
    720       if (n == NULL)
    721 	return false;
    722       char *a = mempcpy (alternate_name, module_name, n - module_name);
    723       *a++ = to;
    724       ++n;
    725       const char *p;
    726       while ((p = memchr (n, from, namelen - (n - module_name))) != NULL)
    727 	{
    728 	  a = mempcpy (a, n, p - n);
    729 	  *a++ = to;
    730 	  n = p + 1;
    731 	}
    732       memcpy (a, n, namelen - (n - module_name) + 1);
    733       return true;
    734     }
    735   if (!subst_name ('-', '_') && !subst_name ('_', '-'))
    736     alternate_name[0] = '\0';
    737 
    738   FTSENT *f;
    739   int error = ENOENT;
    740   while ((f = fts_read (fts)) != NULL)
    741     {
    742       /* Skip a "source" subtree, which tends to be large.
    743 	 This insane hard-coding of names is what depmod does too.  */
    744       if (f->fts_namelen == sizeof "source" - 1
    745 	  && !strcmp (f->fts_name, "source"))
    746 	{
    747 	  fts_set (fts, f, FTS_SKIP);
    748 	  continue;
    749 	}
    750 
    751       error = ENOENT;
    752       switch (f->fts_info)
    753 	{
    754 	case FTS_F:
    755 	case FTS_SL:
    756 	case FTS_NSOK:
    757 	  /* See if this file name is "MODULE_NAME.ko".  */
    758 	  if (check_suffix (f, namelen)
    759 	      && (!memcmp (f->fts_name, module_name, namelen)
    760 		  || !memcmp (f->fts_name, alternate_name, namelen)))
    761 	    {
    762 	      int fd = open64 (f->fts_accpath, O_RDONLY);
    763 	      *file_name = strdup (f->fts_path);
    764 	      fts_close (fts);
    765 	      free (modulesdir[0]);
    766 	      if (fd < 0)
    767 		free (*file_name);
    768 	      else if (*file_name == NULL)
    769 		{
    770 		  close (fd);
    771 		  fd = -1;
    772 		}
    773 	      return fd;
    774 	    }
    775 	  break;
    776 
    777 	case FTS_ERR:
    778 	case FTS_DNR:
    779 	case FTS_NS:
    780 	  error = f->fts_errno;
    781 	  break;
    782 
    783 	case FTS_SLNONE:
    784 	default:
    785 	  break;
    786 	}
    787     }
    788 
    789   fts_close (fts);
    790   free (modulesdir[0]);
    791   errno = error;
    792   return -1;
    793 }
    794 INTDEF (dwfl_linux_kernel_find_elf)
    795 
    796 
    797 /* Dwfl_Callbacks.section_address for kernel modules in the running Linux.
    798    We read the information from /sys/module directly.  */
    799 
    800 int
    801 dwfl_linux_kernel_module_section_address
    802 (Dwfl_Module *mod __attribute__ ((unused)),
    803  void **userdata __attribute__ ((unused)),
    804  const char *modname, Dwarf_Addr base __attribute__ ((unused)),
    805  const char *secname, Elf32_Word shndx __attribute__ ((unused)),
    806  const GElf_Shdr *shdr __attribute__ ((unused)),
    807  Dwarf_Addr *addr)
    808 {
    809   char *sysfile;
    810   if (asprintf (&sysfile, SECADDRDIRFMT "%s", modname, secname) < 0)
    811     return DWARF_CB_ABORT;
    812 
    813   FILE *f = fopen (sysfile, "r");
    814   free (sysfile);
    815 
    816   if (f == NULL)
    817     {
    818       if (errno == ENOENT)
    819 	{
    820 	  /* The .modinfo and .data.percpu sections are never kept
    821 	     loaded in the kernel.  If the kernel was compiled without
    822 	     CONFIG_MODULE_UNLOAD, the .exit.* sections are not
    823 	     actually loaded at all.
    824 
    825 	     Setting *ADDR to -1 tells the caller this section is
    826 	     actually absent from memory.  */
    827 
    828 	  if (!strcmp (secname, ".modinfo")
    829 	      || !strcmp (secname, ".data.percpu")
    830 	      || !strncmp (secname, ".exit", 5))
    831 	    {
    832 	      *addr = (Dwarf_Addr) -1l;
    833 	      return DWARF_CB_OK;
    834 	    }
    835 
    836 	  /* The goofy PPC64 module_frob_arch_sections function tweaks
    837 	     the section names as a way to control other kernel code's
    838 	     behavior, and this cruft leaks out into the /sys information.
    839 	     The file name for ".init*" may actually look like "_init*".  */
    840 
    841 	  const bool is_init = !strncmp (secname, ".init", 5);
    842 	  if (is_init)
    843 	    {
    844 	      if (asprintf (&sysfile, SECADDRDIRFMT "_%s",
    845 			    modname, &secname[1]) < 0)
    846 		return ENOMEM;
    847 	      f = fopen (sysfile, "r");
    848 	      free (sysfile);
    849 	      if (f != NULL)
    850 		goto ok;
    851 	    }
    852 
    853 	  /* The kernel truncates section names to MODULE_SECT_NAME_LEN - 1.
    854 	     In case that size increases in the future, look for longer
    855 	     truncated names first.  */
    856 	  size_t namelen = strlen (secname);
    857 	  if (namelen >= MODULE_SECT_NAME_LEN)
    858 	    {
    859 	      int len = asprintf (&sysfile, SECADDRDIRFMT "%s",
    860 				  modname, secname);
    861 	      if (len < 0)
    862 		return DWARF_CB_ABORT;
    863 	      char *end = sysfile + len;
    864 	      do
    865 		{
    866 		  *--end = '\0';
    867 		  f = fopen (sysfile, "r");
    868 		  if (is_init && f == NULL && errno == ENOENT)
    869 		    {
    870 		      sysfile[len - namelen] = '_';
    871 		      f = fopen (sysfile, "r");
    872 		      sysfile[len - namelen] = '.';
    873 		    }
    874 		}
    875 	      while (f == NULL && errno == ENOENT
    876 		     && end - &sysfile[len - namelen] >= MODULE_SECT_NAME_LEN);
    877 	      free (sysfile);
    878 
    879 	      if (f != NULL)
    880 		goto ok;
    881 	    }
    882 	}
    883 
    884       return DWARF_CB_ABORT;
    885     }
    886 
    887  ok:
    888   (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
    889 
    890   int result = (fscanf (f, "%" PRIx64 "\n", addr) == 1 ? 0
    891 		: ferror_unlocked (f) ? errno : ENOEXEC);
    892   fclose (f);
    893 
    894   if (result == 0)
    895     return DWARF_CB_OK;
    896 
    897   errno = result;
    898   return DWARF_CB_ABORT;
    899 }
    900 INTDEF (dwfl_linux_kernel_module_section_address)
    901 
    902 int
    903 dwfl_linux_kernel_report_modules (Dwfl *dwfl)
    904 {
    905   FILE *f = fopen (MODULELIST, "r");
    906   if (f == NULL)
    907     return errno;
    908 
    909   (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
    910 
    911   int result = 0;
    912   Dwarf_Addr modaddr;
    913   unsigned long int modsz;
    914   char modname[128];
    915   char *line = NULL;
    916   size_t linesz = 0;
    917   /* We can't just use fscanf here because it's not easy to distinguish \n
    918      from other whitespace so as to take the optional word following the
    919      address but always stop at the end of the line.  */
    920   while (getline (&line, &linesz, f) > 0
    921 	 && sscanf (line, "%128s %lu %*s %*s %*s %" PRIx64 " %*s\n",
    922 		    modname, &modsz, &modaddr) == 3)
    923     {
    924       Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, modname,
    925 						     modaddr, modaddr + modsz);
    926       if (mod == NULL)
    927 	{
    928 	  result = -1;
    929 	  break;
    930 	}
    931 
    932       result = check_module_notes (mod);
    933     }
    934   free (line);
    935 
    936   if (result == 0)
    937     result = ferror_unlocked (f) ? errno : feof_unlocked (f) ? 0 : ENOEXEC;
    938 
    939   fclose (f);
    940 
    941   return result;
    942 }
    943 INTDEF (dwfl_linux_kernel_report_modules)
    944