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@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
gelf_update_symshndx(symdata,shndxdata,ndx,src,srcshndx)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