Blame libdwfl/elf-from-memory.c

Packit Service 97d2fb
/* Reconstruct an ELF file by reading the segments out of remote memory.
Packit Service 97d2fb
   Copyright (C) 2005-2011, 2014, 2015 Red Hat, Inc.
Packit Service 97d2fb
   This file is part of elfutils.
Packit Service 97d2fb
Packit Service 97d2fb
   This file is free software; you can redistribute it and/or modify
Packit Service 97d2fb
   it under the terms of either
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU Lesser General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 3 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 2 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or both in parallel, as here.
Packit Service 97d2fb
Packit Service 97d2fb
   elfutils is distributed in the hope that it will be useful, but
Packit Service 97d2fb
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 97d2fb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 97d2fb
   General Public License for more details.
Packit Service 97d2fb
Packit Service 97d2fb
   You should have received copies of the GNU General Public License and
Packit Service 97d2fb
   the GNU Lesser General Public License along with this program.  If
Packit Service 97d2fb
   not, see <http://www.gnu.org/licenses/>.  */
Packit Service 97d2fb
Packit Service 97d2fb
#include <config.h>
Packit Service 97d2fb
#include "../libelf/libelfP.h"
Packit Service 97d2fb
#undef _
Packit Service 97d2fb
Packit Service 97d2fb
#include "libdwflP.h"
Packit Service 97d2fb
Packit Service 97d2fb
#include <gelf.h>
Packit Service 97d2fb
#include <sys/types.h>
Packit Service 97d2fb
#include <stdbool.h>
Packit Service 97d2fb
#include <stdlib.h>
Packit Service 97d2fb
#include <string.h>
Packit Service 97d2fb
Packit Service 97d2fb
/* Reconstruct an ELF file by reading the segments out of remote memory
Packit Service 97d2fb
   based on the ELF file header at EHDR_VMA and the ELF program headers it
Packit Service 97d2fb
   points to.  If not null, *LOADBASEP is filled in with the difference
Packit Service 97d2fb
   between the addresses from which the segments were read, and the
Packit Service 97d2fb
   addresses the file headers put them at.
Packit Service 97d2fb
Packit Service 97d2fb
   The function READ_MEMORY is called to copy at least MINREAD and at most
Packit Service 97d2fb
   MAXREAD bytes from the remote memory at target address ADDRESS into the
Packit Service 97d2fb
   local buffer at DATA; it should return -1 for errors (with code in
Packit Service 97d2fb
   `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or
Packit Service 97d2fb
   the number of bytes read if >= MINREAD.  ARG is passed through.
Packit Service 97d2fb
Packit Service 97d2fb
   PAGESIZE is the minimum page size and alignment used for the PT_LOAD
Packit Service 97d2fb
   segments.  */
Packit Service 97d2fb
Packit Service 97d2fb
Elf *
Packit Service 97d2fb
elf_from_remote_memory (GElf_Addr ehdr_vma,
Packit Service 97d2fb
			GElf_Xword pagesize,
Packit Service 97d2fb
			GElf_Addr *loadbasep,
Packit Service 97d2fb
			ssize_t (*read_memory) (void *arg, void *data,
Packit Service 97d2fb
						GElf_Addr address,
Packit Service 97d2fb
						size_t minread,
Packit Service 97d2fb
						size_t maxread),
Packit Service 97d2fb
			void *arg)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* We might have to reserve some memory for the phdrs.  Set to NULL
Packit Service 97d2fb
     here so we can always safely free it.  */
Packit Service 97d2fb
  void *phdrsp = NULL;
Packit Service 97d2fb
Packit Service 97d2fb
  /* First read in the file header and check its sanity.  */
Packit Service 97d2fb
Packit Service 97d2fb
  const size_t initial_bufsize = 256;
Packit Service 97d2fb
  unsigned char *buffer = malloc (initial_bufsize);
Packit Service 97d2fb
  if (unlikely (buffer == NULL))
