1 /* Report modules by examining dynamic linker data structures.
2 Copyright (C) 2008 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. */
77 static bool
auxv_format_probe(const void * auxv,size_t size,uint_fast8_t * elfclass,uint_fast8_t * elfdata)78 auxv_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 size_t i;
127 for (i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
128 {
129 if (check64 (i))
130 {
131 *elfclass = ELFCLASS64;
132 return true;
133 }
134
135 if (check32 (i))
136 {
137 *elfclass = ELFCLASS32;
138 return true;
139 }
140 }
141 for (; i < size / sizeof (Elf64_auxv_t); ++i)
142 if (check32 (i))
143 {
144 *elfclass = ELFCLASS32;
145 return true;
146 }
147
148 return false;
149 }
150
151 /* This is a Dwfl_Memory_Callback that wraps another memory callback.
152 If the underlying callback cannot fill the data, then this will
153 fall back to fetching data from module files. */
154
155 struct integrated_memory_callback
156 {
157 Dwfl_Memory_Callback *memory_callback;
158 void *memory_callback_arg;
159 void *buffer;
160 };
161
162 static bool
integrated_memory_callback(Dwfl * dwfl,int ndx,void ** buffer,size_t * buffer_available,GElf_Addr vaddr,size_t minread,void * arg)163 integrated_memory_callback (Dwfl *dwfl, int ndx,
164 void **buffer, size_t *buffer_available,
165 GElf_Addr vaddr,
166 size_t minread,
167 void *arg)
168 {
169 struct integrated_memory_callback *info = arg;
170
171 if (ndx == -1)
172 {
173 /* Called for cleanup. */
174 if (info->buffer != NULL)
175 {
176 /* The last probe buffer came from the underlying callback.
177 Let it do its cleanup. */
178 assert (*buffer == info->buffer); /* XXX */
179 *buffer = info->buffer;
180 info->buffer = NULL;
181 return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
182 vaddr, minread,
183 info->memory_callback_arg);
184 }
185 *buffer = NULL;
186 *buffer_available = 0;
187 return false;
188 }
189
190 if (*buffer != NULL)
191 /* For a final-read request, we only use the underlying callback. */
192 return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
193 vaddr, minread, info->memory_callback_arg);
194
195 /* Let the underlying callback try to fill this request. */
196 if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available,
197 vaddr, minread, info->memory_callback_arg))
198 {
199 *buffer = info->buffer;
200 return true;
201 }
202
203 /* Now look for module text covering this address. */
204
205 Dwfl_Module *mod;
206 (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod);
207 if (mod == NULL)
208 return false;
209
210 Dwarf_Addr bias;
211 Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias);
212 if (unlikely (scn == NULL))
213 {
214 #if 0 // XXX would have to handle ndx=-1 cleanup calls passed down.
215 /* If we have no sections we can try to fill it from the module file
216 based on its phdr mappings. */
217 if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL)
218 return INTUSE(dwfl_elf_phdr_memory_callback)
219 (dwfl, 0, buffer, buffer_available,
220 vaddr - mod->main.bias, minread, mod->main.elf);
221 #endif
222 return false;
223 }
224
225 Elf_Data *data = elf_rawdata (scn, NULL);
226 if (unlikely (data == NULL))
227 // XXX throw error?
228 return false;
229
230 if (unlikely (data->d_size < vaddr))
231 return false;
232
233 /* Provide as much data as we have. */
234 void *contents = data->d_buf + vaddr;
235 size_t avail = data->d_size - vaddr;
236 if (unlikely (avail < minread))
237 return false;
238
239 /* If probing for a string, make sure it's terminated. */
240 if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL))
241 return false;
242
243 /* We have it! */
244 *buffer = contents;
245 *buffer_available = avail;
246 return true;
247 }
248
249 static size_t
addrsize(uint_fast8_t elfclass)250 addrsize (uint_fast8_t elfclass)
251 {
252 return elfclass * 4;
253 }
254
255 /* Report a module for each struct link_map in the linked list at r_map
256 in the struct r_debug at R_DEBUG_VADDR.
257
258 For each link_map entry, if an existing module resides at its address,
259 this just modifies that module's name and suggested file name. If
260 no such module exists, this calls dwfl_report_elf on the l_name string.
261
262 Returns the number of modules found, or -1 for errors. */
263
264 static int
report_r_debug(uint_fast8_t elfclass,uint_fast8_t elfdata,Dwfl * dwfl,GElf_Addr r_debug_vaddr,Dwfl_Memory_Callback * memory_callback,void * memory_callback_arg)265 report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
266 Dwfl *dwfl, GElf_Addr r_debug_vaddr,
267 Dwfl_Memory_Callback *memory_callback,
268 void *memory_callback_arg)
269 {
270 /* Skip r_version, to aligned r_map field. */
271 GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
272
273 void *buffer = NULL;
274 size_t buffer_available = 0;
275 inline int release_buffer (int result)
276 {
277 if (buffer != NULL)
278 (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
279 memory_callback_arg);
280 return result;
281 }
282
283 GElf_Addr addrs[4];
284 inline bool read_addrs (GElf_Addr vaddr, size_t n)
285 {
286 size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */
287
288 /* Read a new buffer if the old one doesn't cover these words. */
289 if (buffer == NULL
290 || vaddr < read_vaddr
291 || vaddr - read_vaddr + nb > buffer_available)
292 {
293 release_buffer (0);
294
295 read_vaddr = vaddr;
296 int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
297 if (unlikely (segndx < 0)
298 || unlikely (! (*memory_callback) (dwfl, segndx,
299 &buffer, &buffer_available,
300 vaddr, nb, memory_callback_arg)))
301 return true;
302 }
303
304 const union
305 {
306 Elf32_Addr a32[n];
307 Elf64_Addr a64[n];
308 } *in = vaddr - read_vaddr + buffer;
309
310 if (elfclass == ELFCLASS32)
311 {
312 if (elfdata == ELFDATA2MSB)
313 for (size_t i = 0; i < n; ++i)
314 addrs[i] = BE32 (in->a32[i]);
315 else
316 for (size_t i = 0; i < n; ++i)
317 addrs[i] = LE32 (in->a32[i]);
318 }
319 else
320 {
321 if (elfdata == ELFDATA2MSB)
322 for (size_t i = 0; i < n; ++i)
323 addrs[i] = BE64 (in->a64[i]);
324 else
325 for (size_t i = 0; i < n; ++i)
326 addrs[i] = LE64 (in->a64[i]);
327 }
328
329 return false;
330 }
331
332 if (unlikely (read_addrs (read_vaddr, 1)))
333 return release_buffer (-1);
334
335 GElf_Addr next = addrs[0];
336
337 Dwfl_Module **lastmodp = &dwfl->modulelist;
338 int result = 0;
339 while (next != 0)
340 {
341 if (read_addrs (next, 4))
342 return release_buffer (-1);
343
344 GElf_Addr l_addr = addrs[0];
345 GElf_Addr l_name = addrs[1];
346 GElf_Addr l_ld = addrs[2];
347 next = addrs[3];
348
349 /* Fetch the string at the l_name address. */
350 const char *name = NULL;
351 if (buffer != NULL
352 && read_vaddr <= l_name
353 && l_name + 1 - read_vaddr < buffer_available
354 && memchr (l_name - read_vaddr + buffer, '\0',
355 buffer_available - (l_name - read_vaddr)) != NULL)
356 name = l_name - read_vaddr + buffer;
357 else
358 {
359 release_buffer (0);
360 read_vaddr = l_name;
361 int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL);
362 if (likely (segndx >= 0)
363 && (*memory_callback) (dwfl, segndx,
364 &buffer, &buffer_available,
365 l_name, 0, memory_callback_arg))
366 name = buffer;
367 }
368
369 if (name != NULL && name[0] == '\0')
370 name = NULL;
371
372 /* If content-sniffing already reported a module covering
373 the same area, find that existing module to adjust.
374 The l_ld address is the only one we know for sure
375 to be within the module's own segments (its .dynamic). */
376 Dwfl_Module *mod;
377 int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_ld, &mod);
378 if (unlikely (segndx < 0))
379 return release_buffer (-1);
380
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
402 && mod->main.elf == NULL
403 && mod->main.name == NULL)
404 mod->main.name = strdup (name);
405 }
406 else if (name != NULL)
407 {
408 /* We have to find the file's phdrs to compute along with l_addr
409 what its runtime address boundaries are. */
410
411 // XXX hook for sysroot
412 mod = INTUSE(dwfl_report_elf) (dwfl, basename (name),
413 name, -1, l_addr);
414 }
415
416 if (mod != NULL)
417 {
418 ++result;
419
420 /* Move this module to the end of the list, so that we end
421 up with a list in the same order as the link_map chain. */
422 if (mod->next != NULL)
423 {
424 if (*lastmodp != mod)
425 {
426 lastmodp = &dwfl->modulelist;
427 while (*lastmodp != mod)
428 lastmodp = &(*lastmodp)->next;
429 }
430 *lastmodp = mod->next;
431 mod->next = NULL;
432 while (*lastmodp != NULL)
433 lastmodp = &(*lastmodp)->next;
434 *lastmodp = mod;
435 }
436
437 lastmodp = &mod->next;
438 }
439 }
440
441 return release_buffer (result);
442 }
443
444 static GElf_Addr
consider_executable(Dwfl_Module * mod,GElf_Addr at_phdr,GElf_Addr at_entry,uint_fast8_t * elfclass,uint_fast8_t * elfdata,Dwfl_Memory_Callback * memory_callback,void * memory_callback_arg)445 consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry,
446 uint_fast8_t *elfclass, uint_fast8_t *elfdata,
447 Dwfl_Memory_Callback *memory_callback,
448 void *memory_callback_arg)
449 {
450 GElf_Ehdr ehdr;
451 if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL))
452 return 0;
453
454 if (at_entry != 0)
455 {
456 /* If we have an AT_ENTRY value, reject this executable if
457 its entry point address could not have supplied that. */
458
459 if (ehdr.e_entry == 0)
460 return 0;
461
462 if (mod->e_type == ET_EXEC)
463 {
464 if (ehdr.e_entry != at_entry)
465 return 0;
466 }
467 else
468 {
469 /* It could be a PIE. */
470 }
471 }
472
473 // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr
474 /* Find the vaddr of the DT_DEBUG's d_ptr. This is the memory
475 address where &r_debug was written at runtime. */
476 GElf_Xword align = mod->dwfl->segment_align;
477 GElf_Addr d_val_vaddr = 0;
478 for (uint_fast16_t i = 0; i < ehdr.e_phnum; ++i)
479 {
480 GElf_Phdr phdr_mem;
481 GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
482 if (phdr == NULL)
483 break;
484
485 if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align))
486 align = phdr->p_align;
487
488 if (at_phdr != 0
489 && phdr->p_type == PT_LOAD
490 && (phdr->p_offset & -align) == (ehdr.e_phoff & -align))
491 {
492 /* This is the segment that would map the phdrs.
493 If we have an AT_PHDR value, reject this executable
494 if its phdr mapping could not have supplied that. */
495 if (mod->e_type == ET_EXEC)
496 {
497 if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr)
498 return 0;
499 }
500 else
501 {
502 /* It could be a PIE. If the AT_PHDR value and our
503 phdr address don't match modulo ALIGN, then this
504 could not have been the right PIE. */
505 if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align)
506 != (at_phdr & -align))
507 return 0;
508
509 /* Calculate the bias applied to the PIE's p_vaddr values. */
510 GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset
511 + phdr->p_vaddr));
512
513 /* Final sanity check: if we have an AT_ENTRY value,
514 reject this PIE unless its biased e_entry matches. */
515 if (at_entry != 0 && at_entry != ehdr.e_entry + bias)
516 return 0;
517
518 /* If we're changing the module's address range,
519 we've just invalidated the module lookup table. */
520 if (bias != mod->main.bias)
521 {
522 mod->low_addr -= mod->main.bias;
523 mod->high_addr -= mod->main.bias;
524 mod->main.bias = bias;
525 mod->low_addr += bias;
526 mod->high_addr += bias;
527
528 free (mod->dwfl->lookup_module);
529 mod->dwfl->lookup_module = NULL;
530 }
531 }
532 }
533
534 if (phdr->p_type == PT_DYNAMIC)
535 {
536 Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset,
537 phdr->p_filesz, ELF_T_DYN);
538 if (data == NULL)
539 continue;
540 const size_t entsize = gelf_fsize (mod->main.elf,
541 ELF_T_DYN, 1, EV_CURRENT);
542 const size_t n = data->d_size / entsize;
543 for (size_t j = 0; j < n; ++j)
544 {
545 GElf_Dyn dyn_mem;
546 GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
547 if (dyn != NULL && dyn->d_tag == DT_DEBUG)
548 {
549 d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2;
550 break;
551 }
552 }
553 }
554 }
555
556 if (d_val_vaddr != 0)
557 {
558 /* Now we have the final address from which to read &r_debug. */
559 d_val_vaddr += mod->main.bias;
560
561 void *buffer = NULL;
562 size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]);
563
564 Dwfl_Module *m;
565 int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, &m);
566 assert (m == mod);
567
568 if ((*memory_callback) (mod->dwfl, segndx,
569 &buffer, &buffer_available,
570 d_val_vaddr, buffer_available,
571 memory_callback_arg))
572 {
573 const union
574 {
575 Elf32_Addr a32;
576 Elf64_Addr a64;
577 } *u = buffer;
578
579 GElf_Addr vaddr;
580 if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
581 vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
582 ? BE32 (u->a32) : LE32 (u->a32));
583 else
584 vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
585 ? BE64 (u->a64) : LE64 (u->a64));
586
587 (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0,
588 memory_callback_arg);
589
590
591 if (*elfclass == ELFCLASSNONE)
592 *elfclass = ehdr.e_ident[EI_CLASS];
593 else if (*elfclass != ehdr.e_ident[EI_CLASS])
594 return 0;
595
596 if (*elfdata == ELFDATANONE)
597 *elfdata = ehdr.e_ident[EI_DATA];
598 else if (*elfdata != ehdr.e_ident[EI_DATA])
599 return 0;
600
601 return vaddr;
602 }
603 }
604
605 return 0;
606 }
607
608 /* Try to find an existing executable module with a DT_DEBUG. */
609 static GElf_Addr
find_executable(Dwfl * dwfl,GElf_Addr at_phdr,GElf_Addr at_entry,uint_fast8_t * elfclass,uint_fast8_t * elfdata,Dwfl_Memory_Callback * memory_callback,void * memory_callback_arg)610 find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
611 uint_fast8_t *elfclass, uint_fast8_t *elfdata,
612 Dwfl_Memory_Callback *memory_callback,
613 void *memory_callback_arg)
614 {
615 for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
616 if (mod->main.elf != NULL)
617 {
618 GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry,
619 elfclass, elfdata,
620 memory_callback,
621 memory_callback_arg);
622 if (r_debug_vaddr != 0)
623 return r_debug_vaddr;
624 }
625
626 return 0;
627 }
628
629
630 int
dwfl_link_map_report(Dwfl * dwfl,const void * auxv,size_t auxv_size,Dwfl_Memory_Callback * memory_callback,void * memory_callback_arg)631 dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
632 Dwfl_Memory_Callback *memory_callback,
633 void *memory_callback_arg)
634 {
635 GElf_Addr r_debug_vaddr = 0;
636
637 uint_fast8_t elfclass = ELFCLASSNONE;
638 uint_fast8_t elfdata = ELFDATANONE;
639 if (likely (auxv != NULL)
640 && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata)))
641 {
642 GElf_Addr entry = 0;
643 GElf_Addr phdr = 0;
644 GElf_Xword phent = 0;
645 GElf_Xword phnum = 0;
646
647 #define AUXV_SCAN(NN, BL) do \
648 { \
649 const Elf##NN##_auxv_t *av = auxv; \
650 for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i) \
651 { \
652 Elf##NN##_Addr val = BL##NN (av[i].a_un.a_val); \
653 if (av[i].a_type == BL##NN (AT_ENTRY)) \
654 entry = val; \
655 else if (av[i].a_type == BL##NN (AT_PHDR)) \
656 phdr = val; \
657 else if (av[i].a_type == BL##NN (AT_PHNUM)) \
658 phnum = val; \
659 else if (av[i].a_type == BL##NN (AT_PHENT)) \
660 phent = val; \
661 else if (av[i].a_type == BL##NN (AT_PAGESZ)) \
662 { \
663 if (val > 1 \
664 && (dwfl->segment_align == 0 \
665 || val < dwfl->segment_align)) \
666 dwfl->segment_align = val; \
667 } \
668 } \
669 } \
670 while (0)
671
672 if (elfclass == ELFCLASS32)
673 {
674 if (elfdata == ELFDATA2MSB)
675 AUXV_SCAN (32, BE);
676 else
677 AUXV_SCAN (32, LE);
678 }
679 else
680 {
681 if (elfdata == ELFDATA2MSB)
682 AUXV_SCAN (64, BE);
683 else
684 AUXV_SCAN (64, LE);
685 }
686
687 /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC. */
688 GElf_Addr dyn_vaddr = 0;
689 GElf_Xword dyn_filesz = 0;
690 if (phdr != 0 && phnum != 0)
691 {
692 Dwfl_Module *phdr_mod;
693 int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod);
694 Elf_Data in =
695 {
696 .d_type = ELF_T_PHDR,
697 .d_version = EV_CURRENT,
698 .d_size = phnum * phent,
699 .d_buf = NULL
700 };
701 if ((*memory_callback) (dwfl, phdr_segndx, &in.d_buf, &in.d_size,
702 phdr, phnum * phent, memory_callback_arg))
703 {
704 union
705 {
706 Elf32_Phdr p32;
707 Elf64_Phdr p64;
708 char data[phnum * phent];
709 } buf;
710 Elf_Data out =
711 {
712 .d_type = ELF_T_PHDR,
713 .d_version = EV_CURRENT,
714 .d_size = phnum * phent,
715 .d_buf = &buf
716 };
717 in.d_size = out.d_size;
718 if (likely ((elfclass == ELFCLASS32
719 ? elf32_xlatetom : elf64_xlatetom)
720 (&out, &in, elfdata) != NULL))
721 {
722 /* We are looking for PT_DYNAMIC. */
723 const union
724 {
725 Elf32_Phdr p32[phnum];
726 Elf64_Phdr p64[phnum];
727 } *u = (void *) &buf;
728 if (elfclass == ELFCLASS32)
729 {
730 for (size_t i = 0; i < phnum; ++i)
731 if (u->p32[i].p_type == PT_DYNAMIC)
732 {
733 dyn_vaddr = u->p32[i].p_vaddr;
734 dyn_filesz = u->p32[i].p_filesz;
735 break;
736 }
737 }
738 else
739 {
740 for (size_t i = 0; i < phnum; ++i)
741 if (u->p64[i].p_type == PT_DYNAMIC)
742 {
743 dyn_vaddr = u->p64[i].p_vaddr;
744 dyn_filesz = u->p64[i].p_filesz;
745 break;
746 }
747 }
748 }
749
750 (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
751 memory_callback_arg);
752 }
753 else
754 /* We could not read the executable's phdrs from the
755 memory image. If we have a presupplied executable,
756 we can still use the AT_PHDR and AT_ENTRY values to
757 verify it, and to adjust its bias if it's a PIE.
758
759 If there was an ET_EXEC module presupplied that contains
760 the AT_PHDR address, then we only consider that one.
761 We'll either accept it if its phdr location and e_entry
762 make sense or reject it if they don't. If there is no
763 presupplied ET_EXEC, then look for a presupplied module,
764 which might be a PIE (ET_DYN) that needs its bias adjusted. */
765 r_debug_vaddr = ((phdr_mod == NULL
766 || phdr_mod->main.elf == NULL
767 || phdr_mod->e_type != ET_EXEC)
768 ? find_executable (dwfl, phdr, entry,
769 &elfclass, &elfdata,
770 memory_callback,
771 memory_callback_arg)
772 : consider_executable (phdr_mod, phdr, entry,
773 &elfclass, &elfdata,
774 memory_callback,
775 memory_callback_arg));
776 }
777
778 /* If we found PT_DYNAMIC, search it for DT_DEBUG. */
779 if (dyn_filesz != 0)
780 {
781 Elf_Data in =
782 {
783 .d_type = ELF_T_DYN,
784 .d_version = EV_CURRENT,
785 .d_size = dyn_filesz,
786 .d_buf = NULL
787 };
788 int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL);
789 if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size,
790 dyn_vaddr, dyn_filesz, memory_callback_arg))
791 {
792 union
793 {
794 Elf32_Dyn d32;
795 Elf64_Dyn d64;
796 char data[dyn_filesz];
797 } buf;
798 Elf_Data out =
799 {
800 .d_type = ELF_T_DYN,
801 .d_version = EV_CURRENT,
802 .d_size = dyn_filesz,
803 .d_buf = &buf
804 };
805 in.d_size = out.d_size;
806 if (likely ((elfclass == ELFCLASS32
807 ? elf32_xlatetom : elf64_xlatetom)
808 (&out, &in, elfdata) != NULL))
809 {
810 /* We are looking for PT_DYNAMIC. */
811 const union
812 {
813 Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)];
814 Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)];
815 } *u = (void *) &buf;
816 if (elfclass == ELFCLASS32)
817 {
818 size_t n = dyn_filesz / sizeof (Elf32_Dyn);
819 for (size_t i = 0; i < n; ++i)
820 if (u->d32[i].d_tag == DT_DEBUG)
821 {
822 r_debug_vaddr = u->d32[i].d_un.d_val;
823 break;
824 }
825 }
826 else
827 {
828 size_t n = dyn_filesz / sizeof (Elf64_Dyn);
829 for (size_t i = 0; i < n; ++i)
830 if (u->d64[i].d_tag == DT_DEBUG)
831 {
832 r_debug_vaddr = u->d64[i].d_un.d_val;
833 break;
834 }
835 }
836 }
837
838 (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
839 memory_callback_arg);
840 }
841 }
842 }
843 else
844 /* We have to look for a presupplied executable file to determine
845 the vaddr of its dynamic section and DT_DEBUG therein. */
846 r_debug_vaddr = find_executable (dwfl, 0, 0, &elfclass, &elfdata,
847 memory_callback, memory_callback_arg);
848
849 if (r_debug_vaddr == 0)
850 return 0;
851
852 /* For following pointers from struct link_map, we will use an
853 integrated memory access callback that can consult module text
854 elided from the core file. This is necessary when the l_name
855 pointer for the dynamic linker's own entry is a pointer into the
856 executable's .interp section. */
857 struct integrated_memory_callback mcb =
858 {
859 .memory_callback = memory_callback,
860 .memory_callback_arg = memory_callback_arg
861 };
862
863 /* Now we can follow the dynamic linker's library list. */
864 return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr,
865 &integrated_memory_callback, &mcb);
866 }
867 INTDEF (dwfl_link_map_report)
868