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 : 4966 : load_shdr_wrlock (Elf_Scn *scn)
48 : : {
49 : 4966 : ElfW2(LIBELFBITS,Shdr) *result;
50 : :
51 : : /* Read the section header table. */
52 : 4966 : Elf *elf = scn->elf;
53 : 4966 : ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
54 : :
55 : : /* Try again, maybe the data is there now. */
56 : 4966 : result = scn->shdr.ELFW(e,LIBELFBITS);
57 [ - + ]: 4966 : if (result != NULL)
58 : 0 : goto out;
59 : :
60 : 4966 : size_t shnum;
61 [ + - ]: 4966 : if (__elf_getshdrnum_rdlock (elf, &shnum) != 0
62 [ - + ]: 4966 : || shnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Shdr)))
63 : 0 : goto out;
64 : 4966 : 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 : 4966 : ElfW2(LIBELFBITS,Shdr) *shdr = elf->state.ELFW(elf,LIBELFBITS).shdr =
69 : 4966 : (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
70 [ - + ]: 4966 : if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
71 : : {
72 : 0 : __libelf_seterrno (ELF_E_NOMEM);
73 : 0 : goto out;
74 : : }
75 : 4966 : elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1;
76 : :
77 [ + + ]: 4966 : 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 [ + - ]: 2768 : if (unlikely (ehdr->e_shoff >= elf->maximum_size)
82 [ - + ]: 2768 : || 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 : 2768 : 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 : 2768 : void *file_shdr = ((char *) elf->map_address
96 : 2768 : + elf->start_offset + ehdr->e_shoff);
97 : :
98 [ + + + + : 2768 : 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 [ + + ]: 2768 : if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
107 : : {
108 [ + + - + ]: 1818 : assert ((elf->flags & ELF_F_MALLOCED)
109 : : || elf->cmd == ELF_C_READ_MMAP
110 : : || ! ALLOW_UNALIGNED);
111 : 1818 : 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 free_and_out;
130 : : }
131 : : memcpy (notcvt, ((char *) elf->map_address
132 : : + elf->start_offset + ehdr->e_shoff),
133 : : size);
134 : : }
135 : :
136 [ + + ]: 2510982 : for (size_t cnt = 0; cnt < shnum; ++cnt)
137 : : {
138 : 2510032 : CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name);
139 : 2510032 : CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type);
140 : 2510032 : CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags);
141 : 2510032 : CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr);
142 : 2510032 : CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset);
143 : 2510032 : CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size);
144 : 2510032 : CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link);
145 : 2510032 : CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info);
146 : 2510032 : CONVERT_TO (shdr[cnt].sh_addralign,
147 : : notcvt[cnt].sh_addralign);
148 : 2510032 : CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
149 : : }
150 : :
151 : : if (copy)
152 : : free (notcvt);
153 : : }
154 : : }
155 [ + - ]: 2198 : else if (likely (elf->fildes != -1))
156 : : {
157 : : /* Read the header. */
158 : 4396 : ssize_t n = pread_retry (elf->fildes,
159 : : elf->state.ELFW(elf,LIBELFBITS).shdr, size,
160 : 2198 : elf->start_offset + ehdr->e_shoff);
161 [ - + ]: 2198 : if (unlikely ((size_t) n != size))
162 : : {
163 : : /* Severe problems. We cannot read the data. */
164 : 0 : __libelf_seterrno (ELF_E_READ_ERROR);
165 : 0 : goto free_and_out;
166 : : }
167 : :
168 : : /* If the byte order of the file is not the same as the one
169 : : of the host convert the data now. */
170 [ + + ]: 2198 : if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
171 [ + + ]: 539832 : for (size_t cnt = 0; cnt < shnum; ++cnt)
172 : : {
173 : 539202 : CONVERT (shdr[cnt].sh_name);
174 : 539202 : CONVERT (shdr[cnt].sh_type);
175 : 539202 : CONVERT (shdr[cnt].sh_flags);
176 : 539202 : CONVERT (shdr[cnt].sh_addr);
177 : 539202 : CONVERT (shdr[cnt].sh_offset);
178 : 539202 : CONVERT (shdr[cnt].sh_size);
179 : 539202 : CONVERT (shdr[cnt].sh_link);
180 : 539202 : CONVERT (shdr[cnt].sh_info);
181 : 539202 : CONVERT (shdr[cnt].sh_addralign);
182 : 539202 : CONVERT (shdr[cnt].sh_entsize);
183 : : }
184 : : }
185 : : else
186 : : {
187 : : /* The file descriptor was already enabled and not all data was
188 : : read. Undo the allocation. */
189 : 0 : __libelf_seterrno (ELF_E_FD_DISABLED);
190 : :
191 : 0 : free_and_out:
192 : 0 : free (shdr);
193 : 0 : elf->state.ELFW(elf,LIBELFBITS).shdr = NULL;
194 : 0 : elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 0;
195 : :
196 : 0 : goto out;
197 : : }
198 : :
199 : : /* Set the pointers in the `scn's. */
200 [ + + ]: 6948706 : for (size_t cnt = 0; cnt < shnum; ++cnt)
201 : 6943740 : elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shdr.ELFW(e,LIBELFBITS)
202 : 6943740 : = &elf->state.ELFW(elf,LIBELFBITS).shdr[cnt];
203 : :
204 : 4966 : result = scn->shdr.ELFW(e,LIBELFBITS);
205 [ - + ]: 4966 : assert (result != NULL);
206 : :
207 : 4966 : out:
208 : 4966 : return result;
209 : : }
210 : :
211 : : static bool
212 : 1619000 : scn_valid (Elf_Scn *scn)
213 : : {
214 [ + + ]: 1619000 : if (scn == NULL)
215 : : return false;
216 : :
217 [ - + ]: 1618998 : if (unlikely (scn->elf->state.elf.ehdr == NULL))
218 : : {
219 : 0 : __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
220 : 0 : return false;
221 : : }
222 : :
223 [ - + ]: 1618998 : if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS)))
224 : : {
225 : 0 : __libelf_seterrno (ELF_E_INVALID_CLASS);
226 : 0 : return false;
227 : : }
228 : :
229 : : return true;
230 : : }
231 : :
232 : : ElfW2(LIBELFBITS,Shdr) *
233 : : internal_function
234 : 811676 : __elfw2(LIBELFBITS,getshdr_rdlock) (Elf_Scn *scn)
235 : : {
236 : 811676 : ElfW2(LIBELFBITS,Shdr) *result;
237 : :
238 [ + - ]: 811676 : if (!scn_valid (scn))
239 : : return NULL;
240 : :
241 : 811676 : result = scn->shdr.ELFW(e,LIBELFBITS);
242 [ + + ]: 811676 : if (result == NULL)
243 : : {
244 : 4838 : rwlock_unlock (scn->elf->lock);
245 : 4838 : rwlock_wrlock (scn->elf->lock);
246 : 4838 : result = scn->shdr.ELFW(e,LIBELFBITS);
247 : 4838 : if (result == NULL)
248 : 4838 : result = load_shdr_wrlock (scn);
249 : : }
250 : :
251 : : return result;
252 : : }
253 : :
254 : : ElfW2(LIBELFBITS,Shdr) *
255 : : internal_function
256 : 146 : __elfw2(LIBELFBITS,getshdr_wrlock) (Elf_Scn *scn)
257 : : {
258 : 146 : ElfW2(LIBELFBITS,Shdr) *result;
259 : :
260 [ + - ]: 146 : if (!scn_valid (scn))
261 : : return NULL;
262 : :
263 : 146 : result = scn->shdr.ELFW(e,LIBELFBITS);
264 [ + + ]: 146 : if (result == NULL)
265 : 128 : result = load_shdr_wrlock (scn);
266 : :
267 : : return result;
268 : : }
269 : :
270 : : ElfW2(LIBELFBITS,Shdr) *
271 : 807178 : elfw2(LIBELFBITS,getshdr) (Elf_Scn *scn)
272 : : {
273 : 807178 : ElfW2(LIBELFBITS,Shdr) *result;
274 : :
275 [ + + ]: 807178 : if (!scn_valid (scn))
276 : : return NULL;
277 : :
278 : 807176 : rwlock_rdlock (scn->elf->lock);
279 : 807176 : result = __elfw2(LIBELFBITS,getshdr_rdlock) (scn);
280 : 807176 : rwlock_unlock (scn->elf->lock);
281 : :
282 : 807176 : return result;
283 : : }
|