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