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