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