Packit Service 97d2fb
    {
Packit Service 97d2fb
    no_memory:
Packit Service 97d2fb
      __libdwfl_seterrno (DWFL_E_NOMEM);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
Packit Service 97d2fb
				  sizeof (Elf32_Ehdr), initial_bufsize);
Packit Service 97d2fb
  if (nread <= 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
    read_error:
Packit Service 97d2fb
      free (buffer);
Packit Service 97d2fb
      free (phdrsp);
Packit Service 97d2fb
      __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
    bad_elf:
Packit Service 97d2fb
      free (buffer);
Packit Service 97d2fb
      free (phdrsp);
Packit Service 97d2fb
      __libdwfl_seterrno (DWFL_E_BADELF);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* Extract the information we need from the file header.  */
Packit Service 97d2fb
Packit Service 97d2fb
  union
Packit Service 97d2fb
  {
Packit Service 97d2fb
    Elf32_Ehdr e32;
Packit Service 97d2fb
    Elf64_Ehdr e64;
Packit Service 97d2fb
  } ehdr;
Packit Service 97d2fb
  Elf_Data xlatefrom =
Packit Service 97d2fb
    {
Packit Service 97d2fb
      .d_type = ELF_T_EHDR,
Packit Service 97d2fb
      .d_buf = buffer,
Packit Service 97d2fb
      .d_version = EV_CURRENT,
Packit Service 97d2fb
    };
Packit Service 97d2fb
  Elf_Data xlateto =
Packit Service 97d2fb
    {
Packit Service 97d2fb
      .d_type = ELF_T_EHDR,
Packit Service 97d2fb
      .d_buf = &ehdr,
Packit Service 97d2fb
      .d_size = sizeof ehdr,
Packit Service 97d2fb
      .d_version = EV_CURRENT,
Packit Service 97d2fb
    };
Packit Service 97d2fb
Packit Service 97d2fb
  GElf_Off phoff;
Packit Service 97d2fb
  uint_fast16_t phnum;
Packit Service 97d2fb
  uint_fast16_t phentsize;
Packit Service 97d2fb
  GElf_Off shdrs_end;
Packit Service 97d2fb
Packit Service 97d2fb
  switch (buffer[EI_CLASS])
Packit Service 97d2fb
    {
Packit Service 97d2fb
    case ELFCLASS32:
Packit Service 97d2fb
      xlatefrom.d_size = sizeof (Elf32_Ehdr);
Packit Service 97d2fb
      if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	libelf_error:
Packit Service 97d2fb
	  __libdwfl_seterrno (DWFL_E_LIBELF);
Packit Service 97d2fb
	  return NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      phoff = ehdr.e32.e_phoff;
Packit Service 97d2fb
      phnum = ehdr.e32.e_phnum;
Packit Service 97d2fb
      phentsize = ehdr.e32.e_phentsize;
Packit Service 97d2fb
      if (phentsize != sizeof (Elf32_Phdr) || phnum == 0)
Packit Service 97d2fb
	goto bad_elf;
Packit Service 97d2fb
      /* NOTE if the number of sections is > 0xff00 then e_shnum
Packit Service 97d2fb
	 is zero and the actual number would come from the section
Packit Service 97d2fb
	 zero sh_size field. We ignore this here because getting shdrs
Packit Service 97d2fb
	 is just a nice bonus (see below where we trim the last phdrs
Packit Service 97d2fb
	 PT_LOAD segment).  */
Packit Service 97d2fb
      shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case ELFCLASS64:
Packit Service 97d2fb
      xlatefrom.d_size = sizeof (Elf64_Ehdr);
Packit Service 97d2fb
      if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
Packit Service 97d2fb
	goto libelf_error;
Packit Service 97d2fb
      phoff = ehdr.e64.e_phoff;
Packit Service 97d2fb
      phnum = ehdr.e64.e_phnum;
Packit Service 97d2fb
      phentsize = ehdr.e64.e_phentsize;
Packit Service 97d2fb
      if (phentsize != sizeof (Elf64_Phdr) || phnum == 0)
Packit Service 97d2fb
	goto bad_elf;
Packit Service 97d2fb
      /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum.  */
Packit Service 97d2fb
      shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    default:
Packit Service 97d2fb
      goto bad_elf;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
  /* The file header tells where to find the program headers.
Packit Service 97d2fb
     These are what we use to actually choose what to read.  */
Packit Service 97d2fb
Packit Service 97d2fb
  xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
Packit Service 97d2fb
  xlatefrom.d_size = phnum * phentsize;
Packit Service 97d2fb
Packit Service 97d2fb
  if ((size_t) nread >= phoff + phnum * phentsize)
Packit Service 97d2fb
    /* We already have all the phdrs from the initial read.  */
Packit Service 97d2fb
    xlatefrom.d_buf = buffer + phoff;
Packit Service 97d2fb
  else
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* Read in the program headers.  */
Packit Service 97d2fb
Packit Service 97d2fb
      if (initial_bufsize < (size_t)phnum * phentsize)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  unsigned char *newbuf = realloc (buffer, phnum * phentsize);
Packit Service 97d2fb
	  if (newbuf == NULL)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      free (buffer);
Packit Service 97d2fb
	      free (phdrsp);
Packit Service 97d2fb
	      goto no_memory;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	  buffer = newbuf;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
Packit Service 97d2fb
			      phnum * phentsize, phnum * phentsize);
Packit Service 97d2fb
      if (nread <= 0)
Packit Service 97d2fb
	goto read_error;
Packit Service 97d2fb
Packit Service 97d2fb
      xlatefrom.d_buf = buffer;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
Packit Service 97d2fb
  size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
Packit Service 97d2fb
  if (unlikely (phnum > SIZE_MAX / phdr_size))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      free (buffer);
Packit Service 97d2fb
      goto no_memory;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  const size_t phdrsp_bytes = phnum * phdr_size;
Packit Service 97d2fb
  phdrsp = malloc (phdrsp_bytes);
Packit Service 97d2fb
  if (unlikely (phdrsp == NULL))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      free (buffer);
Packit Service 97d2fb
      goto no_memory;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  xlateto.d_buf = phdrsp;
Packit Service 97d2fb
  xlateto.d_size = phdrsp_bytes;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Scan for PT_LOAD segments to find the total size of the file image.  */
Packit Service 97d2fb
  size_t contents_size = 0;
Packit Service 97d2fb
  GElf_Off segments_end = 0;
Packit Service 97d2fb
  GElf_Off segments_end_mem = 0;
Packit Service 97d2fb
  GElf_Addr loadbase = ehdr_vma;
Packit Service 97d2fb
  bool found_base = false;
Packit Service 97d2fb
  Elf32_Phdr (*p32)[phnum] = phdrsp;
Packit Service 97d2fb
  Elf64_Phdr (*p64)[phnum] = phdrsp;
Packit Service 97d2fb
  switch (ehdr.e32.e_ident[EI_CLASS])
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* Sanity checks segments and calculates segment_end,
Packit Service 97d2fb
	 segments_end, segments_end_mem and loadbase (if not
Packit Service 97d2fb
	 found_base yet).  Returns true if sanity checking failed,
Packit Service 97d2fb
	 false otherwise.  */
Packit Service 97d2fb
      inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
Packit Service 97d2fb
				  GElf_Xword filesz, GElf_Xword memsz)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  /* Sanity check the segment load aligns with the pagesize.  */
