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