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