Packit Service 97d2fb
	  if (((vaddr - offset) & (pagesize - 1)) != 0)
Packit Service 97d2fb
	    return true;
Packit Service 97d2fb
Packit Service 97d2fb
	  GElf_Off segment_end = ((offset + filesz + pagesize - 1)
Packit Service 97d2fb
				  & -pagesize);
Packit Service 97d2fb
Packit Service 97d2fb
	  if (segment_end > (GElf_Off) contents_size)
Packit Service 97d2fb
	    contents_size = segment_end;
Packit Service 97d2fb
Packit Service 97d2fb
	  if (!found_base && (offset & -pagesize) == 0)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      loadbase = ehdr_vma - (vaddr & -pagesize);
Packit Service 97d2fb
	      found_base = true;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
Packit Service 97d2fb
	  segments_end = offset + filesz;
Packit Service 97d2fb
	  segments_end_mem = offset + memsz;
Packit Service 97d2fb
	  return false;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
    case ELFCLASS32:
Packit Service 97d2fb
      if (elf32_xlatetom (&xlateto, &xlatefrom,
Packit Service 97d2fb
			  ehdr.e32.e_ident[EI_DATA]) == NULL)
Packit Service 97d2fb
	goto libelf_error;
Packit Service 97d2fb
      for (uint_fast16_t i = 0; i < phnum; ++i)
