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#ifndef MAX
57# define MAX(a, b) ((a) > (b) ? (a) : (b))
58#endif
59
60
61/* Return user segment index closest to ADDR but not above it.
62   If NEXT, return the closest to ADDR but not below it.  */
63static int
64addr_segndx (Dwfl *dwfl, size_t segment, GElf_Addr addr, bool next)
65{
66  int ndx = -1;
67  do
68    {
69      if (dwfl->lookup_segndx[segment] >= 0)
70	ndx = dwfl->lookup_segndx[segment];
71      if (++segment >= dwfl->lookup_elts - 1)
72	return next ? ndx + 1 : ndx;
73    }
74  while (dwfl->lookup_addr[segment] < addr);
75
76  if (next)
77    {
78      while (dwfl->lookup_segndx[segment] < 0)
79	if (++segment >= dwfl->lookup_elts - 1)
80	  return ndx + 1;
81      ndx = dwfl->lookup_segndx[segment];
82    }
83
84  return ndx;
85}
86
87/* Return whether there is SZ bytes available at PTR till END.  */
88
89static bool
90buf_has_data (const void *ptr, const void *end, size_t sz)
91{
92  return ptr < end && (size_t) (end - ptr) >= sz;
93}
94
95/* Read SZ bytes into *RETP from *PTRP (limited by END) in format EI_DATA.
96   Function comes from src/readelf.c .  */
97
98static bool
99buf_read_ulong (unsigned char ei_data, size_t sz,
100		const void **ptrp, const void *end, uint64_t *retp)
101{
102  if (! buf_has_data (*ptrp, end, sz))
103    return false;
104
105  union
106  {
107    uint64_t u64;
108    uint32_t u32;
109  } u;
110
111  memcpy (&u, *ptrp, sz);
112  (*ptrp) += sz;
113
114  if (retp == NULL)
115    return true;
116
117  if (MY_ELFDATA != ei_data)
118    {
119      if (sz == 4)
120	CONVERT (u.u32);
121      else
122	CONVERT (u.u64);
123    }
124  if (sz == 4)
125    *retp = u.u32;
126  else
127    *retp = u.u64;
128  return true;
129}
130
131/* Try to find matching entry for module from address MODULE_START to
132   MODULE_END in NT_FILE note located at NOTE_FILE of NOTE_FILE_SIZE
133   bytes in format EI_CLASS and EI_DATA.  */
134
135static const char *
136handle_file_note (GElf_Addr module_start, GElf_Addr module_end,
137		  unsigned char ei_class, unsigned char ei_data,
138		  const void *note_file, size_t note_file_size)
139{
140  if (note_file == NULL)
141    return NULL;
142
143  size_t sz;
144  switch (ei_class)
145    {
146    case ELFCLASS32:
147      sz = 4;
148      break;
149    case ELFCLASS64:
150      sz = 8;
151      break;
152    default:
153      return NULL;
154    }
155
156  const void *ptr = note_file;
157  const void *end = note_file + note_file_size;
158  uint64_t count;
159  if (! buf_read_ulong (ei_data, sz, &ptr, end, &count))
160    return NULL;
161  if (! buf_read_ulong (ei_data, sz, &ptr, end, NULL)) // page_size
162    return NULL;
163
164  uint64_t maxcount = (size_t) (end - ptr) / (3 * sz);
165  if (count > maxcount)
166    return NULL;
167
168  /* Where file names are stored.  */
169  const char *fptr = ptr + 3 * count * sz;
170
171  ssize_t firstix = -1;
172  ssize_t lastix = -1;
173  for (size_t mix = 0; mix < count; mix++)
174    {
175      uint64_t mstart, mend, moffset;
176      if (! buf_read_ulong (ei_data, sz, &ptr, fptr, &mstart)
177	  || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &mend)
178	  || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &moffset))
179	return NULL;
180      if (mstart == module_start && moffset == 0)
181	firstix = lastix = mix;
182      if (firstix != -1 && mstart < module_end)
183	lastix = mix;
184      if (mend >= module_end)
185	break;
186    }
187  if (firstix == -1)
188    return NULL;
189
190  const char *retval = NULL;
191  for (ssize_t mix = 0; mix <= lastix; mix++)
192    {
193      const char *fnext = memchr (fptr, 0, (const char *) end - fptr);
194      if (fnext == NULL)
195	return NULL;
196      if (mix == firstix)
197	retval = fptr;
198      if (firstix < mix && mix <= lastix && strcmp (fptr, retval) != 0)
199	return NULL;
200      fptr = fnext + 1;
201    }
202  return retval;
203}
204
205/* Return true iff we are certain ELF cannot match BUILD_ID of
206   BUILD_ID_LEN bytes.  Pass DISK_FILE_HAS_BUILD_ID as false if it is
207   certain ELF does not contain build-id (it is only a performance hit
208   to pass it always as true).  */
209
210static bool
211invalid_elf (Elf *elf, bool disk_file_has_build_id,
212	     const void *build_id, size_t build_id_len)
213{
214  if (! disk_file_has_build_id && build_id_len > 0)
215    {
216      /* Module found in segments with build-id is more reliable
217	 than a module found via DT_DEBUG on disk without any
218	 build-id.   */
219      return true;
220    }
221  if (disk_file_has_build_id && build_id_len > 0)
222    {
223      const void *elf_build_id;
224      ssize_t elf_build_id_len;
225
226      /* If there is a build id in the elf file, check it.  */
227      elf_build_id_len = INTUSE(dwelf_elf_gnu_build_id) (elf, &elf_build_id);
228      if (elf_build_id_len > 0)
229	{
230	  if (build_id_len != (size_t) elf_build_id_len
231	      || memcmp (build_id, elf_build_id, build_id_len) != 0)
232	    return true;
233	}
234    }
235  return false;
236}
237
238int
239dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
240			    Dwfl_Memory_Callback *memory_callback,
241			    void *memory_callback_arg,
242			    Dwfl_Module_Callback *read_eagerly,
243			    void *read_eagerly_arg,
244			    const void *note_file, size_t note_file_size,
245			    const struct r_debug_info *r_debug_info)
246{
247  size_t segment = ndx;
248
249  if (segment >= dwfl->lookup_elts)
250    segment = dwfl->lookup_elts - 1;
251
252  while (segment > 0
253	 && (dwfl->lookup_segndx[segment] > ndx
254	     || dwfl->lookup_segndx[segment] == -1))
255    --segment;
256
257  while (dwfl->lookup_segndx[segment] < ndx)
258    if (++segment == dwfl->lookup_elts)
259      return 0;
260
261  GElf_Addr start = dwfl->lookup_addr[segment];
262
263  inline bool segment_read (int segndx,
264			    void **buffer, size_t *buffer_available,
265			    GElf_Addr addr, size_t minread)
266  {
267    return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available,
268				 addr, minread, memory_callback_arg);
269  }
270
271  inline void release_buffer (void **buffer, size_t *buffer_available)
272  {
273    if (*buffer != NULL)
274      (void) segment_read (-1, buffer, buffer_available, 0, 0);
275  }
276
277  /* First read in the file header and check its sanity.  */
278
279  void *buffer = NULL;
280  size_t buffer_available = INITIAL_READ;
281  Elf *elf = NULL;
282  int fd = -1;
283
284  /* We might have to reserve some memory for the phdrs.  Set to NULL
285     here so we can always safely free it.  */
286  void *phdrsp = NULL;
287
288  inline int finish (void)
289  {
290    free (phdrsp);
291    release_buffer (&buffer, &buffer_available);
292    if (elf != NULL)
293      elf_end (elf);
294    if (fd != -1)
295      close (fd);
296    return ndx;
297  }
298
299  if (segment_read (ndx, &buffer, &buffer_available,
300		    start, sizeof (Elf64_Ehdr))
301      || memcmp (buffer, ELFMAG, SELFMAG) != 0)
302    return finish ();
303
304  inline bool read_portion (void **data, size_t *data_size,
305			    GElf_Addr vaddr, size_t filesz)
306  {
307    if (vaddr - start + filesz > buffer_available
308	/* If we're in string mode, then don't consider the buffer we have
309	   sufficient unless it contains the terminator of the string.  */
310	|| (filesz == 0 && memchr (vaddr - start + buffer, '\0',
311				   buffer_available - (vaddr - start)) == NULL))
312      {
313	*data = NULL;
314	*data_size = filesz;
315	return segment_read (addr_segndx (dwfl, segment, vaddr, false),
316			     data, data_size, vaddr, filesz);
317      }
318
319    /* We already have this whole note segment from our initial read.  */
320    *data = vaddr - start + buffer;
321    *data_size = 0;
322    return false;
323  }
324
325  inline void finish_portion (void **data, size_t *data_size)
326  {
327    if (*data_size != 0)
328      release_buffer (data, data_size);
329  }
330
331  /* Extract the information we need from the file header.  */
332  const unsigned char *e_ident;
333  unsigned char ei_class;
334  unsigned char ei_data;
335  uint16_t e_type;
336  union
337  {
338    Elf32_Ehdr e32;
339    Elf64_Ehdr e64;
340  } ehdr;
341  GElf_Off phoff;
342  uint_fast16_t phnum;
343  uint_fast16_t phentsize;
344  GElf_Off shdrs_end;
345  Elf_Data xlatefrom =
346    {
347      .d_type = ELF_T_EHDR,
348      .d_buf = (void *) buffer,
349      .d_version = EV_CURRENT,
350    };
351  Elf_Data xlateto =
352    {
353      .d_type = ELF_T_EHDR,
354      .d_buf = &ehdr,
355      .d_size = sizeof ehdr,
356      .d_version = EV_CURRENT,
357    };
358  e_ident = ((const unsigned char *) buffer);
359  ei_class = e_ident[EI_CLASS];
360  ei_data = e_ident[EI_DATA];
361  switch (ei_class)
362    {
363    case ELFCLASS32:
364      xlatefrom.d_size = sizeof (Elf32_Ehdr);
365      if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
366	return finish ();
367      e_type = ehdr.e32.e_type;
368      phoff = ehdr.e32.e_phoff;
369      phnum = ehdr.e32.e_phnum;
370      phentsize = ehdr.e32.e_phentsize;
371      if (phentsize != sizeof (Elf32_Phdr))
372	return finish ();
373      shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
374      break;
375
376    case ELFCLASS64:
377      xlatefrom.d_size = sizeof (Elf64_Ehdr);
378      if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
379	return finish ();
380      e_type = ehdr.e64.e_type;
381      phoff = ehdr.e64.e_phoff;
382      phnum = ehdr.e64.e_phnum;
383      phentsize = ehdr.e64.e_phentsize;
384      if (phentsize != sizeof (Elf64_Phdr))
385	return finish ();
386      shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
387      break;
388
389    default:
390      return finish ();
391    }
392
393  /* The file header tells where to find the program headers.
394     These are what we need to find the boundaries of the module.
395     Without them, we don't have a module to report.  */
396
397  if (phnum == 0)
398    return finish ();
399
400  xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
401  xlatefrom.d_size = phnum * phentsize;
402
403  void *ph_buffer = NULL;
404  size_t ph_buffer_size = 0;
405  if (read_portion (&ph_buffer, &ph_buffer_size,
406		    start + phoff, xlatefrom.d_size))
407    return finish ();
408
409  xlatefrom.d_buf = ph_buffer;
410
411  bool class32 = ei_class == ELFCLASS32;
412  size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
413  if (unlikely (phnum > SIZE_MAX / phdr_size))
414    return finish ();
415  const size_t phdrsp_bytes = phnum * phdr_size;
416  phdrsp = malloc (phdrsp_bytes);
417  if (unlikely (phdrsp == NULL))
418    return finish ();
419
420  xlateto.d_buf = phdrsp;
421  xlateto.d_size = phdrsp_bytes;
422
423  /* Track the bounds of the file visible in memory.  */
424  GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end.  */
425  GElf_Off file_end = 0;	 /* Rounded up to effective page size.  */
426  GElf_Off contiguous = 0;	 /* Visible as contiguous file from START.  */
427  GElf_Off total_filesz = 0;	 /* Total size of data to read.  */
428
429  /* Collect the bias between START and the containing PT_LOAD's p_vaddr.  */
430  GElf_Addr bias = 0;
431  bool found_bias = false;
432
433  /* Collect the unbiased bounds of the module here.  */
434  GElf_Addr module_start = -1l;
435  GElf_Addr module_end = 0;
436  GElf_Addr module_address_sync = 0;
437
438  /* If we see PT_DYNAMIC, record it here.  */
439  GElf_Addr dyn_vaddr = 0;
440  GElf_Xword dyn_filesz = 0;
441
442  /* Collect the build ID bits here.  */
443  void *build_id = NULL;
444  size_t build_id_len = 0;
445  GElf_Addr build_id_vaddr = 0;
446
447  /* Consider a PT_NOTE we've found in the image.  */
448  inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz)
449  {
450    /* If we have already seen a build ID, we don't care any more.  */
451    if (build_id != NULL || filesz == 0)
452      return;
453
454    void *data;
455    size_t data_size;
456    if (read_portion (&data, &data_size, vaddr, filesz))
457      return;
458
459    assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
460
461    void *notes;
462    if (ei_data == MY_ELFDATA)
463      notes = data;
464    else
465      {
466	notes = malloc (filesz);
467	if (unlikely (notes == NULL))
468	  return;
469	xlatefrom.d_type = xlateto.d_type = ELF_T_NHDR;
470	xlatefrom.d_buf = (void *) data;
471	xlatefrom.d_size = filesz;
472	xlateto.d_buf = notes;
473	xlateto.d_size = filesz;
474	if (elf32_xlatetom (&xlateto, &xlatefrom,
475			    ehdr.e32.e_ident[EI_DATA]) == NULL)
476	  goto done;
477      }
478
479    const GElf_Nhdr *nh = notes;
480    while ((const void *) nh < (const void *) notes + filesz)
481     {
482	const void *note_name = nh + 1;
483	const void *note_desc = note_name + NOTE_ALIGN (nh->n_namesz);
484	if (unlikely ((size_t) ((const void *) notes + filesz
485				- note_desc) < nh->n_descsz))
486	  break;
487
488	if (nh->n_type == NT_GNU_BUILD_ID
489	    && nh->n_descsz > 0
490	    && nh->n_namesz == sizeof "GNU"
491	    && !memcmp (note_name, "GNU", sizeof "GNU"))
492	  {
493	    build_id_vaddr = note_desc - (const void *) notes + vaddr;
494	    build_id_len = nh->n_descsz;
495	    build_id = malloc (nh->n_descsz);
496	    if (likely (build_id != NULL))
497	      memcpy (build_id, note_desc, build_id_len);
498	    break;
499	  }
500
501	nh = note_desc + NOTE_ALIGN (nh->n_descsz);
502      }
503
504  done:
505    if (notes != data)
506      free (notes);
507    finish_portion (&data, &data_size);
508  }
509
510  /* Consider each of the program headers we've read from the image.  */
511  inline void consider_phdr (GElf_Word type,
512			     GElf_Addr vaddr, GElf_Xword memsz,
513			     GElf_Off offset, GElf_Xword filesz,
514			     GElf_Xword align)
515  {
516    switch (type)
517      {
518      case PT_DYNAMIC:
519	dyn_vaddr = vaddr;
520	dyn_filesz = filesz;
521	break;
522
523      case PT_NOTE:
524	/* We calculate from the p_offset of the note segment,
525	   because we don't yet know the bias for its p_vaddr.  */
526	consider_notes (start + offset, filesz);
527	break;
528
529      case PT_LOAD:
530	align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
531
532	GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
533	GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
534	GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
535
536	if (file_trimmed_end < offset + filesz)
537	  {
538	    file_trimmed_end = offset + filesz;
539
540	    /* Trim the last segment so we don't bother with zeros
541	       in the last page that are off the end of the file.
542	       However, if the extra bit in that page includes the
543	       section headers, keep them.  */
544	    if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
545	      {
546		filesz += shdrs_end - file_trimmed_end;
547		file_trimmed_end = shdrs_end;
548	      }
549	  }
550
551	total_filesz += filesz;
552
553	if (file_end < filesz_offset)
554	  {
555	    file_end = filesz_offset;
556	    if (filesz_vaddr - start == filesz_offset)
557	      contiguous = file_end;
558	  }
559
560	if (!found_bias && (offset & -align) == 0
561	    && likely (filesz_offset >= phoff + phnum * phentsize))
562	  {
563	    bias = start - vaddr;
564	    found_bias = true;
565	  }
566
567	if ((vaddr & -align) < module_start)
568	  {
569	    module_start = vaddr & -align;
570	    module_address_sync = vaddr + memsz;
571	  }
572
573	if (module_end < vaddr_end)
574	  module_end = vaddr_end;
575	break;
576      }
577  }
578
579  Elf32_Phdr (*p32)[phnum] = phdrsp;
580  Elf64_Phdr (*p64)[phnum] = phdrsp;
581  if (ei_class == ELFCLASS32)
582    {
583      if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
584	found_bias = false;	/* Trigger error check.  */
585      else
586	for (uint_fast16_t i = 0; i < phnum; ++i)
587	  consider_phdr ((*p32)[i].p_type,
588			 (*p32)[i].p_vaddr, (*p32)[i].p_memsz,
589			 (*p32)[i].p_offset, (*p32)[i].p_filesz,
590			 (*p32)[i].p_align);
591    }
592  else
593    {
594      if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
595	found_bias = false;	/* Trigger error check.  */
596      else
597	for (uint_fast16_t i = 0; i < phnum; ++i)
598	  consider_phdr ((*p64)[i].p_type,
599			 (*p64)[i].p_vaddr, (*p64)[i].p_memsz,
600			 (*p64)[i].p_offset, (*p64)[i].p_filesz,
601			 (*p64)[i].p_align);
602    }
603
604  finish_portion (&ph_buffer, &ph_buffer_size);
605
606  /* We must have seen the segment covering offset 0, or else the ELF
607     header we read at START was not produced by these program headers.  */
608  if (unlikely (!found_bias))
609    {
610      free (build_id);
611      return finish ();
612    }
613
614  /* Now we know enough to report a module for sure: its bounds.  */
615  module_start += bias;
616  module_end += bias;
617
618  dyn_vaddr += bias;
619
620  /* NAME found from link map has precedence over DT_SONAME possibly read
621     below.  */
622  bool name_is_final = false;
623
624  /* Try to match up DYN_VADDR against L_LD as found in link map.
625     Segments sniffing may guess invalid address as the first read-only memory
626     mapping may not be dumped to the core file (if ELF headers are not dumped)
627     and the ELF header is dumped first with the read/write mapping of the same
628     file at higher addresses.  */
629  if (r_debug_info != NULL)
630    for (const struct r_debug_info_module *module = r_debug_info->module;
631	 module != NULL; module = module->next)
632      if (module_start <= module->l_ld && module->l_ld < module_end)
633	{
634	  /* L_LD read from link map must be right while DYN_VADDR is unsafe.
635	     Therefore subtract DYN_VADDR and add L_LD to get a possibly
636	     corrective displacement for all addresses computed so far.  */
637	  GElf_Addr fixup = module->l_ld - dyn_vaddr;
638	  if ((fixup & (dwfl->segment_align - 1)) == 0
639	      && module_start + fixup <= module->l_ld
640	      && module->l_ld < module_end + fixup)
641	    {
642	      module_start += fixup;
643	      module_end += fixup;
644	      dyn_vaddr += fixup;
645	      bias += fixup;
646	      if (module->name[0] != '\0')
647		{
648		  name = basename (module->name);
649		  name_is_final = true;
650		}
651	      break;
652	    }
653	}
654
655  if (r_debug_info != NULL)
656    {
657      bool skip_this_module = false;
658      for (struct r_debug_info_module *module = r_debug_info->module;
659	   module != NULL; module = module->next)
660	if ((module_end > module->start && module_start < module->end)
661	    || dyn_vaddr == module->l_ld)
662	  {
663	    if (module->elf != NULL
664	        && invalid_elf (module->elf, module->disk_file_has_build_id,
665				build_id, build_id_len))
666	      {
667		elf_end (module->elf);
668		close (module->fd);
669		module->elf = NULL;
670		module->fd = -1;
671	      }
672	    if (module->elf != NULL)
673	      {
674		/* Ignore this found module if it would conflict in address
675		   space with any already existing module of DWFL.  */
676		skip_this_module = true;
677	      }
678	  }
679      if (skip_this_module)
680	{
681	  free (build_id);
682	  return finish ();
683	}
684    }
685
686  const char *file_note_name = handle_file_note (module_start, module_end,
687						 ei_class, ei_data,
688						 note_file, note_file_size);
689  if (file_note_name)
690    {
691      name = file_note_name;
692      name_is_final = true;
693      bool invalid = false;
694      fd = open (name, O_RDONLY);
695      if (fd >= 0)
696	{
697	  Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
698	  if (error == DWFL_E_NOERROR)
699	    invalid = invalid_elf (elf, true /* disk_file_has_build_id */,
700				   build_id, build_id_len);
701	}
702      if (invalid)
703	{
704	  /* The file was there, but the build_id didn't match.  We
705	     still want to report the module, but need to get the ELF
706	     some other way if possible.  */
707	  close (fd);
708	  fd = -1;
709	  elf_end (elf);
710	  elf = NULL;
711	}
712    }
713
714  /* Our return value now says to skip the segments contained
715     within the module.  */
716  ndx = addr_segndx (dwfl, segment, module_end, true);
717
718  /* Examine its .dynamic section to get more interesting details.
719     If it has DT_SONAME, we'll use that as the module name.
720     If it has a DT_DEBUG, then it's actually a PIE rather than a DSO.
721     We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME,
722     and they also tell us the essential portion of the file
723     for fetching symbols.  */
724  GElf_Addr soname_stroff = 0;
725  GElf_Addr dynstr_vaddr = 0;
726  GElf_Xword dynstrsz = 0;
727  bool execlike = false;
728  inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val)
729  {
730    switch (tag)
731      {
732      default:
733	return false;
734
735      case DT_DEBUG:
736	execlike = true;
737	break;
738
739      case DT_SONAME:
740	soname_stroff = val;
741	break;
742
743      case DT_STRTAB:
744	dynstr_vaddr = val;
745	break;
746
747      case DT_STRSZ:
748	dynstrsz = val;
749	break;
750      }
751
752    return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0;
753  }
754
755  const size_t dyn_entsize = (ei_class == ELFCLASS32
756			      ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
757  void *dyn_data = NULL;
758  size_t dyn_data_size = 0;
759  if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
760      && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz))
761    {
762      void *dyns = malloc (dyn_filesz);
763      Elf32_Dyn (*d32)[dyn_filesz / sizeof (Elf32_Dyn)] = dyns;
764      Elf64_Dyn (*d64)[dyn_filesz / sizeof (Elf64_Dyn)] = dyns;
765      if (unlikely (dyns == NULL))
766	return finish ();
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 = dyns;
772      xlateto.d_size = dyn_filesz;
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 ((*d32)[i].d_tag, (*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 ((*d64)[i].d_tag, (*d64)[i].d_un.d_val))
786		break;
787	}
788      free (dyns);
789    }
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 ((*p32)[i].p_type, (*p32)[i].p_vaddr,
905			 (*p32)[i].p_offset, (*p32)[i].p_filesz);
906	  else
907	    for (uint_fast16_t i = 0; i < phnum; ++i)
908	      read_phdr ((*p64)[i].p_type, (*p64)[i].p_vaddr,
909			 (*p64)[i].p_offset, (*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}
943