Imported Upstream version 0.153
[platform/upstream/elfutils.git] / libdwfl / link_map.c
1 /* 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.  */
77 static bool
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   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 \f
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
148 struct integrated_memory_callback
149 {
150   Dwfl_Memory_Callback *memory_callback;
151   void *memory_callback_arg;
152   void *buffer;
153 };
154
155 static bool
156 integrated_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 \f
242 static size_t
243 addrsize (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
257 static int
258 report_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 \f
442 static GElf_Addr
443 consider_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.  */
604 static GElf_Addr
605 find_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 \f
624
625 int
626 dwfl_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 }
888 INTDEF (dwfl_link_map_report)