Home | History | Annotate | Download | only in libelf
      1 /* Create new ELF program header table.
      2    Copyright (C) 1999, 2000, 2002 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 1998.
      4 
      5    This program is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation, version 2.
      8 
      9    This program is distributed in the hope that it will be useful,
     10    but WITHOUT ANY WARRANTY; without even the implied warranty of
     11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12    GNU General Public License for more details.
     13 
     14    You should have received a copy of the GNU General Public License
     15    along with this program; if not, write to the Free Software Foundation,
     16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
     17 
     18 #ifdef HAVE_CONFIG_H
     19 # include <config.h>
     20 #endif
     21 
     22 #include <assert.h>
     23 #include <stdlib.h>
     24 #include <string.h>
     25 
     26 #include "libelfP.h"
     27 
     28 #ifndef LIBELFBITS
     29 # define LIBELFBITS 32
     30 #endif
     31 
     32 
     33 ElfW2(LIBELFBITS,Phdr) *
     34 elfw2(LIBELFBITS,newphdr) (elf, count)
     35      Elf *elf;
     36      size_t count;
     37 {
     38   ElfW2(LIBELFBITS,Phdr) *result;
     39 
     40   if (elf == NULL)
     41     return NULL;
     42 
     43   if (unlikely (elf->kind != ELF_K_ELF))
     44     {
     45       __libelf_seterrno (ELF_E_INVALID_HANDLE);
     46       return NULL;
     47     }
     48 
     49   rwlock_wrlock (elf->lock);
     50 
     51   if (elf->class == 0)
     52     elf->class = ELFW(ELFCLASS,LIBELFBITS);
     53   else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
     54     {
     55       __libelf_seterrno (ELF_E_INVALID_CLASS);
     56       result = NULL;
     57       goto out;
     58     }
     59 
     60   if (unlikely (elf->state.ELFW(elf,LIBELFBITS).ehdr == NULL))
     61     {
     62       __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
     63       result = NULL;
     64       goto out;
     65     }
     66 
     67   /* A COUNT of zero means remove existing table.  */
     68   if (count == 0)
     69     {
     70       /* Free the old program header.  */
     71       if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
     72 	{
     73 	  if (elf->state.ELFW(elf,LIBELFBITS).phdr_flags & ELF_F_MALLOCED)
     74 	    free (elf->state.ELFW(elf,LIBELFBITS).phdr);
     75 
     76 	  /* Set the pointer to NULL.  */
     77 	  elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
     78 	  /* Set the `e_phnum' member to the new value.  */
     79 	  elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = 0;
     80 	  /* Also set the size.  */
     81 	  elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
     82 	    sizeof (ElfW2(LIBELFBITS,Phdr));
     83 
     84 	  elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
     85 	  elf->flags |= ELF_F_DIRTY;
     86 	  __libelf_seterrno (ELF_E_NOERROR);
     87 	}
     88 
     89       result = NULL;
     90     }
     91   else if (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum != count
     92 	   || elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
     93     {
     94       /* Allocate a new program header with the appropriate number of
     95 	 elements.  */
     96       result = (ElfW2(LIBELFBITS,Phdr) *)
     97 	realloc (elf->state.ELFW(elf,LIBELFBITS).phdr,
     98 		 count * sizeof (ElfW2(LIBELFBITS,Phdr)));
     99       if (result == NULL)
    100 	__libelf_seterrno (ELF_E_NOMEM);
    101       else
    102 	{
    103 	  /* Now set the result.  */
    104 	  elf->state.ELFW(elf,LIBELFBITS).phdr = result;
    105 	  /* Clear the whole memory.  */
    106 	  memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
    107 	  /* Set the `e_phnum' member to the new value.  */
    108 	  elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = count;
    109 	  /* Also set the size.  */
    110 	  elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
    111 	    elf_typesize (LIBELFBITS, ELF_T_PHDR, 1);
    112 	  /* Remember we allocated the array and mark the structure is
    113 	     modified.  */
    114 	  elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
    115 	    ELF_F_DIRTY | ELF_F_MALLOCED;
    116 	  /* We have to rewrite the entire file if the size of the
    117 	     program header is changed.  */
    118 	  elf->flags |= ELF_F_DIRTY;
    119 	}
    120     }
    121   else
    122     {
    123       /* We have the same number of entries.  Just clear the array.  */
    124       assert (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize
    125 	      == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
    126 
    127       /* Mark the structure as modified.  */
    128       elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
    129 
    130       result = elf->state.ELFW(elf,LIBELFBITS).phdr;
    131     }
    132 
    133  out:
    134   rwlock_unlock (elf->lock);
    135 
    136   return result;
    137 }
    138 INTDEF(elfw2(LIBELFBITS,newphdr))
    139