• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.  */
63 static int
addr_segndx(Dwfl * dwfl,size_t segment,GElf_Addr addr,bool next)64 addr_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 
89 static bool
buf_has_data(const void * ptr,const void * end,size_t sz)90 buf_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 
98 static bool
buf_read_ulong(unsigned char ei_data,size_t sz,const void ** ptrp,const void * end,uint64_t * retp)99 buf_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 
135 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)136 handle_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 
210 static bool
invalid_elf(Elf * elf,bool disk_file_has_build_id,const void * build_id,size_t build_id_len)211 invalid_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 
238 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)239 dwfl_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