libdwfl: Make dwfl_linux_proc_attach work even without any Dwfl_Modules.
[platform/upstream/elfutils.git] / libdwfl / dwfl_segment_report_module.c
1 /* Sniff out modules from ELF headers visible in memory segments.
2    Copyright (C) 2008-2012, 2014, 2015 Red Hat, Inc.
3    This file is part of elfutils.
4
5    This file is free software; you can redistribute it and/or modify
6    it under the terms of either
7
8      * the GNU Lesser General Public License as published by the Free
9        Software Foundation; either version 3 of the License, or (at
10        your option) any later version
11
12    or
13
14      * the GNU General Public License as published by the Free
15        Software Foundation; either version 2 of the License, or (at
16        your option) any later version
17
18    or both in parallel, as here.
19
20    elfutils is distributed in the hope that it will be useful, but
21    WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23    General Public License for more details.
24
25    You should have received copies of the GNU General Public License and
26    the GNU Lesser General Public License along with this program.  If
27    not, see <http://www.gnu.org/licenses/>.  */
28
29 #include <config.h>
30 #include "../libelf/libelfP.h"  /* For NOTE_ALIGN.  */
31 #undef  _
32 #include "libdwflP.h"
33 #include "common.h"
34
35 #include <elf.h>
36 #include <gelf.h>
37 #include <inttypes.h>
38 #include <sys/param.h>
39 #include <endian.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42
43
44 /* A good size for the initial read from memory, if it's not too costly.
45    This more than covers the phdrs and note segment in the average 64-bit
46    binary.  */
47
48 #define INITIAL_READ    1024
49
50 #if __BYTE_ORDER == __LITTLE_ENDIAN
51 # define MY_ELFDATA     ELFDATA2LSB
52 #else
53 # define MY_ELFDATA     ELFDATA2MSB
54 #endif
55
56
57 /* Return user segment index closest to ADDR but not above it.
58    If NEXT, return the closest to ADDR but not below it.  */
59 static int
60 addr_segndx (Dwfl *dwfl, size_t segment, GElf_Addr addr, bool next)
61 {
62   int ndx = -1;
63   do
64     {
65       if (dwfl->lookup_segndx[segment] >= 0)
66         ndx = dwfl->lookup_segndx[segment];
67       if (++segment >= dwfl->lookup_elts - 1)
68         return next ? ndx + 1 : ndx;
69     }
70   while (dwfl->lookup_addr[segment] < addr);
71
72   if (next)
73     {
74       while (dwfl->lookup_segndx[segment] < 0)
75         if (++segment >= dwfl->lookup_elts - 1)
76           return ndx + 1;
77       ndx = dwfl->lookup_segndx[segment];
78     }
79
80   return ndx;
81 }
82
83 /* Return whether there is SZ bytes available at PTR till END.  */
84
85 static bool
86 buf_has_data (const void *ptr, const void *end, size_t sz)
87 {
88   return ptr < end && (size_t) (end - ptr) >= sz;
89 }
90
91 /* Read SZ bytes into *RETP from *PTRP (limited by END) in format EI_DATA.
92    Function comes from src/readelf.c .  */
93
94 static bool
95 buf_read_ulong (unsigned char ei_data, size_t sz,
96                 const void **ptrp, const void *end, uint64_t *retp)
97 {
98   if (! buf_has_data (*ptrp, end, sz))
99     return false;
100
101   union
102   {
103     uint64_t u64;
104     uint32_t u32;
105   } u;
106
107   memcpy (&u, *ptrp, sz);
108   (*ptrp) += sz;
109
110   if (retp == NULL)
111     return true;
112
113   if (MY_ELFDATA != ei_data)
114     {
115       if (sz == 4)
116         CONVERT (u.u32);
117       else
118         CONVERT (u.u64);
119     }
120   if (sz == 4)
121     *retp = u.u32;
122   else
123     *retp = u.u64;
124   return true;
125 }
126
127 /* Try to find matching entry for module from address MODULE_START to
128    MODULE_END in NT_FILE note located at NOTE_FILE of NOTE_FILE_SIZE
129    bytes in format EI_CLASS and EI_DATA.  */
130
131 static const char *
132 handle_file_note (GElf_Addr module_start, GElf_Addr module_end,
133                   unsigned char ei_class, unsigned char ei_data,
134                   const void *note_file, size_t note_file_size)
135 {
136   if (note_file == NULL)
137     return NULL;
138
139   size_t sz;
140   switch (ei_class)
141     {
142     case ELFCLASS32:
143       sz = 4;
144       break;
145     case ELFCLASS64:
146       sz = 8;
147       break;
148     default:
149       return NULL;
150     }
151
152   const void *ptr = note_file;
153   const void *end = note_file + note_file_size;
154   uint64_t count;
155   if (! buf_read_ulong (ei_data, sz, &ptr, end, &count))
156     return NULL;
157   if (! buf_read_ulong (ei_data, sz, &ptr, end, NULL)) // page_size
158     return NULL;
159
160   uint64_t maxcount = (size_t) (end - ptr) / (3 * sz);
161   if (count > maxcount)
162     return NULL;
163
164   /* Where file names are stored.  */
165   const char *fptr = ptr + 3 * count * sz;
166
167   ssize_t firstix = -1;
168   ssize_t lastix = -1;
169   for (size_t mix = 0; mix < count; mix++)
170     {
171       uint64_t mstart, mend, moffset;
172       if (! buf_read_ulong (ei_data, sz, &ptr, fptr, &mstart)
173           || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &mend)
174           || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &moffset))
175         return NULL;
176       if (mstart == module_start && moffset == 0)
177         firstix = lastix = mix;
178       if (firstix != -1 && mstart < module_end)
179         lastix = mix;
180       if (mend >= module_end)
181         break;
182     }
183   if (firstix == -1)
184     return NULL;
185
186   const char *retval = NULL;
187   for (ssize_t mix = 0; mix <= lastix; mix++)
188     {
189       const char *fnext = memchr (fptr, 0, (const char *) end - fptr);
190       if (fnext == NULL)
191         return NULL;
192       if (mix == firstix)
193         retval = fptr;
194       if (firstix < mix && mix <= lastix && strcmp (fptr, retval) != 0)
195         return NULL;
196       fptr = fnext + 1;
197     }
198   return retval;
199 }
200
201 /* Return true iff we are certain ELF cannot match BUILD_ID of
202    BUILD_ID_LEN bytes.  Pass DISK_FILE_HAS_BUILD_ID as false if it is
203    certain ELF does not contain build-id (it is only a performance hit
204    to pass it always as true).  */
205
206 static bool
207 invalid_elf (Elf *elf, bool disk_file_has_build_id,
208              const void *build_id, size_t build_id_len)
209 {
210   if (! disk_file_has_build_id && build_id_len > 0)
211     {
212       /* Module found in segments with build-id is more reliable
213          than a module found via DT_DEBUG on disk without any
214          build-id.   */
215       return true;
216     }
217   if (disk_file_has_build_id && build_id_len > 0)
218     {
219       const void *elf_build_id;
220       ssize_t elf_build_id_len;
221
222       /* If there is a build id in the elf file, check it.  */
223       elf_build_id_len = INTUSE(dwelf_elf_gnu_build_id) (elf, &elf_build_id);
224       if (elf_build_id_len > 0)
225         {
226           if (build_id_len != (size_t) elf_build_id_len
227               || memcmp (build_id, elf_build_id, build_id_len) != 0)
228             return true;
229         }
230     }
231   return false;
232 }
233
234 int
235 dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
236                             Dwfl_Memory_Callback *memory_callback,
237                             void *memory_callback_arg,
238                             Dwfl_Module_Callback *read_eagerly,
239                             void *read_eagerly_arg,
240                             const void *note_file, size_t note_file_size,
241                             const struct r_debug_info *r_debug_info)
242 {
243   size_t segment = ndx;
244
245   if (segment >= dwfl->lookup_elts)
246     segment = dwfl->lookup_elts - 1;
247
248   while (segment > 0
249          && (dwfl->lookup_segndx[segment] > ndx
250              || dwfl->lookup_segndx[segment] == -1))
251     --segment;
252
253   while (dwfl->lookup_segndx[segment] < ndx)
254     if (++segment == dwfl->lookup_elts)
255       return 0;
256
257   GElf_Addr start = dwfl->lookup_addr[segment];
258
259   inline bool segment_read (int segndx,
260                             void **buffer, size_t *buffer_available,
261                             GElf_Addr addr, size_t minread)
262   {
263     return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available,
264                                  addr, minread, memory_callback_arg);
265   }
266
267   inline void release_buffer (void **buffer, size_t *buffer_available)
268   {
269     if (*buffer != NULL)
270       (void) segment_read (-1, buffer, buffer_available, 0, 0);
271   }
272
273   /* First read in the file header and check its sanity.  */
274
275   void *buffer = NULL;
276   size_t buffer_available = INITIAL_READ;
277   Elf *elf = NULL;
278   int fd = -1;
279
280   /* We might have to reserve some memory for the phdrs.  Set to NULL
281      here so we can always safely free it.  */
282   void *phdrsp = NULL;
283
284   inline int finish (void)
285   {
286     free (phdrsp);
287     release_buffer (&buffer, &buffer_available);
288     if (elf != NULL)
289       elf_end (elf);
290     if (fd != -1)
291       close (fd);
292     return ndx;
293   }
294
295   if (segment_read (ndx, &buffer, &buffer_available,
296                     start, sizeof (Elf64_Ehdr))
297       || memcmp (buffer, ELFMAG, SELFMAG) != 0)
298     return finish ();
299
300   inline bool read_portion (void **data, size_t *data_size,
301                             GElf_Addr vaddr, size_t filesz)
302   {
303     if (vaddr - start + filesz > buffer_available
304         /* If we're in string mode, then don't consider the buffer we have
305            sufficient unless it contains the terminator of the string.  */
306         || (filesz == 0 && memchr (vaddr - start + buffer, '\0',
307                                    buffer_available - (vaddr - start)) == NULL))
308       {
309         *data = NULL;
310         *data_size = filesz;
311         return segment_read (addr_segndx (dwfl, segment, vaddr, false),
312                              data, data_size, vaddr, filesz);
313       }
314
315     /* We already have this whole note segment from our initial read.  */
316     *data = vaddr - start + buffer;
317     *data_size = 0;
318     return false;
319   }
320
321   inline void finish_portion (void **data, size_t *data_size)
322   {
323     if (*data_size != 0)
324       release_buffer (data, data_size);
325   }
326
327   /* Extract the information we need from the file header.  */
328   const unsigned char *e_ident;
329   unsigned char ei_class;
330   unsigned char ei_data;
331   uint16_t e_type;
332   union
333   {
334     Elf32_Ehdr e32;
335     Elf64_Ehdr e64;
336   } ehdr;
337   GElf_Off phoff;
338   uint_fast16_t phnum;
339   uint_fast16_t phentsize;
340   GElf_Off shdrs_end;
341   Elf_Data xlatefrom =
342     {
343       .d_type = ELF_T_EHDR,
344       .d_buf = (void *) buffer,
345       .d_version = EV_CURRENT,
346     };
347   Elf_Data xlateto =
348     {
349       .d_type = ELF_T_EHDR,
350       .d_buf = &ehdr,
351       .d_size = sizeof ehdr,
352       .d_version = EV_CURRENT,
353     };
354   e_ident = ((const unsigned char *) buffer);
355   ei_class = e_ident[EI_CLASS];
356   ei_data = e_ident[EI_DATA];
357   switch (ei_class)
358     {
359     case ELFCLASS32:
360       xlatefrom.d_size = sizeof (Elf32_Ehdr);
361       if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
362         return finish ();
363       e_type = ehdr.e32.e_type;
364       phoff = ehdr.e32.e_phoff;
365       phnum = ehdr.e32.e_phnum;
366       phentsize = ehdr.e32.e_phentsize;
367       if (phentsize != sizeof (Elf32_Phdr))
368         return finish ();
369       shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
370       break;
371
372     case ELFCLASS64:
373       xlatefrom.d_size = sizeof (Elf64_Ehdr);
374       if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
375         return finish ();
376       e_type = ehdr.e64.e_type;
377       phoff = ehdr.e64.e_phoff;
378       phnum = ehdr.e64.e_phnum;
379       phentsize = ehdr.e64.e_phentsize;
380       if (phentsize != sizeof (Elf64_Phdr))
381         return finish ();
382       shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
383       break;
384
385     default:
386       return finish ();
387     }
388
389   /* The file header tells where to find the program headers.
390      These are what we need to find the boundaries of the module.
391      Without them, we don't have a module to report.  */
392
393   if (phnum == 0)
394     return finish ();
395
396   xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
397   xlatefrom.d_size = phnum * phentsize;
398
399   void *ph_buffer = NULL;
400   size_t ph_buffer_size = 0;
401   if (read_portion (&ph_buffer, &ph_buffer_size,
402                     start + phoff, xlatefrom.d_size))
403     return finish ();
404
405   xlatefrom.d_buf = ph_buffer;
406
407   typedef union
408   {
409     Elf32_Phdr p32[phnum];
410     Elf64_Phdr p64[phnum];
411   } phdrsn;
412
413   phdrsp = malloc (sizeof (phdrsn));
414   if (unlikely (phdrsp == NULL))
415     return finish ();
416   phdrsn *phdrs = (phdrsn *) phdrsp;
417
418   xlateto.d_buf = phdrs;
419   xlateto.d_size = sizeof (phdrsn);
420
421   /* Track the bounds of the file visible in memory.  */
422   GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end.  */
423   GElf_Off file_end = 0;         /* Rounded up to effective page size.  */
424   GElf_Off contiguous = 0;       /* Visible as contiguous file from START.  */
425   GElf_Off total_filesz = 0;     /* Total size of data to read.  */
426
427   /* Collect the bias between START and the containing PT_LOAD's p_vaddr.  */
428   GElf_Addr bias = 0;
429   bool found_bias = false;
430
431   /* Collect the unbiased bounds of the module here.  */
432   GElf_Addr module_start = -1l;
433   GElf_Addr module_end = 0;
434   GElf_Addr module_address_sync = 0;
435
436   /* If we see PT_DYNAMIC, record it here.  */
437   GElf_Addr dyn_vaddr = 0;
438   GElf_Xword dyn_filesz = 0;
439
440   /* Collect the build ID bits here.  */
441   void *build_id = NULL;
442   size_t build_id_len = 0;
443   GElf_Addr build_id_vaddr = 0;
444
445   /* Consider a PT_NOTE we've found in the image.  */
446   inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz)
447   {
448     /* If we have already seen a build ID, we don't care any more.  */
449     if (build_id != NULL || filesz == 0)
450       return;
451
452     void *data;
453     size_t data_size;
454     if (read_portion (&data, &data_size, vaddr, filesz))
455       return;
456
457     assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
458
459     void *notes;
460     if (ei_data == MY_ELFDATA)
461       notes = data;
462     else
463       {
464         notes = malloc (filesz);
465         if (unlikely (notes == NULL))
466           return;
467         xlatefrom.d_type = xlateto.d_type = ELF_T_NHDR;
468         xlatefrom.d_buf = (void *) data;
469         xlatefrom.d_size = filesz;
470         xlateto.d_buf = notes;
471         xlateto.d_size = filesz;
472         if (elf32_xlatetom (&xlateto, &xlatefrom,
473                             ehdr.e32.e_ident[EI_DATA]) == NULL)
474           goto done;
475       }
476
477     const GElf_Nhdr *nh = notes;
478     while ((const void *) nh < (const void *) notes + filesz)
479      {
480         const void *note_name = nh + 1;
481         const void *note_desc = note_name + NOTE_ALIGN (nh->n_namesz);
482         if (unlikely ((size_t) ((const void *) notes + filesz
483                                 - note_desc) < nh->n_descsz))
484           break;
485
486         if (nh->n_type == NT_GNU_BUILD_ID
487             && nh->n_descsz > 0
488             && nh->n_namesz == sizeof "GNU"
489             && !memcmp (note_name, "GNU", sizeof "GNU"))
490           {
491             build_id_vaddr = note_desc - (const void *) notes + vaddr;
492             build_id_len = nh->n_descsz;
493             build_id = malloc (nh->n_descsz);
494             if (likely (build_id != NULL))
495               memcpy (build_id, note_desc, build_id_len);
496             break;
497           }
498
499         nh = note_desc + NOTE_ALIGN (nh->n_descsz);
500       }
501
502   done:
503     if (notes != data)
504       free (notes);
505     finish_portion (&data, &data_size);
506   }
507
508   /* Consider each of the program headers we've read from the image.  */
509   inline void consider_phdr (GElf_Word type,
510                              GElf_Addr vaddr, GElf_Xword memsz,
511                              GElf_Off offset, GElf_Xword filesz,
512                              GElf_Xword align)
513   {
514     switch (type)
515       {
516       case PT_DYNAMIC:
517         dyn_vaddr = vaddr;
518         dyn_filesz = filesz;
519         break;
520
521       case PT_NOTE:
522         /* We calculate from the p_offset of the note segment,
523            because we don't yet know the bias for its p_vaddr.  */
524         consider_notes (start + offset, filesz);
525         break;
526
527       case PT_LOAD:
528         align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
529
530         GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
531         GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
532         GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
533
534         if (file_trimmed_end < offset + filesz)
535           {
536             file_trimmed_end = offset + filesz;
537
538             /* Trim the last segment so we don't bother with zeros
539                in the last page that are off the end of the file.
540                However, if the extra bit in that page includes the
541                section headers, keep them.  */
542             if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
543               {
544                 filesz += shdrs_end - file_trimmed_end;
545                 file_trimmed_end = shdrs_end;
546               }
547           }
548
549         total_filesz += filesz;
550
551         if (file_end < filesz_offset)
552           {
553             file_end = filesz_offset;
554             if (filesz_vaddr - start == filesz_offset)
555               contiguous = file_end;
556           }
557
558         if (!found_bias && (offset & -align) == 0
559             && likely (filesz_offset >= phoff + phnum * phentsize))
560           {
561             bias = start - vaddr;
562             found_bias = true;
563           }
564
565         if ((vaddr & -align) < module_start)
566           {
567             module_start = vaddr & -align;
568             module_address_sync = vaddr + memsz;
569           }
570
571         if (module_end < vaddr_end)
572           module_end = vaddr_end;
573         break;
574       }
575   }
576   if (ei_class == ELFCLASS32)
577     {
578       if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
579         found_bias = false;     /* Trigger error check.  */
580       else
581         for (uint_fast16_t i = 0; i < phnum; ++i)
582           consider_phdr (phdrs->p32[i].p_type,
583                          phdrs->p32[i].p_vaddr, phdrs->p32[i].p_memsz,
584                          phdrs->p32[i].p_offset, phdrs->p32[i].p_filesz,
585                          phdrs->p32[i].p_align);
586     }
587   else
588     {
589       if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
590         found_bias = false;     /* Trigger error check.  */
591       else
592         for (uint_fast16_t i = 0; i < phnum; ++i)
593           consider_phdr (phdrs->p64[i].p_type,
594                          phdrs->p64[i].p_vaddr, phdrs->p64[i].p_memsz,
595                          phdrs->p64[i].p_offset, phdrs->p64[i].p_filesz,
596                          phdrs->p64[i].p_align);
597     }
598
599   finish_portion (&ph_buffer, &ph_buffer_size);
600
601   /* We must have seen the segment covering offset 0, or else the ELF
602      header we read at START was not produced by these program headers.  */
603   if (unlikely (!found_bias))
604     {
605       free (build_id);
606       return finish ();
607     }
608
609   /* Now we know enough to report a module for sure: its bounds.  */
610   module_start += bias;
611   module_end += bias;
612
613   dyn_vaddr += bias;
614
615   /* NAME found from link map has precedence over DT_SONAME possibly read
616      below.  */
617   bool name_is_final = false;
618
619   /* Try to match up DYN_VADDR against L_LD as found in link map.
620      Segments sniffing may guess invalid address as the first read-only memory
621      mapping may not be dumped to the core file (if ELF headers are not dumped)
622      and the ELF header is dumped first with the read/write mapping of the same
623      file at higher addresses.  */
624   if (r_debug_info != NULL)
625     for (const struct r_debug_info_module *module = r_debug_info->module;
626          module != NULL; module = module->next)
627       if (module_start <= module->l_ld && module->l_ld < module_end)
628         {
629           /* L_LD read from link map must be right while DYN_VADDR is unsafe.
630              Therefore subtract DYN_VADDR and add L_LD to get a possibly
631              corrective displacement for all addresses computed so far.  */
632           GElf_Addr fixup = module->l_ld - dyn_vaddr;
633           if ((fixup & (dwfl->segment_align - 1)) == 0
634               && module_start + fixup <= module->l_ld
635               && module->l_ld < module_end + fixup)
636             {
637               module_start += fixup;
638               module_end += fixup;
639               dyn_vaddr += fixup;
640               bias += fixup;
641               if (module->name[0] != '\0')
642                 {
643                   name = basename (module->name);
644                   name_is_final = true;
645                 }
646               break;
647             }
648         }
649
650   if (r_debug_info != NULL)
651     {
652       bool skip_this_module = false;
653       for (struct r_debug_info_module *module = r_debug_info->module;
654            module != NULL; module = module->next)
655         if ((module_end > module->start && module_start < module->end)
656             || dyn_vaddr == module->l_ld)
657           {
658             if (module->elf != NULL
659                 && invalid_elf (module->elf, module->disk_file_has_build_id,
660                                 build_id, build_id_len))
661               {
662                 elf_end (module->elf);
663                 close (module->fd);
664                 module->elf = NULL;
665                 module->fd = -1;
666               }
667             if (module->elf != NULL)
668               {
669                 /* Ignore this found module if it would conflict in address
670                    space with any already existing module of DWFL.  */
671                 skip_this_module = true;
672               }
673           }
674       if (skip_this_module)
675         {
676           free (build_id);
677           return finish ();
678         }
679     }
680
681   const char *file_note_name = handle_file_note (module_start, module_end,
682                                                  ei_class, ei_data,
683                                                  note_file, note_file_size);
684   if (file_note_name)
685     {
686       name = file_note_name;
687       name_is_final = true;
688       bool invalid = false;
689       fd = open64 (name, O_RDONLY);
690       if (fd >= 0)
691         {
692           Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
693           if (error == DWFL_E_NOERROR)
694             invalid = invalid_elf (elf, true /* disk_file_has_build_id */,
695                                    build_id, build_id_len);
696         }
697       if (invalid)
698         {
699           /* The file was there, but the build_id didn't match.  We
700              still want to report the module, but need to get the ELF
701              some other way if possible.  */
702           close (fd);
703           fd = -1;
704           elf_end (elf);
705           elf = NULL;
706         }
707     }
708
709   /* Our return value now says to skip the segments contained
710      within the module.  */
711   ndx = addr_segndx (dwfl, segment, module_end, true);
712
713   /* Examine its .dynamic section to get more interesting details.
714      If it has DT_SONAME, we'll use that as the module name.
715      If it has a DT_DEBUG, then it's actually a PIE rather than a DSO.
716      We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME,
717      and they also tell us the essential portion of the file
718      for fetching symbols.  */
719   GElf_Addr soname_stroff = 0;
720   GElf_Addr dynstr_vaddr = 0;
721   GElf_Xword dynstrsz = 0;
722   bool execlike = false;
723   inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val)
724   {
725     switch (tag)
726       {
727       default:
728         return false;
729
730       case DT_DEBUG:
731         execlike = true;
732         break;
733
734       case DT_SONAME:
735         soname_stroff = val;
736         break;
737
738       case DT_STRTAB:
739         dynstr_vaddr = val;
740         break;
741
742       case DT_STRSZ:
743         dynstrsz = val;
744         break;
745       }
746
747     return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0;
748   }
749
750   const size_t dyn_entsize = (ei_class == ELFCLASS32
751                               ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
752   void *dyns = NULL;
753   void *dyn_data = NULL;
754   size_t dyn_data_size = 0;
755   if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
756       && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz))
757     {
758       typedef union
759       {
760         Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)];
761         Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)];
762       } dynn;
763       dyns = malloc (sizeof (dynn));
764       if (unlikely (dyns == NULL))
765         return finish ();
766       dynn *dyn = (dynn *) dyns;
767
768       xlatefrom.d_type = xlateto.d_type = ELF_T_DYN;
769       xlatefrom.d_buf = (void *) dyn_data;
770       xlatefrom.d_size = dyn_filesz;
771       xlateto.d_buf = dyn;
772       xlateto.d_size = sizeof (dynn);
773
774       if (ei_class == ELFCLASS32)
775         {
776           if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
777             for (size_t i = 0; i < dyn_filesz / sizeof (Elf32_Dyn); ++i)
778               if (consider_dyn (dyn->d32[i].d_tag, dyn->d32[i].d_un.d_val))
779                 break;
780         }
781       else
782         {
783           if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
784             for (size_t i = 0; i < dyn_filesz / sizeof (Elf64_Dyn); ++i)
785               if (consider_dyn (dyn->d64[i].d_tag, dyn->d64[i].d_un.d_val))
786                 break;
787         }
788     }
789   free (dyns);
790   finish_portion (&dyn_data, &dyn_data_size);
791
792   /* We'll use the name passed in or a stupid default if not DT_SONAME.  */
793   if (name == NULL)
794     name = e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]";
795
796   void *soname = NULL;
797   size_t soname_size = 0;
798   if (! name_is_final && dynstrsz != 0 && dynstr_vaddr != 0)
799     {
800       /* We know the bounds of the .dynstr section.
801
802          The DYNSTR_VADDR pointer comes from the .dynamic section
803          (DT_STRTAB, detected above).  Ordinarily the dynamic linker
804          will have adjusted this pointer in place so it's now an
805          absolute address.  But sometimes .dynamic is read-only (in
806          vDSOs and odd architectures), and sometimes the adjustment
807          just hasn't happened yet in the memory image we looked at.
808          So treat DYNSTR_VADDR as an absolute address if it falls
809          within the module bounds, or try applying the phdr bias
810          when that adjusts it to fall within the module bounds.  */
811
812       if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end)
813           && dynstr_vaddr + bias >= module_start
814           && dynstr_vaddr + bias < module_end)
815         dynstr_vaddr += bias;
816
817       if (unlikely (dynstr_vaddr + dynstrsz > module_end))
818         dynstrsz = 0;
819
820       /* Try to get the DT_SONAME string.  */
821       if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz
822           && ! read_portion (&soname, &soname_size,
823                              dynstr_vaddr + soname_stroff, 0))
824         name = soname;
825     }
826
827   /* Now that we have chosen the module's name and bounds, report it.
828      If we found a build ID, report that too.  */
829
830   Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name,
831                                                  module_start, module_end);
832
833   // !execlike && ET_EXEC is PIE.
834   // execlike && !ET_EXEC is a static executable.
835   if (mod != NULL && (execlike || ehdr.e32.e_type == ET_EXEC))
836     mod->is_executable = true;
837
838   if (likely (mod != NULL) && build_id != NULL
839       && unlikely (INTUSE(dwfl_module_report_build_id) (mod,
840                                                         build_id,
841                                                         build_id_len,
842                                                         build_id_vaddr)))
843     {
844       mod->gc = true;
845       mod = NULL;
846     }
847
848   /* At this point we do not need BUILD_ID or NAME any more.
849      They have been copied.  */
850   free (build_id);
851   finish_portion (&soname, &soname_size);
852
853   if (unlikely (mod == NULL))
854     {
855       ndx = -1;
856       return finish ();
857     }
858
859   /* We have reported the module.  Now let the caller decide whether we
860      should read the whole thing in right now.  */
861
862   const GElf_Off cost = (contiguous < file_trimmed_end ? total_filesz
863                          : buffer_available >= contiguous ? 0
864                          : contiguous - buffer_available);
865   const GElf_Off worthwhile = ((dynstr_vaddr == 0 || dynstrsz == 0) ? 0
866                                : dynstr_vaddr + dynstrsz - start);
867   const GElf_Off whole = MAX (file_trimmed_end, shdrs_end);
868
869   if (elf == NULL
870       && (*read_eagerly) (MODCB_ARGS (mod), &buffer, &buffer_available,
871                           cost, worthwhile, whole, contiguous,
872                           read_eagerly_arg, &elf)
873       && elf == NULL)
874     {
875       /* The caller wants to read the whole file in right now, but hasn't
876          done it for us.  Fill in a local image of the virtual file.  */
877
878       void *contents = calloc (1, file_trimmed_end);
879       if (unlikely (contents == NULL))
880         return finish ();
881
882       inline void final_read (size_t offset, GElf_Addr vaddr, size_t size)
883       {
884         void *into = contents + offset;
885         size_t read_size = size;
886         (void) segment_read (addr_segndx (dwfl, segment, vaddr, false),
887                              &into, &read_size, vaddr, size);
888       }
889
890       if (contiguous < file_trimmed_end)
891         {
892           /* We can't use the memory image verbatim as the file image.
893              So we'll be reading into a local image of the virtual file.  */
894
895           inline void read_phdr (GElf_Word type, GElf_Addr vaddr,
896                                  GElf_Off offset, GElf_Xword filesz)
897           {
898             if (type == PT_LOAD)
899               final_read (offset, vaddr + bias, filesz);
900           }
901
902           if (ei_class == ELFCLASS32)
903             for (uint_fast16_t i = 0; i < phnum; ++i)
904               read_phdr (phdrs->p32[i].p_type, phdrs->p32[i].p_vaddr,
905                          phdrs->p32[i].p_offset, phdrs->p32[i].p_filesz);
906           else
907             for (uint_fast16_t i = 0; i < phnum; ++i)
908               read_phdr (phdrs->p64[i].p_type, phdrs->p64[i].p_vaddr,
909                          phdrs->p64[i].p_offset, phdrs->p64[i].p_filesz);
910         }
911       else
912         {
913           /* The whole file sits contiguous in memory,
914              but the caller didn't want to just do it.  */
915
916           const size_t have = MIN (buffer_available, file_trimmed_end);
917           memcpy (contents, buffer, have);
918
919           if (have < file_trimmed_end)
920             final_read (have, start + have, file_trimmed_end - have);
921         }
922
923       elf = elf_memory (contents, file_trimmed_end);
924       if (unlikely (elf == NULL))
925         free (contents);
926       else
927         elf->flags |= ELF_F_MALLOCED;
928     }
929
930   if (elf != NULL)
931     {
932       /* Install the file in the module.  */
933       mod->main.elf = elf;
934       elf = NULL;
935       fd = -1;
936       mod->main.vaddr = module_start - bias;
937       mod->main.address_sync = module_address_sync;
938       mod->main_bias = bias;
939     }
940
941   return finish ();
942 }