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