1*7304104dSAndroid Build Coastguard Worker /* Report modules by examining dynamic linker data structures.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2008-2016 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker Copyright (C) 2021 Mark J. Wielaard <[email protected]>
4*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
5*7304104dSAndroid Build Coastguard Worker
6*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker it under the terms of either
8*7304104dSAndroid Build Coastguard Worker
9*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker your option) any later version
12*7304104dSAndroid Build Coastguard Worker
13*7304104dSAndroid Build Coastguard Worker or
14*7304104dSAndroid Build Coastguard Worker
15*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker your option) any later version
18*7304104dSAndroid Build Coastguard Worker
19*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker
21*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24*7304104dSAndroid Build Coastguard Worker General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker
26*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
28*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
29*7304104dSAndroid Build Coastguard Worker
30*7304104dSAndroid Build Coastguard Worker #include <config.h>
31*7304104dSAndroid Build Coastguard Worker #include "libdwflP.h"
32*7304104dSAndroid Build Coastguard Worker #include "memory-access.h"
33*7304104dSAndroid Build Coastguard Worker #include "system.h"
34*7304104dSAndroid Build Coastguard Worker
35*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
36*7304104dSAndroid Build Coastguard Worker
37*7304104dSAndroid Build Coastguard Worker /* This element is always provided and always has a constant value.
38*7304104dSAndroid Build Coastguard Worker This makes it an easy thing to scan for to discern the format. */
39*7304104dSAndroid Build Coastguard Worker #define PROBE_TYPE AT_PHENT
40*7304104dSAndroid Build Coastguard Worker #define PROBE_VAL32 sizeof (Elf32_Phdr)
41*7304104dSAndroid Build Coastguard Worker #define PROBE_VAL64 sizeof (Elf64_Phdr)
42*7304104dSAndroid Build Coastguard Worker
43*7304104dSAndroid Build Coastguard Worker
44*7304104dSAndroid Build Coastguard Worker static inline bool
do_check64(const char * a64,uint_fast8_t * elfdata)45*7304104dSAndroid Build Coastguard Worker do_check64 (const char *a64, uint_fast8_t *elfdata)
46*7304104dSAndroid Build Coastguard Worker {
47*7304104dSAndroid Build Coastguard Worker /* The AUXV pointer might not even be naturally aligned for 64-bit
48*7304104dSAndroid Build Coastguard Worker data, because note payloads in a core file are not aligned. */
49*7304104dSAndroid Build Coastguard Worker const char *typep = a64 + offsetof (Elf64_auxv_t, a_type);
50*7304104dSAndroid Build Coastguard Worker uint64_t type = read_8ubyte_unaligned_noncvt (typep);
51*7304104dSAndroid Build Coastguard Worker const char *valp = a64 + offsetof (Elf64_auxv_t, a_un.a_val);
52*7304104dSAndroid Build Coastguard Worker uint64_t val = read_8ubyte_unaligned_noncvt (valp);
53*7304104dSAndroid Build Coastguard Worker
54*7304104dSAndroid Build Coastguard Worker if (type == BE64 (PROBE_TYPE)
55*7304104dSAndroid Build Coastguard Worker && val == BE64 (PROBE_VAL64))
56*7304104dSAndroid Build Coastguard Worker {
57*7304104dSAndroid Build Coastguard Worker *elfdata = ELFDATA2MSB;
58*7304104dSAndroid Build Coastguard Worker return true;
59*7304104dSAndroid Build Coastguard Worker }
60*7304104dSAndroid Build Coastguard Worker
61*7304104dSAndroid Build Coastguard Worker if (type == LE64 (PROBE_TYPE)
62*7304104dSAndroid Build Coastguard Worker && val == LE64 (PROBE_VAL64))
63*7304104dSAndroid Build Coastguard Worker {
64*7304104dSAndroid Build Coastguard Worker *elfdata = ELFDATA2LSB;
65*7304104dSAndroid Build Coastguard Worker return true;
66*7304104dSAndroid Build Coastguard Worker }
67*7304104dSAndroid Build Coastguard Worker
68*7304104dSAndroid Build Coastguard Worker return false;
69*7304104dSAndroid Build Coastguard Worker }
70*7304104dSAndroid Build Coastguard Worker
71*7304104dSAndroid Build Coastguard Worker static inline bool
do_check32(const char * a32,uint_fast8_t * elfdata)72*7304104dSAndroid Build Coastguard Worker do_check32 (const char *a32, uint_fast8_t *elfdata)
73*7304104dSAndroid Build Coastguard Worker {
74*7304104dSAndroid Build Coastguard Worker /* The AUXV pointer might not even be naturally aligned for 32-bit
75*7304104dSAndroid Build Coastguard Worker data, because note payloads in a core file are not aligned. */
76*7304104dSAndroid Build Coastguard Worker const char *typep = a32 + offsetof (Elf32_auxv_t, a_type);
77*7304104dSAndroid Build Coastguard Worker uint32_t type = read_4ubyte_unaligned_noncvt (typep);
78*7304104dSAndroid Build Coastguard Worker const char *valp = a32 + offsetof (Elf32_auxv_t, a_un.a_val);
79*7304104dSAndroid Build Coastguard Worker uint32_t val = read_4ubyte_unaligned_noncvt (valp);
80*7304104dSAndroid Build Coastguard Worker
81*7304104dSAndroid Build Coastguard Worker if (type == BE32 (PROBE_TYPE)
82*7304104dSAndroid Build Coastguard Worker && val == BE32 (PROBE_VAL32))
83*7304104dSAndroid Build Coastguard Worker {
84*7304104dSAndroid Build Coastguard Worker *elfdata = ELFDATA2MSB;
85*7304104dSAndroid Build Coastguard Worker return true;
86*7304104dSAndroid Build Coastguard Worker }
87*7304104dSAndroid Build Coastguard Worker
88*7304104dSAndroid Build Coastguard Worker if (type == LE32 (PROBE_TYPE)
89*7304104dSAndroid Build Coastguard Worker && val == LE32 (PROBE_VAL32))
90*7304104dSAndroid Build Coastguard Worker {
91*7304104dSAndroid Build Coastguard Worker *elfdata = ELFDATA2LSB;
92*7304104dSAndroid Build Coastguard Worker return true;
93*7304104dSAndroid Build Coastguard Worker }
94*7304104dSAndroid Build Coastguard Worker
95*7304104dSAndroid Build Coastguard Worker return false;
96*7304104dSAndroid Build Coastguard Worker }
97*7304104dSAndroid Build Coastguard Worker
98*7304104dSAndroid Build Coastguard Worker /* Examine an auxv data block and determine its format.
99*7304104dSAndroid Build Coastguard Worker Return true iff we figured it out. */
100*7304104dSAndroid Build Coastguard Worker static bool
auxv_format_probe(const void * auxv,size_t size,uint_fast8_t * elfclass,uint_fast8_t * elfdata)101*7304104dSAndroid Build Coastguard Worker auxv_format_probe (const void *auxv, size_t size,
102*7304104dSAndroid Build Coastguard Worker uint_fast8_t *elfclass, uint_fast8_t *elfdata)
103*7304104dSAndroid Build Coastguard Worker {
104*7304104dSAndroid Build Coastguard Worker for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
105*7304104dSAndroid Build Coastguard Worker {
106*7304104dSAndroid Build Coastguard Worker if (do_check64 (auxv + i * sizeof (Elf64_auxv_t), elfdata))
107*7304104dSAndroid Build Coastguard Worker {
108*7304104dSAndroid Build Coastguard Worker *elfclass = ELFCLASS64;
109*7304104dSAndroid Build Coastguard Worker return true;
110*7304104dSAndroid Build Coastguard Worker }
111*7304104dSAndroid Build Coastguard Worker
112*7304104dSAndroid Build Coastguard Worker if (do_check32 (auxv + (i * 2) * sizeof (Elf32_auxv_t), elfdata)
113*7304104dSAndroid Build Coastguard Worker || do_check32 (auxv + (i * 2 + 1) * sizeof (Elf32_auxv_t), elfdata))
114*7304104dSAndroid Build Coastguard Worker {
115*7304104dSAndroid Build Coastguard Worker *elfclass = ELFCLASS32;
116*7304104dSAndroid Build Coastguard Worker return true;
117*7304104dSAndroid Build Coastguard Worker }
118*7304104dSAndroid Build Coastguard Worker }
119*7304104dSAndroid Build Coastguard Worker
120*7304104dSAndroid Build Coastguard Worker return false;
121*7304104dSAndroid Build Coastguard Worker }
122*7304104dSAndroid Build Coastguard Worker
123*7304104dSAndroid Build Coastguard Worker /* This is a Dwfl_Memory_Callback that wraps another memory callback.
124*7304104dSAndroid Build Coastguard Worker If the underlying callback cannot fill the data, then this will
125*7304104dSAndroid Build Coastguard Worker fall back to fetching data from module files. */
126*7304104dSAndroid Build Coastguard Worker
127*7304104dSAndroid Build Coastguard Worker struct integrated_memory_callback
128*7304104dSAndroid Build Coastguard Worker {
129*7304104dSAndroid Build Coastguard Worker Dwfl_Memory_Callback *memory_callback;
130*7304104dSAndroid Build Coastguard Worker void *memory_callback_arg;
131*7304104dSAndroid Build Coastguard Worker void *buffer;
132*7304104dSAndroid Build Coastguard Worker };
133*7304104dSAndroid Build Coastguard Worker
134*7304104dSAndroid Build Coastguard Worker static bool
integrated_memory_callback(Dwfl * dwfl,int ndx,void ** buffer,size_t * buffer_available,GElf_Addr vaddr,size_t minread,void * arg)135*7304104dSAndroid Build Coastguard Worker integrated_memory_callback (Dwfl *dwfl, int ndx,
136*7304104dSAndroid Build Coastguard Worker void **buffer, size_t *buffer_available,
137*7304104dSAndroid Build Coastguard Worker GElf_Addr vaddr,
138*7304104dSAndroid Build Coastguard Worker size_t minread,
139*7304104dSAndroid Build Coastguard Worker void *arg)
140*7304104dSAndroid Build Coastguard Worker {
141*7304104dSAndroid Build Coastguard Worker struct integrated_memory_callback *info = arg;
142*7304104dSAndroid Build Coastguard Worker
143*7304104dSAndroid Build Coastguard Worker if (ndx == -1)
144*7304104dSAndroid Build Coastguard Worker {
145*7304104dSAndroid Build Coastguard Worker /* Called for cleanup. */
146*7304104dSAndroid Build Coastguard Worker if (info->buffer != NULL)
147*7304104dSAndroid Build Coastguard Worker {
148*7304104dSAndroid Build Coastguard Worker /* The last probe buffer came from the underlying callback.
149*7304104dSAndroid Build Coastguard Worker Let it do its cleanup. */
150*7304104dSAndroid Build Coastguard Worker assert (*buffer == info->buffer); /* XXX */
151*7304104dSAndroid Build Coastguard Worker *buffer = info->buffer;
152*7304104dSAndroid Build Coastguard Worker info->buffer = NULL;
153*7304104dSAndroid Build Coastguard Worker return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
154*7304104dSAndroid Build Coastguard Worker vaddr, minread,
155*7304104dSAndroid Build Coastguard Worker info->memory_callback_arg);
156*7304104dSAndroid Build Coastguard Worker }
157*7304104dSAndroid Build Coastguard Worker *buffer = NULL;
158*7304104dSAndroid Build Coastguard Worker *buffer_available = 0;
159*7304104dSAndroid Build Coastguard Worker return false;
160*7304104dSAndroid Build Coastguard Worker }
161*7304104dSAndroid Build Coastguard Worker
162*7304104dSAndroid Build Coastguard Worker if (*buffer != NULL)
163*7304104dSAndroid Build Coastguard Worker /* For a final-read request, we only use the underlying callback. */
164*7304104dSAndroid Build Coastguard Worker return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
165*7304104dSAndroid Build Coastguard Worker vaddr, minread, info->memory_callback_arg);
166*7304104dSAndroid Build Coastguard Worker
167*7304104dSAndroid Build Coastguard Worker /* Let the underlying callback try to fill this request. */
168*7304104dSAndroid Build Coastguard Worker if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available,
169*7304104dSAndroid Build Coastguard Worker vaddr, minread, info->memory_callback_arg))
170*7304104dSAndroid Build Coastguard Worker {
171*7304104dSAndroid Build Coastguard Worker *buffer = info->buffer;
172*7304104dSAndroid Build Coastguard Worker return true;
173*7304104dSAndroid Build Coastguard Worker }
174*7304104dSAndroid Build Coastguard Worker
175*7304104dSAndroid Build Coastguard Worker /* Now look for module text covering this address. */
176*7304104dSAndroid Build Coastguard Worker
177*7304104dSAndroid Build Coastguard Worker Dwfl_Module *mod;
178*7304104dSAndroid Build Coastguard Worker (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod);
179*7304104dSAndroid Build Coastguard Worker if (mod == NULL)
180*7304104dSAndroid Build Coastguard Worker return false;
181*7304104dSAndroid Build Coastguard Worker
182*7304104dSAndroid Build Coastguard Worker Dwarf_Addr bias;
183*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias);
184*7304104dSAndroid Build Coastguard Worker if (unlikely (scn == NULL))
185*7304104dSAndroid Build Coastguard Worker {
186*7304104dSAndroid Build Coastguard Worker #if 0 // XXX would have to handle ndx=-1 cleanup calls passed down.
187*7304104dSAndroid Build Coastguard Worker /* If we have no sections we can try to fill it from the module file
188*7304104dSAndroid Build Coastguard Worker based on its phdr mappings. */
189*7304104dSAndroid Build Coastguard Worker if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL)
190*7304104dSAndroid Build Coastguard Worker return INTUSE(dwfl_elf_phdr_memory_callback)
191*7304104dSAndroid Build Coastguard Worker (dwfl, 0, buffer, buffer_available,
192*7304104dSAndroid Build Coastguard Worker vaddr - mod->main.bias, minread, mod->main.elf);
193*7304104dSAndroid Build Coastguard Worker #endif
194*7304104dSAndroid Build Coastguard Worker return false;
195*7304104dSAndroid Build Coastguard Worker }
196*7304104dSAndroid Build Coastguard Worker
197*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_rawdata (scn, NULL);
198*7304104dSAndroid Build Coastguard Worker if (unlikely (data == NULL))
199*7304104dSAndroid Build Coastguard Worker // XXX throw error?
200*7304104dSAndroid Build Coastguard Worker return false;
201*7304104dSAndroid Build Coastguard Worker
202*7304104dSAndroid Build Coastguard Worker if (unlikely (data->d_size < vaddr))
203*7304104dSAndroid Build Coastguard Worker return false;
204*7304104dSAndroid Build Coastguard Worker
205*7304104dSAndroid Build Coastguard Worker /* Provide as much data as we have. */
206*7304104dSAndroid Build Coastguard Worker void *contents = data->d_buf + vaddr;
207*7304104dSAndroid Build Coastguard Worker size_t avail = data->d_size - vaddr;
208*7304104dSAndroid Build Coastguard Worker if (unlikely (avail < minread))
209*7304104dSAndroid Build Coastguard Worker return false;
210*7304104dSAndroid Build Coastguard Worker
211*7304104dSAndroid Build Coastguard Worker /* If probing for a string, make sure it's terminated. */
212*7304104dSAndroid Build Coastguard Worker if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL))
213*7304104dSAndroid Build Coastguard Worker return false;
214*7304104dSAndroid Build Coastguard Worker
215*7304104dSAndroid Build Coastguard Worker /* We have it! */
216*7304104dSAndroid Build Coastguard Worker *buffer = contents;
217*7304104dSAndroid Build Coastguard Worker *buffer_available = avail;
218*7304104dSAndroid Build Coastguard Worker return true;
219*7304104dSAndroid Build Coastguard Worker }
220*7304104dSAndroid Build Coastguard Worker
221*7304104dSAndroid Build Coastguard Worker static size_t
addrsize(uint_fast8_t elfclass)222*7304104dSAndroid Build Coastguard Worker addrsize (uint_fast8_t elfclass)
223*7304104dSAndroid Build Coastguard Worker {
224*7304104dSAndroid Build Coastguard Worker return elfclass * 4;
225*7304104dSAndroid Build Coastguard Worker }
226*7304104dSAndroid Build Coastguard Worker
227*7304104dSAndroid Build Coastguard Worker struct memory_closure
228*7304104dSAndroid Build Coastguard Worker {
229*7304104dSAndroid Build Coastguard Worker Dwfl *dwfl;
230*7304104dSAndroid Build Coastguard Worker Dwfl_Memory_Callback *callback;
231*7304104dSAndroid Build Coastguard Worker void *arg;
232*7304104dSAndroid Build Coastguard Worker };
233*7304104dSAndroid Build Coastguard Worker
234*7304104dSAndroid Build Coastguard Worker static inline int
release_buffer(struct memory_closure * closure,void ** buffer,size_t * buffer_available,int result)235*7304104dSAndroid Build Coastguard Worker release_buffer (struct memory_closure *closure,
236*7304104dSAndroid Build Coastguard Worker void **buffer, size_t *buffer_available, int result)
237*7304104dSAndroid Build Coastguard Worker {
238*7304104dSAndroid Build Coastguard Worker if (*buffer != NULL)
239*7304104dSAndroid Build Coastguard Worker (*closure->callback) (closure->dwfl, -1, buffer, buffer_available, 0, 0,
240*7304104dSAndroid Build Coastguard Worker closure->arg);
241*7304104dSAndroid Build Coastguard Worker
242*7304104dSAndroid Build Coastguard Worker return result;
243*7304104dSAndroid Build Coastguard Worker }
244*7304104dSAndroid Build Coastguard Worker
245*7304104dSAndroid Build Coastguard Worker static inline bool
read_addrs(struct memory_closure * closure,uint_fast8_t elfclass,uint_fast8_t elfdata,void ** buffer,size_t * buffer_available,GElf_Addr vaddr,GElf_Addr * read_vaddr,size_t n,GElf_Addr * addrs)246*7304104dSAndroid Build Coastguard Worker read_addrs (struct memory_closure *closure,
247*7304104dSAndroid Build Coastguard Worker uint_fast8_t elfclass, uint_fast8_t elfdata,
248*7304104dSAndroid Build Coastguard Worker void **buffer, size_t *buffer_available,
249*7304104dSAndroid Build Coastguard Worker GElf_Addr vaddr, GElf_Addr *read_vaddr,
250*7304104dSAndroid Build Coastguard Worker size_t n, GElf_Addr *addrs /* [4] */)
251*7304104dSAndroid Build Coastguard Worker {
252*7304104dSAndroid Build Coastguard Worker size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */
253*7304104dSAndroid Build Coastguard Worker Dwfl *dwfl = closure->dwfl;
254*7304104dSAndroid Build Coastguard Worker
255*7304104dSAndroid Build Coastguard Worker /* Read a new buffer if the old one doesn't cover these words. */
256*7304104dSAndroid Build Coastguard Worker if (*buffer == NULL
257*7304104dSAndroid Build Coastguard Worker || vaddr < *read_vaddr
258*7304104dSAndroid Build Coastguard Worker || nb > *buffer_available
259*7304104dSAndroid Build Coastguard Worker || vaddr - (*read_vaddr) > *buffer_available - nb)
260*7304104dSAndroid Build Coastguard Worker {
261*7304104dSAndroid Build Coastguard Worker release_buffer (closure, buffer, buffer_available, 0);
262*7304104dSAndroid Build Coastguard Worker
263*7304104dSAndroid Build Coastguard Worker *read_vaddr = vaddr;
264*7304104dSAndroid Build Coastguard Worker int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
265*7304104dSAndroid Build Coastguard Worker if (unlikely (segndx < 0)
266*7304104dSAndroid Build Coastguard Worker || unlikely (! (*closure->callback) (dwfl, segndx,
267*7304104dSAndroid Build Coastguard Worker buffer, buffer_available,
268*7304104dSAndroid Build Coastguard Worker vaddr, nb, closure->arg)))
269*7304104dSAndroid Build Coastguard Worker return true;
270*7304104dSAndroid Build Coastguard Worker }
271*7304104dSAndroid Build Coastguard Worker
272*7304104dSAndroid Build Coastguard Worker unsigned char *addr = vaddr - (*read_vaddr) + (*buffer);
273*7304104dSAndroid Build Coastguard Worker
274*7304104dSAndroid Build Coastguard Worker if (elfclass == ELFCLASS32)
275*7304104dSAndroid Build Coastguard Worker {
276*7304104dSAndroid Build Coastguard Worker if (elfdata == ELFDATA2MSB)
277*7304104dSAndroid Build Coastguard Worker for (size_t i = 0; i < n; ++i)
278*7304104dSAndroid Build Coastguard Worker addrs[i] = BE32 (read_4ubyte_unaligned_noncvt (addr + i * 4));
279*7304104dSAndroid Build Coastguard Worker else
280*7304104dSAndroid Build Coastguard Worker for (size_t i = 0; i < n; ++i)
281*7304104dSAndroid Build Coastguard Worker addrs[i] = LE32 (read_4ubyte_unaligned_noncvt (addr + i * 4));
282*7304104dSAndroid Build Coastguard Worker }
283*7304104dSAndroid Build Coastguard Worker else
284*7304104dSAndroid Build Coastguard Worker {
285*7304104dSAndroid Build Coastguard Worker if (elfdata == ELFDATA2MSB)
286*7304104dSAndroid Build Coastguard Worker for (size_t i = 0; i < n; ++i)
287*7304104dSAndroid Build Coastguard Worker addrs[i] = BE64 (read_8ubyte_unaligned_noncvt (addr + i * 8));
288*7304104dSAndroid Build Coastguard Worker else
289*7304104dSAndroid Build Coastguard Worker for (size_t i = 0; i < n; ++i)
290*7304104dSAndroid Build Coastguard Worker addrs[i] = LE64 (read_8ubyte_unaligned_noncvt (addr + i * 8));
291*7304104dSAndroid Build Coastguard Worker }
292*7304104dSAndroid Build Coastguard Worker
293*7304104dSAndroid Build Coastguard Worker return false;
294*7304104dSAndroid Build Coastguard Worker }
295*7304104dSAndroid Build Coastguard Worker
296*7304104dSAndroid Build Coastguard Worker /* Report a module for each struct link_map in the linked list at r_map
297*7304104dSAndroid Build Coastguard Worker in the struct r_debug at R_DEBUG_VADDR. For r_debug_info description
298*7304104dSAndroid Build Coastguard Worker see dwfl_link_map_report in libdwflP.h. If R_DEBUG_INFO is not NULL then no
299*7304104dSAndroid Build Coastguard Worker modules get added to DWFL, caller has to add them from filled in
300*7304104dSAndroid Build Coastguard Worker R_DEBUG_INFO.
301*7304104dSAndroid Build Coastguard Worker
302*7304104dSAndroid Build Coastguard Worker For each link_map entry, if an existing module resides at its address,
303*7304104dSAndroid Build Coastguard Worker this just modifies that module's name and suggested file name. If
304*7304104dSAndroid Build Coastguard Worker no such module exists, this calls dwfl_report_elf on the l_name string.
305*7304104dSAndroid Build Coastguard Worker
306*7304104dSAndroid Build Coastguard Worker Returns the number of modules found, or -1 for errors. */
307*7304104dSAndroid Build Coastguard Worker
308*7304104dSAndroid Build Coastguard Worker static int
report_r_debug(uint_fast8_t elfclass,uint_fast8_t elfdata,Dwfl * dwfl,GElf_Addr r_debug_vaddr,Dwfl_Memory_Callback * memory_callback,void * memory_callback_arg,struct r_debug_info * r_debug_info)309*7304104dSAndroid Build Coastguard Worker report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
310*7304104dSAndroid Build Coastguard Worker Dwfl *dwfl, GElf_Addr r_debug_vaddr,
311*7304104dSAndroid Build Coastguard Worker Dwfl_Memory_Callback *memory_callback,
312*7304104dSAndroid Build Coastguard Worker void *memory_callback_arg,
313*7304104dSAndroid Build Coastguard Worker struct r_debug_info *r_debug_info)
314*7304104dSAndroid Build Coastguard Worker {
315*7304104dSAndroid Build Coastguard Worker /* Skip r_version, to aligned r_map field. */
316*7304104dSAndroid Build Coastguard Worker GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
317*7304104dSAndroid Build Coastguard Worker
318*7304104dSAndroid Build Coastguard Worker void *buffer = NULL;
319*7304104dSAndroid Build Coastguard Worker size_t buffer_available = 0;
320*7304104dSAndroid Build Coastguard Worker GElf_Addr addrs[4];
321*7304104dSAndroid Build Coastguard Worker struct memory_closure memory_closure = { dwfl, memory_callback,
322*7304104dSAndroid Build Coastguard Worker memory_callback_arg };
323*7304104dSAndroid Build Coastguard Worker if (unlikely (read_addrs (&memory_closure, elfclass, elfdata,
324*7304104dSAndroid Build Coastguard Worker &buffer, &buffer_available, read_vaddr, &read_vaddr,
325*7304104dSAndroid Build Coastguard Worker 1, addrs)))
326*7304104dSAndroid Build Coastguard Worker return release_buffer (&memory_closure, &buffer, &buffer_available, -1);
327*7304104dSAndroid Build Coastguard Worker
328*7304104dSAndroid Build Coastguard Worker GElf_Addr next = addrs[0];
329*7304104dSAndroid Build Coastguard Worker
330*7304104dSAndroid Build Coastguard Worker Dwfl_Module **lastmodp = &dwfl->modulelist;
331*7304104dSAndroid Build Coastguard Worker int result = 0;
332*7304104dSAndroid Build Coastguard Worker
333*7304104dSAndroid Build Coastguard Worker /* There can't be more elements in the link_map list than there are
334*7304104dSAndroid Build Coastguard Worker segments. A segment is created for each PT_LOAD and there can be
335*7304104dSAndroid Build Coastguard Worker up to 5 per module (-z separate-code, tends to create four LOAD
336*7304104dSAndroid Build Coastguard Worker segments, gold has -z text-unlikely-segment, which might result
337*7304104dSAndroid Build Coastguard Worker in creating that number of load segments) DWFL->lookup_elts is
338*7304104dSAndroid Build Coastguard Worker probably twice the number of modules, so that multiplied by max
339*7304104dSAndroid Build Coastguard Worker PT_LOADs is certainly above the upper bound. If we iterate too
340*7304104dSAndroid Build Coastguard Worker many times, there must be a loop in the pointers due to link_map
341*7304104dSAndroid Build Coastguard Worker clobberation. */
342*7304104dSAndroid Build Coastguard Worker #define MAX_PT_LOAD 5
343*7304104dSAndroid Build Coastguard Worker size_t iterations = 0;
344*7304104dSAndroid Build Coastguard Worker while (next != 0 && ++iterations < dwfl->lookup_elts * MAX_PT_LOAD)
345*7304104dSAndroid Build Coastguard Worker {
346*7304104dSAndroid Build Coastguard Worker if (read_addrs (&memory_closure, elfclass, elfdata,
347*7304104dSAndroid Build Coastguard Worker &buffer, &buffer_available, next, &read_vaddr,
348*7304104dSAndroid Build Coastguard Worker 4, addrs))
349*7304104dSAndroid Build Coastguard Worker return release_buffer (&memory_closure, &buffer, &buffer_available, -1);
350*7304104dSAndroid Build Coastguard Worker
351*7304104dSAndroid Build Coastguard Worker /* Unused: l_addr is the difference between the address in memory
352*7304104dSAndroid Build Coastguard Worker and the ELF file when the core was created. We need to
353*7304104dSAndroid Build Coastguard Worker recalculate the difference below because the ELF file we use
354*7304104dSAndroid Build Coastguard Worker might be differently pre-linked. */
355*7304104dSAndroid Build Coastguard Worker // GElf_Addr l_addr = addrs[0];
356*7304104dSAndroid Build Coastguard Worker GElf_Addr l_name = addrs[1];
357*7304104dSAndroid Build Coastguard Worker GElf_Addr l_ld = addrs[2];
358*7304104dSAndroid Build Coastguard Worker next = addrs[3];
359*7304104dSAndroid Build Coastguard Worker
360*7304104dSAndroid Build Coastguard Worker /* If a clobbered or truncated memory image has no useful pointer,
361*7304104dSAndroid Build Coastguard Worker just skip this element. */
362*7304104dSAndroid Build Coastguard Worker if (l_ld == 0)
363*7304104dSAndroid Build Coastguard Worker continue;
364*7304104dSAndroid Build Coastguard Worker
365*7304104dSAndroid Build Coastguard Worker /* Fetch the string at the l_name address. */
366*7304104dSAndroid Build Coastguard Worker const char *name = NULL;
367*7304104dSAndroid Build Coastguard Worker if (buffer != NULL
368*7304104dSAndroid Build Coastguard Worker && read_vaddr <= l_name
369*7304104dSAndroid Build Coastguard Worker && l_name + 1 - read_vaddr < buffer_available
370*7304104dSAndroid Build Coastguard Worker && memchr (l_name - read_vaddr + buffer, '\0',
371*7304104dSAndroid Build Coastguard Worker buffer_available - (l_name - read_vaddr)) != NULL)
372*7304104dSAndroid Build Coastguard Worker name = l_name - read_vaddr + buffer;
373*7304104dSAndroid Build Coastguard Worker else
374*7304104dSAndroid Build Coastguard Worker {
375*7304104dSAndroid Build Coastguard Worker release_buffer (&memory_closure, &buffer, &buffer_available, 0);
376*7304104dSAndroid Build Coastguard Worker read_vaddr = l_name;
377*7304104dSAndroid Build Coastguard Worker int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL);
378*7304104dSAndroid Build Coastguard Worker if (likely (segndx >= 0)
379*7304104dSAndroid Build Coastguard Worker && (*memory_callback) (dwfl, segndx,
380*7304104dSAndroid Build Coastguard Worker &buffer, &buffer_available,
381*7304104dSAndroid Build Coastguard Worker l_name, 0, memory_callback_arg))
382*7304104dSAndroid Build Coastguard Worker name = buffer;
383*7304104dSAndroid Build Coastguard Worker }
384*7304104dSAndroid Build Coastguard Worker
385*7304104dSAndroid Build Coastguard Worker if (name != NULL && name[0] == '\0')
386*7304104dSAndroid Build Coastguard Worker name = NULL;
387*7304104dSAndroid Build Coastguard Worker
388*7304104dSAndroid Build Coastguard Worker if (iterations == 1
389*7304104dSAndroid Build Coastguard Worker && dwfl->user_core != NULL
390*7304104dSAndroid Build Coastguard Worker && dwfl->user_core->executable_for_core != NULL)
391*7304104dSAndroid Build Coastguard Worker name = dwfl->user_core->executable_for_core;
392*7304104dSAndroid Build Coastguard Worker
393*7304104dSAndroid Build Coastguard Worker struct r_debug_info_module *r_debug_info_module = NULL;
394*7304104dSAndroid Build Coastguard Worker if (r_debug_info != NULL)
395*7304104dSAndroid Build Coastguard Worker {
396*7304104dSAndroid Build Coastguard Worker /* Save link map information about valid shared library (or
397*7304104dSAndroid Build Coastguard Worker executable) which has not been found on disk. */
398*7304104dSAndroid Build Coastguard Worker const char *name1 = name == NULL ? "" : name;
399*7304104dSAndroid Build Coastguard Worker r_debug_info_module = malloc (sizeof (*r_debug_info_module)
400*7304104dSAndroid Build Coastguard Worker + strlen (name1) + 1);
401*7304104dSAndroid Build Coastguard Worker if (unlikely (r_debug_info_module == NULL))
402*7304104dSAndroid Build Coastguard Worker release_buffer (&memory_closure, &buffer,
403*7304104dSAndroid Build Coastguard Worker &buffer_available, result);
404*7304104dSAndroid Build Coastguard Worker r_debug_info_module->fd = -1;
405*7304104dSAndroid Build Coastguard Worker r_debug_info_module->elf = NULL;
406*7304104dSAndroid Build Coastguard Worker r_debug_info_module->l_ld = l_ld;
407*7304104dSAndroid Build Coastguard Worker r_debug_info_module->start = 0;
408*7304104dSAndroid Build Coastguard Worker r_debug_info_module->end = 0;
409*7304104dSAndroid Build Coastguard Worker r_debug_info_module->disk_file_has_build_id = false;
410*7304104dSAndroid Build Coastguard Worker strcpy (r_debug_info_module->name, name1);
411*7304104dSAndroid Build Coastguard Worker r_debug_info_module->next = r_debug_info->module;
412*7304104dSAndroid Build Coastguard Worker r_debug_info->module = r_debug_info_module;
413*7304104dSAndroid Build Coastguard Worker }
414*7304104dSAndroid Build Coastguard Worker
415*7304104dSAndroid Build Coastguard Worker Dwfl_Module *mod = NULL;
416*7304104dSAndroid Build Coastguard Worker if (name != NULL)
417*7304104dSAndroid Build Coastguard Worker {
418*7304104dSAndroid Build Coastguard Worker /* This code is mostly inlined dwfl_report_elf. */
419*7304104dSAndroid Build Coastguard Worker // XXX hook for sysroot
420*7304104dSAndroid Build Coastguard Worker int fd = open (name, O_RDONLY);
421*7304104dSAndroid Build Coastguard Worker if (fd >= 0)
422*7304104dSAndroid Build Coastguard Worker {
423*7304104dSAndroid Build Coastguard Worker Elf *elf;
424*7304104dSAndroid Build Coastguard Worker Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
425*7304104dSAndroid Build Coastguard Worker GElf_Addr elf_dynamic_vaddr;
426*7304104dSAndroid Build Coastguard Worker if (error == DWFL_E_NOERROR
427*7304104dSAndroid Build Coastguard Worker && __libdwfl_dynamic_vaddr_get (elf, &elf_dynamic_vaddr))
428*7304104dSAndroid Build Coastguard Worker {
429*7304104dSAndroid Build Coastguard Worker const void *build_id_bits;
430*7304104dSAndroid Build Coastguard Worker GElf_Addr build_id_elfaddr;
431*7304104dSAndroid Build Coastguard Worker int build_id_len;
432*7304104dSAndroid Build Coastguard Worker bool valid = true;
433*7304104dSAndroid Build Coastguard Worker
434*7304104dSAndroid Build Coastguard Worker if (__libdwfl_find_elf_build_id (NULL, elf, &build_id_bits,
435*7304104dSAndroid Build Coastguard Worker &build_id_elfaddr,
436*7304104dSAndroid Build Coastguard Worker &build_id_len) > 0
437*7304104dSAndroid Build Coastguard Worker && build_id_elfaddr != 0)
438*7304104dSAndroid Build Coastguard Worker {
439*7304104dSAndroid Build Coastguard Worker if (r_debug_info_module != NULL)
440*7304104dSAndroid Build Coastguard Worker r_debug_info_module->disk_file_has_build_id = true;
441*7304104dSAndroid Build Coastguard Worker GElf_Addr build_id_vaddr = (build_id_elfaddr
442*7304104dSAndroid Build Coastguard Worker - elf_dynamic_vaddr + l_ld);
443*7304104dSAndroid Build Coastguard Worker
444*7304104dSAndroid Build Coastguard Worker release_buffer (&memory_closure, &buffer,
445*7304104dSAndroid Build Coastguard Worker &buffer_available, 0);
446*7304104dSAndroid Build Coastguard Worker int segndx = INTUSE(dwfl_addrsegment) (dwfl,
447*7304104dSAndroid Build Coastguard Worker build_id_vaddr,
448*7304104dSAndroid Build Coastguard Worker NULL);
449*7304104dSAndroid Build Coastguard Worker if (! (*memory_callback) (dwfl, segndx,
450*7304104dSAndroid Build Coastguard Worker &buffer, &buffer_available,
451*7304104dSAndroid Build Coastguard Worker build_id_vaddr, build_id_len,
452*7304104dSAndroid Build Coastguard Worker memory_callback_arg))
453*7304104dSAndroid Build Coastguard Worker {
454*7304104dSAndroid Build Coastguard Worker /* File has valid build-id which cannot be read from
455*7304104dSAndroid Build Coastguard Worker memory. This happens for core files without bit 4
456*7304104dSAndroid Build Coastguard Worker (0x10) set in Linux /proc/PID/coredump_filter. */
457*7304104dSAndroid Build Coastguard Worker }
458*7304104dSAndroid Build Coastguard Worker else
459*7304104dSAndroid Build Coastguard Worker {
460*7304104dSAndroid Build Coastguard Worker if (memcmp (build_id_bits, buffer, build_id_len) != 0)
461*7304104dSAndroid Build Coastguard Worker /* File has valid build-id which does not match
462*7304104dSAndroid Build Coastguard Worker the one in memory. */
463*7304104dSAndroid Build Coastguard Worker valid = false;
464*7304104dSAndroid Build Coastguard Worker release_buffer (&memory_closure, &buffer,
465*7304104dSAndroid Build Coastguard Worker &buffer_available, 0);
466*7304104dSAndroid Build Coastguard Worker
467*7304104dSAndroid Build Coastguard Worker }
468*7304104dSAndroid Build Coastguard Worker }
469*7304104dSAndroid Build Coastguard Worker
470*7304104dSAndroid Build Coastguard Worker if (valid)
471*7304104dSAndroid Build Coastguard Worker {
472*7304104dSAndroid Build Coastguard Worker // It is like l_addr but it handles differently prelinked
473*7304104dSAndroid Build Coastguard Worker // files at core dumping vs. core loading time.
474*7304104dSAndroid Build Coastguard Worker GElf_Addr base = l_ld - elf_dynamic_vaddr;
475*7304104dSAndroid Build Coastguard Worker if (r_debug_info_module == NULL)
476*7304104dSAndroid Build Coastguard Worker {
477*7304104dSAndroid Build Coastguard Worker // XXX hook for sysroot
478*7304104dSAndroid Build Coastguard Worker mod = __libdwfl_report_elf (dwfl, xbasename (name),
479*7304104dSAndroid Build Coastguard Worker name, fd, elf, base,
480*7304104dSAndroid Build Coastguard Worker true, true);
481*7304104dSAndroid Build Coastguard Worker if (mod != NULL)
482*7304104dSAndroid Build Coastguard Worker {
483*7304104dSAndroid Build Coastguard Worker elf = NULL;
484*7304104dSAndroid Build Coastguard Worker fd = -1;
485*7304104dSAndroid Build Coastguard Worker }
486*7304104dSAndroid Build Coastguard Worker }
487*7304104dSAndroid Build Coastguard Worker else if (__libdwfl_elf_address_range (elf, base, true,
488*7304104dSAndroid Build Coastguard Worker true, NULL, NULL,
489*7304104dSAndroid Build Coastguard Worker &r_debug_info_module->start,
490*7304104dSAndroid Build Coastguard Worker &r_debug_info_module->end,
491*7304104dSAndroid Build Coastguard Worker NULL, NULL))
492*7304104dSAndroid Build Coastguard Worker {
493*7304104dSAndroid Build Coastguard Worker r_debug_info_module->elf = elf;
494*7304104dSAndroid Build Coastguard Worker r_debug_info_module->fd = fd;
495*7304104dSAndroid Build Coastguard Worker elf = NULL;
496*7304104dSAndroid Build Coastguard Worker fd = -1;
497*7304104dSAndroid Build Coastguard Worker }
498*7304104dSAndroid Build Coastguard Worker }
499*7304104dSAndroid Build Coastguard Worker if (elf != NULL)
500*7304104dSAndroid Build Coastguard Worker elf_end (elf);
501*7304104dSAndroid Build Coastguard Worker if (fd != -1)
502*7304104dSAndroid Build Coastguard Worker close (fd);
503*7304104dSAndroid Build Coastguard Worker }
504*7304104dSAndroid Build Coastguard Worker }
505*7304104dSAndroid Build Coastguard Worker }
506*7304104dSAndroid Build Coastguard Worker
507*7304104dSAndroid Build Coastguard Worker if (mod != NULL)
508*7304104dSAndroid Build Coastguard Worker {
509*7304104dSAndroid Build Coastguard Worker ++result;
510*7304104dSAndroid Build Coastguard Worker
511*7304104dSAndroid Build Coastguard Worker /* Move this module to the end of the list, so that we end
512*7304104dSAndroid Build Coastguard Worker up with a list in the same order as the link_map chain. */
513*7304104dSAndroid Build Coastguard Worker if (mod->next != NULL)
514*7304104dSAndroid Build Coastguard Worker {
515*7304104dSAndroid Build Coastguard Worker if (*lastmodp != mod)
516*7304104dSAndroid Build Coastguard Worker {
517*7304104dSAndroid Build Coastguard Worker lastmodp = &dwfl->modulelist;
518*7304104dSAndroid Build Coastguard Worker while (*lastmodp != mod)
519*7304104dSAndroid Build Coastguard Worker lastmodp = &(*lastmodp)->next;
520*7304104dSAndroid Build Coastguard Worker }
521*7304104dSAndroid Build Coastguard Worker *lastmodp = mod->next;
522*7304104dSAndroid Build Coastguard Worker mod->next = NULL;
523*7304104dSAndroid Build Coastguard Worker while (*lastmodp != NULL)
524*7304104dSAndroid Build Coastguard Worker lastmodp = &(*lastmodp)->next;
525*7304104dSAndroid Build Coastguard Worker *lastmodp = mod;
526*7304104dSAndroid Build Coastguard Worker }
527*7304104dSAndroid Build Coastguard Worker
528*7304104dSAndroid Build Coastguard Worker lastmodp = &mod->next;
529*7304104dSAndroid Build Coastguard Worker }
530*7304104dSAndroid Build Coastguard Worker }
531*7304104dSAndroid Build Coastguard Worker
532*7304104dSAndroid Build Coastguard Worker return release_buffer (&memory_closure, &buffer, &buffer_available, result);
533*7304104dSAndroid Build Coastguard Worker }
534*7304104dSAndroid Build Coastguard Worker
535*7304104dSAndroid Build Coastguard Worker static GElf_Addr
consider_executable(Dwfl_Module * mod,GElf_Addr at_phdr,GElf_Addr at_entry,uint_fast8_t * elfclass,uint_fast8_t * elfdata,Dwfl_Memory_Callback * memory_callback,void * memory_callback_arg)536*7304104dSAndroid Build Coastguard Worker consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry,
537*7304104dSAndroid Build Coastguard Worker uint_fast8_t *elfclass, uint_fast8_t *elfdata,
538*7304104dSAndroid Build Coastguard Worker Dwfl_Memory_Callback *memory_callback,
539*7304104dSAndroid Build Coastguard Worker void *memory_callback_arg)
540*7304104dSAndroid Build Coastguard Worker {
541*7304104dSAndroid Build Coastguard Worker GElf_Ehdr ehdr;
542*7304104dSAndroid Build Coastguard Worker if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL))
543*7304104dSAndroid Build Coastguard Worker return 0;
544*7304104dSAndroid Build Coastguard Worker
545*7304104dSAndroid Build Coastguard Worker if (at_entry != 0)
546*7304104dSAndroid Build Coastguard Worker {
547*7304104dSAndroid Build Coastguard Worker /* If we have an AT_ENTRY value, reject this executable if
548*7304104dSAndroid Build Coastguard Worker its entry point address could not have supplied that. */
549*7304104dSAndroid Build Coastguard Worker
550*7304104dSAndroid Build Coastguard Worker if (ehdr.e_entry == 0)
551*7304104dSAndroid Build Coastguard Worker return 0;
552*7304104dSAndroid Build Coastguard Worker
553*7304104dSAndroid Build Coastguard Worker if (mod->e_type == ET_EXEC)
554*7304104dSAndroid Build Coastguard Worker {
555*7304104dSAndroid Build Coastguard Worker if (ehdr.e_entry != at_entry)
556*7304104dSAndroid Build Coastguard Worker return 0;
557*7304104dSAndroid Build Coastguard Worker }
558*7304104dSAndroid Build Coastguard Worker else
559*7304104dSAndroid Build Coastguard Worker {
560*7304104dSAndroid Build Coastguard Worker /* It could be a PIE. */
561*7304104dSAndroid Build Coastguard Worker }
562*7304104dSAndroid Build Coastguard Worker }
563*7304104dSAndroid Build Coastguard Worker
564*7304104dSAndroid Build Coastguard Worker // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr
565*7304104dSAndroid Build Coastguard Worker /* Find the vaddr of the DT_DEBUG's d_ptr. This is the memory
566*7304104dSAndroid Build Coastguard Worker address where &r_debug was written at runtime. */
567*7304104dSAndroid Build Coastguard Worker GElf_Xword align = mod->dwfl->segment_align;
568*7304104dSAndroid Build Coastguard Worker GElf_Addr d_val_vaddr = 0;
569*7304104dSAndroid Build Coastguard Worker size_t phnum;
570*7304104dSAndroid Build Coastguard Worker if (elf_getphdrnum (mod->main.elf, &phnum) != 0)
571*7304104dSAndroid Build Coastguard Worker return 0;
572*7304104dSAndroid Build Coastguard Worker
573*7304104dSAndroid Build Coastguard Worker for (size_t i = 0; i < phnum; ++i)
574*7304104dSAndroid Build Coastguard Worker {
575*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr_mem;
576*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
577*7304104dSAndroid Build Coastguard Worker if (phdr == NULL)
578*7304104dSAndroid Build Coastguard Worker break;
579*7304104dSAndroid Build Coastguard Worker
580*7304104dSAndroid Build Coastguard Worker if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align))
581*7304104dSAndroid Build Coastguard Worker align = phdr->p_align;
582*7304104dSAndroid Build Coastguard Worker
583*7304104dSAndroid Build Coastguard Worker if (at_phdr != 0
584*7304104dSAndroid Build Coastguard Worker && phdr->p_type == PT_LOAD
585*7304104dSAndroid Build Coastguard Worker && (phdr->p_offset & -align) == (ehdr.e_phoff & -align))
586*7304104dSAndroid Build Coastguard Worker {
587*7304104dSAndroid Build Coastguard Worker /* This is the segment that would map the phdrs.
588*7304104dSAndroid Build Coastguard Worker If we have an AT_PHDR value, reject this executable
589*7304104dSAndroid Build Coastguard Worker if its phdr mapping could not have supplied that. */
590*7304104dSAndroid Build Coastguard Worker if (mod->e_type == ET_EXEC)
591*7304104dSAndroid Build Coastguard Worker {
592*7304104dSAndroid Build Coastguard Worker if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr)
593*7304104dSAndroid Build Coastguard Worker return 0;
594*7304104dSAndroid Build Coastguard Worker }
595*7304104dSAndroid Build Coastguard Worker else
596*7304104dSAndroid Build Coastguard Worker {
597*7304104dSAndroid Build Coastguard Worker /* It could be a PIE. If the AT_PHDR value and our
598*7304104dSAndroid Build Coastguard Worker phdr address don't match modulo ALIGN, then this
599*7304104dSAndroid Build Coastguard Worker could not have been the right PIE. */
600*7304104dSAndroid Build Coastguard Worker if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align)
601*7304104dSAndroid Build Coastguard Worker != (at_phdr & -align))
602*7304104dSAndroid Build Coastguard Worker return 0;
603*7304104dSAndroid Build Coastguard Worker
604*7304104dSAndroid Build Coastguard Worker /* Calculate the bias applied to the PIE's p_vaddr values. */
605*7304104dSAndroid Build Coastguard Worker GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset
606*7304104dSAndroid Build Coastguard Worker + phdr->p_vaddr));
607*7304104dSAndroid Build Coastguard Worker
608*7304104dSAndroid Build Coastguard Worker /* Final sanity check: if we have an AT_ENTRY value,
609*7304104dSAndroid Build Coastguard Worker reject this PIE unless its biased e_entry matches. */
610*7304104dSAndroid Build Coastguard Worker if (at_entry != 0 && at_entry != ehdr.e_entry + bias)
611*7304104dSAndroid Build Coastguard Worker return 0;
612*7304104dSAndroid Build Coastguard Worker
613*7304104dSAndroid Build Coastguard Worker /* If we're changing the module's address range,
614*7304104dSAndroid Build Coastguard Worker we've just invalidated the module lookup table. */
615*7304104dSAndroid Build Coastguard Worker GElf_Addr mod_bias = dwfl_adjusted_address (mod, 0);
616*7304104dSAndroid Build Coastguard Worker if (bias != mod_bias)
617*7304104dSAndroid Build Coastguard Worker {
618*7304104dSAndroid Build Coastguard Worker mod->low_addr -= mod_bias;
619*7304104dSAndroid Build Coastguard Worker mod->high_addr -= mod_bias;
620*7304104dSAndroid Build Coastguard Worker mod->low_addr += bias;
621*7304104dSAndroid Build Coastguard Worker mod->high_addr += bias;
622*7304104dSAndroid Build Coastguard Worker
623*7304104dSAndroid Build Coastguard Worker free (mod->dwfl->lookup_module);
624*7304104dSAndroid Build Coastguard Worker mod->dwfl->lookup_module = NULL;
625*7304104dSAndroid Build Coastguard Worker }
626*7304104dSAndroid Build Coastguard Worker }
627*7304104dSAndroid Build Coastguard Worker }
628*7304104dSAndroid Build Coastguard Worker
629*7304104dSAndroid Build Coastguard Worker if (phdr->p_type == PT_DYNAMIC)
630*7304104dSAndroid Build Coastguard Worker {
631*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset,
632*7304104dSAndroid Build Coastguard Worker phdr->p_filesz, ELF_T_DYN);
633*7304104dSAndroid Build Coastguard Worker if (data == NULL)
634*7304104dSAndroid Build Coastguard Worker continue;
635*7304104dSAndroid Build Coastguard Worker const size_t entsize = gelf_fsize (mod->main.elf,
636*7304104dSAndroid Build Coastguard Worker ELF_T_DYN, 1, EV_CURRENT);
637*7304104dSAndroid Build Coastguard Worker const size_t n = data->d_size / entsize;
638*7304104dSAndroid Build Coastguard Worker for (size_t j = 0; j < n; ++j)
639*7304104dSAndroid Build Coastguard Worker {
640*7304104dSAndroid Build Coastguard Worker GElf_Dyn dyn_mem;
641*7304104dSAndroid Build Coastguard Worker GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
642*7304104dSAndroid Build Coastguard Worker if (dyn != NULL && dyn->d_tag == DT_DEBUG)
643*7304104dSAndroid Build Coastguard Worker {
644*7304104dSAndroid Build Coastguard Worker d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2;
645*7304104dSAndroid Build Coastguard Worker break;
646*7304104dSAndroid Build Coastguard Worker }
647*7304104dSAndroid Build Coastguard Worker }
648*7304104dSAndroid Build Coastguard Worker }
649*7304104dSAndroid Build Coastguard Worker }
650*7304104dSAndroid Build Coastguard Worker
651*7304104dSAndroid Build Coastguard Worker if (d_val_vaddr != 0)
652*7304104dSAndroid Build Coastguard Worker {
653*7304104dSAndroid Build Coastguard Worker /* Now we have the final address from which to read &r_debug. */
654*7304104dSAndroid Build Coastguard Worker d_val_vaddr = dwfl_adjusted_address (mod, d_val_vaddr);
655*7304104dSAndroid Build Coastguard Worker
656*7304104dSAndroid Build Coastguard Worker void *buffer = NULL;
657*7304104dSAndroid Build Coastguard Worker size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]);
658*7304104dSAndroid Build Coastguard Worker
659*7304104dSAndroid Build Coastguard Worker int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, NULL);
660*7304104dSAndroid Build Coastguard Worker
661*7304104dSAndroid Build Coastguard Worker if ((*memory_callback) (mod->dwfl, segndx,
662*7304104dSAndroid Build Coastguard Worker &buffer, &buffer_available,
663*7304104dSAndroid Build Coastguard Worker d_val_vaddr, buffer_available,
664*7304104dSAndroid Build Coastguard Worker memory_callback_arg))
665*7304104dSAndroid Build Coastguard Worker {
666*7304104dSAndroid Build Coastguard Worker const union
667*7304104dSAndroid Build Coastguard Worker {
668*7304104dSAndroid Build Coastguard Worker Elf32_Addr a32;
669*7304104dSAndroid Build Coastguard Worker Elf64_Addr a64;
670*7304104dSAndroid Build Coastguard Worker } *u = buffer;
671*7304104dSAndroid Build Coastguard Worker
672*7304104dSAndroid Build Coastguard Worker GElf_Addr vaddr;
673*7304104dSAndroid Build Coastguard Worker if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
674*7304104dSAndroid Build Coastguard Worker vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
675*7304104dSAndroid Build Coastguard Worker ? BE32 (u->a32) : LE32 (u->a32));
676*7304104dSAndroid Build Coastguard Worker else
677*7304104dSAndroid Build Coastguard Worker vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
678*7304104dSAndroid Build Coastguard Worker ? BE64 (u->a64) : LE64 (u->a64));
679*7304104dSAndroid Build Coastguard Worker
680*7304104dSAndroid Build Coastguard Worker (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0,
681*7304104dSAndroid Build Coastguard Worker memory_callback_arg);
682*7304104dSAndroid Build Coastguard Worker
683*7304104dSAndroid Build Coastguard Worker if (*elfclass == ELFCLASSNONE)
684*7304104dSAndroid Build Coastguard Worker *elfclass = ehdr.e_ident[EI_CLASS];
685*7304104dSAndroid Build Coastguard Worker else if (*elfclass != ehdr.e_ident[EI_CLASS])
686*7304104dSAndroid Build Coastguard Worker return 0;
687*7304104dSAndroid Build Coastguard Worker
688*7304104dSAndroid Build Coastguard Worker if (*elfdata == ELFDATANONE)
689*7304104dSAndroid Build Coastguard Worker *elfdata = ehdr.e_ident[EI_DATA];
690*7304104dSAndroid Build Coastguard Worker else if (*elfdata != ehdr.e_ident[EI_DATA])
691*7304104dSAndroid Build Coastguard Worker return 0;
692*7304104dSAndroid Build Coastguard Worker
693*7304104dSAndroid Build Coastguard Worker return vaddr;
694*7304104dSAndroid Build Coastguard Worker }
695*7304104dSAndroid Build Coastguard Worker }
696*7304104dSAndroid Build Coastguard Worker
697*7304104dSAndroid Build Coastguard Worker return 0;
698*7304104dSAndroid Build Coastguard Worker }
699*7304104dSAndroid Build Coastguard Worker
700*7304104dSAndroid Build Coastguard Worker /* Try to find an existing executable module with a DT_DEBUG. */
701*7304104dSAndroid Build Coastguard Worker static GElf_Addr
find_executable(Dwfl * dwfl,GElf_Addr at_phdr,GElf_Addr at_entry,uint_fast8_t * elfclass,uint_fast8_t * elfdata,Dwfl_Memory_Callback * memory_callback,void * memory_callback_arg)702*7304104dSAndroid Build Coastguard Worker find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
703*7304104dSAndroid Build Coastguard Worker uint_fast8_t *elfclass, uint_fast8_t *elfdata,
704*7304104dSAndroid Build Coastguard Worker Dwfl_Memory_Callback *memory_callback,
705*7304104dSAndroid Build Coastguard Worker void *memory_callback_arg)
706*7304104dSAndroid Build Coastguard Worker {
707*7304104dSAndroid Build Coastguard Worker for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
708*7304104dSAndroid Build Coastguard Worker if (mod->main.elf != NULL)
709*7304104dSAndroid Build Coastguard Worker {
710*7304104dSAndroid Build Coastguard Worker GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry,
711*7304104dSAndroid Build Coastguard Worker elfclass, elfdata,
712*7304104dSAndroid Build Coastguard Worker memory_callback,
713*7304104dSAndroid Build Coastguard Worker memory_callback_arg);
714*7304104dSAndroid Build Coastguard Worker if (r_debug_vaddr != 0)
715*7304104dSAndroid Build Coastguard Worker return r_debug_vaddr;
716*7304104dSAndroid Build Coastguard Worker }
717*7304104dSAndroid Build Coastguard Worker
718*7304104dSAndroid Build Coastguard Worker return 0;
719*7304104dSAndroid Build Coastguard Worker }
720*7304104dSAndroid Build Coastguard Worker
721*7304104dSAndroid Build Coastguard Worker
722*7304104dSAndroid Build Coastguard Worker int
dwfl_link_map_report(Dwfl * dwfl,const void * auxv,size_t auxv_size,Dwfl_Memory_Callback * memory_callback,void * memory_callback_arg,struct r_debug_info * r_debug_info)723*7304104dSAndroid Build Coastguard Worker dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
724*7304104dSAndroid Build Coastguard Worker Dwfl_Memory_Callback *memory_callback,
725*7304104dSAndroid Build Coastguard Worker void *memory_callback_arg,
726*7304104dSAndroid Build Coastguard Worker struct r_debug_info *r_debug_info)
727*7304104dSAndroid Build Coastguard Worker {
728*7304104dSAndroid Build Coastguard Worker GElf_Addr r_debug_vaddr = 0;
729*7304104dSAndroid Build Coastguard Worker
730*7304104dSAndroid Build Coastguard Worker uint_fast8_t elfclass = ELFCLASSNONE;
731*7304104dSAndroid Build Coastguard Worker uint_fast8_t elfdata = ELFDATANONE;
732*7304104dSAndroid Build Coastguard Worker if (likely (auxv != NULL)
733*7304104dSAndroid Build Coastguard Worker && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata)))
734*7304104dSAndroid Build Coastguard Worker {
735*7304104dSAndroid Build Coastguard Worker GElf_Addr entry = 0;
736*7304104dSAndroid Build Coastguard Worker GElf_Addr phdr = 0;
737*7304104dSAndroid Build Coastguard Worker GElf_Xword phent = 0;
738*7304104dSAndroid Build Coastguard Worker GElf_Xword phnum = 0;
739*7304104dSAndroid Build Coastguard Worker
740*7304104dSAndroid Build Coastguard Worker #define READ_AUXV32(ptr) read_4ubyte_unaligned_noncvt (ptr)
741*7304104dSAndroid Build Coastguard Worker #define READ_AUXV64(ptr) read_8ubyte_unaligned_noncvt (ptr)
742*7304104dSAndroid Build Coastguard Worker #define AUXV_SCAN(NN, BL) do \
743*7304104dSAndroid Build Coastguard Worker { \
744*7304104dSAndroid Build Coastguard Worker const Elf##NN##_auxv_t *av = auxv; \
745*7304104dSAndroid Build Coastguard Worker for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i) \
746*7304104dSAndroid Build Coastguard Worker { \
747*7304104dSAndroid Build Coastguard Worker const char *typep = auxv + i * sizeof (Elf##NN##_auxv_t); \
748*7304104dSAndroid Build Coastguard Worker typep += offsetof (Elf##NN##_auxv_t, a_type); \
749*7304104dSAndroid Build Coastguard Worker uint##NN##_t type = READ_AUXV##NN (typep); \
750*7304104dSAndroid Build Coastguard Worker const char *valp = auxv + i * sizeof (Elf##NN##_auxv_t); \
751*7304104dSAndroid Build Coastguard Worker valp += offsetof (Elf##NN##_auxv_t, a_un.a_val); \
752*7304104dSAndroid Build Coastguard Worker uint##NN##_t val = BL##NN (READ_AUXV##NN (valp)); \
753*7304104dSAndroid Build Coastguard Worker if (type == BL##NN (AT_ENTRY)) \
754*7304104dSAndroid Build Coastguard Worker entry = val; \
755*7304104dSAndroid Build Coastguard Worker else if (type == BL##NN (AT_PHDR)) \
756*7304104dSAndroid Build Coastguard Worker phdr = val; \
757*7304104dSAndroid Build Coastguard Worker else if (type == BL##NN (AT_PHNUM)) \
758*7304104dSAndroid Build Coastguard Worker phnum = val; \
759*7304104dSAndroid Build Coastguard Worker else if (type == BL##NN (AT_PHENT)) \
760*7304104dSAndroid Build Coastguard Worker phent = val; \
761*7304104dSAndroid Build Coastguard Worker else if (type == BL##NN (AT_PAGESZ)) \
762*7304104dSAndroid Build Coastguard Worker { \
763*7304104dSAndroid Build Coastguard Worker if (val > 1 \
764*7304104dSAndroid Build Coastguard Worker && (dwfl->segment_align == 0 \
765*7304104dSAndroid Build Coastguard Worker || val < dwfl->segment_align)) \
766*7304104dSAndroid Build Coastguard Worker dwfl->segment_align = val; \
767*7304104dSAndroid Build Coastguard Worker } \
768*7304104dSAndroid Build Coastguard Worker } \
769*7304104dSAndroid Build Coastguard Worker } \
770*7304104dSAndroid Build Coastguard Worker while (0)
771*7304104dSAndroid Build Coastguard Worker
772*7304104dSAndroid Build Coastguard Worker if (elfclass == ELFCLASS32)
773*7304104dSAndroid Build Coastguard Worker {
774*7304104dSAndroid Build Coastguard Worker if (elfdata == ELFDATA2MSB)
775*7304104dSAndroid Build Coastguard Worker AUXV_SCAN (32, BE);
776*7304104dSAndroid Build Coastguard Worker else
777*7304104dSAndroid Build Coastguard Worker AUXV_SCAN (32, LE);
778*7304104dSAndroid Build Coastguard Worker }
779*7304104dSAndroid Build Coastguard Worker else
780*7304104dSAndroid Build Coastguard Worker {
781*7304104dSAndroid Build Coastguard Worker if (elfdata == ELFDATA2MSB)
782*7304104dSAndroid Build Coastguard Worker AUXV_SCAN (64, BE);
783*7304104dSAndroid Build Coastguard Worker else
784*7304104dSAndroid Build Coastguard Worker AUXV_SCAN (64, LE);
785*7304104dSAndroid Build Coastguard Worker }
786*7304104dSAndroid Build Coastguard Worker
787*7304104dSAndroid Build Coastguard Worker /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC. */
788*7304104dSAndroid Build Coastguard Worker GElf_Addr dyn_vaddr = 0;
789*7304104dSAndroid Build Coastguard Worker GElf_Xword dyn_filesz = 0;
790*7304104dSAndroid Build Coastguard Worker GElf_Addr dyn_bias = (GElf_Addr) -1;
791*7304104dSAndroid Build Coastguard Worker
792*7304104dSAndroid Build Coastguard Worker if (phdr != 0 && phnum != 0
793*7304104dSAndroid Build Coastguard Worker && ((elfclass == ELFCLASS32 && phent == sizeof (Elf32_Phdr))
794*7304104dSAndroid Build Coastguard Worker || (elfclass == ELFCLASS64 && phent == sizeof (Elf64_Phdr))))
795*7304104dSAndroid Build Coastguard Worker {
796*7304104dSAndroid Build Coastguard Worker Dwfl_Module *phdr_mod;
797*7304104dSAndroid Build Coastguard Worker int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod);
798*7304104dSAndroid Build Coastguard Worker Elf_Data in =
799*7304104dSAndroid Build Coastguard Worker {
800*7304104dSAndroid Build Coastguard Worker .d_type = ELF_T_PHDR,
801*7304104dSAndroid Build Coastguard Worker .d_version = EV_CURRENT,
802*7304104dSAndroid Build Coastguard Worker .d_size = phnum * phent,
803*7304104dSAndroid Build Coastguard Worker .d_buf = NULL
804*7304104dSAndroid Build Coastguard Worker };
805*7304104dSAndroid Build Coastguard Worker bool in_ok = (*memory_callback) (dwfl, phdr_segndx, &in.d_buf,
806*7304104dSAndroid Build Coastguard Worker &in.d_size, phdr, phnum * phent,
807*7304104dSAndroid Build Coastguard Worker memory_callback_arg);
808*7304104dSAndroid Build Coastguard Worker bool in_from_exec = false;
809*7304104dSAndroid Build Coastguard Worker if (! in_ok
810*7304104dSAndroid Build Coastguard Worker && dwfl->user_core != NULL
811*7304104dSAndroid Build Coastguard Worker && dwfl->user_core->executable_for_core != NULL)
812*7304104dSAndroid Build Coastguard Worker {
813*7304104dSAndroid Build Coastguard Worker /* AUXV -> PHDR -> DYNAMIC
814*7304104dSAndroid Build Coastguard Worker Both AUXV and DYNAMIC should be always present in a core file.
815*7304104dSAndroid Build Coastguard Worker PHDR may be missing in core file, try to read it from
816*7304104dSAndroid Build Coastguard Worker EXECUTABLE_FOR_CORE to find where DYNAMIC is located in the
817*7304104dSAndroid Build Coastguard Worker core file. */
818*7304104dSAndroid Build Coastguard Worker
819*7304104dSAndroid Build Coastguard Worker int fd = open (dwfl->user_core->executable_for_core, O_RDONLY);
820*7304104dSAndroid Build Coastguard Worker Elf *elf;
821*7304104dSAndroid Build Coastguard Worker Dwfl_Error error = DWFL_E_ERRNO;
822*7304104dSAndroid Build Coastguard Worker if (fd != -1)
823*7304104dSAndroid Build Coastguard Worker error = __libdw_open_file (&fd, &elf, true, false);
824*7304104dSAndroid Build Coastguard Worker if (error != DWFL_E_NOERROR)
825*7304104dSAndroid Build Coastguard Worker {
826*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (error);
827*7304104dSAndroid Build Coastguard Worker return false;
828*7304104dSAndroid Build Coastguard Worker }
829*7304104dSAndroid Build Coastguard Worker GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
830*7304104dSAndroid Build Coastguard Worker if (ehdr == NULL)
831*7304104dSAndroid Build Coastguard Worker {
832*7304104dSAndroid Build Coastguard Worker elf_end (elf);
833*7304104dSAndroid Build Coastguard Worker close (fd);
834*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_LIBELF);
835*7304104dSAndroid Build Coastguard Worker return false;
836*7304104dSAndroid Build Coastguard Worker }
837*7304104dSAndroid Build Coastguard Worker size_t e_phnum;
838*7304104dSAndroid Build Coastguard Worker if (elf_getphdrnum (elf, &e_phnum) != 0)
839*7304104dSAndroid Build Coastguard Worker {
840*7304104dSAndroid Build Coastguard Worker elf_end (elf);
841*7304104dSAndroid Build Coastguard Worker close (fd);
842*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_LIBELF);
843*7304104dSAndroid Build Coastguard Worker return false;
844*7304104dSAndroid Build Coastguard Worker }
845*7304104dSAndroid Build Coastguard Worker if (e_phnum != phnum || ehdr->e_phentsize != phent)
846*7304104dSAndroid Build Coastguard Worker {
847*7304104dSAndroid Build Coastguard Worker elf_end (elf);
848*7304104dSAndroid Build Coastguard Worker close (fd);
849*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_BADELF);
850*7304104dSAndroid Build Coastguard Worker return false;
851*7304104dSAndroid Build Coastguard Worker }
852*7304104dSAndroid Build Coastguard Worker off_t off = ehdr->e_phoff;
853*7304104dSAndroid Build Coastguard Worker assert (in.d_buf == NULL);
854*7304104dSAndroid Build Coastguard Worker /* Note this in the !in_ok path. That means memory_callback
855*7304104dSAndroid Build Coastguard Worker failed. But the callback might still have reset the d_size
856*7304104dSAndroid Build Coastguard Worker value (to zero). So explicitly set it here again. */
857*7304104dSAndroid Build Coastguard Worker if (unlikely (phnum > SIZE_MAX / phent))
858*7304104dSAndroid Build Coastguard Worker {
859*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_NOMEM);
860*7304104dSAndroid Build Coastguard Worker return false;
861*7304104dSAndroid Build Coastguard Worker }
862*7304104dSAndroid Build Coastguard Worker in.d_size = phnum * phent;
863*7304104dSAndroid Build Coastguard Worker in.d_buf = malloc (in.d_size);
864*7304104dSAndroid Build Coastguard Worker if (unlikely (in.d_buf == NULL))
865*7304104dSAndroid Build Coastguard Worker {
866*7304104dSAndroid Build Coastguard Worker elf_end (elf);
867*7304104dSAndroid Build Coastguard Worker close (fd);
868*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_NOMEM);
869*7304104dSAndroid Build Coastguard Worker return false;
870*7304104dSAndroid Build Coastguard Worker }
871*7304104dSAndroid Build Coastguard Worker ssize_t nread = pread_retry (fd, in.d_buf, in.d_size, off);
872*7304104dSAndroid Build Coastguard Worker elf_end (elf);
873*7304104dSAndroid Build Coastguard Worker close (fd);
874*7304104dSAndroid Build Coastguard Worker if (nread != (ssize_t) in.d_size)
875*7304104dSAndroid Build Coastguard Worker {
876*7304104dSAndroid Build Coastguard Worker free (in.d_buf);
877*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_ERRNO);
878*7304104dSAndroid Build Coastguard Worker return false;
879*7304104dSAndroid Build Coastguard Worker }
880*7304104dSAndroid Build Coastguard Worker in_ok = true;
881*7304104dSAndroid Build Coastguard Worker in_from_exec = true;
882*7304104dSAndroid Build Coastguard Worker }
883*7304104dSAndroid Build Coastguard Worker if (in_ok)
884*7304104dSAndroid Build Coastguard Worker {
885*7304104dSAndroid Build Coastguard Worker if (unlikely (phnum > SIZE_MAX / phent))
886*7304104dSAndroid Build Coastguard Worker {
887*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_NOMEM);
888*7304104dSAndroid Build Coastguard Worker return false;
889*7304104dSAndroid Build Coastguard Worker }
890*7304104dSAndroid Build Coastguard Worker size_t nbytes = phnum * phent;
891*7304104dSAndroid Build Coastguard Worker /* We can only process as many bytes/phnum as there are
892*7304104dSAndroid Build Coastguard Worker in in.d_size. The data might have been truncated. */
893*7304104dSAndroid Build Coastguard Worker if (nbytes > in.d_size)
894*7304104dSAndroid Build Coastguard Worker {
895*7304104dSAndroid Build Coastguard Worker nbytes = in.d_size;
896*7304104dSAndroid Build Coastguard Worker phnum = nbytes / phent;
897*7304104dSAndroid Build Coastguard Worker if (phnum == 0)
898*7304104dSAndroid Build Coastguard Worker {
899*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_BADELF);
900*7304104dSAndroid Build Coastguard Worker return false;
901*7304104dSAndroid Build Coastguard Worker }
902*7304104dSAndroid Build Coastguard Worker }
903*7304104dSAndroid Build Coastguard Worker void *buf = malloc (nbytes);
904*7304104dSAndroid Build Coastguard Worker Elf32_Phdr (*p32)[phnum] = buf;
905*7304104dSAndroid Build Coastguard Worker Elf64_Phdr (*p64)[phnum] = buf;
906*7304104dSAndroid Build Coastguard Worker if (unlikely (buf == NULL))
907*7304104dSAndroid Build Coastguard Worker {
908*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_NOMEM);
909*7304104dSAndroid Build Coastguard Worker return false;
910*7304104dSAndroid Build Coastguard Worker }
911*7304104dSAndroid Build Coastguard Worker Elf_Data out =
912*7304104dSAndroid Build Coastguard Worker {
913*7304104dSAndroid Build Coastguard Worker .d_type = ELF_T_PHDR,
914*7304104dSAndroid Build Coastguard Worker .d_version = EV_CURRENT,
915*7304104dSAndroid Build Coastguard Worker .d_size = nbytes,
916*7304104dSAndroid Build Coastguard Worker .d_buf = buf
917*7304104dSAndroid Build Coastguard Worker };
918*7304104dSAndroid Build Coastguard Worker if (in.d_size > out.d_size)
919*7304104dSAndroid Build Coastguard Worker {
920*7304104dSAndroid Build Coastguard Worker in.d_size = out.d_size;
921*7304104dSAndroid Build Coastguard Worker phnum = in.d_size / phent;
922*7304104dSAndroid Build Coastguard Worker if (phnum == 0)
923*7304104dSAndroid Build Coastguard Worker {
924*7304104dSAndroid Build Coastguard Worker free (buf);
925*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_BADELF);
926*7304104dSAndroid Build Coastguard Worker return false;
927*7304104dSAndroid Build Coastguard Worker }
928*7304104dSAndroid Build Coastguard Worker }
929*7304104dSAndroid Build Coastguard Worker bool is32 = (elfclass == ELFCLASS32);
930*7304104dSAndroid Build Coastguard Worker size_t phdr_align = (is32
931*7304104dSAndroid Build Coastguard Worker ? __alignof__ (Elf32_Phdr)
932*7304104dSAndroid Build Coastguard Worker : __alignof__ (Elf64_Phdr));
933*7304104dSAndroid Build Coastguard Worker if (!in_from_exec
934*7304104dSAndroid Build Coastguard Worker && ((uintptr_t) in.d_buf & (phdr_align - 1)) != 0)
935*7304104dSAndroid Build Coastguard Worker {
936*7304104dSAndroid Build Coastguard Worker memcpy (out.d_buf, in.d_buf, in.d_size);
937*7304104dSAndroid Build Coastguard Worker in.d_buf = out.d_buf;
938*7304104dSAndroid Build Coastguard Worker }
939*7304104dSAndroid Build Coastguard Worker if (likely ((elfclass == ELFCLASS32
940*7304104dSAndroid Build Coastguard Worker ? elf32_xlatetom : elf64_xlatetom)
941*7304104dSAndroid Build Coastguard Worker (&out, &in, elfdata) != NULL))
942*7304104dSAndroid Build Coastguard Worker {
943*7304104dSAndroid Build Coastguard Worker for (size_t i = 0; i < phnum; ++i)
944*7304104dSAndroid Build Coastguard Worker {
945*7304104dSAndroid Build Coastguard Worker GElf_Word type = (is32
946*7304104dSAndroid Build Coastguard Worker ? (*p32)[i].p_type
947*7304104dSAndroid Build Coastguard Worker : (*p64)[i].p_type);
948*7304104dSAndroid Build Coastguard Worker GElf_Addr vaddr = (is32
949*7304104dSAndroid Build Coastguard Worker ? (*p32)[i].p_vaddr
950*7304104dSAndroid Build Coastguard Worker : (*p64)[i].p_vaddr);
951*7304104dSAndroid Build Coastguard Worker GElf_Xword filesz = (is32
952*7304104dSAndroid Build Coastguard Worker ? (*p32)[i].p_filesz
953*7304104dSAndroid Build Coastguard Worker : (*p64)[i].p_filesz);
954*7304104dSAndroid Build Coastguard Worker
955*7304104dSAndroid Build Coastguard Worker if (type == PT_PHDR)
956*7304104dSAndroid Build Coastguard Worker {
957*7304104dSAndroid Build Coastguard Worker if (dyn_bias == (GElf_Addr) -1
958*7304104dSAndroid Build Coastguard Worker /* Do a sanity check on the putative address. */
959*7304104dSAndroid Build Coastguard Worker && ((vaddr & (dwfl->segment_align - 1))
960*7304104dSAndroid Build Coastguard Worker == (phdr & (dwfl->segment_align - 1))))
961*7304104dSAndroid Build Coastguard Worker {
962*7304104dSAndroid Build Coastguard Worker dyn_bias = phdr - vaddr;
963*7304104dSAndroid Build Coastguard Worker if (dyn_vaddr != 0)
964*7304104dSAndroid Build Coastguard Worker break;
965*7304104dSAndroid Build Coastguard Worker }
966*7304104dSAndroid Build Coastguard Worker
967*7304104dSAndroid Build Coastguard Worker }
968*7304104dSAndroid Build Coastguard Worker else if (type == PT_DYNAMIC)
969*7304104dSAndroid Build Coastguard Worker {
970*7304104dSAndroid Build Coastguard Worker dyn_vaddr = vaddr;
971*7304104dSAndroid Build Coastguard Worker dyn_filesz = filesz;
972*7304104dSAndroid Build Coastguard Worker if (dyn_bias != (GElf_Addr) -1)
973*7304104dSAndroid Build Coastguard Worker break;
974*7304104dSAndroid Build Coastguard Worker }
975*7304104dSAndroid Build Coastguard Worker }
976*7304104dSAndroid Build Coastguard Worker }
977*7304104dSAndroid Build Coastguard Worker
978*7304104dSAndroid Build Coastguard Worker if (in_from_exec)
979*7304104dSAndroid Build Coastguard Worker free (in.d_buf);
980*7304104dSAndroid Build Coastguard Worker else
981*7304104dSAndroid Build Coastguard Worker (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
982*7304104dSAndroid Build Coastguard Worker memory_callback_arg);
983*7304104dSAndroid Build Coastguard Worker free (buf);
984*7304104dSAndroid Build Coastguard Worker }
985*7304104dSAndroid Build Coastguard Worker else
986*7304104dSAndroid Build Coastguard Worker /* We could not read the executable's phdrs from the
987*7304104dSAndroid Build Coastguard Worker memory image. If we have a presupplied executable,
988*7304104dSAndroid Build Coastguard Worker we can still use the AT_PHDR and AT_ENTRY values to
989*7304104dSAndroid Build Coastguard Worker verify it, and to adjust its bias if it's a PIE.
990*7304104dSAndroid Build Coastguard Worker
991*7304104dSAndroid Build Coastguard Worker If there was an ET_EXEC module presupplied that contains
992*7304104dSAndroid Build Coastguard Worker the AT_PHDR address, then we only consider that one.
993*7304104dSAndroid Build Coastguard Worker We'll either accept it if its phdr location and e_entry
994*7304104dSAndroid Build Coastguard Worker make sense or reject it if they don't. If there is no
995*7304104dSAndroid Build Coastguard Worker presupplied ET_EXEC, then look for a presupplied module,
996*7304104dSAndroid Build Coastguard Worker which might be a PIE (ET_DYN) that needs its bias adjusted. */
997*7304104dSAndroid Build Coastguard Worker r_debug_vaddr = ((phdr_mod == NULL
998*7304104dSAndroid Build Coastguard Worker || phdr_mod->main.elf == NULL
999*7304104dSAndroid Build Coastguard Worker || phdr_mod->e_type != ET_EXEC)
1000*7304104dSAndroid Build Coastguard Worker ? find_executable (dwfl, phdr, entry,
1001*7304104dSAndroid Build Coastguard Worker &elfclass, &elfdata,
1002*7304104dSAndroid Build Coastguard Worker memory_callback,
1003*7304104dSAndroid Build Coastguard Worker memory_callback_arg)
1004*7304104dSAndroid Build Coastguard Worker : consider_executable (phdr_mod, phdr, entry,
1005*7304104dSAndroid Build Coastguard Worker &elfclass, &elfdata,
1006*7304104dSAndroid Build Coastguard Worker memory_callback,
1007*7304104dSAndroid Build Coastguard Worker memory_callback_arg));
1008*7304104dSAndroid Build Coastguard Worker }
1009*7304104dSAndroid Build Coastguard Worker
1010*7304104dSAndroid Build Coastguard Worker /* If we found PT_DYNAMIC, search it for DT_DEBUG. */
1011*7304104dSAndroid Build Coastguard Worker if (dyn_filesz != 0)
1012*7304104dSAndroid Build Coastguard Worker {
1013*7304104dSAndroid Build Coastguard Worker if (dyn_bias != (GElf_Addr) -1)
1014*7304104dSAndroid Build Coastguard Worker dyn_vaddr += dyn_bias;
1015*7304104dSAndroid Build Coastguard Worker
1016*7304104dSAndroid Build Coastguard Worker Elf_Data in =
1017*7304104dSAndroid Build Coastguard Worker {
1018*7304104dSAndroid Build Coastguard Worker .d_type = ELF_T_DYN,
1019*7304104dSAndroid Build Coastguard Worker .d_version = EV_CURRENT,
1020*7304104dSAndroid Build Coastguard Worker .d_size = dyn_filesz,
1021*7304104dSAndroid Build Coastguard Worker .d_buf = NULL
1022*7304104dSAndroid Build Coastguard Worker };
1023*7304104dSAndroid Build Coastguard Worker int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL);
1024*7304104dSAndroid Build Coastguard Worker if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size,
1025*7304104dSAndroid Build Coastguard Worker dyn_vaddr, dyn_filesz, memory_callback_arg))
1026*7304104dSAndroid Build Coastguard Worker {
1027*7304104dSAndroid Build Coastguard Worker size_t entsize = (elfclass == ELFCLASS32
1028*7304104dSAndroid Build Coastguard Worker ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
1029*7304104dSAndroid Build Coastguard Worker if (unlikely (dyn_filesz > SIZE_MAX / entsize))
1030*7304104dSAndroid Build Coastguard Worker {
1031*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_NOMEM);
1032*7304104dSAndroid Build Coastguard Worker return false;
1033*7304104dSAndroid Build Coastguard Worker }
1034*7304104dSAndroid Build Coastguard Worker /* We can only process as many bytes as there are in
1035*7304104dSAndroid Build Coastguard Worker in.d_size. The data might have been truncated. */
1036*7304104dSAndroid Build Coastguard Worker if (dyn_filesz > in.d_size)
1037*7304104dSAndroid Build Coastguard Worker dyn_filesz = in.d_size;
1038*7304104dSAndroid Build Coastguard Worker if (dyn_filesz / entsize == 0)
1039*7304104dSAndroid Build Coastguard Worker {
1040*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_BADELF);
1041*7304104dSAndroid Build Coastguard Worker return false;
1042*7304104dSAndroid Build Coastguard Worker }
1043*7304104dSAndroid Build Coastguard Worker void *buf = malloc (dyn_filesz);
1044*7304104dSAndroid Build Coastguard Worker if (unlikely (buf == NULL))
1045*7304104dSAndroid Build Coastguard Worker {
1046*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_NOMEM);
1047*7304104dSAndroid Build Coastguard Worker return false;
1048*7304104dSAndroid Build Coastguard Worker }
1049*7304104dSAndroid Build Coastguard Worker Elf_Data out =
1050*7304104dSAndroid Build Coastguard Worker {
1051*7304104dSAndroid Build Coastguard Worker .d_type = ELF_T_DYN,
1052*7304104dSAndroid Build Coastguard Worker .d_version = EV_CURRENT,
1053*7304104dSAndroid Build Coastguard Worker .d_size = dyn_filesz,
1054*7304104dSAndroid Build Coastguard Worker .d_buf = buf
1055*7304104dSAndroid Build Coastguard Worker };
1056*7304104dSAndroid Build Coastguard Worker if (in.d_size > out.d_size)
1057*7304104dSAndroid Build Coastguard Worker in.d_size = out.d_size;
1058*7304104dSAndroid Build Coastguard Worker size_t dyn_align = (elfclass == ELFCLASS32
1059*7304104dSAndroid Build Coastguard Worker ? __alignof__ (Elf32_Dyn)
1060*7304104dSAndroid Build Coastguard Worker : __alignof__ (Elf64_Dyn));
1061*7304104dSAndroid Build Coastguard Worker if (((uintptr_t) in.d_buf & (dyn_align - 1)) != 0)
1062*7304104dSAndroid Build Coastguard Worker {
1063*7304104dSAndroid Build Coastguard Worker memcpy (out.d_buf, in.d_buf, in.d_size);
1064*7304104dSAndroid Build Coastguard Worker in.d_buf = out.d_buf;
1065*7304104dSAndroid Build Coastguard Worker }
1066*7304104dSAndroid Build Coastguard Worker if (likely ((elfclass == ELFCLASS32
1067*7304104dSAndroid Build Coastguard Worker ? elf32_xlatetom : elf64_xlatetom)
1068*7304104dSAndroid Build Coastguard Worker (&out, &in, elfdata) != NULL))
1069*7304104dSAndroid Build Coastguard Worker {
1070*7304104dSAndroid Build Coastguard Worker /* We are looking for DT_DEBUG. */
1071*7304104dSAndroid Build Coastguard Worker if (elfclass == ELFCLASS32)
1072*7304104dSAndroid Build Coastguard Worker {
1073*7304104dSAndroid Build Coastguard Worker Elf32_Dyn (*d32)[dyn_filesz / sizeof (Elf32_Dyn)] = buf;
1074*7304104dSAndroid Build Coastguard Worker size_t n = dyn_filesz / sizeof (Elf32_Dyn);
1075*7304104dSAndroid Build Coastguard Worker for (size_t i = 0; i < n; ++i)
1076*7304104dSAndroid Build Coastguard Worker if ((*d32)[i].d_tag == DT_DEBUG)
1077*7304104dSAndroid Build Coastguard Worker {
1078*7304104dSAndroid Build Coastguard Worker r_debug_vaddr = (*d32)[i].d_un.d_val;
1079*7304104dSAndroid Build Coastguard Worker break;
1080*7304104dSAndroid Build Coastguard Worker }
1081*7304104dSAndroid Build Coastguard Worker }
1082*7304104dSAndroid Build Coastguard Worker else
1083*7304104dSAndroid Build Coastguard Worker {
1084*7304104dSAndroid Build Coastguard Worker Elf64_Dyn (*d64)[dyn_filesz / sizeof (Elf64_Dyn)] = buf;
1085*7304104dSAndroid Build Coastguard Worker size_t n = dyn_filesz / sizeof (Elf64_Dyn);
1086*7304104dSAndroid Build Coastguard Worker for (size_t i = 0; i < n; ++i)
1087*7304104dSAndroid Build Coastguard Worker if ((*d64)[i].d_tag == DT_DEBUG)
1088*7304104dSAndroid Build Coastguard Worker {
1089*7304104dSAndroid Build Coastguard Worker r_debug_vaddr = (*d64)[i].d_un.d_val;
1090*7304104dSAndroid Build Coastguard Worker break;
1091*7304104dSAndroid Build Coastguard Worker }
1092*7304104dSAndroid Build Coastguard Worker }
1093*7304104dSAndroid Build Coastguard Worker }
1094*7304104dSAndroid Build Coastguard Worker
1095*7304104dSAndroid Build Coastguard Worker (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
1096*7304104dSAndroid Build Coastguard Worker memory_callback_arg);
1097*7304104dSAndroid Build Coastguard Worker free (buf);
1098*7304104dSAndroid Build Coastguard Worker }
1099*7304104dSAndroid Build Coastguard Worker }
1100*7304104dSAndroid Build Coastguard Worker }
1101*7304104dSAndroid Build Coastguard Worker else
1102*7304104dSAndroid Build Coastguard Worker /* We have to look for a presupplied executable file to determine
1103*7304104dSAndroid Build Coastguard Worker the vaddr of its dynamic section and DT_DEBUG therein. */
1104*7304104dSAndroid Build Coastguard Worker r_debug_vaddr = find_executable (dwfl, 0, 0, &elfclass, &elfdata,
1105*7304104dSAndroid Build Coastguard Worker memory_callback, memory_callback_arg);
1106*7304104dSAndroid Build Coastguard Worker
1107*7304104dSAndroid Build Coastguard Worker if (r_debug_vaddr == 0)
1108*7304104dSAndroid Build Coastguard Worker return 0;
1109*7304104dSAndroid Build Coastguard Worker
1110*7304104dSAndroid Build Coastguard Worker /* For following pointers from struct link_map, we will use an
1111*7304104dSAndroid Build Coastguard Worker integrated memory access callback that can consult module text
1112*7304104dSAndroid Build Coastguard Worker elided from the core file. This is necessary when the l_name
1113*7304104dSAndroid Build Coastguard Worker pointer for the dynamic linker's own entry is a pointer into the
1114*7304104dSAndroid Build Coastguard Worker executable's .interp section. */
1115*7304104dSAndroid Build Coastguard Worker struct integrated_memory_callback mcb =
1116*7304104dSAndroid Build Coastguard Worker {
1117*7304104dSAndroid Build Coastguard Worker .memory_callback = memory_callback,
1118*7304104dSAndroid Build Coastguard Worker .memory_callback_arg = memory_callback_arg
1119*7304104dSAndroid Build Coastguard Worker };
1120*7304104dSAndroid Build Coastguard Worker
1121*7304104dSAndroid Build Coastguard Worker /* Now we can follow the dynamic linker's library list. */
1122*7304104dSAndroid Build Coastguard Worker return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr,
1123*7304104dSAndroid Build Coastguard Worker &integrated_memory_callback, &mcb, r_debug_info);
1124*7304104dSAndroid Build Coastguard Worker }
1125*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_link_map_report)
1126