Home | History | Annotate | Download | only in libelf
      1 /* Update symbol information and section index in symbol table at the
      2    given index.
      3    Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 2000.
      5 
      6    This program is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation, version 2.
      9 
     10    This program is distributed in the hope that it will be useful,
     11    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License
     16    along with this program; if not, write to the Free Software Foundation,
     17    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
     18 
     19 #ifdef HAVE_CONFIG_H
     20 # include <config.h>
     21 #endif
     22 
     23 #include <gelf.h>
     24 #include <stdlib.h>
     25 #include <string.h>
     26 
     27 #include "libelfP.h"
     28 
     29 
     30 int
     31 gelf_update_symshndx (symdata, shndxdata, ndx, src, srcshndx)
     32      Elf_Data *symdata;
     33      Elf_Data *shndxdata;
     34      int ndx;
     35      GElf_Sym *src;
     36      Elf32_Word srcshndx;
     37 {
     38   Elf_Data_Scn *symdata_scn = (Elf_Data_Scn *) symdata;
     39   Elf_Data_Scn *shndxdata_scn = (Elf_Data_Scn *) shndxdata;
     40   Elf_Scn *scn;
     41   Elf32_Word *shndx = NULL;
     42   int result = 0;
     43 
     44   if (symdata == NULL)
     45     return 0;
     46 
     47   if (unlikely (ndx < 0))
     48     {
     49       __libelf_seterrno (ELF_E_INVALID_INDEX);
     50       return 0;
     51     }
     52 
     53   if (unlikely (symdata_scn->d.d_type != ELF_T_SYM))
     54     {
     55       /* The type of the data better should match.  */
     56       __libelf_seterrno (ELF_E_DATA_MISMATCH);
     57       return 0;
     58     }
     59 
     60   scn = symdata_scn->s;
     61   /* We simply have to believe the user that the two sections belong to
     62      the same ELF file.  */
     63   rwlock_wrlock (scn->elf->lock);
     64 
     65   /* The user is not required to pass a data descriptor for an extended
     66      section index table.  */
     67   if (shndxdata_scn != NULL)
     68     {
     69       if (unlikely ((ndx + 1) * sizeof (Elf32_Word) > shndxdata_scn->d.d_size))
     70 	{
     71 	  __libelf_seterrno (ELF_E_INVALID_INDEX);
     72 	  goto out;
     73 	}
     74 
     75       shndx = &((Elf32_Word *) shndxdata_scn->d.d_buf)[ndx];
     76     }
     77   /* But if s/he does not the extended sectio index must be zero.  */
     78   else if (unlikely (srcshndx != 0))
     79     {
     80       __libelf_seterrno (ELF_E_INVALID_INDEX);
     81       goto out;
     82     }
     83 
     84   if (scn->elf->class == ELFCLASS32)
     85     {
     86       Elf32_Sym *sym;
     87 
     88       /* There is the possibility that the values in the input are
     89 	 too large.  */
     90       if (unlikely (src->st_value > 0xffffffffull)
     91 	  || unlikely (src->st_size > 0xffffffffull))
     92 	{
     93 	  __libelf_seterrno (ELF_E_INVALID_DATA);
     94 	  goto out;
     95 	}
     96 
     97       /* Check whether we have to resize the data buffer.  */
     98       if (unlikely ((ndx + 1) * sizeof (Elf32_Sym) > symdata_scn->d.d_size))
     99 	{
    100 	  __libelf_seterrno (ELF_E_INVALID_INDEX);
    101 	  goto out;
    102 	}
    103 
    104       sym = &((Elf32_Sym *) symdata_scn->d.d_buf)[ndx];
    105 
    106 #define COPY(name) \
    107       sym->name = src->name
    108       COPY (st_name);
    109       COPY (st_value);
    110       COPY (st_size);
    111       /* Please note that we can simply copy the `st_info' element since
    112 	 the definitions of ELFxx_ST_BIND and ELFxx_ST_TYPE are the same
    113 	 for the 64 bit variant.  */
    114       COPY (st_info);
    115       COPY (st_other);
    116       COPY (st_shndx);
    117     }
    118   else
    119     {
    120       /* Check whether we have to resize the data buffer.  */
    121       if (unlikely ((ndx + 1) * sizeof (Elf64_Sym) > symdata_scn->d.d_size))
    122 	{
    123 	  __libelf_seterrno (ELF_E_INVALID_INDEX);
    124 	  goto out;
    125 	}
    126 
    127       ((Elf64_Sym *) symdata_scn->d.d_buf)[ndx] = *src;
    128     }
    129 
    130   /* Now we can store the section index.  */
    131   if (shndx != NULL)
    132     *shndx = srcshndx;
    133 
    134   result = 1;
    135 
    136   /* Mark the section as modified.  */
    137   scn->flags |= ELF_F_DIRTY;
    138 
    139  out:
    140   rwlock_unlock (scn->elf->lock);
    141 
    142   return result;
    143 }
    144