Packit Service 97d2fb
	if ((*p32)[i].p_type == PT_LOAD)
Packit Service 97d2fb
	  if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
Packit Service 97d2fb
			      (*p32)[i].p_filesz, (*p32)[i].p_memsz))
Packit Service 97d2fb
	    goto bad_elf;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case ELFCLASS64:
Packit Service 97d2fb
      if (elf64_xlatetom (&xlateto, &xlatefrom,
Packit Service 97d2fb
			  ehdr.e64.e_ident[EI_DATA]) == NULL)
Packit Service 97d2fb
	goto libelf_error;
Packit Service 97d2fb
      for (uint_fast16_t i = 0; i < phnum; ++i)
Packit Service 97d2fb
	if ((*p64)[i].p_type == PT_LOAD)
Packit Service 97d2fb
	  if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
Packit Service 97d2fb
			      (*p64)[i].p_filesz, (*p64)[i].p_memsz))
Packit Service 97d2fb
	    goto bad_elf;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    default:
Packit Service 97d2fb
      abort ();
Packit Service 97d2fb
      break;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* Trim the last segment so we don't bother with zeros in the last page
Packit Service 97d2fb
     that are off the end of the file.  However, if the extra bit in that
Packit Service 97d2fb
     page includes the section headers and the memory isn't extended (which
Packit Service 97d2fb
     might indicate it will have been reused otherwise), keep them.  */
Packit Service 97d2fb
  if ((GElf_Off) contents_size > segments_end
Packit Service 97d2fb
      && (GElf_Off) contents_size >= shdrs_end
Packit Service 97d2fb
      && segments_end == segments_end_mem)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      contents_size = segments_end;
Packit Service 97d2fb
      if ((GElf_Off) contents_size < shdrs_end)
Packit Service 97d2fb
	contents_size = shdrs_end;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else
Packit Service 97d2fb
    contents_size = segments_end;
Packit Service 97d2fb
Packit Service 97d2fb
  free (buffer);
Packit Service 97d2fb
Packit Service 97d2fb
  /* Now we know the size of the whole image we want read in.  */
Packit Service 97d2fb
  buffer = calloc (1, contents_size);
Packit Service 97d2fb
  if (buffer == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      free (phdrsp);
Packit Service 97d2fb
      goto no_memory;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  switch (ehdr.e32.e_ident[EI_CLASS])
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* Reads the given segment.  Returns true if reading fails,
Packit Service 97d2fb
	 false otherwise.  */
Packit Service 97d2fb
      inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
Packit Service 97d2fb
				  GElf_Xword filesz)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  GElf_Off start = offset & -pagesize;
Packit Service 97d2fb
	  GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
Packit Service 97d2fb
	  if (end > (GElf_Off) contents_size)
Packit Service 97d2fb
	    end = contents_size;
Packit Service 97d2fb
	  nread = (*read_memory) (arg, buffer + start,
Packit Service 97d2fb
				  (loadbase + vaddr) & -pagesize,
Packit Service 97d2fb
				  end - start, end - start);
