Home | History | Annotate | Download | only in libelf
      1 /* Get ELF program header table.
      2    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 1998.
      5 
      6    Red Hat elfutils is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by the
      8    Free Software Foundation; version 2 of the License.
      9 
     10    Red Hat elfutils is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13    General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License along
     16    with Red Hat elfutils; if not, write to the Free Software Foundation,
     17    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     18 
     19    In addition, as a special exception, Red Hat, Inc. gives You the
     20    additional right to link the code of Red Hat elfutils with code licensed
     21    under any Open Source Initiative certified open source license
     22    (http://www.opensource.org/licenses/index.php) which requires the
     23    distribution of source code with any binary distribution and to
     24    distribute linked combinations of the two.  Non-GPL Code permitted under
     25    this exception must only link to the code of Red Hat elfutils through
     26    those well defined interfaces identified in the file named EXCEPTION
     27    found in the source code files (the "Approved Interfaces").  The files
     28    of Non-GPL Code may instantiate templates or use macros or inline
     29    functions from the Approved Interfaces without causing the resulting
     30    work to be covered by the GNU General Public License.  Only Red Hat,
     31    Inc. may make changes or additions to the list of Approved Interfaces.
     32    Red Hat's grant of this exception is conditioned upon your not adding
     33    any new exceptions.  If you wish to add a new Approved Interface or
     34    exception, please contact Red Hat.  You must obey the GNU General Public
     35    License in all respects for all of the Red Hat elfutils code and other
     36    code used in conjunction with Red Hat elfutils except the Non-GPL Code
     37    covered by this exception.  If you modify this file, you may extend this
     38    exception to your version of the file, but you are not obligated to do
     39    so.  If you do not wish to provide this exception without modification,
     40    you must delete this exception statement from your version and license
     41    this file solely under the GPL without exception.
     42 
     43    Red Hat elfutils is an included package of the Open Invention Network.
     44    An included package of the Open Invention Network is a package for which
     45    Open Invention Network licensees cross-license their patents.  No patent
     46    license is granted, either expressly or impliedly, by designation as an
     47    included package.  Should you wish to participate in the Open Invention
     48    Network licensing program, please visit www.openinventionnetwork.com
     49    <http://www.openinventionnetwork.com>.  */
     50 
     51 #ifdef HAVE_CONFIG_H
     52 # include <config.h>
     53 #endif
     54 
     55 #include <errno.h>
     56 #include <stdbool.h>
     57 #include <stdlib.h>
     58 #include <unistd.h>
     59 #include <assert.h>
     60 
     61 #include <system.h>
     62 #include "libelfP.h"
     63 #include "common.h"
     64 
     65 #ifndef LIBELFBITS
     66 # define LIBELFBITS 32
     67 #endif
     68 
     69 ElfW2(LIBELFBITS,Phdr) *
     70 __elfw2(LIBELFBITS,getphdr_wrlock) (elf)
     71      Elf *elf;
     72 {
     73   ElfW2(LIBELFBITS,Phdr) *result;
     74 
     75   /* If the program header entry has already been filled in the code
     76      below must already have been run.  So the class is set, too.  No
     77      need to waste any more time here.  */
     78   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
     79   if (likely (result != NULL))
     80     return result;
     81 
     82   if (elf->class == 0)
     83     elf->class = ELFW(ELFCLASS,LIBELFBITS);
     84   else if (elf->class != ELFW(ELFCLASS,LIBELFBITS))
     85     {
     86       __libelf_seterrno (ELF_E_INVALID_CLASS);
     87       result = NULL;
     88       goto out;
     89     }
     90 
     91   if (likely (result == NULL))
     92     {
     93       /* Read the section header table.  */
     94       ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
     95 
     96       /* If no program header exists return NULL.  */
     97       size_t phnum = ehdr->e_phnum;
     98       if (phnum == 0)
     99 	{
    100 	  __libelf_seterrno (ELF_E_NO_PHDR);
    101 	  goto out;
    102 	}
    103 
    104       size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
    105 
    106       if (elf->map_address != NULL)
    107 	{
    108 	  /* All the data is already mapped.  Use it.  */
    109 	  void *file_phdr = ((char *) elf->map_address
    110 			     + elf->start_offset + ehdr->e_phoff);
    111 	  if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
    112 	      && (ALLOW_UNALIGNED
    113 		  || ((uintptr_t) file_phdr
    114 		      & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
    115 	    /* Simply use the mapped data.  */
    116 	    elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr;
    117 	  else
    118 	    {
    119 	      ElfW2(LIBELFBITS,Phdr) *notcvt;
    120 	      ElfW2(LIBELFBITS,Phdr) *phdr;
    121 
    122 	      /* Allocate memory for the program headers.  We know the number
    123 		 of entries from the ELF header.  */
    124 	      phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
    125 		(ElfW2(LIBELFBITS,Phdr) *) malloc (size);
    126 	      if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
    127 		{
    128 		  __libelf_seterrno (ELF_E_NOMEM);
    129 		  goto out;
    130 		}
    131 	      elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
    132 		ELF_F_MALLOCED | ELF_F_DIRTY;
    133 
    134 	      /* Now copy the data and at the same time convert the
    135 		 byte order.  */
    136 
    137 	      if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
    138 		{
    139 		  assert (! ALLOW_UNALIGNED);
    140 		  memcpy (phdr, file_phdr, size);
    141 		}
    142 	      else
    143 		{
    144 		  if (ALLOW_UNALIGNED
    145 		      || ((uintptr_t) file_phdr
    146 			  & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0)
    147 		    notcvt = file_phdr;
    148 		  else
    149 		    {
    150 		      notcvt = (ElfW2(LIBELFBITS,Phdr) *) alloca (size);
    151 		      memcpy (notcvt, file_phdr, size);
    152 		    }
    153 
    154 		  for (size_t cnt = 0; cnt < phnum; ++cnt)
    155 		    {
    156 		      CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
    157 		      CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
    158 		      CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
    159 		      CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
    160 		      CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
    161 		      CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
    162 		      CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
    163 		      CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
    164 		    }
    165 		}
    166 	    }
    167 	}
    168       else if (likely (elf->fildes != -1))
    169 	{
    170 	  /* Allocate memory for the program headers.  We know the number
    171 	     of entries from the ELF header.  */
    172 	  elf->state.ELFW(elf,LIBELFBITS).phdr =
    173 	    (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
    174 	  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
    175 	    {
    176 	      __libelf_seterrno (ELF_E_NOMEM);
    177 	      goto out;
    178 	    }
    179 	  elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
    180 
    181 	  /* Read the header.  */
    182 	  ssize_t n = pread_retry (elf->fildes,
    183 				   elf->state.ELFW(elf,LIBELFBITS).phdr, size,
    184 				   elf->start_offset + ehdr->e_phoff);
    185 	  if (unlikely ((size_t) n != size))
    186 	    {
    187 	      /* Severe problems.  We cannot read the data.  */
    188 	      __libelf_seterrno (ELF_E_READ_ERROR);
    189 	      free (elf->state.ELFW(elf,LIBELFBITS).phdr);
    190 	      elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
    191 	      goto out;
    192 	    }
    193 
    194 	  /* If the byte order of the file is not the same as the one
    195 	     of the host convert the data now.  */
    196 	  if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
    197 	    {
    198 	      ElfW2(LIBELFBITS,Phdr) *phdr
    199 		= elf->state.ELFW(elf,LIBELFBITS).phdr;
    200 
    201 	      for (size_t cnt = 0; cnt < phnum; ++cnt)
    202 		{
    203 		  CONVERT (phdr[cnt].p_type);
    204 		  CONVERT (phdr[cnt].p_offset);
    205 		  CONVERT (phdr[cnt].p_vaddr);
    206 		  CONVERT (phdr[cnt].p_paddr);
    207 		  CONVERT (phdr[cnt].p_filesz);
    208 		  CONVERT (phdr[cnt].p_memsz);
    209 		  CONVERT (phdr[cnt].p_flags);
    210 		  CONVERT (phdr[cnt].p_align);
    211 		}
    212 	    }
    213 	}
    214       else
    215 	{
    216 	  /* The file descriptor was already enabled and not all data was
    217 	     read.  */
    218 	  __libelf_seterrno (ELF_E_FD_DISABLED);
    219 	  goto out;
    220 	}
    221 
    222       result = elf->state.ELFW(elf,LIBELFBITS).phdr;
    223     }
    224 
    225  out:
    226   return result;
    227 }
    228 
    229 ElfW2(LIBELFBITS,Phdr) *
    230 elfw2(LIBELFBITS,getphdr) (elf)
    231      Elf *elf;
    232 {
    233   ElfW2(LIBELFBITS,Phdr) *result;
    234 
    235   if (elf == NULL)
    236     return NULL;
    237 
    238   if (unlikely (elf->kind != ELF_K_ELF))
    239     {
    240       __libelf_seterrno (ELF_E_INVALID_HANDLE);
    241       return NULL;
    242     }
    243 
    244   /* If the program header entry has already been filled in the code
    245    * in getphdr_wrlock must already have been run.  So the class is
    246    * set, too.  No need to waste any more time here.  */
    247   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
    248   if (likely (result != NULL))
    249     return result;
    250 
    251   rwlock_wrlock (elf->lock);
    252   result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
    253   rwlock_unlock (elf->lock);
    254 
    255   return result;
    256 }
    257 INTDEF(elfw2(LIBELFBITS,getphdr))
    258