blob: bafe53c083db49698c9d4636f9c2f8eec38a7a5c [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Standard libdwfl callbacks for debugging the running Linux kernel.
Roland McGrath6ecdead2011-02-11 12:29:45 -08002 Copyright (C) 2005-2011 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004
Mark Wielaardde2ed972012-06-05 17:15:16 +02005 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007
Mark Wielaardde2ed972012-06-05 17:15:16 +02008 * 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
Ulrich Drepper361df7d2006-04-04 21:38:57 +000021 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
Mark Wielaardde2ed972012-06-05 17:15:16 +020025 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/>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000028
Roland McGrath1d8bb252008-08-07 08:39:41 +000029/* 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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000034#include <config.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000035
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>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000046
47
Ulrich Drepper6258e742007-03-13 06:22:40 +000048#define KERNEL_MODNAME "kernel"
49
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000050#define MODULEDIRFMT "/lib/modules/%s"
51
Roland McGrath59ea7f32007-10-04 08:50:09 +000052#define KNOTESFILE "/sys/kernel/notes"
53#define MODNOTESFMT "/sys/module/%s/notes"
Ulrich Drepper6258e742007-03-13 06:22:40 +000054#define KSYMSFILE "/proc/kallsyms"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000055#define MODULELIST "/proc/modules"
Roland McGratha1cee072006-08-15 01:37:23 +000056#define SECADDRDIRFMT "/sys/module/%s/sections/"
57#define MODULE_SECT_NAME_LEN 32 /* Minimum any linux/module.h has had. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000058
59
Mark Wielaarddbb490f2011-04-11 17:24:16 +020060#if defined (USE_ZLIB) || defined (USE_BZLIB) || defined (USE_LZMA)
Roland McGrath6ecdead2011-02-11 12:29:45 -080061static 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 };
Mark Wielaarddbb490f2011-04-11 17:24:16 +020073#endif
Roland McGrath6ecdead2011-02-11 12:29:45 -080074
Roland McGrathd17fac72005-08-23 08:20:21 +000075/* Try to open the given file as it is or under the debuginfo directory. */
76static int
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000077try_kernel_name (Dwfl *dwfl, char **fname, bool try_debug)
Roland McGrathd17fac72005-08-23 08:20:21 +000078{
79 if (*fname == NULL)
80 return -1;
81
Roland McGratha1cee072006-08-15 01:37:23 +000082 /* 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)));
Roland McGrath6ecdead2011-02-11 12:29:45 -080088
Roland McGrathd17fac72005-08-23 08:20:21 +000089 if (fd < 0)
90 {
91 char *debugfname = NULL;
92 Dwfl_Module fakemod = { .dwfl = dwfl };
Roland McGratha1cee072006-08-15 01:37:23 +000093 /* First try the file's unadorned basename as DEBUGLINK_FILE,
94 to look for "vmlinux" files. */
Roland McGrathd17fac72005-08-23 08:20:21 +000095 fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0,
96 *fname, basename (*fname), 0,
97 &debugfname);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000098 if (fd < 0 && try_debug)
Roland McGratha1cee072006-08-15 01:37:23 +000099 /* 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);
Roland McGrath6ecdead2011-02-11 12:29:45 -0800104 if (debugfname != NULL)
105 {
106 free (*fname);
107 *fname = debugfname;
108 }
109 }
110
Mark Wielaarddbb490f2011-04-11 17:24:16 +0200111#if defined (USE_ZLIB) || defined (USE_BZLIB) || defined (USE_LZMA)
Roland McGrath6ecdead2011-02-11 12:29:45 -0800112 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 }
Mark Wielaarddbb490f2011-04-11 17:24:16 +0200130#endif
Roland McGrath6ecdead2011-02-11 12:29:45 -0800131
132 if (fd < 0)
133 {
Roland McGrathd17fac72005-08-23 08:20:21 +0000134 free (*fname);
Roland McGrath6ecdead2011-02-11 12:29:45 -0800135 *fname = NULL;
Roland McGrathd17fac72005-08-23 08:20:21 +0000136 }
137
138 return fd;
139}
140
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000141static inline const char *
142kernel_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
Roland McGrathd17fac72005-08-23 08:20:21 +0000151static int
Ulrich Drepper6258e742007-03-13 06:22:40 +0000152find_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
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000159 int fd = try_kernel_name (dwfl, fname, true);
Ulrich Drepper6258e742007-03-13 06:22:40 +0000160 if (fd < 0 && release[0] != '/')
161 {
162 free (*fname);
163 if (asprintf (fname, MODULEDIRFMT "/vmlinux", release) < 0)
164 return -1;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000165 fd = try_kernel_name (dwfl, fname, true);
Ulrich Drepper6258e742007-03-13 06:22:40 +0000166 }
167
168 return fd;
169}
170
171static int
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000172get_release (Dwfl *dwfl, const char **release)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000173{
174 if (dwfl == NULL)
175 return -1;
176
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000177 const char *release_string = release == NULL ? NULL : *release;
178 if (release_string == NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000179 {
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000180 release_string = kernel_release ();
181 if (release_string == NULL)
Ulrich Drepper6258e742007-03-13 06:22:40 +0000182 return errno;
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000183 if (release != NULL)
184 *release = release_string;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000185 }
186
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000187 return 0;
188}
Ulrich Drepper6258e742007-03-13 06:22:40 +0000189
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000190static int
191report_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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000201 if (fd < 0)
Ulrich Drepper6258e742007-03-13 06:22:40 +0000202 result = ((predicate != NULL && !(*predicate) (KERNEL_MODNAME, NULL))
Roland McGrath07d4f2f2005-10-28 06:56:24 +0000203 ? 0 : errno ?: ENOENT);
Roland McGrathd17fac72005-08-23 08:20:21 +0000204 else
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000205 {
Roland McGrathd17fac72005-08-23 08:20:21 +0000206 bool report = true;
207
208 if (predicate != NULL)
209 {
210 /* Let the predicate decide whether to use this one. */
Ulrich Drepper6258e742007-03-13 06:22:40 +0000211 int want = (*predicate) (KERNEL_MODNAME, fname);
Roland McGrathd17fac72005-08-23 08:20:21 +0000212 if (want < 0)
213 result = errno;
214 report = want > 0;
215 }
216
Roland McGrath59ea7f32007-10-04 08:50:09 +0000217 if (report)
Roland McGrathd17fac72005-08-23 08:20:21 +0000218 {
Roland McGrath59ea7f32007-10-04 08:50:09 +0000219 Dwfl_Module *mod = INTUSE(dwfl_report_elf) (dwfl, KERNEL_MODNAME,
220 fname, fd, 0);
221 if (mod == NULL)
222 result = -1;
Roland McGrath9897d662008-04-29 01:49:50 +0000223 else
224 /* The kernel is ET_EXEC, but always treat it as relocatable. */
225 mod->e_type = ET_DYN;
Roland McGrathd17fac72005-08-23 08:20:21 +0000226 }
Roland McGrath59ea7f32007-10-04 08:50:09 +0000227
228 if (!report || result < 0)
229 close (fd);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000230 }
231
232 free (fname);
233
234 return result;
235}
Roland McGrathd17fac72005-08-23 08:20:21 +0000236
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000237/* Look for a kernel debug archive. If we find one, report all its modules.
238 If not, return ENOENT. */
239static int
240report_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
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000257 {
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 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000277
278 free (archive);
279 return result;
280}
281
Roland McGrath705364b2009-01-06 02:04:51 -0800282static size_t
283check_suffix (const FTSENT *f, size_t namelen)
Roland McGrath60205c92009-01-06 00:10:23 -0800284{
Roland McGrath705364b2009-01-06 02:04:51 -0800285#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
Roland McGrath60205c92009-01-06 00:10:23 -0800291
Roland McGrath705364b2009-01-06 02:04:51 -0800292 TRY (".ko");
Roland McGrath60205c92009-01-06 00:10:23 -0800293#if USE_ZLIB
Roland McGrath705364b2009-01-06 02:04:51 -0800294 TRY (".ko.gz");
Roland McGrath60205c92009-01-06 00:10:23 -0800295#endif
296#if USE_BZLIB
Roland McGrath705364b2009-01-06 02:04:51 -0800297 TRY (".ko.bz2");
Roland McGrath60205c92009-01-06 00:10:23 -0800298#endif
Roland McGrath60205c92009-01-06 00:10:23 -0800299
Roland McGrath705364b2009-01-06 02:04:51 -0800300 return 0;
301
302#undef TRY
Roland McGrath60205c92009-01-06 00:10:23 -0800303}
304
Roland McGrathd17fac72005-08-23 08:20:21 +0000305/* 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. */
311int
312dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char *release,
313 int (*predicate) (const char *module,
314 const char *file))
315{
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000316 int result = report_kernel_archive (dwfl, &release, predicate);
317 if (result != ENOENT)
318 return result;
319
Roland McGrathd17fac72005-08-23 08:20:21 +0000320 /* First report the kernel. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000321 result = report_kernel (dwfl, &release, predicate);
Roland McGrathd17fac72005-08-23 08:20:21 +0000322 if (result == 0)
323 {
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000324 /* Do "find /lib/modules/RELEASE -name *.ko". */
Roland McGrathd17fac72005-08-23 08:20:21 +0000325
326 char *modulesdir[] = { NULL, NULL };
327 if (release[0] == '/')
328 modulesdir[0] = (char *) release;
329 else
330 {
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000331 if (asprintf (&modulesdir[0], MODULEDIRFMT, release) < 0)
Roland McGrathd17fac72005-08-23 08:20:21 +0000332 return errno;
333 }
334
Roland McGrath0fa20e82008-05-07 18:37:14 +0000335 FTS *fts = fts_open (modulesdir, FTS_NOSTAT | FTS_LOGICAL, NULL);
Roland McGrathd17fac72005-08-23 08:20:21 +0000336 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 {
Roland McGratha4b1a952009-01-08 20:53:26 -0800347 /* 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
Roland McGrathd17fac72005-08-23 08:20:21 +0000356 switch (f->fts_info)
357 {
358 case FTS_F:
Roland McGrath0fa20e82008-05-07 18:37:14 +0000359 case FTS_SL:
Roland McGrath705364b2009-01-06 02:04:51 -0800360 case FTS_NSOK:;
Roland McGrathd17fac72005-08-23 08:20:21 +0000361 /* See if this file name matches "*.ko". */
Roland McGrath705364b2009-01-06 02:04:51 -0800362 const size_t suffix = check_suffix (f, 0);
363 if (suffix)
Roland McGrathd17fac72005-08-23 08:20:21 +0000364 {
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
Roland McGrath705364b2009-01-06 02:04:51 -0800373 char name[f->fts_namelen - suffix + 1];
Roland McGrathd17fac72005-08-23 08:20:21 +0000374 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];
Roland McGrath705364b2009-01-06 02:04:51 -0800379 name[f->fts_namelen - suffix] = '\0';
Roland McGrathd17fac72005-08-23 08:20:21 +0000380
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
Roland McGrath705364b2009-01-06 02:04:51 -0800394 if (dwfl_report_offline (dwfl, name, f->fts_path, -1) == NULL)
Roland McGrathd17fac72005-08-23 08:20:21 +0000395 {
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
Roland McGrath0fa20e82008-05-07 18:37:14 +0000408 case FTS_SLNONE:
Roland McGrathd17fac72005-08-23 08:20:21 +0000409 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}
422INTDEF (dwfl_linux_kernel_report_offline)
423
424
Ulrich Drepper6258e742007-03-13 06:22:40 +0000425/* Grovel around to guess the bounds of the runtime kernel image. */
426static int
Roland McGrath59ea7f32007-10-04 08:50:09 +0000427intuit_kernel_bounds (Dwarf_Addr *start, Dwarf_Addr *end, Dwarf_Addr *notes)
Ulrich Drepper6258e742007-03-13 06:22:40 +0000428{
429 FILE *f = fopen (KSYMSFILE, "r");
430 if (f == NULL)
431 return errno;
432
433 (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
434
Roland McGrath59ea7f32007-10-04 08:50:09 +0000435 *notes = 0;
436
Ulrich Drepper6258e742007-03-13 06:22:40 +0000437 char *line = NULL;
438 size_t linesz = 0;
Roland McGrathbe9c4d72010-05-19 21:24:27 -0700439 size_t n;
Ulrich Drepper6258e742007-03-13 06:22:40 +0000440 char *p = NULL;
Roland McGrathbe9c4d72010-05-19 21:24:27 -0700441 const char *type;
Roland McGrath59ea7f32007-10-04 08:50:09 +0000442
Roland McGrathbe9c4d72010-05-19 21:24:27 -0700443 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;
Ulrich Drepper6258e742007-03-13 06:22:40 +0000473 }
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
Roland McGrath59ea7f32007-10-04 08:50:09 +0000484
485/* Look for a build ID note in NOTESFILE and associate the ID with MOD. */
486static int
487check_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. */
543static int
544check_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. */
550static int
551check_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
Roland McGrath0fa20e82008-05-07 18:37:14 +0000557 FTS *fts = fts_open (dirs, FTS_NOSTAT | FTS_LOGICAL, NULL);
Roland McGrath59ea7f32007-10-04 08:50:09 +0000558 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:
Roland McGrath0fa20e82008-05-07 18:37:14 +0000571 case FTS_SL:
Roland McGrath59ea7f32007-10-04 08:50:09 +0000572 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:
Roland McGrath0fa20e82008-05-07 18:37:14 +0000587 case FTS_SLNONE:
Roland McGrath59ea7f32007-10-04 08:50:09 +0000588 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
Roland McGrathd17fac72005-08-23 08:20:21 +0000601int
602dwfl_linux_kernel_report_kernel (Dwfl *dwfl)
603{
Ulrich Drepper6258e742007-03-13 06:22:40 +0000604 Dwarf_Addr start;
605 Dwarf_Addr end;
Roland McGrath59ea7f32007-10-04 08:50:09 +0000606 inline Dwfl_Module *report (void)
Ulrich Drepper6258e742007-03-13 06:22:40 +0000607 {
Roland McGrath59ea7f32007-10-04 08:50:09 +0000608 return INTUSE(dwfl_report_module) (dwfl, KERNEL_MODNAME, start, end);
Ulrich Drepper6258e742007-03-13 06:22:40 +0000609 }
Roland McGrathd17fac72005-08-23 08:20:21 +0000610
Ulrich Drepper6258e742007-03-13 06:22:40 +0000611 /* 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;
Roland McGrath59ea7f32007-10-04 08:50:09 +0000618 return report () == NULL ? -1 : 0;
Ulrich Drepper6258e742007-03-13 06:22:40 +0000619 }
620
621 /* Try to figure out the bounds of the kernel image without
622 looking for any vmlinux file. */
Roland McGrath59ea7f32007-10-04 08:50:09 +0000623 Dwarf_Addr notes;
Ulrich Drepper3fc3d7b2007-10-04 18:40:28 +0000624 /* The compiler cannot deduce that if intuit_kernel_bounds returns
625 zero NOTES will be initialized. Fake the initialization. */
626 asm ("" : "=m" (notes));
Roland McGrath59ea7f32007-10-04 08:50:09 +0000627 int result = intuit_kernel_bounds (&start, &end, &notes);
Ulrich Drepper6258e742007-03-13 06:22:40 +0000628 if (result == 0)
Roland McGrath59ea7f32007-10-04 08:50:09 +0000629 {
630 Dwfl_Module *mod = report ();
631 return unlikely (mod == NULL) ? -1 : check_kernel_notes (mod, notes);
632 }
Ulrich Drepper6258e742007-03-13 06:22:40 +0000633 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);
Roland McGrathd17fac72005-08-23 08:20:21 +0000638}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000639INTDEF (dwfl_linux_kernel_report_kernel)
640
Roland McGrathd17fac72005-08-23 08:20:21 +0000641
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000642/* Dwfl_Callbacks.find_elf for the running Linux kernel and its modules. */
643
644int
Roland McGrath59ea7f32007-10-04 08:50:09 +0000645dwfl_linux_kernel_find_elf (Dwfl_Module *mod,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000646 void **userdata __attribute__ ((unused)),
647 const char *module_name,
648 Dwarf_Addr base __attribute__ ((unused)),
Roland McGrath59ea7f32007-10-04 08:50:09 +0000649 char **file_name, Elf **elfp)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000650{
Roland McGrath59ea7f32007-10-04 08:50:09 +0000651 if (mod->build_id_len > 0)
652 {
653 int fd = INTUSE(dwfl_build_id_find_elf) (mod, NULL, NULL, 0,
654 file_name, elfp);
Roland McGrath81cfcca2010-06-30 00:45:58 -0700655 if (fd >= 0 || mod->main.elf != NULL || errno != 0)
Roland McGrath59ea7f32007-10-04 08:50:09 +0000656 return fd;
657 }
658
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000659 const char *release = kernel_release ();
660 if (release == NULL)
Roland McGrathd17fac72005-08-23 08:20:21 +0000661 return errno;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000662
Ulrich Drepper6258e742007-03-13 06:22:40 +0000663 if (!strcmp (module_name, KERNEL_MODNAME))
664 return find_kernel_elf (mod->dwfl, release, file_name);
665
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000666 /* Do "find /lib/modules/`uname -r` -name MODULE_NAME.ko". */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000667
668 char *modulesdir[] = { NULL, NULL };
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000669 if (asprintf (&modulesdir[0], MODULEDIRFMT, release) < 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000670 return -1;
671
Roland McGrath0fa20e82008-05-07 18:37:14 +0000672 FTS *fts = fts_open (modulesdir, FTS_NOSTAT | FTS_LOGICAL, NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000673 if (fts == NULL)
674 {
675 free (modulesdir[0]);
676 return -1;
677 }
678
679 size_t namelen = strlen (module_name);
Roland McGrath5678f872005-08-07 21:42:56 +0000680
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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000714 FTSENT *f;
715 int error = ENOENT;
716 while ((f = fts_read (fts)) != NULL)
717 {
Roland McGratha4b1a952009-01-08 20:53:26 -0800718 /* 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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000727 error = ENOENT;
728 switch (f->fts_info)
729 {
730 case FTS_F:
Roland McGrath0fa20e82008-05-07 18:37:14 +0000731 case FTS_SL:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000732 case FTS_NSOK:
733 /* See if this file name is "MODULE_NAME.ko". */
Roland McGrath705364b2009-01-06 02:04:51 -0800734 if (check_suffix (f, namelen)
Roland McGrath5678f872005-08-07 21:42:56 +0000735 && (!memcmp (f->fts_name, module_name, namelen)
736 || !memcmp (f->fts_name, alternate_name, namelen)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000737 {
738 int fd = open64 (f->fts_accpath, O_RDONLY);
739 *file_name = strdup (f->fts_path);
740 fts_close (fts);
Roland McGrathd17fac72005-08-23 08:20:21 +0000741 free (modulesdir[0]);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000742 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
Roland McGrath0fa20e82008-05-07 18:37:14 +0000759 case FTS_SLNONE:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000760 default:
761 break;
762 }
763 }
764
Roland McGrathd17fac72005-08-23 08:20:21 +0000765 fts_close (fts);
766 free (modulesdir[0]);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000767 errno = error;
768 return -1;
769}
770INTDEF (dwfl_linux_kernel_find_elf)
771
Roland McGrathd17fac72005-08-23 08:20:21 +0000772
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000773/* Dwfl_Callbacks.section_address for kernel modules in the running Linux.
774 We read the information from /sys/module directly. */
775
776int
777dwfl_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)),
Roland McGrathd17fac72005-08-23 08:20:21 +0000781 const char *secname, Elf32_Word shndx __attribute__ ((unused)),
782 const GElf_Shdr *shdr __attribute__ ((unused)),
783 Dwarf_Addr *addr)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000784{
Roland McGrath44865b92007-01-11 05:06:16 +0000785 char *sysfile;
Ulrich Drepper6258e742007-03-13 06:22:40 +0000786 if (asprintf (&sysfile, SECADDRDIRFMT "%s", modname, secname) < 0)
Roland McGrath59ea7f32007-10-04 08:50:09 +0000787 return DWARF_CB_ABORT;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000788
789 FILE *f = fopen (sysfile, "r");
Roland McGrath2e53b992005-11-21 23:40:54 +0000790 free (sysfile);
791
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000792 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
Ulrich Drepperaa915fd2007-02-05 07:25:33 +0000801 Setting *ADDR to -1 tells the caller this section is
802 actually absent from memory. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000803
804 if (!strcmp (secname, ".modinfo")
805 || !strcmp (secname, ".data.percpu")
806 || !strncmp (secname, ".exit", 5))
807 {
Ulrich Drepperaa915fd2007-02-05 07:25:33 +0000808 *addr = (Dwarf_Addr) -1l;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000809 return DWARF_CB_OK;
810 }
Roland McGrath2e53b992005-11-21 23:40:54 +0000811
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
Roland McGratha1cee072006-08-15 01:37:23 +0000817 const bool is_init = !strncmp (secname, ".init", 5);
818 if (is_init)
Roland McGrath2e53b992005-11-21 23:40:54 +0000819 {
Roland McGrath44865b92007-01-11 05:06:16 +0000820 if (asprintf (&sysfile, SECADDRDIRFMT "_%s",
821 modname, &secname[1]) < 0)
Roland McGrath2e53b992005-11-21 23:40:54 +0000822 return ENOMEM;
823 f = fopen (sysfile, "r");
824 free (sysfile);
825 if (f != NULL)
826 goto ok;
827 }
Roland McGratha1cee072006-08-15 01:37:23 +0000828
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 {
Roland McGratha1cee072006-08-15 01:37:23 +0000835 int len = asprintf (&sysfile, SECADDRDIRFMT "%s",
836 modname, secname);
Roland McGrath44865b92007-01-11 05:06:16 +0000837 if (len < 0)
Roland McGrath59ea7f32007-10-04 08:50:09 +0000838 return DWARF_CB_ABORT;
Roland McGratha1cee072006-08-15 01:37:23 +0000839 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 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000858 }
859
860 return DWARF_CB_ABORT;
861 }
862
Roland McGrath2e53b992005-11-21 23:40:54 +0000863 ok:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000864 (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
865
Roland McGrath07d4f2f2005-10-28 06:56:24 +0000866 int result = (fscanf (f, "%" PRIx64 "\n", addr) == 1 ? 0
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000867 : 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}
876INTDEF (dwfl_linux_kernel_module_section_address)
877
878int
879dwfl_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];
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000891 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)
Roland McGrath59ea7f32007-10-04 08:50:09 +0000899 {
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 }
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000910 free (line);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000911
912 if (result == 0)
913 result = ferror_unlocked (f) ? errno : feof_unlocked (f) ? 0 : ENOEXEC;
914
915 fclose (f);
916
917 return result;
918}
919INTDEF (dwfl_linux_kernel_report_modules)