• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
try_kernel_name(Dwfl * dwfl,char ** fname,bool try_debug)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 *
kernel_release(void)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
find_kernel_elf(Dwfl * dwfl,const char * release,char ** fname)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
get_release(Dwfl * dwfl,const char ** release)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
report_kernel(Dwfl * dwfl,const char ** release,int (* predicate)(const char * module,const char * file))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
report_kernel_archive(Dwfl * dwfl,const char ** release,int (* predicate)(const char * module,const char * file))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
check_suffix(const FTSENT * f,size_t namelen)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
dwfl_linux_kernel_report_offline(Dwfl * dwfl,const char * release,int (* predicate)(const char * module,const char * file))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 }
INTDEF(dwfl_linux_kernel_report_offline)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
check_notes(Dwfl_Module * mod,const char * notesfile,Dwarf_Addr vaddr,const char * secname)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
check_kernel_notes(Dwfl_Module * kernelmod,GElf_Addr vaddr)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
check_module_notes(Dwfl_Module * mod)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
dwfl_linux_kernel_report_kernel(Dwfl * dwfl)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 }
INTDEF(dwfl_linux_kernel_report_kernel)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 }
INTDEF(dwfl_linux_kernel_find_elf)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 }
INTDEF(dwfl_linux_kernel_module_section_address)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