• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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