Packit Service 97d2fb
	  return nread <= 0;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
    case ELFCLASS32:
Packit Service 97d2fb
      for (uint_fast16_t i = 0; i < phnum; ++i)
Packit Service 97d2fb
	if ((*p32)[i].p_type == PT_LOAD)
Packit Service 97d2fb
	  if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
Packit Service 97d2fb
			      (*p32)[i].p_filesz))
Packit Service 97d2fb
	    goto read_error;
Packit Service 97d2fb
Packit Service 97d2fb
      /* If the segments visible in memory didn't include the section
Packit Service 97d2fb
	 headers, then clear them from the file header.  */
Packit Service 97d2fb
      if (contents_size < shdrs_end)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  ehdr.e32.e_shoff = 0;
Packit Service 97d2fb
	  ehdr.e32.e_shnum = 0;
Packit Service 97d2fb
	  ehdr.e32.e_shstrndx = 0;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      /* This will normally have been in the first PT_LOAD segment.  But it
Packit Service 97d2fb
	 conceivably could be missing, and we might have just changed it.  */
Packit Service 97d2fb
      xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
Packit Service 97d2fb
      xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
Packit Service 97d2fb
      xlatefrom.d_buf = &ehdr.e32;
Packit Service 97d2fb
      xlateto.d_buf = buffer;
Packit Service 97d2fb
      if (elf32_xlatetof (&xlateto, &xlatefrom,
Packit Service 97d2fb
			  ehdr.e32.e_ident[EI_DATA]) == NULL)
Packit Service 97d2fb
	goto libelf_error;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    case ELFCLASS64:
Packit Service 97d2fb
      for (uint_fast16_t i = 0; i < phnum; ++i)
Packit Service 97d2fb
	if ((*p64)[i].p_type == PT_LOAD)
Packit Service 97d2fb
	  if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
Packit Service 97d2fb
			      (*p64)[i].p_filesz))
Packit Service 97d2fb
	    goto read_error;
Packit Service 97d2fb
Packit Service 97d2fb
      /* If the segments visible in memory didn't include the section
Packit Service 97d2fb
	 headers, then clear them from the file header.  */
Packit Service 97d2fb
      if (contents_size < shdrs_end)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  ehdr.e64.e_shoff = 0;
Packit Service 97d2fb
	  ehdr.e64.e_shnum = 0;
Packit Service 97d2fb
	  ehdr.e64.e_shstrndx = 0;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      /* This will normally have been in the first PT_LOAD segment.  But it
Packit Service 97d2fb
	 conceivably could be missing, and we might have just changed it.  */
Packit Service 97d2fb
      xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
Packit Service 97d2fb
      xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
Packit Service 97d2fb
      xlatefrom.d_buf = &ehdr.e64;
Packit Service 97d2fb
      xlateto.d_buf = buffer;
Packit Service 97d2fb
      if (elf64_xlatetof (&xlateto, &xlatefrom,
Packit Service 97d2fb
			  ehdr.e64.e_ident[EI_DATA]) == NULL)
Packit Service 97d2fb
	goto libelf_error;
Packit Service 97d2fb
      break;
Packit Service 97d2fb
Packit Service 97d2fb
    default:
Packit Service 97d2fb
      abort ();
Packit Service 97d2fb
      break;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  free (phdrsp);
Packit Service 97d2fb
  phdrsp = NULL;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Now we have the image.  Open libelf on it.  */
Packit Service 97d2fb
Packit Service 97d2fb
  Elf *elf = elf_memory ((char *) buffer, contents_size);
Packit Service 97d2fb
  if (elf == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      free (buffer);
Packit Service 97d2fb
      goto libelf_error;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  elf->flags |= ELF_F_MALLOCED;
Packit Service 97d2fb
  if (loadbasep != NULL)
Packit Service 97d2fb
    *loadbasep = loadbase;
Packit Service 97d2fb
  return elf;
Packit Service 97d2fb
}