012a0fdeb61be330dc262d0f9849f18336900cb4
[platform/upstream/elfutils.git] / libdwfl / dwfl_segment_report_module.c
1 /* Sniff out modules from ELF headers visible in memory segments.
2    Copyright (C) 2008-2010 Red Hat, Inc.
3    This file is part of Red Hat elfutils.
4
5    Red Hat elfutils is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by the
7    Free Software Foundation; version 2 of the License.
8
9    Red Hat elfutils is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13
14    You should have received a copy of the GNU General Public License along
15    with Red Hat elfutils; if not, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
17
18    In addition, as a special exception, Red Hat, Inc. gives You the
19    additional right to link the code of Red Hat elfutils with code licensed
20    under any Open Source Initiative certified open source license
21    (http://www.opensource.org/licenses/index.php) which requires the
22    distribution of source code with any binary distribution and to
23    distribute linked combinations of the two.  Non-GPL Code permitted under
24    this exception must only link to the code of Red Hat elfutils through
25    those well defined interfaces identified in the file named EXCEPTION
26    found in the source code files (the "Approved Interfaces").  The files
27    of Non-GPL Code may instantiate templates or use macros or inline
28    functions from the Approved Interfaces without causing the resulting
29    work to be covered by the GNU General Public License.  Only Red Hat,
30    Inc. may make changes or additions to the list of Approved Interfaces.
31    Red Hat's grant of this exception is conditioned upon your not adding
32    any new exceptions.  If you wish to add a new Approved Interface or
33    exception, please contact Red Hat.  You must obey the GNU General Public
34    License in all respects for all of the Red Hat elfutils code and other
35    code used in conjunction with Red Hat elfutils except the Non-GPL Code
36    covered by this exception.  If you modify this file, you may extend this
37    exception to your version of the file, but you are not obligated to do
38    so.  If you do not wish to provide this exception without modification,
39    you must delete this exception statement from your version and license
40    this file solely under the GPL without exception.
41
42    Red Hat elfutils is an included package of the Open Invention Network.
43    An included package of the Open Invention Network is a package for which
44    Open Invention Network licensees cross-license their patents.  No patent
45    license is granted, either expressly or impliedly, by designation as an
46    included package.  Should you wish to participate in the Open Invention
47    Network licensing program, please visit www.openinventionnetwork.com
48    <http://www.openinventionnetwork.com>.  */
49
50 #include <config.h>
51 #include "../libelf/libelfP.h"  /* For NOTE_ALIGN.  */
52 #undef  _
53 #include "libdwflP.h"
54
55 #include <elf.h>
56 #include <gelf.h>
57 #include <inttypes.h>
58 #include <sys/param.h>
59 #include <alloca.h>
60 #include <endian.h>
61
62
63 /* A good size for the initial read from memory, if it's not too costly.
64    This more than covers the phdrs and note segment in the average 64-bit
65    binary.  */
66
67 #define INITIAL_READ    1024
68
69 #if __BYTE_ORDER == __LITTLE_ENDIAN
70 # define MY_ELFDATA     ELFDATA2LSB
71 #else
72 # define MY_ELFDATA     ELFDATA2MSB
73 #endif
74
75
76 /* Return user segment index closest to ADDR but not above it.
77    If NEXT, return the closest to ADDR but not below it.  */
78 static int
79 addr_segndx (Dwfl *dwfl, size_t segment, GElf_Addr addr, bool next)
80 {
81   int ndx = -1;
82   do
83     {
84       if (dwfl->lookup_segndx[segment] >= 0)
85         ndx = dwfl->lookup_segndx[segment];
86       if (++segment >= dwfl->lookup_elts - 1)
87         return next ? ndx + 1 : ndx;
88     }
89   while (dwfl->lookup_addr[segment] < addr);
90
91   if (next)
92     {
93       while (dwfl->lookup_segndx[segment] < 0)
94         if (++segment >= dwfl->lookup_elts - 1)
95           return ndx + 1;
96       ndx = dwfl->lookup_segndx[segment];
97     }
98
99   return ndx;
100 }
101
102 int
103 dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
104                             Dwfl_Memory_Callback *memory_callback,
105                             void *memory_callback_arg,
106                             Dwfl_Module_Callback *read_eagerly,
107                             void *read_eagerly_arg)
108 {
109   size_t segment = ndx;
110
111   if (segment >= dwfl->lookup_elts)
112     segment = dwfl->lookup_elts - 1;
113
114   while (segment > 0
115          && (dwfl->lookup_segndx[segment] > ndx
116              || dwfl->lookup_segndx[segment] == -1))
117     --segment;
118
119   while (dwfl->lookup_segndx[segment] < ndx)
120     if (++segment == dwfl->lookup_elts)
121       return 0;
122
123   GElf_Addr start = dwfl->lookup_addr[segment];
124
125   inline bool segment_read (int segndx,
126                             void **buffer, size_t *buffer_available,
127                             GElf_Addr addr, size_t minread)
128   {
129     return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available,
130                                  addr, minread, memory_callback_arg);
131   }
132
133   inline void release_buffer (void **buffer, size_t *buffer_available)
134   {
135     if (*buffer != NULL)
136       (void) segment_read (-1, buffer, buffer_available, 0, 0);
137   }
138
139   /* First read in the file header and check its sanity.  */
140
141   void *buffer = NULL;
142   size_t buffer_available = INITIAL_READ;
143
144   inline int finish (void)
145   {
146     release_buffer (&buffer, &buffer_available);
147     return ndx;
148   }
149
150   if (segment_read (ndx, &buffer, &buffer_available,
151                     start, sizeof (Elf64_Ehdr))
152       || memcmp (buffer, ELFMAG, SELFMAG) != 0)
153     return finish ();
154
155   inline bool read_portion (void **data, size_t *data_size,
156                             GElf_Addr vaddr, size_t filesz)
157   {
158     if (vaddr - start + filesz > buffer_available)
159       {
160         *data = NULL;
161         *data_size = filesz;
162         return segment_read (addr_segndx (dwfl, segment, vaddr, false),
163                              data, data_size, vaddr, filesz);
164       }
165
166     /* We already have this whole note segment from our initial read.  */
167     *data = vaddr - start + buffer;
168     *data_size = 0;
169     return false;
170   }
171
172   inline void finish_portion (void **data, size_t *data_size)
173   {
174     if (*data_size != 0)
175       release_buffer (data, data_size);
176   }
177
178   /* Extract the information we need from the file header.  */
179   union
180   {
181     Elf32_Ehdr e32;
182     Elf64_Ehdr e64;
183   } ehdr;
184   GElf_Off phoff;
185   uint_fast16_t phnum;
186   uint_fast16_t phentsize;
187   GElf_Off shdrs_end;
188   Elf_Data xlatefrom =
189     {
190       .d_type = ELF_T_EHDR,
191       .d_buf = (void *) buffer,
192       .d_version = EV_CURRENT,
193     };
194   Elf_Data xlateto =
195     {
196       .d_type = ELF_T_EHDR,
197       .d_buf = &ehdr,
198       .d_size = sizeof ehdr,
199       .d_version = EV_CURRENT,
200     };
201   switch (((const unsigned char *) buffer)[EI_CLASS])
202     {
203     case ELFCLASS32:
204       xlatefrom.d_size = sizeof (Elf32_Ehdr);
205       if (elf32_xlatetom (&xlateto, &xlatefrom,
206                           ((const unsigned char *) buffer)[EI_DATA]) == NULL)
207         return finish ();
208       phoff = ehdr.e32.e_phoff;
209       phnum = ehdr.e32.e_phnum;
210       phentsize = ehdr.e32.e_phentsize;
211       if (phentsize != sizeof (Elf32_Phdr))
212         return finish ();
213       shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
214       break;
215
216     case ELFCLASS64:
217       xlatefrom.d_size = sizeof (Elf64_Ehdr);
218       if (elf64_xlatetom (&xlateto, &xlatefrom,
219                           ((const unsigned char *) buffer)[EI_DATA]) == NULL)
220         return finish ();
221       phoff = ehdr.e64.e_phoff;
222       phnum = ehdr.e64.e_phnum;
223       phentsize = ehdr.e64.e_phentsize;
224       if (phentsize != sizeof (Elf64_Phdr))
225         return finish ();
226       shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
227       break;
228
229     default:
230       return finish ();
231     }
232
233   /* The file header tells where to find the program headers.
234      These are what we need to find the boundaries of the module.
235      Without them, we don't have a module to report.  */
236
237   if (phnum == 0)
238     return finish ();
239
240   xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
241   xlatefrom.d_size = phnum * phentsize;
242
243   void *ph_buffer = NULL;
244   size_t ph_buffer_size = 0;
245   if (read_portion (&ph_buffer, &ph_buffer_size,
246                     start + phoff, xlatefrom.d_size))
247     return finish ();
248
249   xlatefrom.d_buf = ph_buffer;
250
251   union
252   {
253     Elf32_Phdr p32[phnum];
254     Elf64_Phdr p64[phnum];
255   } phdrs;
256
257   xlateto.d_buf = &phdrs;
258   xlateto.d_size = sizeof phdrs;
259
260   /* Track the bounds of the file visible in memory.  */
261   GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end.  */
262   GElf_Off file_end = 0;         /* Rounded up to effective page size.  */
263   GElf_Off contiguous = 0;       /* Visible as contiguous file from START.  */
264   GElf_Off total_filesz = 0;     /* Total size of data to read.  */
265
266   /* Collect the bias between START and the containing PT_LOAD's p_vaddr.  */
267   GElf_Addr bias = 0;
268   bool found_bias = false;
269
270   /* Collect the unbiased bounds of the module here.  */
271   GElf_Addr module_start = -1l;
272   GElf_Addr module_end = 0;
273   GElf_Addr module_address_sync = 0;
274
275   /* If we see PT_DYNAMIC, record it here.  */
276   GElf_Addr dyn_vaddr = 0;
277   GElf_Xword dyn_filesz = 0;
278
279   /* Collect the build ID bits here.  */
280   void *build_id = NULL;
281   size_t build_id_len = 0;
282   GElf_Addr build_id_vaddr = 0;
283
284   /* Consider a PT_NOTE we've found in the image.  */
285   inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz)
286   {
287     /* If we have already seen a build ID, we don't care any more.  */
288     if (build_id != NULL || filesz == 0)
289       return;
290
291     void *data;
292     size_t data_size;
293     if (read_portion (&data, &data_size, vaddr, filesz))
294       return;
295
296     assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
297
298     void *notes;
299     if (ehdr.e32.e_ident[EI_DATA] == MY_ELFDATA)
300       notes = data;
301     else
302       {
303         notes = malloc (filesz);
304         if (unlikely (notes == NULL))
305           return;
306         xlatefrom.d_type = xlateto.d_type = ELF_T_NHDR;
307         xlatefrom.d_buf = (void *) data;
308         xlatefrom.d_size = filesz;
309         xlateto.d_buf = notes;
310         xlateto.d_size = filesz;
311         if (elf32_xlatetom (&xlateto, &xlatefrom,
312                             ehdr.e32.e_ident[EI_DATA]) == NULL)
313           goto done;
314       }
315
316     const GElf_Nhdr *nh = notes;
317     while ((const void *) nh < (const void *) notes + filesz)
318      {
319         const void *note_name = nh + 1;
320         const void *note_desc = note_name + NOTE_ALIGN (nh->n_namesz);
321         if (unlikely ((size_t) ((const void *) notes + filesz
322                                 - note_desc) < nh->n_descsz))
323           break;
324
325         if (nh->n_type == NT_GNU_BUILD_ID
326             && nh->n_descsz > 0
327             && nh->n_namesz == sizeof "GNU"
328             && !memcmp (note_name, "GNU", sizeof "GNU"))
329           {
330             build_id_vaddr = note_desc - (const void *) notes + vaddr;
331             build_id_len = nh->n_descsz;
332             build_id = malloc (nh->n_descsz);
333             if (likely (build_id != NULL))
334               memcpy (build_id, note_desc, build_id_len);
335             break;
336           }
337
338         nh = note_desc + NOTE_ALIGN (nh->n_descsz);
339       }
340
341   done:
342     if (notes != data)
343       free (notes);
344     finish_portion (&data, &data_size);
345   }
346
347   /* Consider each of the program headers we've read from the image.  */
348   inline void consider_phdr (GElf_Word type,
349                              GElf_Addr vaddr, GElf_Xword memsz,
350                              GElf_Off offset, GElf_Xword filesz,
351                              GElf_Xword align)
352   {
353     switch (type)
354       {
355       case PT_DYNAMIC:
356         dyn_vaddr = vaddr;
357         dyn_filesz = filesz;
358         break;
359
360       case PT_NOTE:
361         /* We calculate from the p_offset of the note segment,
362            because we don't yet know the bias for its p_vaddr.  */
363         consider_notes (start + offset, filesz);
364         break;
365
366       case PT_LOAD:
367         align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
368
369         GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
370         GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
371         GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
372
373         if (file_trimmed_end < offset + filesz)
374           {
375             file_trimmed_end = offset + filesz;
376
377             /* Trim the last segment so we don't bother with zeros
378                in the last page that are off the end of the file.
379                However, if the extra bit in that page includes the
380                section headers, keep them.  */
381             if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
382               {
383                 filesz += shdrs_end - file_trimmed_end;
384                 file_trimmed_end = shdrs_end;
385               }
386           }
387
388         total_filesz += filesz;
389
390         if (file_end < filesz_offset)
391           {
392             file_end = filesz_offset;
393             if (filesz_vaddr - start == filesz_offset)
394               contiguous = file_end;
395           }
396
397         if (!found_bias && (offset & -align) == 0
398             && likely (filesz_offset >= phoff + phnum * phentsize))
399           {
400             bias = start - vaddr;
401             found_bias = true;
402           }
403
404         if ((vaddr & -align) < module_start)
405           {
406             module_start = vaddr & -align;
407             module_address_sync = vaddr + memsz;
408           }
409
410         if (module_end < vaddr_end)
411           module_end = vaddr_end;
412         break;
413       }
414   }
415   if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
416     {
417       if (elf32_xlatetom (&xlateto, &xlatefrom,
418                           ehdr.e32.e_ident[EI_DATA]) == NULL)
419         found_bias = false;     /* Trigger error check.  */
420       else
421         for (uint_fast16_t i = 0; i < phnum; ++i)
422           consider_phdr (phdrs.p32[i].p_type,
423                          phdrs.p32[i].p_vaddr, phdrs.p32[i].p_memsz,
424                          phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz,
425                          phdrs.p32[i].p_align);
426     }
427   else
428     {
429       if (elf64_xlatetom (&xlateto, &xlatefrom,
430                           ehdr.e32.e_ident[EI_DATA]) == NULL)
431         found_bias = false;     /* Trigger error check.  */
432       else
433         for (uint_fast16_t i = 0; i < phnum; ++i)
434           consider_phdr (phdrs.p64[i].p_type,
435                          phdrs.p64[i].p_vaddr, phdrs.p64[i].p_memsz,
436                          phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz,
437                          phdrs.p64[i].p_align);
438     }
439
440   finish_portion (&ph_buffer, &ph_buffer_size);
441
442   /* We must have seen the segment covering offset 0, or else the ELF
443      header we read at START was not produced by these program headers.  */
444   if (unlikely (!found_bias))
445     return finish ();
446
447   /* Now we know enough to report a module for sure: its bounds.  */
448   module_start += bias;
449   module_end += bias;
450
451   dyn_vaddr += bias;
452
453   /* Our return value now says to skip the segments contained
454      within the module.  */
455   ndx = addr_segndx (dwfl, segment, module_end, true);
456
457   /* Examine its .dynamic section to get more interesting details.
458      If it has DT_SONAME, we'll use that as the module name.
459      If it has a DT_DEBUG, then it's actually a PIE rather than a DSO.
460      We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME,
461      and they also tell us the essential portion of the file
462      for fetching symbols.  */
463   GElf_Addr soname_stroff = 0;
464   GElf_Addr dynstr_vaddr = 0;
465   GElf_Xword dynstrsz = 0;
466   bool execlike = false;
467   inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val)
468   {
469     switch (tag)
470       {
471       default:
472         return false;
473
474       case DT_DEBUG:
475         execlike = true;
476         break;
477
478       case DT_SONAME:
479         soname_stroff = val;
480         break;
481
482       case DT_STRTAB:
483         dynstr_vaddr = val;
484         break;
485
486       case DT_STRSZ:
487         dynstrsz = val;
488         break;
489       }
490
491     return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0;
492   }
493
494   const size_t dyn_entsize = (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32
495                               ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
496   void *dyn_data = NULL;
497   size_t dyn_data_size = 0;
498   if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
499       && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz))
500     {
501       union
502       {
503         Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)];
504         Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)];
505       } dyn;
506
507       xlatefrom.d_type = xlateto.d_type = ELF_T_DYN;
508       xlatefrom.d_buf = (void *) dyn_data;
509       xlatefrom.d_size = dyn_filesz;
510       xlateto.d_buf = &dyn;
511       xlateto.d_size = sizeof dyn;
512
513       if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
514         {
515           if (elf32_xlatetom (&xlateto, &xlatefrom,
516                               ehdr.e32.e_ident[EI_DATA]) != NULL)
517             for (size_t i = 0; i < dyn_filesz / sizeof dyn.d32[0]; ++i)
518               if (consider_dyn (dyn.d32[i].d_tag, dyn.d32[i].d_un.d_val))
519                 break;
520         }
521       else
522         {
523           if (elf64_xlatetom (&xlateto, &xlatefrom,
524                               ehdr.e32.e_ident[EI_DATA]) != NULL)
525             for (size_t i = 0; i < dyn_filesz / sizeof dyn.d64[0]; ++i)
526               if (consider_dyn (dyn.d64[i].d_tag, dyn.d64[i].d_un.d_val))
527                 break;
528         }
529     }
530   finish_portion (&dyn_data, &dyn_data_size);
531
532   /* We'll use the name passed in or a stupid default if not DT_SONAME.  */
533   if (name == NULL)
534     name = ehdr.e32.e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]";
535
536   void *soname = NULL;
537   size_t soname_size = 0;
538   if (dynstrsz != 0 && dynstr_vaddr != 0)
539     {
540       /* We know the bounds of the .dynstr section.
541
542          The DYNSTR_VADDR pointer comes from the .dynamic section
543          (DT_STRTAB, detected above).  Ordinarily the dynamic linker
544          will have adjusted this pointer in place so it's now an
545          absolute address.  But sometimes .dynamic is read-only (in
546          vDSOs and odd architectures), and sometimes the adjustment
547          just hasn't happened yet in the memory image we looked at.
548          So treat DYNSTR_VADDR as an absolute address if it falls
549          within the module bounds, or try applying the phdr bias
550          when that adjusts it to fall within the module bounds.  */
551
552       if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end)
553           && dynstr_vaddr + bias >= module_start
554           && dynstr_vaddr + bias < module_end)
555         dynstr_vaddr += bias;
556
557       if (unlikely (dynstr_vaddr + dynstrsz > module_end))
558         dynstrsz = 0;
559
560       /* Try to get the DT_SONAME string.  */
561       if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz
562           && ! read_portion (&soname, &soname_size,
563                              dynstr_vaddr + soname_stroff, 0))
564         name = soname;
565     }
566
567   /* Now that we have chosen the module's name and bounds, report it.
568      If we found a build ID, report that too.  */
569
570   Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name,
571                                                  module_start, module_end);
572   if (likely (mod != NULL) && build_id != NULL
573       && unlikely (INTUSE(dwfl_module_report_build_id) (mod,
574                                                         build_id,
575                                                         build_id_len,
576                                                         build_id_vaddr)))
577     {
578       mod->gc = true;
579       mod = NULL;
580     }
581
582   /* At this point we do not need BUILD_ID or NAME any more.
583      They have been copied.  */
584   free (build_id);
585   finish_portion (&soname, &soname_size);
586
587   if (unlikely (mod == NULL))
588     {
589       ndx = -1;
590       return finish ();
591     }
592
593   /* We have reported the module.  Now let the caller decide whether we
594      should read the whole thing in right now.  */
595
596   const GElf_Off cost = (contiguous < file_trimmed_end ? total_filesz
597                          : buffer_available >= contiguous ? 0
598                          : contiguous - buffer_available);
599   const GElf_Off worthwhile = ((dynstr_vaddr == 0 || dynstrsz == 0) ? 0
600                                : dynstr_vaddr + dynstrsz - start);
601   const GElf_Off whole = MAX (file_trimmed_end, shdrs_end);
602
603   Elf *elf = NULL;
604   if ((*read_eagerly) (MODCB_ARGS (mod), &buffer, &buffer_available,
605                        cost, worthwhile, whole, contiguous,
606                        read_eagerly_arg, &elf)
607       && elf == NULL)
608     {
609       /* The caller wants to read the whole file in right now, but hasn't
610          done it for us.  Fill in a local image of the virtual file.  */
611
612       void *contents = calloc (1, file_trimmed_end);
613       if (unlikely (contents == NULL))
614         return finish ();
615
616       inline void final_read (size_t offset, GElf_Addr vaddr, size_t size)
617       {
618         void *into = contents + offset;
619         size_t read_size = size;
620         (void) segment_read (addr_segndx (dwfl, segment, vaddr, false),
621                              &into, &read_size, vaddr, size);
622       }
623
624       if (contiguous < file_trimmed_end)
625         {
626           /* We can't use the memory image verbatim as the file image.
627              So we'll be reading into a local image of the virtual file.  */
628
629           inline void read_phdr (GElf_Word type, GElf_Addr vaddr,
630                                  GElf_Off offset, GElf_Xword filesz)
631           {
632             if (type == PT_LOAD)
633               final_read (offset, vaddr + bias, filesz);
634           }
635
636           if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
637             for (uint_fast16_t i = 0; i < phnum; ++i)
638               read_phdr (phdrs.p32[i].p_type, phdrs.p32[i].p_vaddr,
639                          phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz);
640           else
641             for (uint_fast16_t i = 0; i < phnum; ++i)
642               read_phdr (phdrs.p64[i].p_type, phdrs.p64[i].p_vaddr,
643                          phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz);
644         }
645       else
646         {
647           /* The whole file sits contiguous in memory,
648              but the caller didn't want to just do it.  */
649
650           const size_t have = MIN (buffer_available, file_trimmed_end);
651           memcpy (contents, buffer, have);
652
653           if (have < file_trimmed_end)
654             final_read (have, start + have, file_trimmed_end - have);
655         }
656
657       elf = elf_memory (contents, file_trimmed_end);
658       if (unlikely (elf == NULL))
659         free (contents);
660       else
661         elf->flags |= ELF_F_MALLOCED;
662     }
663
664   if (elf != NULL)
665     {
666       /* Install the file in the module.  */
667       mod->main.elf = elf;
668       mod->main.vaddr = module_start - bias;
669       mod->main.address_sync = module_address_sync;
670     }
671
672   return finish ();
673 }