blob: 05839b3aad80e3b9fb8f39fe68396b1cefd57c33 [file] [log] [blame]
Ben Cheng25b3c042013-11-20 14:45:36 -08001/* Report modules by examining dynamic linker data structures.
2 Copyright (C) 2008-2010 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
4
5 Red Hat elfutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by the
7 Free Software Foundation; version 2 of the License.
8
9 Red Hat elfutils is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with Red Hat elfutils; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
17
18 In addition, as a special exception, Red Hat, Inc. gives You the
19 additional right to link the code of Red Hat elfutils with code licensed
20 under any Open Source Initiative certified open source license
21 (http://www.opensource.org/licenses/index.php) which requires the
22 distribution of source code with any binary distribution and to
23 distribute linked combinations of the two. Non-GPL Code permitted under
24 this exception must only link to the code of Red Hat elfutils through
25 those well defined interfaces identified in the file named EXCEPTION
26 found in the source code files (the "Approved Interfaces"). The files
27 of Non-GPL Code may instantiate templates or use macros or inline
28 functions from the Approved Interfaces without causing the resulting
29 work to be covered by the GNU General Public License. Only Red Hat,
30 Inc. may make changes or additions to the list of Approved Interfaces.
31 Red Hat's grant of this exception is conditioned upon your not adding
32 any new exceptions. If you wish to add a new Approved Interface or
33 exception, please contact Red Hat. You must obey the GNU General Public
34 License in all respects for all of the Red Hat elfutils code and other
35 code used in conjunction with Red Hat elfutils except the Non-GPL Code
36 covered by this exception. If you modify this file, you may extend this
37 exception to your version of the file, but you are not obligated to do
38 so. If you do not wish to provide this exception without modification,
39 you must delete this exception statement from your version and license
40 this file solely under the GPL without exception.
41
42 Red Hat elfutils is an included package of the Open Invention Network.
43 An included package of the Open Invention Network is a package for which
44 Open Invention Network licensees cross-license their patents. No patent
45 license is granted, either expressly or impliedly, by designation as an
46 included package. Should you wish to participate in the Open Invention
47 Network licensing program, please visit www.openinventionnetwork.com
48 <http://www.openinventionnetwork.com>. */
49
50#include <config.h>
51#include "libdwflP.h"
52
53#include <byteswap.h>
54#include <endian.h>
55
56/* This element is always provided and always has a constant value.
57 This makes it an easy thing to scan for to discern the format. */
58#define PROBE_TYPE AT_PHENT
59#define PROBE_VAL32 sizeof (Elf32_Phdr)
60#define PROBE_VAL64 sizeof (Elf64_Phdr)
61
62#if BYTE_ORDER == BIG_ENDIAN
63# define BE32(x) (x)
64# define BE64(x) (x)
65# define LE32(x) bswap_32 (x)
66# define LE64(x) bswap_64 (x)
67#else
68# define LE32(x) (x)
69# define LE64(x) (x)
70# define BE32(x) bswap_32 (x)
71# define BE64(x) bswap_64 (x)
72#endif
73
74
75/* Examine an auxv data block and determine its format.
76 Return true iff we figured it out. */
77static bool
78auxv_format_probe (const void *auxv, size_t size,
79 uint_fast8_t *elfclass, uint_fast8_t *elfdata)
80{
81 const union
82 {
83 char buf[size];
84 Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)];
85 Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)];
86 } *u = auxv;
87
88 inline bool check64 (size_t i)
89 {
90 if (u->a64[i].a_type == BE64 (PROBE_TYPE)
91 && u->a64[i].a_un.a_val == BE64 (PROBE_VAL64))
92 {
93 *elfdata = ELFDATA2MSB;
94 return true;
95 }
96
97 if (u->a64[i].a_type == LE64 (PROBE_TYPE)
98 && u->a64[i].a_un.a_val == LE64 (PROBE_VAL64))
99 {
100 *elfdata = ELFDATA2LSB;
101 return true;
102 }
103
104 return false;
105 }
106
107 inline bool check32 (size_t i)
108 {
109 if (u->a32[i].a_type == BE32 (PROBE_TYPE)
110 && u->a32[i].a_un.a_val == BE32 (PROBE_VAL32))
111 {
112 *elfdata = ELFDATA2MSB;
113 return true;
114 }
115
116 if (u->a32[i].a_type == LE32 (PROBE_TYPE)
117 && u->a32[i].a_un.a_val == LE32 (PROBE_VAL32))
118 {
119 *elfdata = ELFDATA2LSB;
120 return true;
121 }
122
123 return false;
124 }
125
126 for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
127 {
128 if (check64 (i))
129 {
130 *elfclass = ELFCLASS64;
131 return true;
132 }
133
134 if (check32 (i * 2) || check32 (i * 2 + 1))
135 {
136 *elfclass = ELFCLASS32;
137 return true;
138 }
139 }
140
141 return false;
142}
143
144/* This is a Dwfl_Memory_Callback that wraps another memory callback.
145 If the underlying callback cannot fill the data, then this will
146 fall back to fetching data from module files. */
147
148struct integrated_memory_callback
149{
150 Dwfl_Memory_Callback *memory_callback;
151 void *memory_callback_arg;
152 void *buffer;
153};
154
155static bool
156integrated_memory_callback (Dwfl *dwfl, int ndx,
157 void **buffer, size_t *buffer_available,
158 GElf_Addr vaddr,
159 size_t minread,
160 void *arg)
161{
162 struct integrated_memory_callback *info = arg;
163
164 if (ndx == -1)
165 {
166 /* Called for cleanup. */
167 if (info->buffer != NULL)
168 {
169 /* The last probe buffer came from the underlying callback.
170 Let it do its cleanup. */
171 assert (*buffer == info->buffer); /* XXX */
172 *buffer = info->buffer;
173 info->buffer = NULL;
174 return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
175 vaddr, minread,
176 info->memory_callback_arg);
177 }
178 *buffer = NULL;
179 *buffer_available = 0;
180 return false;
181 }
182
183 if (*buffer != NULL)
184 /* For a final-read request, we only use the underlying callback. */
185 return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
186 vaddr, minread, info->memory_callback_arg);
187
188 /* Let the underlying callback try to fill this request. */
189 if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available,
190 vaddr, minread, info->memory_callback_arg))
191 {
192 *buffer = info->buffer;
193 return true;
194 }
195
196 /* Now look for module text covering this address. */
197
198 Dwfl_Module *mod;
199 (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod);
200 if (mod == NULL)
201 return false;
202
203 Dwarf_Addr bias;
204 Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias);
205 if (unlikely (scn == NULL))
206 {
207#if 0 // XXX would have to handle ndx=-1 cleanup calls passed down.
208 /* If we have no sections we can try to fill it from the module file
209 based on its phdr mappings. */
210 if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL)
211 return INTUSE(dwfl_elf_phdr_memory_callback)
212 (dwfl, 0, buffer, buffer_available,
213 vaddr - mod->main.bias, minread, mod->main.elf);
214#endif
215 return false;
216 }
217
218 Elf_Data *data = elf_rawdata (scn, NULL);
219 if (unlikely (data == NULL))
220 // XXX throw error?
221 return false;
222
223 if (unlikely (data->d_size < vaddr))
224 return false;
225
226 /* Provide as much data as we have. */
227 void *contents = data->d_buf + vaddr;
228 size_t avail = data->d_size - vaddr;
229 if (unlikely (avail < minread))
230 return false;
231
232 /* If probing for a string, make sure it's terminated. */
233 if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL))
234 return false;
235
236 /* We have it! */
237 *buffer = contents;
238 *buffer_available = avail;
239 return true;
240}
241
242static size_t
243addrsize (uint_fast8_t elfclass)
244{
245 return elfclass * 4;
246}
247
248/* Report a module for each struct link_map in the linked list at r_map
249 in the struct r_debug at R_DEBUG_VADDR.
250
251 For each link_map entry, if an existing module resides at its address,
252 this just modifies that module's name and suggested file name. If
253 no such module exists, this calls dwfl_report_elf on the l_name string.
254
255 Returns the number of modules found, or -1 for errors. */
256
257static int
258report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
259 Dwfl *dwfl, GElf_Addr r_debug_vaddr,
260 Dwfl_Memory_Callback *memory_callback,
261 void *memory_callback_arg)
262{
263 /* Skip r_version, to aligned r_map field. */
264 GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
265
266 void *buffer = NULL;
267 size_t buffer_available = 0;
268 inline int release_buffer (int result)
269 {
270 if (buffer != NULL)
271 (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
272 memory_callback_arg);
273 return result;
274 }
275
276 GElf_Addr addrs[4];
277 inline bool read_addrs (GElf_Addr vaddr, size_t n)
278 {
279 size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */
280
281 /* Read a new buffer if the old one doesn't cover these words. */
282 if (buffer == NULL
283 || vaddr < read_vaddr
284 || vaddr - read_vaddr + nb > buffer_available)
285 {
286 release_buffer (0);
287
288 read_vaddr = vaddr;
289 int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
290 if (unlikely (segndx < 0)
291 || unlikely (! (*memory_callback) (dwfl, segndx,
292 &buffer, &buffer_available,
293 vaddr, nb, memory_callback_arg)))
294 return true;
295 }
296
297 const union
298 {
299 Elf32_Addr a32[n];
300 Elf64_Addr a64[n];
301 } *in = vaddr - read_vaddr + buffer;
302
303 if (elfclass == ELFCLASS32)
304 {
305 if (elfdata == ELFDATA2MSB)
306 for (size_t i = 0; i < n; ++i)
307 addrs[i] = BE32 (in->a32[i]);
308 else
309 for (size_t i = 0; i < n; ++i)
310 addrs[i] = LE32 (in->a32[i]);
311 }
312 else
313 {
314 if (elfdata == ELFDATA2MSB)
315 for (size_t i = 0; i < n; ++i)
316 addrs[i] = BE64 (in->a64[i]);
317 else
318 for (size_t i = 0; i < n; ++i)
319 addrs[i] = LE64 (in->a64[i]);
320 }
321
322 return false;
323 }
324
325 if (unlikely (read_addrs (read_vaddr, 1)))
326 return release_buffer (-1);
327
328 GElf_Addr next = addrs[0];
329
330 Dwfl_Module **lastmodp = &dwfl->modulelist;
331 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 size_t iterations = 0;
338 while (next != 0 && ++iterations < dwfl->lookup_elts)
339 {
340 if (read_addrs (next, 4))
341 return release_buffer (-1);
342
343 GElf_Addr l_addr = addrs[0];
344 GElf_Addr l_name = addrs[1];
345 GElf_Addr l_ld = addrs[2];
346 next = addrs[3];
347
348 /* If a clobbered or truncated memory image has no useful pointer,
349 just skip this element. */
350 if (l_ld == 0)
351 continue;
352
353 /* Fetch the string at the l_name address. */
354 const char *name = NULL;
355 if (buffer != NULL
356 && read_vaddr <= l_name
357 && l_name + 1 - read_vaddr < buffer_available
358 && memchr (l_name - read_vaddr + buffer, '\0',
359 buffer_available - (l_name - read_vaddr)) != NULL)
360 name = l_name - read_vaddr + buffer;
361 else
362 {
363 release_buffer (0);
364 read_vaddr = l_name;
365 int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL);
366 if (likely (segndx >= 0)
367 && (*memory_callback) (dwfl, segndx,
368 &buffer, &buffer_available,
369 l_name, 0, memory_callback_arg))
370 name = buffer;
371 }
372
373 if (name != NULL && name[0] == '\0')
374 name = NULL;
375
376 /* If content-sniffing already reported a module covering
377 the same area, find that existing module to adjust.
378 The l_ld address is the only one we know for sure
379 to be within the module's own segments (its .dynamic). */
380 Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (dwfl, l_ld);
381 if (mod != NULL)
382 {
383 /* We have a module. We can give it a better name from l_name. */
384 if (name != NULL && mod->name[0] == '[')
385 {
386 char *newname = strdup (basename (name));
387 if (newname != NULL)
388 {
389 free (mod->name);
390 mod->name = newname;
391 }
392 }
393
394 if (name == NULL && mod->name[0] == '/')
395 name = mod->name;
396
397 /* If we don't have a file for it already, we can pre-install
398 the full file name from l_name. Opening the file by this
399 name will be the fallback when no build ID match is found.
400 XXX hook for sysroot */
401 if (name != NULL && mod->main.name == NULL)
402 mod->main.name = strdup (name);
403 }
404 else if (name != NULL)
405 {
406 /* We have to find the file's phdrs to compute along with l_addr
407 what its runtime address boundaries are. */
408
409 // XXX hook for sysroot
410 mod = INTUSE(dwfl_report_elf) (dwfl, basename (name),
411 name, -1, l_addr);
412 }
413
414 if (mod != NULL)
415 {
416 ++result;
417
418 /* Move this module to the end of the list, so that we end
419 up with a list in the same order as the link_map chain. */
420 if (mod->next != NULL)
421 {
422 if (*lastmodp != mod)
423 {
424 lastmodp = &dwfl->modulelist;
425 while (*lastmodp != mod)
426 lastmodp = &(*lastmodp)->next;
427 }
428 *lastmodp = mod->next;
429 mod->next = NULL;
430 while (*lastmodp != NULL)
431 lastmodp = &(*lastmodp)->next;
432 *lastmodp = mod;
433 }
434
435 lastmodp = &mod->next;
436 }
437 }
438
439 return release_buffer (result);
440}
441
442static GElf_Addr
443consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry,
444 uint_fast8_t *elfclass, uint_fast8_t *elfdata,
445 Dwfl_Memory_Callback *memory_callback,
446 void *memory_callback_arg)
447{
448 GElf_Ehdr ehdr;
449 if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL))
450 return 0;
451
452 if (at_entry != 0)
453 {
454 /* If we have an AT_ENTRY value, reject this executable if
455 its entry point address could not have supplied that. */
456
457 if (ehdr.e_entry == 0)
458 return 0;
459
460 if (mod->e_type == ET_EXEC)
461 {
462 if (ehdr.e_entry != at_entry)
463 return 0;
464 }
465 else
466 {
467 /* It could be a PIE. */
468 }
469 }
470
471 // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr
472 /* Find the vaddr of the DT_DEBUG's d_ptr. This is the memory
473 address where &r_debug was written at runtime. */
474 GElf_Xword align = mod->dwfl->segment_align;
475 GElf_Addr d_val_vaddr = 0;
476 for (uint_fast16_t i = 0; i < ehdr.e_phnum; ++i)
477 {
478 GElf_Phdr phdr_mem;
479 GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
480 if (phdr == NULL)
481 break;
482
483 if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align))
484 align = phdr->p_align;
485
486 if (at_phdr != 0
487 && phdr->p_type == PT_LOAD
488 && (phdr->p_offset & -align) == (ehdr.e_phoff & -align))
489 {
490 /* This is the segment that would map the phdrs.
491 If we have an AT_PHDR value, reject this executable
492 if its phdr mapping could not have supplied that. */
493 if (mod->e_type == ET_EXEC)
494 {
495 if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr)
496 return 0;
497 }
498 else
499 {
500 /* It could be a PIE. If the AT_PHDR value and our
501 phdr address don't match modulo ALIGN, then this
502 could not have been the right PIE. */
503 if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align)
504 != (at_phdr & -align))
505 return 0;
506
507 /* Calculate the bias applied to the PIE's p_vaddr values. */
508 GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset
509 + phdr->p_vaddr));
510
511 /* Final sanity check: if we have an AT_ENTRY value,
512 reject this PIE unless its biased e_entry matches. */
513 if (at_entry != 0 && at_entry != ehdr.e_entry + bias)
514 return 0;
515
516 /* If we're changing the module's address range,
517 we've just invalidated the module lookup table. */
518 GElf_Addr mod_bias = dwfl_adjusted_address (mod, 0);
519 if (bias != mod_bias)
520 {
521 mod->low_addr -= mod_bias;
522 mod->high_addr -= mod_bias;
523 mod->low_addr += bias;
524 mod->high_addr += bias;
525
526 free (mod->dwfl->lookup_module);
527 mod->dwfl->lookup_module = NULL;
528 }
529 }
530 }
531
532 if (phdr->p_type == PT_DYNAMIC)
533 {
534 Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset,
535 phdr->p_filesz, ELF_T_DYN);
536 if (data == NULL)
537 continue;
538 const size_t entsize = gelf_fsize (mod->main.elf,
539 ELF_T_DYN, 1, EV_CURRENT);
540 const size_t n = data->d_size / entsize;
541 for (size_t j = 0; j < n; ++j)
542 {
543 GElf_Dyn dyn_mem;
544 GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
545 if (dyn != NULL && dyn->d_tag == DT_DEBUG)
546 {
547 d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2;
548 break;
549 }
550 }
551 }
552 }
553
554 if (d_val_vaddr != 0)
555 {
556 /* Now we have the final address from which to read &r_debug. */
557 d_val_vaddr = dwfl_adjusted_address (mod, d_val_vaddr);
558
559 void *buffer = NULL;
560 size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]);
561
562 int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, NULL);
563
564 if ((*memory_callback) (mod->dwfl, segndx,
565 &buffer, &buffer_available,
566 d_val_vaddr, buffer_available,
567 memory_callback_arg))
568 {
569 const union
570 {
571 Elf32_Addr a32;
572 Elf64_Addr a64;
573 } *u = buffer;
574
575 GElf_Addr vaddr;
576 if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
577 vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
578 ? BE32 (u->a32) : LE32 (u->a32));
579 else
580 vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
581 ? BE64 (u->a64) : LE64 (u->a64));
582
583 (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0,
584 memory_callback_arg);
585
586 if (*elfclass == ELFCLASSNONE)
587 *elfclass = ehdr.e_ident[EI_CLASS];
588 else if (*elfclass != ehdr.e_ident[EI_CLASS])
589 return 0;
590
591 if (*elfdata == ELFDATANONE)
592 *elfdata = ehdr.e_ident[EI_DATA];
593 else if (*elfdata != ehdr.e_ident[EI_DATA])
594 return 0;
595
596 return vaddr;
597 }
598 }
599
600 return 0;
601}
602
603/* Try to find an existing executable module with a DT_DEBUG. */
604static GElf_Addr
605find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
606 uint_fast8_t *elfclass, uint_fast8_t *elfdata,
607 Dwfl_Memory_Callback *memory_callback,
608 void *memory_callback_arg)
609{
610 for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
611 if (mod->main.elf != NULL)
612 {
613 GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry,
614 elfclass, elfdata,
615 memory_callback,
616 memory_callback_arg);
617 if (r_debug_vaddr != 0)
618 return r_debug_vaddr;
619 }
620
621 return 0;
622}
623
624
625int
626dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
627 Dwfl_Memory_Callback *memory_callback,
628 void *memory_callback_arg)
629{
630 GElf_Addr r_debug_vaddr = 0;
631
632 uint_fast8_t elfclass = ELFCLASSNONE;
633 uint_fast8_t elfdata = ELFDATANONE;
634 if (likely (auxv != NULL)
635 && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata)))
636 {
637 GElf_Addr entry = 0;
638 GElf_Addr phdr = 0;
639 GElf_Xword phent = 0;
640 GElf_Xword phnum = 0;
641
642#define AUXV_SCAN(NN, BL) do \
643 { \
644 const Elf##NN##_auxv_t *av = auxv; \
645 for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i) \
646 { \
647 Elf##NN##_Addr val = BL##NN (av[i].a_un.a_val); \
648 if (av[i].a_type == BL##NN (AT_ENTRY)) \
649 entry = val; \
650 else if (av[i].a_type == BL##NN (AT_PHDR)) \
651 phdr = val; \
652 else if (av[i].a_type == BL##NN (AT_PHNUM)) \
653 phnum = val; \
654 else if (av[i].a_type == BL##NN (AT_PHENT)) \
655 phent = val; \
656 else if (av[i].a_type == BL##NN (AT_PAGESZ)) \
657 { \
658 if (val > 1 \
659 && (dwfl->segment_align == 0 \
660 || val < dwfl->segment_align)) \
661 dwfl->segment_align = val; \
662 } \
663 } \
664 } \
665 while (0)
666
667 if (elfclass == ELFCLASS32)
668 {
669 if (elfdata == ELFDATA2MSB)
670 AUXV_SCAN (32, BE);
671 else
672 AUXV_SCAN (32, LE);
673 }
674 else
675 {
676 if (elfdata == ELFDATA2MSB)
677 AUXV_SCAN (64, BE);
678 else
679 AUXV_SCAN (64, LE);
680 }
681
682 /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC. */
683 GElf_Addr dyn_vaddr = 0;
684 GElf_Xword dyn_filesz = 0;
685 GElf_Addr dyn_bias = (GElf_Addr) -1;
686
687 inline bool consider_phdr (GElf_Word type,
688 GElf_Addr vaddr, GElf_Xword filesz)
689 {
690 switch (type)
691 {
692 case PT_PHDR:
693 if (dyn_bias == (GElf_Addr) -1
694 /* Do a sanity check on the putative address. */
695 && ((vaddr & (dwfl->segment_align - 1))
696 == (phdr & (dwfl->segment_align - 1))))
697 {
698 dyn_bias = phdr - vaddr;
699 return dyn_vaddr != 0;
700 }
701 break;
702
703 case PT_DYNAMIC:
704 dyn_vaddr = vaddr;
705 dyn_filesz = filesz;
706 return dyn_bias != (GElf_Addr) -1;
707 }
708
709 return false;
710 }
711
712 if (phdr != 0 && phnum != 0)
713 {
714 Dwfl_Module *phdr_mod;
715 int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod);
716 Elf_Data in =
717 {
718 .d_type = ELF_T_PHDR,
719 .d_version = EV_CURRENT,
720 .d_size = phnum * phent,
721 .d_buf = NULL
722 };
723 if ((*memory_callback) (dwfl, phdr_segndx, &in.d_buf, &in.d_size,
724 phdr, phnum * phent, memory_callback_arg))
725 {
726 union
727 {
728 Elf32_Phdr p32;
729 Elf64_Phdr p64;
730 char data[phnum * phent];
731 } buf;
732 Elf_Data out =
733 {
734 .d_type = ELF_T_PHDR,
735 .d_version = EV_CURRENT,
736 .d_size = phnum * phent,
737 .d_buf = &buf
738 };
739 in.d_size = out.d_size;
740 if (likely ((elfclass == ELFCLASS32
741 ? elf32_xlatetom : elf64_xlatetom)
742 (&out, &in, elfdata) != NULL))
743 {
744 /* We are looking for PT_DYNAMIC. */
745 const union
746 {
747 Elf32_Phdr p32[phnum];
748 Elf64_Phdr p64[phnum];
749 } *u = (void *) &buf;
750 if (elfclass == ELFCLASS32)
751 {
752 for (size_t i = 0; i < phnum; ++i)
753 if (consider_phdr (u->p32[i].p_type,
754 u->p32[i].p_vaddr,
755 u->p32[i].p_filesz))
756 break;
757 }
758 else
759 {
760 for (size_t i = 0; i < phnum; ++i)
761 if (consider_phdr (u->p64[i].p_type,
762 u->p64[i].p_vaddr,
763 u->p64[i].p_filesz))
764 break;
765 }
766 }
767
768 (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
769 memory_callback_arg);
770 }
771 else
772 /* We could not read the executable's phdrs from the
773 memory image. If we have a presupplied executable,
774 we can still use the AT_PHDR and AT_ENTRY values to
775 verify it, and to adjust its bias if it's a PIE.
776
777 If there was an ET_EXEC module presupplied that contains
778 the AT_PHDR address, then we only consider that one.
779 We'll either accept it if its phdr location and e_entry
780 make sense or reject it if they don't. If there is no
781 presupplied ET_EXEC, then look for a presupplied module,
782 which might be a PIE (ET_DYN) that needs its bias adjusted. */
783 r_debug_vaddr = ((phdr_mod == NULL
784 || phdr_mod->main.elf == NULL
785 || phdr_mod->e_type != ET_EXEC)
786 ? find_executable (dwfl, phdr, entry,
787 &elfclass, &elfdata,
788 memory_callback,
789 memory_callback_arg)
790 : consider_executable (phdr_mod, phdr, entry,
791 &elfclass, &elfdata,
792 memory_callback,
793 memory_callback_arg));
794 }
795
796 /* If we found PT_DYNAMIC, search it for DT_DEBUG. */
797 if (dyn_filesz != 0)
798 {
799 if (dyn_bias != (GElf_Addr) -1)
800 dyn_vaddr += dyn_bias;
801
802 Elf_Data in =
803 {
804 .d_type = ELF_T_DYN,
805 .d_version = EV_CURRENT,
806 .d_size = dyn_filesz,
807 .d_buf = NULL
808 };
809 int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL);
810 if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size,
811 dyn_vaddr, dyn_filesz, memory_callback_arg))
812 {
813 union
814 {
815 Elf32_Dyn d32;
816 Elf64_Dyn d64;
817 char data[dyn_filesz];
818 } buf;
819 Elf_Data out =
820 {
821 .d_type = ELF_T_DYN,
822 .d_version = EV_CURRENT,
823 .d_size = dyn_filesz,
824 .d_buf = &buf
825 };
826 in.d_size = out.d_size;
827 if (likely ((elfclass == ELFCLASS32
828 ? elf32_xlatetom : elf64_xlatetom)
829 (&out, &in, elfdata) != NULL))
830 {
831 /* We are looking for DT_DEBUG. */
832 const union
833 {
834 Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)];
835 Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)];
836 } *u = (void *) &buf;
837 if (elfclass == ELFCLASS32)
838 {
839 size_t n = dyn_filesz / sizeof (Elf32_Dyn);
840 for (size_t i = 0; i < n; ++i)
841 if (u->d32[i].d_tag == DT_DEBUG)
842 {
843 r_debug_vaddr = u->d32[i].d_un.d_val;
844 break;
845 }
846 }
847 else
848 {
849 size_t n = dyn_filesz / sizeof (Elf64_Dyn);
850 for (size_t i = 0; i < n; ++i)
851 if (u->d64[i].d_tag == DT_DEBUG)
852 {
853 r_debug_vaddr = u->d64[i].d_un.d_val;
854 break;
855 }
856 }
857 }
858
859 (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
860 memory_callback_arg);
861 }
862 }
863 }
864 else
865 /* We have to look for a presupplied executable file to determine
866 the vaddr of its dynamic section and DT_DEBUG therein. */
867 r_debug_vaddr = find_executable (dwfl, 0, 0, &elfclass, &elfdata,
868 memory_callback, memory_callback_arg);
869
870 if (r_debug_vaddr == 0)
871 return 0;
872
873 /* For following pointers from struct link_map, we will use an
874 integrated memory access callback that can consult module text
875 elided from the core file. This is necessary when the l_name
876 pointer for the dynamic linker's own entry is a pointer into the
877 executable's .interp section. */
878 struct integrated_memory_callback mcb =
879 {
880 .memory_callback = memory_callback,
881 .memory_callback_arg = memory_callback_arg
882 };
883
884 /* Now we can follow the dynamic linker's library list. */
885 return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr,
886 &integrated_memory_callback, &mcb);
887}
888INTDEF (dwfl_link_map_report)