dwfl_segment_report_module.c revision b4bb301f76828bcbd84e467b736fedf44fe50317
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 274 /* If we see PT_DYNAMIC, record it here. */ 275 GElf_Addr dyn_vaddr = 0; 276 GElf_Xword dyn_filesz = 0; 277 278 /* Collect the build ID bits here. */ 279 void *build_id = NULL; 280 size_t build_id_len = 0; 281 GElf_Addr build_id_vaddr = 0; 282 283 /* Consider a PT_NOTE we've found in the image. */ 284 inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz) 285 { 286 /* If we have already seen a build ID, we don't care any more. */ 287 if (build_id != NULL || filesz == 0) 288 return; 289 290 void *data; 291 size_t data_size; 292 if (read_portion (&data, &data_size, vaddr, filesz)) 293 return; 294 295 assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr)); 296 297 void *notes; 298 if (ehdr.e32.e_ident[EI_DATA] == MY_ELFDATA) 299 notes = data; 300 else 301 { 302 notes = malloc (filesz); 303 if (unlikely (notes == NULL)) 304 return; 305 xlatefrom.d_type = xlateto.d_type = ELF_T_NHDR; 306 xlatefrom.d_buf = (void *) data; 307 xlatefrom.d_size = filesz; 308 xlateto.d_buf = notes; 309 xlateto.d_size = filesz; 310 if (elf32_xlatetom (&xlateto, &xlatefrom, 311 ehdr.e32.e_ident[EI_DATA]) == NULL) 312 goto done; 313 } 314 315 const GElf_Nhdr *nh = notes; 316 while ((const void *) nh < (const void *) notes + filesz) 317 { 318 const void *note_name = nh + 1; 319 const void *note_desc = note_name + NOTE_ALIGN (nh->n_namesz); 320 if (unlikely ((size_t) ((const void *) notes + filesz 321 - note_desc) < nh->n_descsz)) 322 break; 323 324 if (nh->n_type == NT_GNU_BUILD_ID 325 && nh->n_descsz > 0 326 && nh->n_namesz == sizeof "GNU" 327 && !memcmp (note_name, "GNU", sizeof "GNU")) 328 { 329 build_id_vaddr = note_desc - (const void *) notes + vaddr; 330 build_id_len = nh->n_descsz; 331 build_id = malloc (nh->n_descsz); 332 if (likely (build_id != NULL)) 333 memcpy (build_id, note_desc, build_id_len); 334 break; 335 } 336 337 nh = note_desc + NOTE_ALIGN (nh->n_descsz); 338 } 339 340 done: 341 if (notes != data) 342 free (notes); 343 finish_portion (&data, &data_size); 344 } 345 346 /* Consider each of the program headers we've read from the image. */ 347 inline void consider_phdr (GElf_Word type, 348 GElf_Addr vaddr, GElf_Xword memsz, 349 GElf_Off offset, GElf_Xword filesz, 350 GElf_Xword align) 351 { 352 switch (type) 353 { 354 case PT_DYNAMIC: 355 dyn_vaddr = vaddr; 356 dyn_filesz = filesz; 357 break; 358 359 case PT_NOTE: 360 /* We calculate from the p_offset of the note segment, 361 because we don't yet know the bias for its p_vaddr. */ 362 consider_notes (start + offset, filesz); 363 break; 364 365 case PT_LOAD: 366 align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1; 367 368 GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align; 369 GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end; 370 GElf_Off filesz_offset = filesz_vaddr - vaddr + offset; 371 372 if (file_trimmed_end < offset + filesz) 373 { 374 file_trimmed_end = offset + filesz; 375 376 /* Trim the last segment so we don't bother with zeros 377 in the last page that are off the end of the file. 378 However, if the extra bit in that page includes the 379 section headers, keep them. */ 380 if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end) 381 { 382 filesz += shdrs_end - file_trimmed_end; 383 file_trimmed_end = shdrs_end; 384 } 385 } 386 387 total_filesz += filesz; 388 389 if (file_end < filesz_offset) 390 { 391 file_end = filesz_offset; 392 if (filesz_vaddr - start == filesz_offset) 393 contiguous = file_end; 394 } 395 396 if (!found_bias && (offset & -align) == 0 397 && likely (filesz_offset >= phoff + phnum * phentsize)) 398 { 399 bias = start - vaddr; 400 found_bias = true; 401 } 402 403 vaddr &= -align; 404 if (vaddr < module_start) 405 module_start = vaddr; 406 407 if (module_end < vaddr_end) 408 module_end = vaddr_end; 409 break; 410 } 411 } 412 if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) 413 { 414 if (elf32_xlatetom (&xlateto, &xlatefrom, 415 ehdr.e32.e_ident[EI_DATA]) == NULL) 416 found_bias = false; /* Trigger error check. */ 417 else 418 for (uint_fast16_t i = 0; i < phnum; ++i) 419 consider_phdr (phdrs.p32[i].p_type, 420 phdrs.p32[i].p_vaddr, phdrs.p32[i].p_memsz, 421 phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz, 422 phdrs.p32[i].p_align); 423 } 424 else 425 { 426 if (elf64_xlatetom (&xlateto, &xlatefrom, 427 ehdr.e32.e_ident[EI_DATA]) == NULL) 428 found_bias = false; /* Trigger error check. */ 429 else 430 for (uint_fast16_t i = 0; i < phnum; ++i) 431 consider_phdr (phdrs.p64[i].p_type, 432 phdrs.p64[i].p_vaddr, phdrs.p64[i].p_memsz, 433 phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz, 434 phdrs.p64[i].p_align); 435 } 436 437 finish_portion (&ph_buffer, &ph_buffer_size); 438 439 /* We must have seen the segment covering offset 0, or else the ELF 440 header we read at START was not produced by these program headers. */ 441 if (unlikely (!found_bias)) 442 return finish (); 443 444 /* Now we know enough to report a module for sure: its bounds. */ 445 module_start += bias; 446 module_end += bias; 447 448 dyn_vaddr += bias; 449 450 /* Our return value now says to skip the segments contained 451 within the module. */ 452 ndx = addr_segndx (dwfl, segment, module_end, true); 453 454 /* Examine its .dynamic section to get more interesting details. 455 If it has DT_SONAME, we'll use that as the module name. 456 If it has a DT_DEBUG, then it's actually a PIE rather than a DSO. 457 We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME, 458 and they also tell us the essential portion of the file 459 for fetching symbols. */ 460 GElf_Addr soname_stroff = 0; 461 GElf_Addr dynstr_vaddr = 0; 462 GElf_Xword dynstrsz = 0; 463 bool execlike = false; 464 inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val) 465 { 466 switch (tag) 467 { 468 default: 469 return false; 470 471 case DT_DEBUG: 472 execlike = true; 473 break; 474 475 case DT_SONAME: 476 soname_stroff = val; 477 break; 478 479 case DT_STRTAB: 480 dynstr_vaddr = val; 481 break; 482 483 case DT_STRSZ: 484 dynstrsz = val; 485 break; 486 } 487 488 return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0; 489 } 490 491 const size_t dyn_entsize = (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32 492 ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn)); 493 void *dyn_data = NULL; 494 size_t dyn_data_size = 0; 495 if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0 496 && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz)) 497 { 498 union 499 { 500 Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)]; 501 Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)]; 502 } dyn; 503 504 xlatefrom.d_type = xlateto.d_type = ELF_T_DYN; 505 xlatefrom.d_buf = (void *) dyn_data; 506 xlatefrom.d_size = dyn_filesz; 507 xlateto.d_buf = &dyn; 508 xlateto.d_size = sizeof dyn; 509 510 if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) 511 { 512 if (elf32_xlatetom (&xlateto, &xlatefrom, 513 ehdr.e32.e_ident[EI_DATA]) != NULL) 514 for (size_t i = 0; i < dyn_filesz / sizeof dyn.d32[0]; ++i) 515 if (consider_dyn (dyn.d32[i].d_tag, dyn.d32[i].d_un.d_val)) 516 break; 517 } 518 else 519 { 520 if (elf64_xlatetom (&xlateto, &xlatefrom, 521 ehdr.e32.e_ident[EI_DATA]) != NULL) 522 for (size_t i = 0; i < dyn_filesz / sizeof dyn.d64[0]; ++i) 523 if (consider_dyn (dyn.d64[i].d_tag, dyn.d64[i].d_un.d_val)) 524 break; 525 } 526 } 527 finish_portion (&dyn_data, &dyn_data_size); 528 529 /* We'll use the name passed in or a stupid default if not DT_SONAME. */ 530 if (name == NULL) 531 name = ehdr.e32.e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]"; 532 533 void *soname = NULL; 534 size_t soname_size = 0; 535 if (dynstrsz != 0 && dynstr_vaddr != 0) 536 { 537 /* We know the bounds of the .dynstr section. 538 539 The DYNSTR_VADDR pointer comes from the .dynamic section 540 (DT_STRTAB, detected above). Ordinarily the dynamic linker 541 will have adjusted this pointer in place so it's now an 542 absolute address. But sometimes .dynamic is read-only (in 543 vDSOs and odd architectures), and sometimes the adjustment 544 just hasn't happened yet in the memory image we looked at. 545 So treat DYNSTR_VADDR as an absolute address if it falls 546 within the module bounds, or try applying the phdr bias 547 when that adjusts it to fall within the module bounds. */ 548 549 if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end) 550 && dynstr_vaddr + bias >= module_start 551 && dynstr_vaddr + bias < module_end) 552 dynstr_vaddr += bias; 553 554 if (unlikely (dynstr_vaddr + dynstrsz > module_end)) 555 dynstrsz = 0; 556 557 /* Try to get the DT_SONAME string. */ 558 if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz 559 && ! read_portion (&soname, &soname_size, 560 dynstr_vaddr + soname_stroff, 0)) 561 name = soname; 562 } 563 564 /* Now that we have chosen the module's name and bounds, report it. 565 If we found a build ID, report that too. */ 566 567 Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name, 568 module_start, module_end); 569 if (likely (mod != NULL) && build_id != NULL 570 && unlikely (INTUSE(dwfl_module_report_build_id) (mod, 571 build_id, 572 build_id_len, 573 build_id_vaddr))) 574 { 575 mod->gc = true; 576 mod = NULL; 577 } 578 579 /* At this point we do not need BUILD_ID or NAME any more. 580 They have been copied. */ 581 free (build_id); 582 finish_portion (&soname, &soname_size); 583 584 if (unlikely (mod == NULL)) 585 { 586 ndx = -1; 587 return finish (); 588 } 589 590 /* We have reported the module. Now let the caller decide whether we 591 should read the whole thing in right now. */ 592 593 const GElf_Off cost = (contiguous < file_trimmed_end ? total_filesz 594 : buffer_available >= contiguous ? 0 595 : contiguous - buffer_available); 596 const GElf_Off worthwhile = ((dynstr_vaddr == 0 || dynstrsz == 0) ? 0 597 : dynstr_vaddr + dynstrsz - start); 598 const GElf_Off whole = MAX (file_trimmed_end, shdrs_end); 599 600 Elf *elf = NULL; 601 if ((*read_eagerly) (MODCB_ARGS (mod), &buffer, &buffer_available, 602 cost, worthwhile, whole, contiguous, 603 read_eagerly_arg, &elf) 604 && elf == NULL) 605 { 606 /* The caller wants to read the whole file in right now, but hasn't 607 done it for us. Fill in a local image of the virtual file. */ 608 609 void *contents = calloc (1, file_trimmed_end); 610 if (unlikely (contents == NULL)) 611 return finish (); 612 613 inline void final_read (size_t offset, GElf_Addr vaddr, size_t size) 614 { 615 void *into = contents + offset; 616 size_t read_size = size; 617 (void) segment_read (addr_segndx (dwfl, segment, vaddr, false), 618 &into, &read_size, vaddr, size); 619 } 620 621 if (contiguous < file_trimmed_end) 622 { 623 /* We can't use the memory image verbatim as the file image. 624 So we'll be reading into a local image of the virtual file. */ 625 626 inline void read_phdr (GElf_Word type, GElf_Addr vaddr, 627 GElf_Off offset, GElf_Xword filesz) 628 { 629 if (type == PT_LOAD) 630 final_read (offset, vaddr + bias, filesz); 631 } 632 633 if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) 634 for (uint_fast16_t i = 0; i < phnum; ++i) 635 read_phdr (phdrs.p32[i].p_type, phdrs.p32[i].p_vaddr, 636 phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz); 637 else 638 for (uint_fast16_t i = 0; i < phnum; ++i) 639 read_phdr (phdrs.p64[i].p_type, phdrs.p64[i].p_vaddr, 640 phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz); 641 } 642 else 643 { 644 /* The whole file sits contiguous in memory, 645 but the caller didn't want to just do it. */ 646 647 const size_t have = MIN (buffer_available, file_trimmed_end); 648 memcpy (contents, buffer, have); 649 650 if (have < file_trimmed_end) 651 final_read (have, start + have, file_trimmed_end - have); 652 } 653 654 elf = elf_memory (contents, file_trimmed_end); 655 if (unlikely (elf == NULL)) 656 free (contents); 657 else 658 elf->flags |= ELF_F_MALLOCED; 659 } 660 661 if (elf != NULL) 662 { 663 /* Install the file in the module. */ 664 mod->main.elf = elf; 665 mod->main.bias = bias; 666 } 667 668 return finish (); 669} 670