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, ¬es);
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