1*7304104dSAndroid Build Coastguard Worker /* Standard libdwfl callbacks for debugging a live Linux process.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2005-2010, 2013, 2014, 2016 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 #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker
33*7304104dSAndroid Build Coastguard Worker #include "libdwflP.h"
34*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
35*7304104dSAndroid Build Coastguard Worker #include <sys/types.h>
36*7304104dSAndroid Build Coastguard Worker #include <sys/stat.h>
37*7304104dSAndroid Build Coastguard Worker #include <errno.h>
38*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
39*7304104dSAndroid Build Coastguard Worker #include <stdio_ext.h>
40*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
41*7304104dSAndroid Build Coastguard Worker #include <string.h>
42*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
43*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
44*7304104dSAndroid Build Coastguard Worker #include <unistd.h>
45*7304104dSAndroid Build Coastguard Worker #include <assert.h>
46*7304104dSAndroid Build Coastguard Worker #include <endian.h>
47*7304104dSAndroid Build Coastguard Worker #include "system.h"
48*7304104dSAndroid Build Coastguard Worker
49*7304104dSAndroid Build Coastguard Worker
50*7304104dSAndroid Build Coastguard Worker #define PROCMAPSFMT "/proc/%d/maps"
51*7304104dSAndroid Build Coastguard Worker #define PROCMEMFMT "/proc/%d/mem"
52*7304104dSAndroid Build Coastguard Worker #define PROCAUXVFMT "/proc/%d/auxv"
53*7304104dSAndroid Build Coastguard Worker #define PROCEXEFMT "/proc/%d/exe"
54*7304104dSAndroid Build Coastguard Worker
55*7304104dSAndroid Build Coastguard Worker
56*7304104dSAndroid Build Coastguard Worker /* Return ELFCLASS64 or ELFCLASS32 for the main ELF executable. Return
57*7304104dSAndroid Build Coastguard Worker ELFCLASSNONE for an error. */
58*7304104dSAndroid Build Coastguard Worker
59*7304104dSAndroid Build Coastguard Worker static unsigned char
get_pid_class(pid_t pid)60*7304104dSAndroid Build Coastguard Worker get_pid_class (pid_t pid)
61*7304104dSAndroid Build Coastguard Worker {
62*7304104dSAndroid Build Coastguard Worker char *fname;
63*7304104dSAndroid Build Coastguard Worker if (asprintf (&fname, PROCEXEFMT, pid) < 0)
64*7304104dSAndroid Build Coastguard Worker return ELFCLASSNONE;
65*7304104dSAndroid Build Coastguard Worker
66*7304104dSAndroid Build Coastguard Worker int fd = open (fname, O_RDONLY);
67*7304104dSAndroid Build Coastguard Worker free (fname);
68*7304104dSAndroid Build Coastguard Worker if (fd < 0)
69*7304104dSAndroid Build Coastguard Worker return ELFCLASSNONE;
70*7304104dSAndroid Build Coastguard Worker
71*7304104dSAndroid Build Coastguard Worker unsigned char buf[EI_CLASS + 1];
72*7304104dSAndroid Build Coastguard Worker ssize_t nread = pread_retry (fd, &buf, sizeof buf, 0);
73*7304104dSAndroid Build Coastguard Worker close (fd);
74*7304104dSAndroid Build Coastguard Worker if (nread != sizeof buf || buf[EI_MAG0] != ELFMAG0
75*7304104dSAndroid Build Coastguard Worker || buf[EI_MAG1] != ELFMAG1 || buf[EI_MAG2] != ELFMAG2
76*7304104dSAndroid Build Coastguard Worker || buf[EI_MAG3] != ELFMAG3
77*7304104dSAndroid Build Coastguard Worker || (buf[EI_CLASS] != ELFCLASS64 && buf[EI_CLASS] != ELFCLASS32))
78*7304104dSAndroid Build Coastguard Worker return ELFCLASSNONE;
79*7304104dSAndroid Build Coastguard Worker
80*7304104dSAndroid Build Coastguard Worker return buf[EI_CLASS];
81*7304104dSAndroid Build Coastguard Worker }
82*7304104dSAndroid Build Coastguard Worker
83*7304104dSAndroid Build Coastguard Worker /* Search /proc/PID/auxv for the AT_SYSINFO_EHDR tag.
84*7304104dSAndroid Build Coastguard Worker
85*7304104dSAndroid Build Coastguard Worker It would be easiest to call get_pid_class and parse everything according to
86*7304104dSAndroid Build Coastguard Worker the 32-bit or 64-bit class. But this would bring the overhead of syscalls
87*7304104dSAndroid Build Coastguard Worker to open and read the "/proc/%d/exe" file.
88*7304104dSAndroid Build Coastguard Worker
89*7304104dSAndroid Build Coastguard Worker Therefore this function tries to parse the "/proc/%d/auxv" content both
90*7304104dSAndroid Build Coastguard Worker ways, as if it were the 32-bit format and also if it were the 64-bit format.
91*7304104dSAndroid Build Coastguard Worker Only if it gives some valid data in both cases get_pid_class gets called.
92*7304104dSAndroid Build Coastguard Worker In most cases only one of the format bit sizes gives valid data and the
93*7304104dSAndroid Build Coastguard Worker get_pid_class call overhead can be saved. */
94*7304104dSAndroid Build Coastguard Worker
95*7304104dSAndroid Build Coastguard Worker static int
grovel_auxv(pid_t pid,Dwfl * dwfl,GElf_Addr * sysinfo_ehdr)96*7304104dSAndroid Build Coastguard Worker grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr)
97*7304104dSAndroid Build Coastguard Worker {
98*7304104dSAndroid Build Coastguard Worker char *fname;
99*7304104dSAndroid Build Coastguard Worker if (asprintf (&fname, PROCAUXVFMT, pid) < 0)
100*7304104dSAndroid Build Coastguard Worker return ENOMEM;
101*7304104dSAndroid Build Coastguard Worker
102*7304104dSAndroid Build Coastguard Worker int fd = open (fname, O_RDONLY);
103*7304104dSAndroid Build Coastguard Worker free (fname);
104*7304104dSAndroid Build Coastguard Worker if (fd < 0)
105*7304104dSAndroid Build Coastguard Worker return errno == ENOENT ? 0 : errno;
106*7304104dSAndroid Build Coastguard Worker
107*7304104dSAndroid Build Coastguard Worker GElf_Addr sysinfo_ehdr64 = 0;
108*7304104dSAndroid Build Coastguard Worker GElf_Addr sysinfo_ehdr32 = 0;
109*7304104dSAndroid Build Coastguard Worker GElf_Addr segment_align64 = dwfl->segment_align;
110*7304104dSAndroid Build Coastguard Worker GElf_Addr segment_align32 = dwfl->segment_align;
111*7304104dSAndroid Build Coastguard Worker off_t offset = 0;
112*7304104dSAndroid Build Coastguard Worker ssize_t nread;
113*7304104dSAndroid Build Coastguard Worker union
114*7304104dSAndroid Build Coastguard Worker {
115*7304104dSAndroid Build Coastguard Worker Elf64_auxv_t a64[64];
116*7304104dSAndroid Build Coastguard Worker Elf32_auxv_t a32[128];
117*7304104dSAndroid Build Coastguard Worker } d;
118*7304104dSAndroid Build Coastguard Worker do
119*7304104dSAndroid Build Coastguard Worker {
120*7304104dSAndroid Build Coastguard Worker eu_static_assert (sizeof d.a64 == sizeof d.a32);
121*7304104dSAndroid Build Coastguard Worker nread = pread_retry (fd, d.a64, sizeof d.a64, offset);
122*7304104dSAndroid Build Coastguard Worker if (nread < 0)
123*7304104dSAndroid Build Coastguard Worker {
124*7304104dSAndroid Build Coastguard Worker int ret = errno;
125*7304104dSAndroid Build Coastguard Worker close (fd);
126*7304104dSAndroid Build Coastguard Worker return ret;
127*7304104dSAndroid Build Coastguard Worker }
128*7304104dSAndroid Build Coastguard Worker for (size_t a32i = 0; a32i < nread / sizeof d.a32[0]; a32i++)
129*7304104dSAndroid Build Coastguard Worker {
130*7304104dSAndroid Build Coastguard Worker const Elf32_auxv_t *a32 = d.a32 + a32i;
131*7304104dSAndroid Build Coastguard Worker switch (a32->a_type)
132*7304104dSAndroid Build Coastguard Worker {
133*7304104dSAndroid Build Coastguard Worker case AT_SYSINFO_EHDR:
134*7304104dSAndroid Build Coastguard Worker sysinfo_ehdr32 = a32->a_un.a_val;
135*7304104dSAndroid Build Coastguard Worker break;
136*7304104dSAndroid Build Coastguard Worker case AT_PAGESZ:
137*7304104dSAndroid Build Coastguard Worker segment_align32 = a32->a_un.a_val;
138*7304104dSAndroid Build Coastguard Worker break;
139*7304104dSAndroid Build Coastguard Worker }
140*7304104dSAndroid Build Coastguard Worker }
141*7304104dSAndroid Build Coastguard Worker for (size_t a64i = 0; a64i < nread / sizeof d.a64[0]; a64i++)
142*7304104dSAndroid Build Coastguard Worker {
143*7304104dSAndroid Build Coastguard Worker const Elf64_auxv_t *a64 = d.a64 + a64i;
144*7304104dSAndroid Build Coastguard Worker switch (a64->a_type)
145*7304104dSAndroid Build Coastguard Worker {
146*7304104dSAndroid Build Coastguard Worker case AT_SYSINFO_EHDR:
147*7304104dSAndroid Build Coastguard Worker sysinfo_ehdr64 = a64->a_un.a_val;
148*7304104dSAndroid Build Coastguard Worker break;
149*7304104dSAndroid Build Coastguard Worker case AT_PAGESZ:
150*7304104dSAndroid Build Coastguard Worker segment_align64 = a64->a_un.a_val;
151*7304104dSAndroid Build Coastguard Worker break;
152*7304104dSAndroid Build Coastguard Worker }
153*7304104dSAndroid Build Coastguard Worker }
154*7304104dSAndroid Build Coastguard Worker offset += nread;
155*7304104dSAndroid Build Coastguard Worker }
156*7304104dSAndroid Build Coastguard Worker while (nread == sizeof d.a64);
157*7304104dSAndroid Build Coastguard Worker
158*7304104dSAndroid Build Coastguard Worker close (fd);
159*7304104dSAndroid Build Coastguard Worker
160*7304104dSAndroid Build Coastguard Worker bool valid64 = sysinfo_ehdr64 != 0 || segment_align64 != dwfl->segment_align;
161*7304104dSAndroid Build Coastguard Worker bool valid32 = sysinfo_ehdr32 != 0 || segment_align32 != dwfl->segment_align;
162*7304104dSAndroid Build Coastguard Worker
163*7304104dSAndroid Build Coastguard Worker unsigned char pid_class = ELFCLASSNONE;
164*7304104dSAndroid Build Coastguard Worker if (valid64 && valid32)
165*7304104dSAndroid Build Coastguard Worker pid_class = get_pid_class (pid);
166*7304104dSAndroid Build Coastguard Worker
167*7304104dSAndroid Build Coastguard Worker if (pid_class == ELFCLASS64 || (valid64 && ! valid32))
168*7304104dSAndroid Build Coastguard Worker {
169*7304104dSAndroid Build Coastguard Worker *sysinfo_ehdr = sysinfo_ehdr64;
170*7304104dSAndroid Build Coastguard Worker dwfl->segment_align = segment_align64;
171*7304104dSAndroid Build Coastguard Worker return 0;
172*7304104dSAndroid Build Coastguard Worker }
173*7304104dSAndroid Build Coastguard Worker if (pid_class == ELFCLASS32 || (! valid64 && valid32))
174*7304104dSAndroid Build Coastguard Worker {
175*7304104dSAndroid Build Coastguard Worker *sysinfo_ehdr = sysinfo_ehdr32;
176*7304104dSAndroid Build Coastguard Worker dwfl->segment_align = segment_align32;
177*7304104dSAndroid Build Coastguard Worker return 0;
178*7304104dSAndroid Build Coastguard Worker }
179*7304104dSAndroid Build Coastguard Worker return ENOEXEC;
180*7304104dSAndroid Build Coastguard Worker }
181*7304104dSAndroid Build Coastguard Worker
182*7304104dSAndroid Build Coastguard Worker static inline bool
do_report(Dwfl * dwfl,char ** plast_file,Dwarf_Addr low,Dwarf_Addr high)183*7304104dSAndroid Build Coastguard Worker do_report (Dwfl *dwfl, char **plast_file, Dwarf_Addr low, Dwarf_Addr high)
184*7304104dSAndroid Build Coastguard Worker {
185*7304104dSAndroid Build Coastguard Worker if (*plast_file != NULL)
186*7304104dSAndroid Build Coastguard Worker {
187*7304104dSAndroid Build Coastguard Worker Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, *plast_file,
188*7304104dSAndroid Build Coastguard Worker low, high);
189*7304104dSAndroid Build Coastguard Worker free (*plast_file);
190*7304104dSAndroid Build Coastguard Worker *plast_file = NULL;
191*7304104dSAndroid Build Coastguard Worker if (unlikely (mod == NULL))
192*7304104dSAndroid Build Coastguard Worker return true;
193*7304104dSAndroid Build Coastguard Worker }
194*7304104dSAndroid Build Coastguard Worker return false;
195*7304104dSAndroid Build Coastguard Worker }
196*7304104dSAndroid Build Coastguard Worker
197*7304104dSAndroid Build Coastguard Worker #define report() do_report(dwfl, &last_file, low, high)
198*7304104dSAndroid Build Coastguard Worker
199*7304104dSAndroid Build Coastguard Worker static int
proc_maps_report(Dwfl * dwfl,FILE * f,GElf_Addr sysinfo_ehdr,pid_t pid)200*7304104dSAndroid Build Coastguard Worker proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid)
201*7304104dSAndroid Build Coastguard Worker {
202*7304104dSAndroid Build Coastguard Worker unsigned int last_dmajor = -1, last_dminor = -1;
203*7304104dSAndroid Build Coastguard Worker uint64_t last_ino = -1;
204*7304104dSAndroid Build Coastguard Worker char *last_file = NULL;
205*7304104dSAndroid Build Coastguard Worker Dwarf_Addr low = 0, high = 0;
206*7304104dSAndroid Build Coastguard Worker
207*7304104dSAndroid Build Coastguard Worker char *line = NULL;
208*7304104dSAndroid Build Coastguard Worker size_t linesz;
209*7304104dSAndroid Build Coastguard Worker ssize_t len;
210*7304104dSAndroid Build Coastguard Worker while ((len = getline (&line, &linesz, f)) > 0)
211*7304104dSAndroid Build Coastguard Worker {
212*7304104dSAndroid Build Coastguard Worker if (line[len - 1] == '\n')
213*7304104dSAndroid Build Coastguard Worker line[len - 1] = '\0';
214*7304104dSAndroid Build Coastguard Worker
215*7304104dSAndroid Build Coastguard Worker Dwarf_Addr start, end, offset;
216*7304104dSAndroid Build Coastguard Worker unsigned int dmajor, dminor;
217*7304104dSAndroid Build Coastguard Worker uint64_t ino;
218*7304104dSAndroid Build Coastguard Worker int nread = -1;
219*7304104dSAndroid Build Coastguard Worker if (sscanf (line, "%" PRIx64 "-%" PRIx64 " %*s %" PRIx64
220*7304104dSAndroid Build Coastguard Worker " %x:%x %" PRIu64 " %n",
221*7304104dSAndroid Build Coastguard Worker &start, &end, &offset, &dmajor, &dminor, &ino, &nread) < 6
222*7304104dSAndroid Build Coastguard Worker || nread <= 0)
223*7304104dSAndroid Build Coastguard Worker {
224*7304104dSAndroid Build Coastguard Worker free (line);
225*7304104dSAndroid Build Coastguard Worker free (last_file);
226*7304104dSAndroid Build Coastguard Worker return ENOEXEC;
227*7304104dSAndroid Build Coastguard Worker }
228*7304104dSAndroid Build Coastguard Worker
229*7304104dSAndroid Build Coastguard Worker /* If this is the special mapping AT_SYSINFO_EHDR pointed us at,
230*7304104dSAndroid Build Coastguard Worker report the last one and then this special one. */
231*7304104dSAndroid Build Coastguard Worker if (start == sysinfo_ehdr && start != 0)
232*7304104dSAndroid Build Coastguard Worker {
233*7304104dSAndroid Build Coastguard Worker if (report ())
234*7304104dSAndroid Build Coastguard Worker {
235*7304104dSAndroid Build Coastguard Worker bad_report:
236*7304104dSAndroid Build Coastguard Worker free (line);
237*7304104dSAndroid Build Coastguard Worker return -1;
238*7304104dSAndroid Build Coastguard Worker }
239*7304104dSAndroid Build Coastguard Worker
240*7304104dSAndroid Build Coastguard Worker low = start;
241*7304104dSAndroid Build Coastguard Worker high = end;
242*7304104dSAndroid Build Coastguard Worker if (asprintf (&last_file, "[vdso: %d]", (int) pid) < 0
243*7304104dSAndroid Build Coastguard Worker || report ())
244*7304104dSAndroid Build Coastguard Worker goto bad_report;
245*7304104dSAndroid Build Coastguard Worker }
246*7304104dSAndroid Build Coastguard Worker
247*7304104dSAndroid Build Coastguard Worker char *file = line + nread + strspn (line + nread, " \t");
248*7304104dSAndroid Build Coastguard Worker if (file[0] != '/' || (ino == 0 && dmajor == 0 && dminor == 0))
249*7304104dSAndroid Build Coastguard Worker /* This line doesn't indicate a file mapping. */
250*7304104dSAndroid Build Coastguard Worker continue;
251*7304104dSAndroid Build Coastguard Worker
252*7304104dSAndroid Build Coastguard Worker if (last_file != NULL
253*7304104dSAndroid Build Coastguard Worker && ino == last_ino && dmajor == last_dmajor && dminor == last_dminor)
254*7304104dSAndroid Build Coastguard Worker {
255*7304104dSAndroid Build Coastguard Worker /* This is another portion of the same file's mapping. */
256*7304104dSAndroid Build Coastguard Worker if (strcmp (last_file, file) != 0)
257*7304104dSAndroid Build Coastguard Worker {
258*7304104dSAndroid Build Coastguard Worker free (last_file);
259*7304104dSAndroid Build Coastguard Worker goto bad_report;
260*7304104dSAndroid Build Coastguard Worker }
261*7304104dSAndroid Build Coastguard Worker high = end;
262*7304104dSAndroid Build Coastguard Worker }
263*7304104dSAndroid Build Coastguard Worker else
264*7304104dSAndroid Build Coastguard Worker {
265*7304104dSAndroid Build Coastguard Worker /* This is a different file mapping. Report the last one. */
266*7304104dSAndroid Build Coastguard Worker if (report ())
267*7304104dSAndroid Build Coastguard Worker goto bad_report;
268*7304104dSAndroid Build Coastguard Worker low = start;
269*7304104dSAndroid Build Coastguard Worker high = end;
270*7304104dSAndroid Build Coastguard Worker last_file = strdup (file);
271*7304104dSAndroid Build Coastguard Worker last_ino = ino;
272*7304104dSAndroid Build Coastguard Worker last_dmajor = dmajor;
273*7304104dSAndroid Build Coastguard Worker last_dminor = dminor;
274*7304104dSAndroid Build Coastguard Worker }
275*7304104dSAndroid Build Coastguard Worker }
276*7304104dSAndroid Build Coastguard Worker free (line);
277*7304104dSAndroid Build Coastguard Worker
278*7304104dSAndroid Build Coastguard Worker int result = ferror_unlocked (f) ? errno : feof_unlocked (f) ? 0 : ENOEXEC;
279*7304104dSAndroid Build Coastguard Worker
280*7304104dSAndroid Build Coastguard Worker /* Report the final one. */
281*7304104dSAndroid Build Coastguard Worker bool lose = report ();
282*7304104dSAndroid Build Coastguard Worker
283*7304104dSAndroid Build Coastguard Worker return result != 0 ? result : lose ? -1 : 0;
284*7304104dSAndroid Build Coastguard Worker }
285*7304104dSAndroid Build Coastguard Worker
286*7304104dSAndroid Build Coastguard Worker int
dwfl_linux_proc_maps_report(Dwfl * dwfl,FILE * f)287*7304104dSAndroid Build Coastguard Worker dwfl_linux_proc_maps_report (Dwfl *dwfl, FILE *f)
288*7304104dSAndroid Build Coastguard Worker {
289*7304104dSAndroid Build Coastguard Worker return proc_maps_report (dwfl, f, 0, 0);
290*7304104dSAndroid Build Coastguard Worker }
INTDEF(dwfl_linux_proc_maps_report)291*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_linux_proc_maps_report)
292*7304104dSAndroid Build Coastguard Worker
293*7304104dSAndroid Build Coastguard Worker int
294*7304104dSAndroid Build Coastguard Worker dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid)
295*7304104dSAndroid Build Coastguard Worker {
296*7304104dSAndroid Build Coastguard Worker if (dwfl == NULL)
297*7304104dSAndroid Build Coastguard Worker return -1;
298*7304104dSAndroid Build Coastguard Worker
299*7304104dSAndroid Build Coastguard Worker /* We'll notice the AT_SYSINFO_EHDR address specially when we hit it. */
300*7304104dSAndroid Build Coastguard Worker GElf_Addr sysinfo_ehdr = 0;
301*7304104dSAndroid Build Coastguard Worker int result = grovel_auxv (pid, dwfl, &sysinfo_ehdr);
302*7304104dSAndroid Build Coastguard Worker if (result != 0)
303*7304104dSAndroid Build Coastguard Worker return result;
304*7304104dSAndroid Build Coastguard Worker
305*7304104dSAndroid Build Coastguard Worker char *fname;
306*7304104dSAndroid Build Coastguard Worker if (asprintf (&fname, PROCMAPSFMT, pid) < 0)
307*7304104dSAndroid Build Coastguard Worker return ENOMEM;
308*7304104dSAndroid Build Coastguard Worker
309*7304104dSAndroid Build Coastguard Worker FILE *f = fopen (fname, "r");
310*7304104dSAndroid Build Coastguard Worker free (fname);
311*7304104dSAndroid Build Coastguard Worker if (f == NULL)
312*7304104dSAndroid Build Coastguard Worker return errno;
313*7304104dSAndroid Build Coastguard Worker
314*7304104dSAndroid Build Coastguard Worker (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
315*7304104dSAndroid Build Coastguard Worker
316*7304104dSAndroid Build Coastguard Worker result = proc_maps_report (dwfl, f, sysinfo_ehdr, pid);
317*7304104dSAndroid Build Coastguard Worker
318*7304104dSAndroid Build Coastguard Worker fclose (f);
319*7304104dSAndroid Build Coastguard Worker
320*7304104dSAndroid Build Coastguard Worker return result;
321*7304104dSAndroid Build Coastguard Worker }
INTDEF(dwfl_linux_proc_report)322*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_linux_proc_report)
323*7304104dSAndroid Build Coastguard Worker
324*7304104dSAndroid Build Coastguard Worker static ssize_t
325*7304104dSAndroid Build Coastguard Worker read_proc_memory (void *arg, void *data, GElf_Addr address,
326*7304104dSAndroid Build Coastguard Worker size_t minread, size_t maxread)
327*7304104dSAndroid Build Coastguard Worker {
328*7304104dSAndroid Build Coastguard Worker const int fd = *(const int *) arg;
329*7304104dSAndroid Build Coastguard Worker
330*7304104dSAndroid Build Coastguard Worker /* This code relies on the fact the Linux kernel accepts negative
331*7304104dSAndroid Build Coastguard Worker offsets when seeking /dev/$$/mem files, as a special case. In
332*7304104dSAndroid Build Coastguard Worker particular pread cannot be used here, because it will always
333*7304104dSAndroid Build Coastguard Worker return EINVAL when passed a negative offset. */
334*7304104dSAndroid Build Coastguard Worker
335*7304104dSAndroid Build Coastguard Worker if (lseek (fd, (off_t) address, SEEK_SET) == -1)
336*7304104dSAndroid Build Coastguard Worker return -1;
337*7304104dSAndroid Build Coastguard Worker
338*7304104dSAndroid Build Coastguard Worker ssize_t nread = read (fd, data, maxread);
339*7304104dSAndroid Build Coastguard Worker
340*7304104dSAndroid Build Coastguard Worker if (nread > 0 && (size_t) nread < minread)
341*7304104dSAndroid Build Coastguard Worker nread = 0;
342*7304104dSAndroid Build Coastguard Worker return nread;
343*7304104dSAndroid Build Coastguard Worker }
344*7304104dSAndroid Build Coastguard Worker
345*7304104dSAndroid Build Coastguard Worker extern Elf *elf_from_remote_memory (GElf_Addr ehdr_vma,
346*7304104dSAndroid Build Coastguard Worker GElf_Xword pagesize,
347*7304104dSAndroid Build Coastguard Worker GElf_Addr *loadbasep,
348*7304104dSAndroid Build Coastguard Worker ssize_t (*read_memory) (void *arg,
349*7304104dSAndroid Build Coastguard Worker void *data,
350*7304104dSAndroid Build Coastguard Worker GElf_Addr address,
351*7304104dSAndroid Build Coastguard Worker size_t minread,
352*7304104dSAndroid Build Coastguard Worker size_t maxread),
353*7304104dSAndroid Build Coastguard Worker void *arg);
354*7304104dSAndroid Build Coastguard Worker
355*7304104dSAndroid Build Coastguard Worker
356*7304104dSAndroid Build Coastguard Worker /* Dwfl_Callbacks.find_elf */
357*7304104dSAndroid Build Coastguard Worker
358*7304104dSAndroid Build Coastguard Worker int
dwfl_linux_proc_find_elf(Dwfl_Module * mod,void ** userdata,const char * module_name,Dwarf_Addr base,char ** file_name,Elf ** elfp)359*7304104dSAndroid Build Coastguard Worker dwfl_linux_proc_find_elf (Dwfl_Module *mod __attribute__ ((unused)),
360*7304104dSAndroid Build Coastguard Worker void **userdata __attribute__ ((unused)),
361*7304104dSAndroid Build Coastguard Worker const char *module_name, Dwarf_Addr base,
362*7304104dSAndroid Build Coastguard Worker char **file_name, Elf **elfp)
363*7304104dSAndroid Build Coastguard Worker {
364*7304104dSAndroid Build Coastguard Worker int pid = -1;
365*7304104dSAndroid Build Coastguard Worker if (module_name[0] == '/')
366*7304104dSAndroid Build Coastguard Worker {
367*7304104dSAndroid Build Coastguard Worker /* When this callback is used together with dwfl_linux_proc_report
368*7304104dSAndroid Build Coastguard Worker then we might see mappings of special character devices. Make
369*7304104dSAndroid Build Coastguard Worker sure we only open and return regular files. Special devices
370*7304104dSAndroid Build Coastguard Worker might hang on open or read. (deleted) files are super special.
371*7304104dSAndroid Build Coastguard Worker The image might come from memory if we are attached. */
372*7304104dSAndroid Build Coastguard Worker struct stat sb;
373*7304104dSAndroid Build Coastguard Worker if (stat (module_name, &sb) == -1 || (sb.st_mode & S_IFMT) != S_IFREG)
374*7304104dSAndroid Build Coastguard Worker {
375*7304104dSAndroid Build Coastguard Worker if (strcmp (strrchr (module_name, ' ') ?: "", " (deleted)") == 0)
376*7304104dSAndroid Build Coastguard Worker pid = INTUSE(dwfl_pid) (mod->dwfl);
377*7304104dSAndroid Build Coastguard Worker else
378*7304104dSAndroid Build Coastguard Worker return -1;
379*7304104dSAndroid Build Coastguard Worker }
380*7304104dSAndroid Build Coastguard Worker
381*7304104dSAndroid Build Coastguard Worker if (pid == -1)
382*7304104dSAndroid Build Coastguard Worker {
383*7304104dSAndroid Build Coastguard Worker int fd = open (module_name, O_RDONLY);
384*7304104dSAndroid Build Coastguard Worker if (fd >= 0)
385*7304104dSAndroid Build Coastguard Worker {
386*7304104dSAndroid Build Coastguard Worker *file_name = strdup (module_name);
387*7304104dSAndroid Build Coastguard Worker if (*file_name == NULL)
388*7304104dSAndroid Build Coastguard Worker {
389*7304104dSAndroid Build Coastguard Worker close (fd);
390*7304104dSAndroid Build Coastguard Worker return ENOMEM;
391*7304104dSAndroid Build Coastguard Worker }
392*7304104dSAndroid Build Coastguard Worker }
393*7304104dSAndroid Build Coastguard Worker return fd;
394*7304104dSAndroid Build Coastguard Worker }
395*7304104dSAndroid Build Coastguard Worker }
396*7304104dSAndroid Build Coastguard Worker
397*7304104dSAndroid Build Coastguard Worker if (pid != -1 || sscanf (module_name, "[vdso: %d]", &pid) == 1)
398*7304104dSAndroid Build Coastguard Worker {
399*7304104dSAndroid Build Coastguard Worker /* Special case for in-memory ELF image. */
400*7304104dSAndroid Build Coastguard Worker
401*7304104dSAndroid Build Coastguard Worker bool detach = false;
402*7304104dSAndroid Build Coastguard Worker bool tid_was_stopped = false;
403*7304104dSAndroid Build Coastguard Worker struct __libdwfl_pid_arg *pid_arg = __libdwfl_get_pid_arg (mod->dwfl);
404*7304104dSAndroid Build Coastguard Worker if (pid_arg != NULL && ! pid_arg->assume_ptrace_stopped)
405*7304104dSAndroid Build Coastguard Worker {
406*7304104dSAndroid Build Coastguard Worker /* If any thread is already attached we are fine. Read
407*7304104dSAndroid Build Coastguard Worker through that thread. It doesn't have to be the main
408*7304104dSAndroid Build Coastguard Worker thread pid. */
409*7304104dSAndroid Build Coastguard Worker pid_t tid = pid_arg->tid_attached;
410*7304104dSAndroid Build Coastguard Worker if (tid != 0)
411*7304104dSAndroid Build Coastguard Worker pid = tid;
412*7304104dSAndroid Build Coastguard Worker else
413*7304104dSAndroid Build Coastguard Worker detach = __libdwfl_ptrace_attach (pid, &tid_was_stopped);
414*7304104dSAndroid Build Coastguard Worker }
415*7304104dSAndroid Build Coastguard Worker
416*7304104dSAndroid Build Coastguard Worker char *fname;
417*7304104dSAndroid Build Coastguard Worker if (asprintf (&fname, PROCMEMFMT, pid) < 0)
418*7304104dSAndroid Build Coastguard Worker goto detach;
419*7304104dSAndroid Build Coastguard Worker
420*7304104dSAndroid Build Coastguard Worker int fd = open (fname, O_RDONLY);
421*7304104dSAndroid Build Coastguard Worker free (fname);
422*7304104dSAndroid Build Coastguard Worker if (fd < 0)
423*7304104dSAndroid Build Coastguard Worker goto detach;
424*7304104dSAndroid Build Coastguard Worker
425*7304104dSAndroid Build Coastguard Worker *elfp = elf_from_remote_memory (base, sysconf (_SC_PAGESIZE), NULL,
426*7304104dSAndroid Build Coastguard Worker &read_proc_memory, &fd);
427*7304104dSAndroid Build Coastguard Worker
428*7304104dSAndroid Build Coastguard Worker close (fd);
429*7304104dSAndroid Build Coastguard Worker
430*7304104dSAndroid Build Coastguard Worker *file_name = NULL;
431*7304104dSAndroid Build Coastguard Worker
432*7304104dSAndroid Build Coastguard Worker detach:
433*7304104dSAndroid Build Coastguard Worker if (detach)
434*7304104dSAndroid Build Coastguard Worker __libdwfl_ptrace_detach (pid, tid_was_stopped);
435*7304104dSAndroid Build Coastguard Worker return -1;
436*7304104dSAndroid Build Coastguard Worker }
437*7304104dSAndroid Build Coastguard Worker
438*7304104dSAndroid Build Coastguard Worker return -1;
439*7304104dSAndroid Build Coastguard Worker }
440*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_linux_proc_find_elf)
441