Home | History | Annotate | Download | only in libdwfl
      1 /* Reconstruct an ELF file by reading the segments out of remote memory.
      2    Copyright (C) 2005-2011, 2014, 2015 Red Hat, Inc.
      3    This file is part of elfutils.
      4 
      5    This file is free software; you can redistribute it and/or modify
      6    it under the terms of either
      7 
      8      * the GNU Lesser General Public License as published by the Free
      9        Software Foundation; either version 3 of the License, or (at
     10        your option) any later version
     11 
     12    or
     13 
     14      * the GNU General Public License as published by the Free
     15        Software Foundation; either version 2 of the License, or (at
     16        your option) any later version
     17 
     18    or both in parallel, as here.
     19 
     20    elfutils is distributed in the hope that it will be useful, but
     21    WITHOUT ANY WARRANTY; without even the implied warranty of
     22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     23    General Public License for more details.
     24 
     25    You should have received copies of the GNU General Public License and
     26    the GNU Lesser General Public License along with this program.  If
     27    not, see <http://www.gnu.org/licenses/>.  */
     28 
     29 #include <config.h>
     30 #include "../libelf/libelfP.h"
     31 #undef _
     32 
     33 #include "libdwflP.h"
     34 
     35 #include <gelf.h>
     36 #include <sys/types.h>
     37 #include <stdbool.h>
     38 #include <stdlib.h>
     39 #include <string.h>
     40 
     41 /* Reconstruct an ELF file by reading the segments out of remote memory
     42    based on the ELF file header at EHDR_VMA and the ELF program headers it
     43    points to.  If not null, *LOADBASEP is filled in with the difference
     44    between the addresses from which the segments were read, and the
     45    addresses the file headers put them at.
     46 
     47    The function READ_MEMORY is called to copy at least MINREAD and at most
     48    MAXREAD bytes from the remote memory at target address ADDRESS into the
     49    local buffer at DATA; it should return -1 for errors (with code in
     50    `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or
     51    the number of bytes read if >= MINREAD.  ARG is passed through.
     52 
     53    PAGESIZE is the minimum page size and alignment used for the PT_LOAD
     54    segments.  */
     55 
     56 Elf *
     57 elf_from_remote_memory (GElf_Addr ehdr_vma,
     58 			GElf_Xword pagesize,
     59 			GElf_Addr *loadbasep,
     60 			ssize_t (*read_memory) (void *arg, void *data,
     61 						GElf_Addr address,
     62 						size_t minread,
     63 						size_t maxread),
     64 			void *arg)
     65 {
     66   /* We might have to reserve some memory for the phdrs.  Set to NULL
     67      here so we can always safely free it.  */
     68   void *phdrsp = NULL;
     69 
     70   /* First read in the file header and check its sanity.  */
     71 
     72   const size_t initial_bufsize = 256;
     73   unsigned char *buffer = malloc (initial_bufsize);
     74   if (unlikely (buffer == NULL))
     75     {
     76     no_memory:
     77       __libdwfl_seterrno (DWFL_E_NOMEM);
     78       return NULL;
     79     }
     80 
     81   ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
     82 				  sizeof (Elf32_Ehdr), initial_bufsize);
     83   if (nread <= 0)
     84     {
     85     read_error:
     86       free (buffer);
     87       free (phdrsp);
     88       __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
     89       return NULL;
     90     }
     91 
     92   if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
     93     {
     94     bad_elf:
     95       free (buffer);
     96       free (phdrsp);
     97       __libdwfl_seterrno (DWFL_E_BADELF);
     98       return NULL;
     99     }
    100 
    101   /* Extract the information we need from the file header.  */
    102 
    103   union
    104   {
    105     Elf32_Ehdr e32;
    106     Elf64_Ehdr e64;
    107   } ehdr;
    108   Elf_Data xlatefrom =
    109     {
    110       .d_type = ELF_T_EHDR,
    111       .d_buf = buffer,
    112       .d_version = EV_CURRENT,
    113     };
    114   Elf_Data xlateto =
    115     {
    116       .d_type = ELF_T_EHDR,
    117       .d_buf = &ehdr,
    118       .d_size = sizeof ehdr,
    119       .d_version = EV_CURRENT,
    120     };
    121 
    122   GElf_Off phoff;
    123   uint_fast16_t phnum;
    124   uint_fast16_t phentsize;
    125   GElf_Off shdrs_end;
    126 
    127   switch (buffer[EI_CLASS])
    128     {
    129     case ELFCLASS32:
    130       xlatefrom.d_size = sizeof (Elf32_Ehdr);
    131       if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
    132 	{
    133 	libelf_error:
    134 	  __libdwfl_seterrno (DWFL_E_LIBELF);
    135 	  return NULL;
    136 	}
    137       phoff = ehdr.e32.e_phoff;
    138       phnum = ehdr.e32.e_phnum;
    139       phentsize = ehdr.e32.e_phentsize;
    140       if (phentsize != sizeof (Elf32_Phdr) || phnum == 0)
    141 	goto bad_elf;
    142       shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
    143       break;
    144 
    145     case ELFCLASS64:
    146       xlatefrom.d_size = sizeof (Elf64_Ehdr);
    147       if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
    148 	goto libelf_error;
    149       phoff = ehdr.e64.e_phoff;
    150       phnum = ehdr.e64.e_phnum;
    151       phentsize = ehdr.e64.e_phentsize;
    152       if (phentsize != sizeof (Elf64_Phdr) || phnum == 0)
    153 	goto bad_elf;
    154       shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
    155       break;
    156 
    157     default:
    158       goto bad_elf;
    159     }
    160 
    161 
    162   /* The file header tells where to find the program headers.
    163      These are what we use to actually choose what to read.  */
    164 
    165   xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
    166   xlatefrom.d_size = phnum * phentsize;
    167 
    168   if ((size_t) nread >= phoff + phnum * phentsize)
    169     /* We already have all the phdrs from the initial read.  */
    170     xlatefrom.d_buf = buffer + phoff;
    171   else
    172     {
    173       /* Read in the program headers.  */
    174 
    175       if (initial_bufsize < phnum * phentsize)
    176 	{
    177 	  unsigned char *newbuf = realloc (buffer, phnum * phentsize);
    178 	  if (newbuf == NULL)
    179 	    {
    180 	      free (buffer);
    181 	      free (phdrsp);
    182 	      goto no_memory;
    183 	    }
    184 	  buffer = newbuf;
    185 	}
    186       nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
    187 			      phnum * phentsize, phnum * phentsize);
    188       if (nread <= 0)
    189 	goto read_error;
    190 
    191       xlatefrom.d_buf = buffer;
    192     }
    193 
    194   bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
    195   size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
    196   if (unlikely (phnum > SIZE_MAX / phdr_size))
    197     {
    198       free (buffer);
    199       goto no_memory;
    200     }
    201   const size_t phdrsp_bytes = phnum * phdr_size;
    202   phdrsp = malloc (phdrsp_bytes);
    203   if (unlikely (phdrsp == NULL))
    204     {
    205       free (buffer);
    206       goto no_memory;
    207     }
    208 
    209   xlateto.d_buf = phdrsp;
    210   xlateto.d_size = phdrsp_bytes;
    211 
    212   /* Scan for PT_LOAD segments to find the total size of the file image.  */
    213   size_t contents_size = 0;
    214   GElf_Off segments_end = 0;
    215   GElf_Off segments_end_mem = 0;
    216   GElf_Addr loadbase = ehdr_vma;
    217   bool found_base = false;
    218   Elf32_Phdr (*p32)[phnum] = phdrsp;
    219   Elf64_Phdr (*p64)[phnum] = phdrsp;
    220   switch (ehdr.e32.e_ident[EI_CLASS])
    221     {
    222       /* Sanity checks segments and calculates segment_end,
    223 	 segments_end, segments_end_mem and loadbase (if not
    224 	 found_base yet).  Returns true if sanity checking failed,
    225 	 false otherwise.  */
    226       inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
    227 				  GElf_Xword filesz, GElf_Xword memsz)
    228 	{
    229 	  /* Sanity check the segment load aligns with the pagesize.  */
    230 	  if (((vaddr - offset) & (pagesize - 1)) != 0)
    231 	    return true;
    232 
    233 	  GElf_Off segment_end = ((offset + filesz + pagesize - 1)
    234 				  & -pagesize);
    235 
    236 	  if (segment_end > (GElf_Off) contents_size)
    237 	    contents_size = segment_end;
    238 
    239 	  if (!found_base && (offset & -pagesize) == 0)
    240 	    {
    241 	      loadbase = ehdr_vma - (vaddr & -pagesize);
    242 	      found_base = true;
    243 	    }
    244 
    245 	  segments_end = offset + filesz;
    246 	  segments_end_mem = offset + memsz;
    247 	  return false;
    248 	}
    249 
    250     case ELFCLASS32:
    251       if (elf32_xlatetom (&xlateto, &xlatefrom,
    252 			  ehdr.e32.e_ident[EI_DATA]) == NULL)
    253 	goto libelf_error;
    254       for (uint_fast16_t i = 0; i < phnum; ++i)
    255 	if ((*p32)[i].p_type == PT_LOAD)
    256 	  if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
    257 			      (*p32)[i].p_filesz, (*p32)[i].p_memsz))
    258 	    goto bad_elf;
    259       break;
    260 
    261     case ELFCLASS64:
    262       if (elf64_xlatetom (&xlateto, &xlatefrom,
    263 			  ehdr.e64.e_ident[EI_DATA]) == NULL)
    264 	goto libelf_error;
    265       for (uint_fast16_t i = 0; i < phnum; ++i)
    266 	if ((*p64)[i].p_type == PT_LOAD)
    267 	  if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
    268 			      (*p64)[i].p_filesz, (*p64)[i].p_memsz))
    269 	    goto bad_elf;
    270       break;
    271 
    272     default:
    273       abort ();
    274       break;
    275     }
    276 
    277   /* Trim the last segment so we don't bother with zeros in the last page
    278      that are off the end of the file.  However, if the extra bit in that
    279      page includes the section headers and the memory isn't extended (which
    280      might indicate it will have been reused otherwise), keep them.  */
    281   if ((GElf_Off) contents_size > segments_end
    282       && (GElf_Off) contents_size >= shdrs_end
    283       && segments_end == segments_end_mem)
    284     {
    285       contents_size = segments_end;
    286       if ((GElf_Off) contents_size < shdrs_end)
    287 	contents_size = shdrs_end;
    288     }
    289   else
    290     contents_size = segments_end;
    291 
    292   free (buffer);
    293 
    294   /* Now we know the size of the whole image we want read in.  */
    295   buffer = calloc (1, contents_size);
    296   if (buffer == NULL)
    297     {
    298       free (phdrsp);
    299       goto no_memory;
    300     }
    301 
    302   switch (ehdr.e32.e_ident[EI_CLASS])
    303     {
    304       /* Reads the given segment.  Returns true if reading fails,
    305 	 false otherwise.  */
    306       inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
    307 				  GElf_Xword filesz)
    308 	{
    309 	  GElf_Off start = offset & -pagesize;
    310 	  GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
    311 	  if (end > (GElf_Off) contents_size)
    312 	    end = contents_size;
    313 	  nread = (*read_memory) (arg, buffer + start,
    314 				  (loadbase + vaddr) & -pagesize,
    315 				  end - start, end - start);
    316 	  return nread <= 0;
    317 	}
    318 
    319     case ELFCLASS32:
    320       for (uint_fast16_t i = 0; i < phnum; ++i)
    321 	if ((*p32)[i].p_type == PT_LOAD)
    322 	  if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
    323 			      (*p32)[i].p_filesz))
    324 	    goto read_error;
    325 
    326       /* If the segments visible in memory didn't include the section
    327 	 headers, then clear them from the file header.  */
    328       if (contents_size < shdrs_end)
    329 	{
    330 	  ehdr.e32.e_shoff = 0;
    331 	  ehdr.e32.e_shnum = 0;
    332 	  ehdr.e32.e_shstrndx = 0;
    333 	}
    334 
    335       /* This will normally have been in the first PT_LOAD segment.  But it
    336 	 conceivably could be missing, and we might have just changed it.  */
    337       xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
    338       xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
    339       xlatefrom.d_buf = &ehdr.e32;
    340       xlateto.d_buf = buffer;
    341       if (elf32_xlatetof (&xlateto, &xlatefrom,
    342 			  ehdr.e32.e_ident[EI_DATA]) == NULL)
    343 	goto libelf_error;
    344       break;
    345 
    346     case ELFCLASS64:
    347       for (uint_fast16_t i = 0; i < phnum; ++i)
    348 	if ((*p64)[i].p_type == PT_LOAD)
    349 	  if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
    350 			      (*p64)[i].p_filesz))
    351 	    goto read_error;
    352 
    353       /* If the segments visible in memory didn't include the section
    354 	 headers, then clear them from the file header.  */
    355       if (contents_size < shdrs_end)
    356 	{
    357 	  ehdr.e64.e_shoff = 0;
    358 	  ehdr.e64.e_shnum = 0;
    359 	  ehdr.e64.e_shstrndx = 0;
    360 	}
    361 
    362       /* This will normally have been in the first PT_LOAD segment.  But it
    363 	 conceivably could be missing, and we might have just changed it.  */
    364       xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
    365       xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
    366       xlatefrom.d_buf = &ehdr.e64;
    367       xlateto.d_buf = buffer;
    368       if (elf64_xlatetof (&xlateto, &xlatefrom,
    369 			  ehdr.e64.e_ident[EI_DATA]) == NULL)
    370 	goto libelf_error;
    371       break;
    372 
    373     default:
    374       abort ();
    375       break;
    376     }
    377 
    378   free (phdrsp);
    379   phdrsp = NULL;
    380 
    381   /* Now we have the image.  Open libelf on it.  */
    382 
    383   Elf *elf = elf_memory ((char *) buffer, contents_size);
    384   if (elf == NULL)
    385     {
    386       free (buffer);
    387       goto libelf_error;
    388     }
    389 
    390   elf->flags |= ELF_F_MALLOCED;
    391   if (loadbasep != NULL)
    392     *loadbasep = loadbase;
    393   return elf;
    394 }
    395