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