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