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