Home | History | Annotate | Download | only in libelf
      1 /* Update data structures for changes and write them out.
      2    Copyright (C) 1999, 2000, 2001, 2002, 2004 Red Hat, Inc.
      3    Contributed by Ulrich Drepper <drepper (at) redhat.com>, 1999.
      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 <libelf.h>
     23 #include <unistd.h>
     24 #include <sys/mman.h>
     25 
     26 #include "libelfP.h"
     27 
     28 
     29 static off_t
     30 write_file (Elf *elf, off_t size, int change_bo, size_t shnum)
     31 {
     32   int class = elf->class;
     33 
     34   /* Adjust the size in any case.  We do this even if we use `write'.
     35      We cannot do this if this file is in an archive.  We also don't
     36      do it *now* if we are shortening the file since this would
     37      prevent programs to use the data of the file in generating the
     38      new file.  We truncate the file later in this case.  */
     39   if (elf->parent == NULL
     40       && (elf->maximum_size == ~((size_t) 0) || size > elf->maximum_size)
     41       && unlikely (ftruncate (elf->fildes, size) != 0))
     42     {
     43       __libelf_seterrno (ELF_E_WRITE_ERROR);
     44       return -1;
     45     }
     46 
     47   /* Try to map the file if this isn't done yet.  */
     48   if (elf->map_address == NULL && elf->cmd == ELF_C_WRITE_MMAP)
     49     {
     50       elf->map_address = mmap (NULL, size, PROT_READ | PROT_WRITE,
     51 			       MAP_SHARED, elf->fildes, 0);
     52       if (unlikely (elf->map_address == MAP_FAILED))
     53 	elf->map_address = NULL;
     54     }
     55 
     56   if (elf->map_address != NULL)
     57     {
     58       /* The file is mmaped.  */
     59       if ((class == ELFCLASS32
     60 	   ? __elf32_updatemmap (elf, change_bo, shnum)
     61 	   : __elf64_updatemmap (elf, change_bo, shnum)) != 0)
     62 	/* Some problem while writing.  */
     63 	size = -1;
     64     }
     65   else
     66     {
     67       /* The file is not mmaped.  */
     68       if ((class == ELFCLASS32
     69 	   ? __elf32_updatefile (elf, change_bo, shnum)
     70 	   : __elf64_updatefile (elf, change_bo, shnum)) != 0)
     71 	/* Some problem while writing.  */
     72 	size = -1;
     73     }
     74 
     75   if (size != -1
     76       && elf->parent == NULL
     77       && elf->maximum_size != ~((size_t) 0)
     78       && size < elf->maximum_size
     79       && unlikely (ftruncate (elf->fildes, size) != 0))
     80     {
     81       __libelf_seterrno (ELF_E_WRITE_ERROR);
     82       size = -1;
     83     }
     84 
     85   if (size != -1 && elf->parent == NULL)
     86     elf->maximum_size = size;
     87 
     88   return size;
     89 }
     90 
     91 
     92 off_t
     93 elf_update (elf, cmd)
     94      Elf *elf;
     95      Elf_Cmd cmd;
     96 {
     97   size_t shnum;
     98   off_t size;
     99   int change_bo = 0;
    100 
    101   if (cmd != ELF_C_NULL
    102       && cmd != ELF_C_WRITE
    103       && unlikely (cmd != ELF_C_WRITE_MMAP))
    104     {
    105       __libelf_seterrno (ELF_E_INVALID_CMD);
    106       return -1;
    107     }
    108 
    109   if (elf == NULL)
    110     return -1;
    111 
    112   if (elf->kind != ELF_K_ELF)
    113     {
    114       __libelf_seterrno (ELF_E_INVALID_HANDLE);
    115       return -1;
    116     }
    117 
    118   rwlock_rdlock (elf->lock);
    119 
    120   /* Make sure we have an ELF header.  */
    121   if (elf->state.elf.ehdr == NULL)
    122     {
    123       __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
    124       size = -1;
    125       goto out;
    126     }
    127 
    128   /* Determine the number of sections.  */
    129   shnum = (elf->state.elf.scns_last->cnt == 0
    130 	   ? 0
    131 	   : 1 + elf->state.elf.scns_last->data[elf->state.elf.scns_last->cnt - 1].index);
    132 
    133   /* Update the ELF descriptor.  First, place the program header.  It
    134      will come right after the ELF header.  The count the size of all
    135      sections and finally place the section table.  */
    136   size = (elf->class == ELFCLASS32
    137 	  ? __elf32_updatenull (elf, &change_bo, shnum)
    138 	  : __elf64_updatenull (elf, &change_bo, shnum));
    139   if (likely (size != -1)
    140       /* See whether we actually have to write out the data.  */
    141       && (cmd == ELF_C_WRITE || cmd == ELF_C_WRITE_MMAP))
    142     {
    143       if (elf->cmd != ELF_C_RDWR
    144 	  && elf->cmd != ELF_C_RDWR_MMAP
    145 	  && elf->cmd != ELF_C_WRITE
    146 	  && unlikely (elf->cmd != ELF_C_WRITE_MMAP))
    147 	{
    148 	  __libelf_seterrno (ELF_E_UPDATE_RO);
    149 	  size = -1;
    150 	}
    151       else if (unlikely (elf->fildes == -1))
    152 	{
    153 	  /* We closed the file already.  */
    154 	  __libelf_seterrno (ELF_E_FD_DISABLED);
    155 	  size = -1;
    156 	}
    157       else
    158 	{
    159 	  if (elf->parent != NULL)
    160 	    {
    161 	      extern int puts (const char *);
    162 	      puts ("this is an archive member");
    163 	    }
    164 
    165 	  size = write_file (elf, size, change_bo, shnum);
    166 	}
    167     }
    168 
    169  out:
    170   rwlock_unlock (elf->lock);
    171 
    172   return size;
    173 }
    174