• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 *
gelf_getsymshndx(symdata,shndxdata,ndx,dst,dstshndx)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