Home | History | Annotate | Download | only in libelf
      1 /* Update program header program header table entry.
      2    Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 2000.
      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 <gelf.h>
     23 #include <string.h>
     24 
     25 #include "libelfP.h"
     26 
     27 
     28 int
     29 gelf_update_phdr (Elf *elf, int ndx, GElf_Phdr *src)
     30 {
     31   int result = 0;
     32 
     33   if (elf == NULL)
     34     return 0;
     35 
     36   if (unlikely (elf->kind != ELF_K_ELF))
     37     {
     38       __libelf_seterrno (ELF_E_INVALID_HANDLE);
     39       return 0;
     40     }
     41 
     42   rwlock_wrlock (elf->lock);
     43 
     44   if (elf->class == ELFCLASS32)
     45     {
     46       Elf32_Phdr *phdr = elf->state.elf32.phdr;
     47 
     48       /* We have to convert the data to the 32 bit format.  This might
     49 	 overflow some fields so we have to test for this case before
     50 	 copying.  */
     51       if (unlikely (src->p_offset > 0xffffffffull)
     52 	  || unlikely (src->p_vaddr > 0xffffffffull)
     53 	  || unlikely (src->p_paddr > 0xffffffffull)
     54 	  || unlikely (src->p_filesz > 0xffffffffull)
     55 	  || unlikely (src->p_memsz > 0xffffffffull)
     56 	  || unlikely (src->p_align > 0xffffffffull))
     57 	{
     58 	  __libelf_seterrno (ELF_E_INVALID_DATA);
     59 	  goto out;
     60 	}
     61 
     62       if (phdr == NULL)
     63 	{
     64 	  phdr = INTUSE(elf32_getphdr) (elf);
     65 	  if (phdr == NULL)
     66 	    /* The error number is already set.  */
     67 	    goto out;
     68 	}
     69 
     70       /* Test whether the index is ok.  */
     71       if (unlikely (ndx >= elf->state.elf32.ehdr->e_phnum))
     72 	{
     73 	  __libelf_seterrno (ELF_E_INVALID_INDEX);
     74 	  goto out;
     75 	}
     76 
     77       /* Now correct the pointer to point to the correct element.  */
     78       phdr += ndx;
     79 
     80 #define COPY(name) \
     81       phdr->name = src->name
     82       COPY (p_type);
     83       COPY (p_offset);
     84       COPY (p_vaddr);
     85       COPY (p_paddr);
     86       COPY (p_filesz);
     87       COPY (p_memsz);
     88       COPY (p_flags);
     89       COPY (p_align);
     90     }
     91   else
     92     {
     93       Elf64_Phdr *phdr = elf->state.elf64.phdr;
     94 
     95       if (phdr == NULL)
     96 	{
     97 	  phdr = INTUSE(elf64_getphdr) (elf);
     98 	  if (phdr == NULL)
     99 	    /* The error number is already set.  */
    100 	    goto out;
    101 	}
    102 
    103       /* Test whether the index is ok.  */
    104       if (unlikely (ndx >= elf->state.elf64.ehdr->e_phnum))
    105 	{
    106 	  __libelf_seterrno (ELF_E_INVALID_INDEX);
    107 	  goto out;
    108 	}
    109 
    110       /* Just copy the data.  */
    111       memcpy (phdr + ndx, src, sizeof (Elf64_Phdr));
    112     }
    113 
    114   result = 1;
    115 
    116  out:
    117   rwlock_unlock (elf->lock);
    118 
    119   return result;
    120 }
    121