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