Branch data Line data Source code
1 : : /* Return section header.
2 : : Copyright (C) 1998-2002, 2005, 2007, 2009, 2012, 2014, 2015 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 1998.
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 <errno.h>
36 : : #include <stdbool.h>
37 : :
38 : : #include "libelfP.h"
39 : : #include "common.h"
40 : :
41 : : #ifndef LIBELFBITS
42 : : # define LIBELFBITS 32
43 : : #endif
44 : :
45 : :
46 : : static ElfW2(LIBELFBITS,Shdr) *
47 : 4843 : load_shdr_wrlock (Elf_Scn *scn)
48 : : {
49 : 4843 : ElfW2(LIBELFBITS,Shdr) *result;
50 : :
51 : : /* Read the section header table. */
52 : 4843 : Elf *elf = scn->elf;
53 : 4843 : ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
54 : :
55 : : /* Try again, maybe the data is there now. */
56 : 4843 : result = scn->shdr.ELFW(e,LIBELFBITS);
57 [ - + ]: 4843 : if (result != NULL)
58 : 0 : goto out;
59 : :
60 : 4843 : size_t shnum;
61 [ + - ]: 4843 : if (__elf_getshdrnum_rdlock (elf, &shnum) != 0
62 [ - + ]: 4843 : || shnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Shdr)))
63 : 0 : goto out;
64 : 4843 : size_t size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr));
65 : :
66 : : /* Allocate memory for the section headers. We know the number
67 : : of entries from the ELF header. */
68 : 4843 : ElfW2(LIBELFBITS,Shdr) *shdr = elf->state.ELFW(elf,LIBELFBITS).shdr =
69 : 4843 : (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
70 [ - + ]: 4843 : if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
71 : : {
72 : 0 : __libelf_seterrno (ELF_E_NOMEM);
73 : 0 : goto out;
74 : : }
75 : 4843 : elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1;
76 : :
77 [ + + ]: 4843 : if (elf->map_address != NULL)
78 : : {
79 : : /* First see whether the information in the ELF header is
80 : : valid and it does not ask for too much. */
81 [ + - ]: 2667 : if (unlikely (ehdr->e_shoff >= elf->maximum_size)
82 [ - + ]: 2667 : || unlikely (elf->maximum_size - ehdr->e_shoff < size))
83 : : {
84 : : /* Something is wrong. */
85 : 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
86 : 0 : goto free_and_out;
87 : : }
88 : :
89 : 2667 : ElfW2(LIBELFBITS,Shdr) *notcvt;
90 : :
91 : : /* All the data is already mapped. If we could use it
92 : : directly this would already have happened. Unless
93 : : we allocated the memory ourselves and the ELF_F_MALLOCED
94 : : flag is set. */
95 : 2667 : void *file_shdr = ((char *) elf->map_address
96 : 2667 : + elf->start_offset + ehdr->e_shoff);
97 : :
98 [ + + + + : 2667 : assert ((elf->flags & ELF_F_MALLOCED)
- + ]
99 : : || ehdr->e_ident[EI_DATA] != MY_ELFDATA
100 : : || elf->cmd == ELF_C_READ_MMAP
101 : : || (! ALLOW_UNALIGNED
102 : : && ((uintptr_t) file_shdr
103 : : & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0));
104 : :
105 : : /* Now copy the data and at the same time convert the byte order. */
106 [ + + ]: 2667 : if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
107 : : {
108 [ + + - + ]: 1712 : assert ((elf->flags & ELF_F_MALLOCED)
109 : : || elf->cmd == ELF_C_READ_MMAP
110 : : || ! ALLOW_UNALIGNED);
111 : 1712 : memcpy (shdr, file_shdr, size);
112 : : }
113 : : else
114 : : {
115 : : bool copy = ! (ALLOW_UNALIGNED
116 : : || ((uintptr_t) file_shdr
117 : : & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1))
118 : : == 0);
119 : : if (! copy)
120 : : notcvt = (ElfW2(LIBELFBITS,Shdr) *)
121 : : ((char *) elf->map_address
122 : : + elf->start_offset + ehdr->e_shoff);
123 : : else
124 : : {
125 : : notcvt = (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
126 : : if (unlikely (notcvt == NULL))
127 : : {
128 : : __libelf_seterrno (ELF_E_NOMEM);
129 : : goto out;
130 : : }
131 : : memcpy (notcvt, ((char *) elf->map_address
132 : : + elf->start_offset + ehdr->e_shoff),
133 : : size);
134 : : }
135 : :
136 [ + + ]: 2511138 : for (size_t cnt = 0; cnt < shnum; ++cnt)
137 : : {
138 [ - + ]: 2510183 : CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name);
139 : 2510183 : CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type);
140 [ - + ]: 2510183 : CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags);
141 : 2510183 : CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr);
142 : 2510183 : CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset);
143 : 2510183 : CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size);
144 : 2510183 : CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link);
145 : 2510183 : CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info);
146 : 2510183 : CONVERT_TO (shdr[cnt].sh_addralign,
147 : : notcvt[cnt].sh_addralign);
148 : 2510183 : CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
149 : :
150 : : /* If this is a section with an extended index add a
151 : : reference in the section which uses the extended
152 : : index. */
153 [ - + ]: 2510183 : if (shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
154 [ # # ]: 0 : && shdr[cnt].sh_link < shnum)
155 : 0 : elf->state.ELFW(elf,LIBELFBITS).scns.data[shdr[cnt].sh_link].shndx_index
156 : 0 : = cnt;
157 : :
158 : : /* Set the own shndx_index field in case it has not yet
159 : : been set. */
160 [ + - ]: 2510183 : if (elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index == 0)
161 : 2510183 : elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index
162 : 2510183 : = -1;
163 : : }
164 : :
165 : : if (copy)
166 : : free (notcvt);
167 : : }
168 : : }
169 [ + - ]: 2176 : else if (likely (elf->fildes != -1))
170 : : {
171 : : /* Read the header. */
172 : 4352 : ssize_t n = pread_retry (elf->fildes,
173 : : elf->state.ELFW(elf,LIBELFBITS).shdr, size,
174 : 2176 : elf->start_offset + ehdr->e_shoff);
175 [ - + ]: 2176 : if (unlikely ((size_t) n != size))
176 : : {
177 : : /* Severe problems. We cannot read the data. */
178 : 0 : __libelf_seterrno (ELF_E_READ_ERROR);
179 : 0 : goto free_and_out;
180 : : }
181 : :
182 : : /* If the byte order of the file is not the same as the one
183 : : of the host convert the data now. */
184 [ + + ]: 2176 : if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
185 [ + + ]: 539917 : for (size_t cnt = 0; cnt < shnum; ++cnt)
186 : : {
187 : 539295 : CONVERT (shdr[cnt].sh_name);
188 : 539295 : CONVERT (shdr[cnt].sh_type);
189 : 539295 : CONVERT (shdr[cnt].sh_flags);
190 : 539295 : CONVERT (shdr[cnt].sh_addr);
191 : 539295 : CONVERT (shdr[cnt].sh_offset);
192 : 539295 : CONVERT (shdr[cnt].sh_size);
193 : 539295 : CONVERT (shdr[cnt].sh_link);
194 : 539295 : CONVERT (shdr[cnt].sh_info);
195 : 539295 : CONVERT (shdr[cnt].sh_addralign);
196 : 539295 : CONVERT (shdr[cnt].sh_entsize);
197 : : }
198 : : }
199 : : else
200 : : {
201 : : /* The file descriptor was already enabled and not all data was
202 : : read. Undo the allocation. */
203 : 0 : __libelf_seterrno (ELF_E_FD_DISABLED);
204 : :
205 : 0 : free_and_out:
206 : 0 : free (shdr);
207 : 0 : elf->state.ELFW(elf,LIBELFBITS).shdr = NULL;
208 : 0 : elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 0;
209 : :
210 : 0 : goto out;
211 : : }
212 : :
213 : : /* Set the pointers in the `scn's. */
214 [ + + ]: 6686318 : for (size_t cnt = 0; cnt < shnum; ++cnt)
215 : 6681475 : elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shdr.ELFW(e,LIBELFBITS)
216 : 6681475 : = &elf->state.ELFW(elf,LIBELFBITS).shdr[cnt];
217 : :
218 : 4843 : result = scn->shdr.ELFW(e,LIBELFBITS);
219 [ - + ]: 4843 : assert (result != NULL);
220 : :
221 : 4843 : out:
222 : 4843 : return result;
223 : : }
224 : :
225 : : static bool
226 : 1627209 : scn_valid (Elf_Scn *scn)
227 : : {
228 [ + + ]: 1627209 : if (scn == NULL)
229 : : return false;
230 : :
231 [ - + ]: 1627207 : if (unlikely (scn->elf->state.elf.ehdr == NULL))
232 : : {
233 : 0 : __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
234 : 0 : return false;
235 : : }
236 : :
237 [ - + ]: 1627207 : if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS)))
238 : : {
239 : 0 : __libelf_seterrno (ELF_E_INVALID_CLASS);
240 : 0 : return false;
241 : : }
242 : :
243 : : return true;
244 : : }
245 : :
246 : : ElfW2(LIBELFBITS,Shdr) *
247 : : internal_function
248 : 815712 : __elfw2(LIBELFBITS,getshdr_rdlock) (Elf_Scn *scn)
249 : : {
250 : 815712 : ElfW2(LIBELFBITS,Shdr) *result;
251 : :
252 [ + - ]: 815712 : if (!scn_valid (scn))
253 : : return NULL;
254 : :
255 : 815712 : result = scn->shdr.ELFW(e,LIBELFBITS);
256 [ + + ]: 815712 : if (result == NULL)
257 : : {
258 : 4710 : rwlock_unlock (scn->elf->lock);
259 : 4710 : rwlock_wrlock (scn->elf->lock);
260 : 4710 : result = scn->shdr.ELFW(e,LIBELFBITS);
261 : 4710 : if (result == NULL)
262 : 4710 : result = load_shdr_wrlock (scn);
263 : : }
264 : :
265 : : return result;
266 : : }
267 : :
268 : : ElfW2(LIBELFBITS,Shdr) *
269 : : internal_function
270 : 151 : __elfw2(LIBELFBITS,getshdr_wrlock) (Elf_Scn *scn)
271 : : {
272 : 151 : ElfW2(LIBELFBITS,Shdr) *result;
273 : :
274 [ + - ]: 151 : if (!scn_valid (scn))
275 : : return NULL;
276 : :
277 : 151 : result = scn->shdr.ELFW(e,LIBELFBITS);
278 [ + + ]: 151 : if (result == NULL)
279 : 133 : result = load_shdr_wrlock (scn);
280 : :
281 : : return result;
282 : : }
283 : :
284 : : ElfW2(LIBELFBITS,Shdr) *
285 : 811346 : elfw2(LIBELFBITS,getshdr) (Elf_Scn *scn)
286 : : {
287 : 811346 : ElfW2(LIBELFBITS,Shdr) *result;
288 : :
289 [ + + ]: 811346 : if (!scn_valid (scn))
290 : : return NULL;
291 : :
292 : 811344 : rwlock_rdlock (scn->elf->lock);
293 : 811344 : result = __elfw2(LIBELFBITS,getshdr_rdlock) (scn);
294 : 811344 : rwlock_unlock (scn->elf->lock);
295 : :
296 : 811344 : return result;
297 : : }
|