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)
85static 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.  */
100static int
101try_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
165static inline const char *
166kernel_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
175static int
176find_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
195static int
196get_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
214static int
215report_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.  */
263static int
264report_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
306static size_t
307check_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.  */
335int
336dwfl_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}
446INTDEF (dwfl_linux_kernel_report_offline)
447
448
449/* Grovel around to guess the bounds of the runtime kernel image.  */
450static int
451intuit_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.  */
510static int
511check_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.  */
567static int
568check_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.  */
574static int
575check_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
625int
626dwfl_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}
663INTDEF (dwfl_linux_kernel_report_kernel)
664
665
666/* Dwfl_Callbacks.find_elf for the running Linux kernel and its modules.  */
667
668int
669dwfl_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}
794INTDEF (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
800int
801dwfl_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}
900INTDEF (dwfl_linux_kernel_module_section_address)
901
902int
903dwfl_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}
943INTDEF (dwfl_linux_kernel_report_modules)
944