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