Home | History | Annotate | Download | only in libelf
      1 /* Get ELF program header table.
      2    Copyright (C) 1998-2010, 2014, 2015 Red Hat, Inc.
      3    This file is part of elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 1998.
      5 
      6    This file is free software; you can redistribute it and/or modify
      7    it under the terms of either
      8 
      9      * the GNU Lesser General Public License as published by the Free
     10        Software Foundation; either version 3 of the License, or (at
     11        your option) any later version
     12 
     13    or
     14 
     15      * the GNU General Public License as published by the Free
     16        Software Foundation; either version 2 of the License, or (at
     17        your option) any later version
     18 
     19    or both in parallel, as here.
     20 
     21    elfutils is distributed in the hope that it will be useful, but
     22    WITHOUT ANY WARRANTY; without even the implied warranty of
     23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     24    General Public License for more details.
     25 
     26    You should have received copies of the GNU General Public License and
     27    the GNU Lesser General Public License along with this program.  If
     28    not, see <http://www.gnu.org/licenses/>.  */
     29 
     30 #ifdef HAVE_CONFIG_H
     31 # include <config.h>
     32 #endif
     33 
     34 #include <errno.h>
     35 #include <stdbool.h>
     36 #include <stdlib.h>
     37 #include <unistd.h>
     38 #include <assert.h>
     39 
     40 #include <system.h>
     41 #include "libelfP.h"
     42 #include "common.h"
     43 
     44 #ifndef LIBELFBITS
     45 # define LIBELFBITS 32
     46 #endif
     47 
     48 ElfW2(LIBELFBITS,Phdr) *
     49 __elfw2(LIBELFBITS,getphdr_wrlock) (Elf *elf)
     50 {
     51   ElfW2(LIBELFBITS,Phdr) *result;
     52 
     53   /* If the program header entry has already been filled in the code
     54      below must already have been run.  So the class is set, too.  No
     55      need to waste any more time here.  */
     56   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
     57   if (likely (result != NULL))
     58     return result;
     59 
     60   if (elf->class == 0)
     61     elf->class = ELFW(ELFCLASS,LIBELFBITS);
     62   else if (elf->class != ELFW(ELFCLASS,LIBELFBITS))
     63     {
     64       __libelf_seterrno (ELF_E_INVALID_CLASS);
     65       result = NULL;
     66       goto out;
     67     }
     68 
     69   if (likely (result == NULL))
     70     {
     71       /* Read the section header table.  */
     72       ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
     73 
     74       /* If no program header exists return NULL.  */
     75       size_t phnum;
     76       if (__elf_getphdrnum_rdlock (elf, &phnum) != 0)
     77 	goto out;
     78       if (phnum == 0 || ehdr->e_phoff == 0)
     79 	{
     80 	  __libelf_seterrno (ELF_E_NO_PHDR);
     81 	  goto out;
     82 	}
     83 
     84       /* Check this doesn't overflow.  */
     85       size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
     86 
     87       if (phnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr))
     88 	  || ehdr->e_phoff > elf->maximum_size
     89 	  || elf->maximum_size - ehdr->e_phoff < size)
     90 	{
     91 	  __libelf_seterrno (ELF_E_INVALID_DATA);
     92 	  goto out;
     93 	}
     94 
     95       if (elf->map_address != NULL)
     96 	{
     97 	  /* First see whether the information in the ELF header is
     98 	     valid and it does not ask for too much.  */
     99 	  if (unlikely (ehdr->e_phoff >= elf->maximum_size)
    100 	      || unlikely (elf->maximum_size - ehdr->e_phoff < size))
    101 	    {
    102 	      /* Something is wrong.  */
    103 	      __libelf_seterrno (ELF_E_INVALID_PHDR);
    104 	      goto out;
    105 	    }
    106 
    107 	  /* All the data is already mapped.  Use it.  */
    108 	  void *file_phdr = ((char *) elf->map_address
    109 			     + elf->start_offset + ehdr->e_phoff);
    110 	  if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
    111 	      && (ALLOW_UNALIGNED
    112 		  || ((uintptr_t) file_phdr
    113 		      & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
    114 	    /* Simply use the mapped data.  */
    115 	    elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr;
    116 	  else
    117 	    {
    118 	      ElfW2(LIBELFBITS,Phdr) *notcvt;
    119 	      ElfW2(LIBELFBITS,Phdr) *phdr;
    120 
    121 	      /* Allocate memory for the program headers.  We know the number
    122 		 of entries from the ELF header.  */
    123 	      phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
    124 		(ElfW2(LIBELFBITS,Phdr) *) malloc (size);
    125 	      if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
    126 		{
    127 		  __libelf_seterrno (ELF_E_NOMEM);
    128 		  goto out;
    129 		}
    130 	      elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
    131 		ELF_F_MALLOCED | ELF_F_DIRTY;
    132 
    133 	      /* Now copy the data and at the same time convert the
    134 		 byte order.  */
    135 
    136 	      if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
    137 		{
    138 		  assert (! ALLOW_UNALIGNED);
    139 		  memcpy (phdr, file_phdr, size);
    140 		}
    141 	      else
    142 		{
    143 		  bool copy = ! (ALLOW_UNALIGNED
    144 				 || ((uintptr_t) file_phdr
    145 				     & (__alignof__ (ElfW2(LIBELFBITS,Phdr))
    146 					- 1)) == 0);
    147 		  if (! copy)
    148 		    notcvt = file_phdr;
    149 		  else
    150 		    {
    151 		      notcvt = (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
    152 		      if (unlikely (notcvt == NULL))
    153 			{
    154 			  __libelf_seterrno (ELF_E_NOMEM);
    155 			  goto out;
    156 			}
    157 		      memcpy (notcvt, file_phdr, size);
    158 		    }
    159 
    160 		  for (size_t cnt = 0; cnt < phnum; ++cnt)
    161 		    {
    162 		      CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
    163 		      CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
    164 		      CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
    165 		      CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
    166 		      CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
    167 		      CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
    168 		      CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
    169 		      CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
    170 		    }
    171 
    172 		  if (copy)
    173 		    free (notcvt);
    174 		}
    175 	    }
    176 	}
    177       else if (likely (elf->fildes != -1))
    178 	{
    179 	  /* Allocate memory for the program headers.  We know the number
    180 	     of entries from the ELF header.  */
    181 	  elf->state.ELFW(elf,LIBELFBITS).phdr =
    182 	    (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
    183 	  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
    184 	    {
    185 	      __libelf_seterrno (ELF_E_NOMEM);
    186 	      goto out;
    187 	    }
    188 	  elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
    189 
    190 	  /* Read the header.  */
    191 	  ssize_t n = pread_retry (elf->fildes,
    192 				   elf->state.ELFW(elf,LIBELFBITS).phdr, size,
    193 				   elf->start_offset + ehdr->e_phoff);
    194 	  if (unlikely ((size_t) n != size))
    195 	    {
    196 	      /* Severe problems.  We cannot read the data.  */
    197 	      __libelf_seterrno (ELF_E_READ_ERROR);
    198 	      free (elf->state.ELFW(elf,LIBELFBITS).phdr);
    199 	      elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
    200 	      goto out;
    201 	    }
    202 
    203 	  /* If the byte order of the file is not the same as the one
    204 	     of the host convert the data now.  */
    205 	  if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
    206 	    {
    207 	      ElfW2(LIBELFBITS,Phdr) *phdr
    208 		= elf->state.ELFW(elf,LIBELFBITS).phdr;
    209 
    210 	      for (size_t cnt = 0; cnt < phnum; ++cnt)
    211 		{
    212 		  CONVERT (phdr[cnt].p_type);
    213 		  CONVERT (phdr[cnt].p_offset);
    214 		  CONVERT (phdr[cnt].p_vaddr);
    215 		  CONVERT (phdr[cnt].p_paddr);
    216 		  CONVERT (phdr[cnt].p_filesz);
    217 		  CONVERT (phdr[cnt].p_memsz);
    218 		  CONVERT (phdr[cnt].p_flags);
    219 		  CONVERT (phdr[cnt].p_align);
    220 		}
    221 	    }
    222 	}
    223       else
    224 	{
    225 	  /* The file descriptor was already enabled and not all data was
    226 	     read.  */
    227 	  __libelf_seterrno (ELF_E_FD_DISABLED);
    228 	  goto out;
    229 	}
    230 
    231       result = elf->state.ELFW(elf,LIBELFBITS).phdr;
    232     }
    233 
    234  out:
    235   return result;
    236 }
    237 
    238 ElfW2(LIBELFBITS,Phdr) *
    239 elfw2(LIBELFBITS,getphdr) (Elf *elf)
    240 {
    241   ElfW2(LIBELFBITS,Phdr) *result;
    242 
    243   if (elf == NULL)
    244     return NULL;
    245 
    246   if (unlikely (elf->kind != ELF_K_ELF))
    247     {
    248       __libelf_seterrno (ELF_E_INVALID_HANDLE);
    249       return NULL;
    250     }
    251 
    252   /* If the program header entry has already been filled in the code
    253    * in getphdr_wrlock must already have been run.  So the class is
    254    * set, too.  No need to waste any more time here.  */
    255   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
    256   if (likely (result != NULL))
    257     return result;
    258 
    259   rwlock_wrlock (elf->lock);
    260   result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
    261   rwlock_unlock (elf->lock);
    262 
    263   return result;
    264 }
    265 INTDEF(elfw2(LIBELFBITS,getphdr))
    266