Home | History | Annotate | Download | only in libelf
      1 /* Get symbol information and separate section index from symbol table
      2    at the 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 <assert.h>
     24 #include <gelf.h>
     25 #include <string.h>
     26 
     27 #include "libelfP.h"
     28 
     29 
     30 GElf_Sym *
     31 gelf_getsymshndx (symdata, shndxdata, ndx, dst, dstshndx)
     32      Elf_Data *symdata;
     33      Elf_Data *shndxdata;
     34      int ndx;
     35      GElf_Sym *dst;
     36      Elf32_Word *dstshndx;
     37 {
     38   Elf_Data_Scn *symdata_scn = (Elf_Data_Scn *) symdata;
     39   Elf_Data_Scn *shndxdata_scn = (Elf_Data_Scn *) shndxdata;
     40   GElf_Sym *result = NULL;
     41   Elf32_Word shndx = 0;
     42 
     43   if (symdata == NULL)
     44     return NULL;
     45 
     46   if (unlikely (symdata->d_type != ELF_T_SYM)
     47       || (likely (shndxdata_scn != NULL)
     48 	  && unlikely (shndxdata->d_type != ELF_T_WORD)))
     49     {
     50       __libelf_seterrno (ELF_E_INVALID_HANDLE);
     51       return NULL;
     52     }
     53 
     54   rwlock_rdlock (symdata_scn->s->elf->lock);
     55 
     56   /* The user is not required to pass a data descriptor for an extended
     57      section index table.  */
     58   if (likely (shndxdata_scn != NULL))
     59     {
     60       if (unlikely ((ndx + 1) * sizeof (Elf32_Word) > shndxdata_scn->d.d_size))
     61 	{
     62 	  __libelf_seterrno (ELF_E_INVALID_INDEX);
     63 	  goto out;
     64 	}
     65 
     66       shndx = ((Elf32_Word *) shndxdata_scn->d.d_buf)[ndx];
     67     }
     68 
     69   /* This is the one place where we have to take advantage of the fact
     70      that an `Elf_Data' pointer is also a pointer to `Elf_Data_Scn'.
     71      The interface is broken so that it requires this hack.  */
     72   if (symdata_scn->s->elf->class == ELFCLASS32)
     73     {
     74       Elf32_Sym *src;
     75 
     76       /* Here it gets a bit more complicated.  The format of the symbol
     77 	 table entries has to be adopted.  The user better has provided
     78 	 a buffer where we can store the information.  While copying the
     79 	 data we are converting the format.  */
     80       if (unlikely ((ndx + 1) * sizeof (Elf32_Sym) > symdata->d_size))
     81 	{
     82 	  __libelf_seterrno (ELF_E_INVALID_INDEX);
     83 	  goto out;
     84 	}
     85 
     86       src = &((Elf32_Sym *) symdata->d_buf)[ndx];
     87 
     88       /* This might look like a simple copy operation but it's
     89 	 not.  There are zero- and sign-extensions going on.  */
     90 #define COPY(name) \
     91       dst->name = src->name
     92       COPY (st_name);
     93       /* Please note that we can simply copy the `st_info' element since
     94 	 the definitions of ELFxx_ST_BIND and ELFxx_ST_TYPE are the same
     95 	 for the 64 bit variant.  */
     96       COPY (st_info);
     97       COPY (st_other);
     98       COPY (st_shndx);
     99       COPY (st_value);
    100       COPY (st_size);
    101     }
    102   else
    103     {
    104       /* If this is a 64 bit object it's easy.  */
    105       assert (sizeof (GElf_Sym) == sizeof (Elf64_Sym));
    106 
    107       /* The data is already in the correct form.  Just make sure the
    108 	 index is OK.  */
    109       if (unlikely ((ndx + 1) * sizeof (GElf_Sym) > symdata->d_size))
    110 	{
    111 	  __libelf_seterrno (ELF_E_INVALID_INDEX);
    112 	  goto out;
    113 	}
    114 
    115       *dst = ((GElf_Sym *) symdata->d_buf)[ndx];
    116     }
    117 
    118   /* Now we can store the section index.  */
    119   if (dstshndx != NULL)
    120     *dstshndx = shndx;
    121 
    122   result = dst;
    123 
    124  out:
    125   rwlock_unlock (symdata_scn->s->elf->lock);
    126 
    127   return result;
    128 }
    129