Branch data Line data Source code
1 : : /* Get symbol information from symbol table at the given index. 2 : : Copyright (C) 1999, 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc. 3 : : This file is part of elfutils. 4 : : Written by Ulrich Drepper <drepper@redhat.com>, 1999. 5 : : 6 : : This file is free software; you can redistribute it and/or modify 7 : : it under the terms of either 8 : : 9 : : * the GNU Lesser General Public License as published by the Free 10 : : Software Foundation; either version 3 of the License, or (at 11 : : your option) any later version 12 : : 13 : : or 14 : : 15 : : * the GNU General Public License as published by the Free 16 : : Software Foundation; either version 2 of the License, or (at 17 : : your option) any later version 18 : : 19 : : or both in parallel, as here. 20 : : 21 : : elfutils is distributed in the hope that it will be useful, but 22 : : WITHOUT ANY WARRANTY; without even the implied warranty of 23 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 : : General Public License for more details. 25 : : 26 : : You should have received copies of the GNU General Public License and 27 : : the GNU Lesser General Public License along with this program. If 28 : : not, see <http://www.gnu.org/licenses/>. */ 29 : : 30 : : #ifdef HAVE_CONFIG_H 31 : : # include <config.h> 32 : : #endif 33 : : 34 : : #include <assert.h> 35 : : #include <gelf.h> 36 : : #include <string.h> 37 : : 38 : : #include "libelfP.h" 39 : : 40 : : 41 : : GElf_Sym * 42 : 389881 : gelf_getsym (Elf_Data *data, int ndx, GElf_Sym *dst) 43 : : { 44 : 389881 : Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data; 45 : 389881 : GElf_Sym *result = NULL; 46 : : 47 [ - + ]: 389881 : if (data == NULL) 48 : : return NULL; 49 : : 50 [ - + ]: 389881 : if (unlikely (data->d_type != ELF_T_SYM)) 51 : : { 52 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE); 53 : 0 : return NULL; 54 : : } 55 : : 56 : 389881 : rwlock_rdlock (data_scn->s->elf->lock); 57 : : 58 : : /* This is the one place where we have to take advantage of the fact 59 : : that an `Elf_Data' pointer is also a pointer to `Elf_Data_Scn'. 60 : : The interface is broken so that it requires this hack. */ 61 [ + + ]: 389881 : if (data_scn->s->elf->class == ELFCLASS32) 62 : : { 63 : 69356 : Elf32_Sym *src; 64 : : 65 : : /* Here it gets a bit more complicated. The format of the symbol 66 : : table entries has to be adopted. The user better has provided 67 : : a buffer where we can store the information. While copying the 68 : : data we are converting the format. */ 69 [ - + ]: 69356 : if (INVALID_NDX (ndx, Elf32_Sym, data)) 70 : : { 71 : 0 : __libelf_seterrno (ELF_E_INVALID_INDEX); 72 : 0 : goto out; 73 : : } 74 : : 75 : 69356 : src = &((Elf32_Sym *) data->d_buf)[ndx]; 76 : : 77 : : /* This might look like a simple copy operation but it's 78 : : not. There are zero- and sign-extensions going on. */ 79 : : #define COPY(name) \ 80 : : dst->name = src->name 81 : 69356 : COPY (st_name); 82 : : /* Please note that we can simply copy the `st_info' element since 83 : : the definitions of ELFxx_ST_BIND and ELFxx_ST_TYPE are the same 84 : : for the 64 bit variant. */ 85 : 69356 : COPY (st_info); 86 : 69356 : COPY (st_other); 87 : 69356 : COPY (st_shndx); 88 : 69356 : COPY (st_value); 89 : 69356 : COPY (st_size); 90 : : } 91 : : else 92 : : { 93 : : /* If this is a 64 bit object it's easy. */ 94 : 320525 : assert (sizeof (GElf_Sym) == sizeof (Elf64_Sym)); 95 : : 96 : : /* The data is already in the correct form. Just make sure the 97 : : index is OK. */ 98 [ - + ]: 320525 : if (INVALID_NDX (ndx, GElf_Sym, data)) 99 : : { 100 : 0 : __libelf_seterrno (ELF_E_INVALID_INDEX); 101 : 0 : goto out; 102 : : } 103 : : 104 : 320525 : *dst = ((GElf_Sym *) data->d_buf)[ndx]; 105 : : } 106 : : 107 : : result = dst; 108 : : 109 : 389881 : out: 110 : 389881 : rwlock_unlock (data_scn->s->elf->lock); 111 : : 112 : 389881 : return result; 113 : : } 114 : : INTDEF(gelf_getsym)