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.  */
78static int
79addr_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
102int
103dwfl_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}
674