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
addr_segndx(Dwfl * dwfl,size_t segment,GElf_Addr addr,bool next)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
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)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 }
674