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.
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
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
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
18 or both in parallel, as here.
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.
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/>. */
30 #include "../libelf/libelfP.h" /* For NOTE_ALIGN. */
38 #include <sys/param.h>
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
48 #define INITIAL_READ 1024
50 #if __BYTE_ORDER == __LITTLE_ENDIAN
51 # define MY_ELFDATA ELFDATA2LSB
53 # define MY_ELFDATA ELFDATA2MSB
57 /* Return user segment index closest to ADDR but not above it.
58 If NEXT, return the closest to ADDR but not below it. */
60 addr_segndx (Dwfl *dwfl, size_t segment, GElf_Addr addr, bool next)
65 if (dwfl->lookup_segndx[segment] >= 0)
66 ndx = dwfl->lookup_segndx[segment];
67 if (++segment >= dwfl->lookup_elts - 1)
68 return next ? ndx + 1 : ndx;
70 while (dwfl->lookup_addr[segment] < addr);
74 while (dwfl->lookup_segndx[segment] < 0)
75 if (++segment >= dwfl->lookup_elts - 1)
77 ndx = dwfl->lookup_segndx[segment];
83 /* Return whether there is SZ bytes available at PTR till END. */
86 buf_has_data (const void *ptr, const void *end, size_t sz)
88 return ptr < end && (size_t) (end - ptr) >= sz;
91 /* Read SZ bytes into *RETP from *PTRP (limited by END) in format EI_DATA.
92 Function comes from src/readelf.c . */
95 buf_read_ulong (unsigned char ei_data, size_t sz,
96 const void **ptrp, const void *end, uint64_t *retp)
98 if (! buf_has_data (*ptrp, end, sz))
107 memcpy (&u, *ptrp, sz);
113 if (MY_ELFDATA != ei_data)
127 /* Try to find matching entry for module from address MODULE_START to
128 MODULE_END in NT_FILE note located at NOTE_FILE of NOTE_FILE_SIZE
129 bytes in format EI_CLASS and EI_DATA. */
132 handle_file_note (GElf_Addr module_start, GElf_Addr module_end,
133 unsigned char ei_class, unsigned char ei_data,
134 const void *note_file, size_t note_file_size)
136 if (note_file == NULL)
152 const void *ptr = note_file;
153 const void *end = note_file + note_file_size;
155 if (! buf_read_ulong (ei_data, sz, &ptr, end, &count))
157 if (! buf_read_ulong (ei_data, sz, &ptr, end, NULL)) // page_size
160 uint64_t maxcount = (size_t) (end - ptr) / (3 * sz);
161 if (count > maxcount)
164 /* Where file names are stored. */
165 const char *fptr = ptr + 3 * count * sz;
167 ssize_t firstix = -1;
169 for (size_t mix = 0; mix < count; mix++)
171 uint64_t mstart, mend, moffset;
172 if (! buf_read_ulong (ei_data, sz, &ptr, fptr, &mstart)
173 || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &mend)
174 || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &moffset))
176 if (mstart == module_start && moffset == 0)
177 firstix = lastix = mix;
178 if (firstix != -1 && mstart < module_end)
180 if (mend >= module_end)
186 const char *retval = NULL;
187 for (ssize_t mix = 0; mix <= lastix; mix++)
189 const char *fnext = memchr (fptr, 0, (const char *) end - fptr);
194 if (firstix < mix && mix <= lastix && strcmp (fptr, retval) != 0)
201 /* Return true iff we are certain ELF cannot match BUILD_ID of
202 BUILD_ID_LEN bytes. Pass DISK_FILE_HAS_BUILD_ID as false if it is
203 certain ELF does not contain build-id (it is only a performance hit
204 to pass it always as true). */
207 invalid_elf (Elf *elf, bool disk_file_has_build_id,
208 const void *build_id, size_t build_id_len)
210 if (! disk_file_has_build_id && build_id_len > 0)
212 /* Module found in segments with build-id is more reliable
213 than a module found via DT_DEBUG on disk without any
217 if (disk_file_has_build_id && build_id_len > 0)
219 const void *elf_build_id;
220 ssize_t elf_build_id_len;
222 /* If there is a build id in the elf file, check it. */
223 elf_build_id_len = INTUSE(dwelf_elf_gnu_build_id) (elf, &elf_build_id);
224 if (elf_build_id_len > 0)
226 if (build_id_len != (size_t) elf_build_id_len
227 || memcmp (build_id, elf_build_id, build_id_len) != 0)
235 dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
236 Dwfl_Memory_Callback *memory_callback,
237 void *memory_callback_arg,
238 Dwfl_Module_Callback *read_eagerly,
239 void *read_eagerly_arg,
240 const void *note_file, size_t note_file_size,
241 const struct r_debug_info *r_debug_info)
243 size_t segment = ndx;
245 if (segment >= dwfl->lookup_elts)
246 segment = dwfl->lookup_elts - 1;
249 && (dwfl->lookup_segndx[segment] > ndx
250 || dwfl->lookup_segndx[segment] == -1))
253 while (dwfl->lookup_segndx[segment] < ndx)
254 if (++segment == dwfl->lookup_elts)
257 GElf_Addr start = dwfl->lookup_addr[segment];
259 inline bool segment_read (int segndx,
260 void **buffer, size_t *buffer_available,
261 GElf_Addr addr, size_t minread)
263 return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available,
264 addr, minread, memory_callback_arg);
267 inline void release_buffer (void **buffer, size_t *buffer_available)
270 (void) segment_read (-1, buffer, buffer_available, 0, 0);
273 /* First read in the file header and check its sanity. */
276 size_t buffer_available = INITIAL_READ;
280 /* We might have to reserve some memory for the phdrs. Set to NULL
281 here so we can always safely free it. */
284 inline int finish (void)
287 release_buffer (&buffer, &buffer_available);
295 if (segment_read (ndx, &buffer, &buffer_available,
296 start, sizeof (Elf64_Ehdr))
297 || memcmp (buffer, ELFMAG, SELFMAG) != 0)
300 inline bool read_portion (void **data, size_t *data_size,
301 GElf_Addr vaddr, size_t filesz)
303 if (vaddr - start + filesz > buffer_available
304 /* If we're in string mode, then don't consider the buffer we have
305 sufficient unless it contains the terminator of the string. */
306 || (filesz == 0 && memchr (vaddr - start + buffer, '\0',
307 buffer_available - (vaddr - start)) == NULL))
311 return segment_read (addr_segndx (dwfl, segment, vaddr, false),
312 data, data_size, vaddr, filesz);
315 /* We already have this whole note segment from our initial read. */
316 *data = vaddr - start + buffer;
321 inline void finish_portion (void **data, size_t *data_size)
324 release_buffer (data, data_size);
327 /* Extract the information we need from the file header. */
328 const unsigned char *e_ident;
329 unsigned char ei_class;
330 unsigned char ei_data;
339 uint_fast16_t phentsize;
343 .d_type = ELF_T_EHDR,
344 .d_buf = (void *) buffer,
345 .d_version = EV_CURRENT,
349 .d_type = ELF_T_EHDR,
351 .d_size = sizeof ehdr,
352 .d_version = EV_CURRENT,
354 e_ident = ((const unsigned char *) buffer);
355 ei_class = e_ident[EI_CLASS];
356 ei_data = e_ident[EI_DATA];
360 xlatefrom.d_size = sizeof (Elf32_Ehdr);
361 if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
363 e_type = ehdr.e32.e_type;
364 phoff = ehdr.e32.e_phoff;
365 phnum = ehdr.e32.e_phnum;
366 phentsize = ehdr.e32.e_phentsize;
367 if (phentsize != sizeof (Elf32_Phdr))
369 shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
373 xlatefrom.d_size = sizeof (Elf64_Ehdr);
374 if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
376 e_type = ehdr.e64.e_type;
377 phoff = ehdr.e64.e_phoff;
378 phnum = ehdr.e64.e_phnum;
379 phentsize = ehdr.e64.e_phentsize;
380 if (phentsize != sizeof (Elf64_Phdr))
382 shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
389 /* The file header tells where to find the program headers.
390 These are what we need to find the boundaries of the module.
391 Without them, we don't have a module to report. */
396 xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
397 xlatefrom.d_size = phnum * phentsize;
399 void *ph_buffer = NULL;
400 size_t ph_buffer_size = 0;
401 if (read_portion (&ph_buffer, &ph_buffer_size,
402 start + phoff, xlatefrom.d_size))
405 xlatefrom.d_buf = ph_buffer;
409 Elf32_Phdr p32[phnum];
410 Elf64_Phdr p64[phnum];
413 phdrsp = malloc (sizeof (phdrsn));
414 if (unlikely (phdrsp == NULL))
416 phdrsn *phdrs = (phdrsn *) phdrsp;
418 xlateto.d_buf = phdrs;
419 xlateto.d_size = sizeof (phdrsn);
421 /* Track the bounds of the file visible in memory. */
422 GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end. */
423 GElf_Off file_end = 0; /* Rounded up to effective page size. */
424 GElf_Off contiguous = 0; /* Visible as contiguous file from START. */
425 GElf_Off total_filesz = 0; /* Total size of data to read. */
427 /* Collect the bias between START and the containing PT_LOAD's p_vaddr. */
429 bool found_bias = false;
431 /* Collect the unbiased bounds of the module here. */
432 GElf_Addr module_start = -1l;
433 GElf_Addr module_end = 0;
434 GElf_Addr module_address_sync = 0;
436 /* If we see PT_DYNAMIC, record it here. */
437 GElf_Addr dyn_vaddr = 0;
438 GElf_Xword dyn_filesz = 0;
440 /* Collect the build ID bits here. */
441 void *build_id = NULL;
442 size_t build_id_len = 0;
443 GElf_Addr build_id_vaddr = 0;
445 /* Consider a PT_NOTE we've found in the image. */
446 inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz)
448 /* If we have already seen a build ID, we don't care any more. */
449 if (build_id != NULL || filesz == 0)
454 if (read_portion (&data, &data_size, vaddr, filesz))
457 assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
460 if (ei_data == MY_ELFDATA)
464 notes = malloc (filesz);
465 if (unlikely (notes == NULL))
467 xlatefrom.d_type = xlateto.d_type = ELF_T_NHDR;
468 xlatefrom.d_buf = (void *) data;
469 xlatefrom.d_size = filesz;
470 xlateto.d_buf = notes;
471 xlateto.d_size = filesz;
472 if (elf32_xlatetom (&xlateto, &xlatefrom,
473 ehdr.e32.e_ident[EI_DATA]) == NULL)
477 const GElf_Nhdr *nh = notes;
478 while ((const void *) nh < (const void *) notes + filesz)
480 const void *note_name = nh + 1;
481 const void *note_desc = note_name + NOTE_ALIGN (nh->n_namesz);
482 if (unlikely ((size_t) ((const void *) notes + filesz
483 - note_desc) < nh->n_descsz))
486 if (nh->n_type == NT_GNU_BUILD_ID
488 && nh->n_namesz == sizeof "GNU"
489 && !memcmp (note_name, "GNU", sizeof "GNU"))
491 build_id_vaddr = note_desc - (const void *) notes + vaddr;
492 build_id_len = nh->n_descsz;
493 build_id = malloc (nh->n_descsz);
494 if (likely (build_id != NULL))
495 memcpy (build_id, note_desc, build_id_len);
499 nh = note_desc + NOTE_ALIGN (nh->n_descsz);
505 finish_portion (&data, &data_size);
508 /* Consider each of the program headers we've read from the image. */
509 inline void consider_phdr (GElf_Word type,
510 GElf_Addr vaddr, GElf_Xword memsz,
511 GElf_Off offset, GElf_Xword filesz,
522 /* We calculate from the p_offset of the note segment,
523 because we don't yet know the bias for its p_vaddr. */
524 consider_notes (start + offset, filesz);
528 align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
530 GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
531 GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
532 GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
534 if (file_trimmed_end < offset + filesz)
536 file_trimmed_end = offset + filesz;
538 /* Trim the last segment so we don't bother with zeros
539 in the last page that are off the end of the file.
540 However, if the extra bit in that page includes the
541 section headers, keep them. */
542 if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
544 filesz += shdrs_end - file_trimmed_end;
545 file_trimmed_end = shdrs_end;
549 total_filesz += filesz;
551 if (file_end < filesz_offset)
553 file_end = filesz_offset;
554 if (filesz_vaddr - start == filesz_offset)
555 contiguous = file_end;
558 if (!found_bias && (offset & -align) == 0
559 && likely (filesz_offset >= phoff + phnum * phentsize))
561 bias = start - vaddr;
565 if ((vaddr & -align) < module_start)
567 module_start = vaddr & -align;
568 module_address_sync = vaddr + memsz;
571 if (module_end < vaddr_end)
572 module_end = vaddr_end;
576 if (ei_class == ELFCLASS32)
578 if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
579 found_bias = false; /* Trigger error check. */
581 for (uint_fast16_t i = 0; i < phnum; ++i)
582 consider_phdr (phdrs->p32[i].p_type,
583 phdrs->p32[i].p_vaddr, phdrs->p32[i].p_memsz,
584 phdrs->p32[i].p_offset, phdrs->p32[i].p_filesz,
585 phdrs->p32[i].p_align);
589 if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
590 found_bias = false; /* Trigger error check. */
592 for (uint_fast16_t i = 0; i < phnum; ++i)
593 consider_phdr (phdrs->p64[i].p_type,
594 phdrs->p64[i].p_vaddr, phdrs->p64[i].p_memsz,
595 phdrs->p64[i].p_offset, phdrs->p64[i].p_filesz,
596 phdrs->p64[i].p_align);
599 finish_portion (&ph_buffer, &ph_buffer_size);
601 /* We must have seen the segment covering offset 0, or else the ELF
602 header we read at START was not produced by these program headers. */
603 if (unlikely (!found_bias))
609 /* Now we know enough to report a module for sure: its bounds. */
610 module_start += bias;
615 /* NAME found from link map has precedence over DT_SONAME possibly read
617 bool name_is_final = false;
619 /* Try to match up DYN_VADDR against L_LD as found in link map.
620 Segments sniffing may guess invalid address as the first read-only memory
621 mapping may not be dumped to the core file (if ELF headers are not dumped)
622 and the ELF header is dumped first with the read/write mapping of the same
623 file at higher addresses. */
624 if (r_debug_info != NULL)
625 for (const struct r_debug_info_module *module = r_debug_info->module;
626 module != NULL; module = module->next)
627 if (module_start <= module->l_ld && module->l_ld < module_end)
629 /* L_LD read from link map must be right while DYN_VADDR is unsafe.
630 Therefore subtract DYN_VADDR and add L_LD to get a possibly
631 corrective displacement for all addresses computed so far. */
632 GElf_Addr fixup = module->l_ld - dyn_vaddr;
633 if ((fixup & (dwfl->segment_align - 1)) == 0
634 && module_start + fixup <= module->l_ld
635 && module->l_ld < module_end + fixup)
637 module_start += fixup;
641 if (module->name[0] != '\0')
643 name = basename (module->name);
644 name_is_final = true;
650 if (r_debug_info != NULL)
652 bool skip_this_module = false;
653 for (struct r_debug_info_module *module = r_debug_info->module;
654 module != NULL; module = module->next)
655 if ((module_end > module->start && module_start < module->end)
656 || dyn_vaddr == module->l_ld)
658 if (module->elf != NULL
659 && invalid_elf (module->elf, module->disk_file_has_build_id,
660 build_id, build_id_len))
662 elf_end (module->elf);
667 if (module->elf != NULL)
669 /* Ignore this found module if it would conflict in address
670 space with any already existing module of DWFL. */
671 skip_this_module = true;
674 if (skip_this_module)
681 const char *file_note_name = handle_file_note (module_start, module_end,
683 note_file, note_file_size);
686 name = file_note_name;
687 name_is_final = true;
688 bool invalid = false;
689 fd = open64 (name, O_RDONLY);
692 Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
693 if (error == DWFL_E_NOERROR)
694 invalid = invalid_elf (elf, true /* disk_file_has_build_id */,
695 build_id, build_id_len);
699 /* The file was there, but the build_id didn't match. We
700 still want to report the module, but need to get the ELF
701 some other way if possible. */
709 /* Our return value now says to skip the segments contained
710 within the module. */
711 ndx = addr_segndx (dwfl, segment, module_end, true);
713 /* Examine its .dynamic section to get more interesting details.
714 If it has DT_SONAME, we'll use that as the module name.
715 If it has a DT_DEBUG, then it's actually a PIE rather than a DSO.
716 We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME,
717 and they also tell us the essential portion of the file
718 for fetching symbols. */
719 GElf_Addr soname_stroff = 0;
720 GElf_Addr dynstr_vaddr = 0;
721 GElf_Xword dynstrsz = 0;
722 bool execlike = false;
723 inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val)
747 return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0;
750 const size_t dyn_entsize = (ei_class == ELFCLASS32
751 ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
753 void *dyn_data = NULL;
754 size_t dyn_data_size = 0;
755 if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
756 && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz))
760 Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)];
761 Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)];
763 dyns = malloc (sizeof (dynn));
764 if (unlikely (dyns == NULL))
766 dynn *dyn = (dynn *) dyns;
768 xlatefrom.d_type = xlateto.d_type = ELF_T_DYN;
769 xlatefrom.d_buf = (void *) dyn_data;
770 xlatefrom.d_size = dyn_filesz;
772 xlateto.d_size = sizeof (dynn);
774 if (ei_class == ELFCLASS32)
776 if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
777 for (size_t i = 0; i < dyn_filesz / sizeof (Elf32_Dyn); ++i)
778 if (consider_dyn (dyn->d32[i].d_tag, dyn->d32[i].d_un.d_val))
783 if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
784 for (size_t i = 0; i < dyn_filesz / sizeof (Elf64_Dyn); ++i)
785 if (consider_dyn (dyn->d64[i].d_tag, dyn->d64[i].d_un.d_val))
790 finish_portion (&dyn_data, &dyn_data_size);
792 /* We'll use the name passed in or a stupid default if not DT_SONAME. */
794 name = e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]";
797 size_t soname_size = 0;
798 if (! name_is_final && dynstrsz != 0 && dynstr_vaddr != 0)
800 /* We know the bounds of the .dynstr section.
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. */
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;
817 if (unlikely (dynstr_vaddr + dynstrsz > module_end))
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))
827 /* Now that we have chosen the module's name and bounds, report it.
828 If we found a build ID, report that too. */
830 Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name,
831 module_start, module_end);
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;
838 if (likely (mod != NULL) && build_id != NULL
839 && unlikely (INTUSE(dwfl_module_report_build_id) (mod,
848 /* At this point we do not need BUILD_ID or NAME any more.
849 They have been copied. */
851 finish_portion (&soname, &soname_size);
853 if (unlikely (mod == NULL))
859 /* We have reported the module. Now let the caller decide whether we
860 should read the whole thing in right now. */
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);
870 && (*read_eagerly) (MODCB_ARGS (mod), &buffer, &buffer_available,
871 cost, worthwhile, whole, contiguous,
872 read_eagerly_arg, &elf)
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. */
878 void *contents = calloc (1, file_trimmed_end);
879 if (unlikely (contents == NULL))
882 inline void final_read (size_t offset, GElf_Addr vaddr, size_t size)
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);
890 if (contiguous < file_trimmed_end)
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. */
895 inline void read_phdr (GElf_Word type, GElf_Addr vaddr,
896 GElf_Off offset, GElf_Xword filesz)
899 final_read (offset, vaddr + bias, filesz);
902 if (ei_class == ELFCLASS32)
903 for (uint_fast16_t i = 0; i < phnum; ++i)
904 read_phdr (phdrs->p32[i].p_type, phdrs->p32[i].p_vaddr,
905 phdrs->p32[i].p_offset, phdrs->p32[i].p_filesz);
907 for (uint_fast16_t i = 0; i < phnum; ++i)
908 read_phdr (phdrs->p64[i].p_type, phdrs->p64[i].p_vaddr,
909 phdrs->p64[i].p_offset, phdrs->p64[i].p_filesz);
913 /* The whole file sits contiguous in memory,
914 but the caller didn't want to just do it. */
916 const size_t have = MIN (buffer_available, file_trimmed_end);
917 memcpy (contents, buffer, have);
919 if (have < file_trimmed_end)
920 final_read (have, start + have, file_trimmed_end - have);
923 elf = elf_memory (contents, file_trimmed_end);
924 if (unlikely (elf == NULL))
927 elf->flags |= ELF_F_MALLOCED;
932 /* Install the file in the module. */
936 mod->main.vaddr = module_start - bias;
937 mod->main.address_sync = module_address_sync;
938 mod->main_bias = bias;