Home | History | Annotate | Download | only in libelf
      1 /* Update data structures for changes.
      2    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 2000.
      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 <assert.h>
     56 #include <endian.h>
     57 #include <libelf.h>
     58 #include <stdbool.h>
     59 #include <string.h>
     60 #include <sys/param.h>
     61 
     62 #include "libelfP.h"
     63 #include "elf-knowledge.h"
     64 
     65 #ifndef LIBELFBITS
     66 # define LIBELFBITS 32
     67 #endif
     68 
     69 
     70 
     71 static int
     72 ELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
     73 			       size_t shnum, int *change_bop)
     74 {
     75   /* Always write the magic bytes.  */
     76   if (memcmp (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
     77     {
     78       memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
     79       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
     80     }
     81 
     82   /* Always set the file class.  */
     83   update_if_changed (ehdr->e_ident[EI_CLASS], ELFW(ELFCLASS,LIBELFBITS),
     84 		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
     85 
     86   /* Set the data encoding if necessary.  */
     87   if (unlikely (ehdr->e_ident[EI_DATA] == ELFDATANONE))
     88     {
     89       ehdr->e_ident[EI_DATA] =
     90 	BYTE_ORDER == BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB;
     91       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
     92     }
     93   else if (unlikely (ehdr->e_ident[EI_DATA] >= ELFDATANUM))
     94     {
     95       __libelf_seterrno (ELF_E_DATA_ENCODING);
     96       return 1;
     97     }
     98   else
     99     *change_bop = ((BYTE_ORDER == LITTLE_ENDIAN
    100 		    && ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
    101 		   || (BYTE_ORDER == BIG_ENDIAN
    102 		       && ehdr->e_ident[EI_DATA] != ELFDATA2MSB));
    103 
    104   /* Unconditionally overwrite the ELF version.  */
    105   update_if_changed (ehdr->e_ident[EI_VERSION], EV_CURRENT,
    106 		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
    107 
    108   if (unlikely (ehdr->e_version == EV_NONE)
    109       || unlikely (ehdr->e_version >= EV_NUM))
    110     {
    111       __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
    112       return 1;
    113     }
    114 
    115   if (unlikely (shnum >= SHN_LORESERVE))
    116     {
    117       update_if_changed (ehdr->e_shnum, 0,
    118 			 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
    119     }
    120   else
    121     update_if_changed (ehdr->e_shnum, shnum,
    122 		       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
    123 
    124   if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)))
    125     {
    126       ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
    127       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
    128     }
    129 
    130   return 0;
    131 }
    132 
    133 
    134 off_t
    135 internal_function
    136 __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
    137 {
    138   ElfW2(LIBELFBITS,Ehdr) *ehdr;
    139   int changed = 0;
    140   int ehdr_flags = 0;
    141 
    142   ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
    143 
    144   /* Set the default values.  */
    145   if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
    146     return -1;
    147 
    148   /* At least the ELF header is there.  */
    149   off_t size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
    150 
    151   /* Set the program header position.  */
    152   if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL
    153       && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
    154 	  || ehdr->e_type == ET_CORE))
    155     (void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
    156   if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
    157     {
    158       /* Only executables, shared objects, and core files have a program
    159 	 header.  */
    160       if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
    161 	  && unlikely (ehdr->e_type != ET_CORE))
    162 	{
    163 	  __libelf_seterrno (ELF_E_INVALID_PHDR);
    164 	  return -1;
    165 	}
    166 
    167       if (elf->flags & ELF_F_LAYOUT)
    168 	{
    169 	  /* The user is supposed to fill out e_phoff.  Use it and
    170 	     e_phnum to determine the maximum extend.  */
    171 	  size = MAX ((size_t) size,
    172 		      ehdr->e_phoff
    173 		      + elf_typesize (LIBELFBITS, ELF_T_PHDR, ehdr->e_phnum));
    174 	}
    175       else
    176 	{
    177 	  update_if_changed (ehdr->e_phoff,
    178 			     elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
    179 			     ehdr_flags);
    180 
    181 	  /* We need no alignment here.  */
    182 	  size += elf_typesize (LIBELFBITS, ELF_T_PHDR, ehdr->e_phnum);
    183 	}
    184     }
    185 
    186   if (shnum > 0)
    187     {
    188       Elf_ScnList *list;
    189       bool first = true;
    190 
    191       assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0);
    192 
    193       if (shnum >= SHN_LORESERVE)
    194 	{
    195 	  /* We have to  fill in the number of sections in the header
    196 	     of the zeroth section.  */
    197 	  Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
    198 
    199 	  update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
    200 			     shnum, scn0->shdr_flags);
    201 	}
    202 
    203       /* Go over all sections and find out how large they are.  */
    204       list = &elf->state.ELFW(elf,LIBELFBITS).scns;
    205 
    206       /* Load the section headers if necessary.  This loads the
    207 	 headers for all sections.  */
    208       if (list->data[1].shdr.ELFW(e,LIBELFBITS) == NULL)
    209 	(void) __elfw2(LIBELFBITS,getshdr_wrlock) (&list->data[1]);
    210 
    211       do
    212 	{
    213 	  for (size_t cnt = first == true; cnt < list->cnt; ++cnt)
    214 	    {
    215 	      Elf_Scn *scn = &list->data[cnt];
    216 	      ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
    217 	      off_t offset = 0;
    218 
    219 	      assert (shdr != NULL);
    220 	      ElfW2(LIBELFBITS,Word) sh_entsize = shdr->sh_entsize;
    221 	      ElfW2(LIBELFBITS,Word) sh_align = shdr->sh_addralign ?: 1;
    222 
    223 	      /* Set the sh_entsize value if we can reliably detect it.  */
    224 	      switch (shdr->sh_type)
    225 		{
    226 		case SHT_SYMTAB:
    227 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
    228 		  break;
    229 		case SHT_RELA:
    230 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELA, 1);
    231 		  break;
    232 		case SHT_GROUP:
    233 		  /* Only relocatable files can contain section groups.  */
    234 		  if (ehdr->e_type != ET_REL)
    235 		    {
    236 		      __libelf_seterrno (ELF_E_GROUP_NOT_REL);
    237 		      return -1;
    238 		    }
    239 		  /* FALLTHROUGH */
    240 		case SHT_SYMTAB_SHNDX:
    241 		  sh_entsize = elf_typesize (32, ELF_T_WORD, 1);
    242 		  break;
    243 		case SHT_HASH:
    244 		  sh_entsize = SH_ENTSIZE_HASH (ehdr);
    245 		  break;
    246 		case SHT_DYNAMIC:
    247 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_DYN, 1);
    248 		  break;
    249 		case SHT_REL:
    250 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_REL, 1);
    251 		  break;
    252 		case SHT_DYNSYM:
    253 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
    254 		  break;
    255 		case SHT_SUNW_move:
    256 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_MOVE, 1);
    257 		  break;
    258 		case SHT_SUNW_syminfo:
    259 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
    260 		  break;
    261 		default:
    262 		  break;
    263 		}
    264 
    265 	      /* If the section header contained the wrong entry size
    266 		 correct it and mark the header as modified.  */
    267 	      update_if_changed (shdr->sh_entsize, sh_entsize,
    268 				 scn->shdr_flags);
    269 
    270 	      if (scn->data_read == 0
    271 		  && __libelf_set_rawdata_wrlock (scn) != 0)
    272 		/* Something went wrong.  The error value is already set.  */
    273 		return -1;
    274 
    275 	      /* Iterate over all data blocks.  */
    276 	      if (list->data[cnt].data_list_rear != NULL)
    277 		{
    278 		  Elf_Data_List *dl = &scn->data_list;
    279 
    280 		  while (dl != NULL)
    281 		    {
    282 		      Elf_Data *data = &dl->data.d;
    283 		      if (dl == &scn->data_list && data->d_buf == NULL
    284 			  && scn->rawdata.d.d_buf != NULL)
    285 			data = &scn->rawdata.d;
    286 
    287 		      if (unlikely (data->d_version == EV_NONE)
    288 			  || unlikely (data->d_version >= EV_NUM))
    289 			{
    290 			  __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
    291 			  return -1;
    292 			}
    293 
    294 		      if (unlikely (! powerof2 (data->d_align)))
    295 			{
    296 			  __libelf_seterrno (ELF_E_INVALID_ALIGN);
    297 			  return -1;
    298 			}
    299 
    300 		      sh_align = MAX (sh_align, data->d_align);
    301 
    302 		      if (elf->flags & ELF_F_LAYOUT)
    303 			{
    304 			  /* The user specified the offset and the size.
    305 			     All we have to do is check whether this block
    306 			     fits in the size specified for the section.  */
    307 			  if (unlikely ((GElf_Word) (data->d_off
    308 						     + data->d_size)
    309 					> shdr->sh_size))
    310 			    {
    311 			      __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
    312 			      return -1;
    313 			    }
    314 			}
    315 		      else
    316 			{
    317 			  /* Determine the padding.  */
    318 			  offset = ((offset + data->d_align - 1)
    319 				    & ~(data->d_align - 1));
    320 
    321 			  update_if_changed (data->d_off, offset, changed);
    322 
    323 			  offset += data->d_size;
    324 			}
    325 
    326 		      /* Next data block.  */
    327 		      dl = dl->next;
    328 		    }
    329 		}
    330 	      else
    331 		/* Get the size of the section from the raw data.  If
    332 		   none is available the value is zero.  */
    333 		offset += scn->rawdata.d.d_size;
    334 
    335 	      if (elf->flags & ELF_F_LAYOUT)
    336 		{
    337 		  size = MAX ((GElf_Word) size,
    338 			      shdr->sh_offset
    339 			      + (shdr->sh_type != SHT_NOBITS
    340 				 ? shdr->sh_size : 0));
    341 
    342 		  /* The alignment must be a power of two.  This is a
    343 		     requirement from the ELF specification.  Additionally
    344 		     we test for the alignment of the section being large
    345 		     enough for the largest alignment required by a data
    346 		     block.  */
    347 		  if (unlikely (! powerof2 (shdr->sh_addralign))
    348 		      || unlikely (shdr->sh_addralign < sh_align))
    349 		    {
    350 		      __libelf_seterrno (ELF_E_INVALID_ALIGN);
    351 		      return -1;
    352 		    }
    353 		}
    354 	      else
    355 		{
    356 		  /* How much alignment do we need for this section.  */
    357 		  update_if_changed (shdr->sh_addralign, sh_align,
    358 				     scn->shdr_flags);
    359 
    360 		  size = (size + sh_align - 1) & ~(sh_align - 1);
    361 		  int offset_changed = 0;
    362 		  update_if_changed (shdr->sh_offset, (GElf_Word) size,
    363 				     offset_changed);
    364 		  changed |= offset_changed;
    365 
    366 		  if (offset_changed && scn->data_list_rear == NULL)
    367 		    {
    368 		      /* The position of the section in the file
    369 			 changed.  Create the section data list.  */
    370 		      if (__elf_getdata_rdlock (scn, NULL) == NULL)
    371 			return -1;
    372 		    }
    373 
    374 		  /* See whether the section size is correct.  */
    375 		  update_if_changed (shdr->sh_size, (GElf_Word) offset,
    376 				     changed);
    377 
    378 		  if (shdr->sh_type != SHT_NOBITS)
    379 		    size += offset;
    380 
    381 		  scn->flags |= changed;
    382 		}
    383 
    384 	      /* Check that the section size is actually a multiple of
    385 		 the entry size.  */
    386 	      if (shdr->sh_entsize != 0
    387 		  && unlikely (shdr->sh_size % shdr->sh_entsize != 0)
    388 		  && (elf->flags & ELF_F_PERMISSIVE) == 0)
    389 		{
    390 		  __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
    391 		  return -1;
    392 		}
    393 	    }
    394 
    395 	  assert (list->next == NULL || list->cnt == list->max);
    396 
    397 	  first = false;
    398 	}
    399       while ((list = list->next) != NULL);
    400 
    401       /* Store section information.  */
    402       if (elf->flags & ELF_F_LAYOUT)
    403 	{
    404 	  /* The user is supposed to fill out e_phoff.  Use it and
    405 	     e_phnum to determine the maximum extend.  */
    406 	  size = MAX ((GElf_Word) size,
    407 		      (ehdr->e_shoff
    408 		       + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
    409 	}
    410       else
    411 	{
    412 	  /* Align for section header table.
    413 
    414 	     Yes, we use `sizeof' and not `__alignof__' since we do not
    415 	     want to be surprised by architectures with less strict
    416 	     alignment rules.  */
    417 #define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
    418 	  size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
    419 
    420 	  update_if_changed (ehdr->e_shoff, (GElf_Word) size, elf->flags);
    421 	  update_if_changed (ehdr->e_shentsize,
    422 			     elf_typesize (LIBELFBITS, ELF_T_SHDR, 1),
    423 			     ehdr_flags);
    424 
    425 	  /* Account for the section header size.  */
    426 	  size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
    427 	}
    428     }
    429 
    430   elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
    431 
    432   return size;
    433 }
    434