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