Branch data Line data Source code
1 : : /* Update data structures for changes.
2 : : Copyright (C) 2000-2010, 2015, 2016 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2000.
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 <libelf.h>
36 : : #include <stdbool.h>
37 : : #include <string.h>
38 : :
39 : : #include "libelfP.h"
40 : : #include "elf-knowledge.h"
41 : :
42 : : #ifndef LIBELFBITS
43 : : # define LIBELFBITS 32
44 : : #endif
45 : :
46 : : /* Some fields contain 32/64 sizes. We cannot use Elf32/64_Word for those,
47 : : since those are both 32bits. Elf32/64_Xword is always 64bits. */
48 : : #define Elf32_SizeWord Elf32_Word
49 : : #define Elf64_SizeWord Elf64_Xword
50 : :
51 : :
52 : : static int
53 : 1466 : ELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
54 : : size_t shnum, int *change_bop)
55 : : {
56 : : /* Always write the magic bytes. */
57 [ + + ]: 1466 : if (memcmp (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
58 : : {
59 : 566 : memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
60 : 566 : elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
61 : : }
62 : :
63 : : /* Always set the file class. */
64 [ + + ]: 1466 : update_if_changed (ehdr->e_ident[EI_CLASS], ELFW(ELFCLASS,LIBELFBITS),
65 : : elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
66 : :
67 : : /* Set the data encoding if necessary. */
68 [ + + ]: 1466 : if (unlikely (ehdr->e_ident[EI_DATA] == ELFDATANONE))
69 : : {
70 : 8 : ehdr->e_ident[EI_DATA] =
71 : : BYTE_ORDER == BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB;
72 : 8 : elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
73 : : }
74 [ - + ]: 1458 : else if (unlikely (ehdr->e_ident[EI_DATA] >= ELFDATANUM))
75 : : {
76 : 0 : __libelf_seterrno (ELF_E_DATA_ENCODING);
77 : 0 : return 1;
78 : : }
79 : : else
80 : 1458 : *change_bop = ((BYTE_ORDER == LITTLE_ENDIAN
81 : : && ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
82 : 1458 : || (BYTE_ORDER == BIG_ENDIAN
83 : : && ehdr->e_ident[EI_DATA] != ELFDATA2MSB));
84 : :
85 : : /* Unconditionally overwrite the ELF version. */
86 [ + + ]: 1466 : update_if_changed (ehdr->e_ident[EI_VERSION], EV_CURRENT,
87 : : elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
88 : :
89 [ + + ]: 1466 : if (unlikely (ehdr->e_version == EV_NONE))
90 : : {
91 : 8 : ehdr->e_version = EV_CURRENT;
92 : 8 : elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
93 : : }
94 [ - + ]: 1458 : else if (unlikely (ehdr->e_version != EV_CURRENT))
95 : : {
96 : 0 : __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
97 : 0 : return 1;
98 : : }
99 : :
100 [ + + ]: 1466 : if (unlikely (shnum >= SHN_LORESERVE))
101 : : {
102 [ + + ]: 38 : update_if_changed (ehdr->e_shnum, 0,
103 : : elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
104 : : }
105 : : else
106 [ + + ]: 1428 : update_if_changed (ehdr->e_shnum, shnum,
107 : : elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
108 : :
109 [ + + ]: 1466 : if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)))
110 : : {
111 : 946 : ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
112 : 946 : elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
113 : : }
114 : :
115 : : /* If phnum is zero make sure e_phoff is also zero and not some random
116 : : value. That would cause trouble in update_file. */
117 [ + + + - ]: 1466 : if (ehdr->e_phnum == 0 && ehdr->e_phoff != 0)
118 : : {
119 : 0 : ehdr->e_phoff = 0;
120 : 0 : elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
121 : : }
122 : :
123 : : return 0;
124 : : }
125 : :
126 : :
127 : : int64_t
128 : : internal_function
129 : 1466 : __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
130 : : {
131 : 1466 : ElfW2(LIBELFBITS,Ehdr) *ehdr;
132 : 1466 : int changed = 0;
133 : 1466 : int ehdr_flags = 0;
134 : :
135 : 1466 : ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
136 : :
137 : : /* Set the default values. */
138 [ + - ]: 1466 : if (ehdr == NULL
139 [ - + ]: 1466 : || ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
140 : 0 : return -1;
141 : :
142 : : /* At least the ELF header is there. */
143 : 1466 : ElfW2(LIBELFBITS,SizeWord) size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
144 : :
145 : : /* Set the program header position. */
146 [ + + ]: 1466 : if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
147 : 668 : (void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
148 [ + + ]: 1466 : if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
149 : : {
150 : 854 : size_t phnum;
151 [ - + ]: 854 : if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
152 : 0 : return -1;
153 : :
154 [ + + ]: 854 : if (elf->flags & ELF_F_LAYOUT)
155 : : {
156 : : /* The user is supposed to fill out e_phoff. Use it and
157 : : e_phnum to determine the maximum extend. */
158 : 724 : size = MAX (size,
159 : : ehdr->e_phoff
160 : : + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
161 : : }
162 : : else
163 : : {
164 [ + + ]: 130 : update_if_changed (ehdr->e_phoff,
165 : : elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
166 : : ehdr_flags);
167 : :
168 : : /* We need no alignment here. */
169 : 130 : size += elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum);
170 : : }
171 : : }
172 : :
173 [ + + ]: 1466 : if (shnum > 0)
174 : : {
175 : 1436 : struct Elf_Scn *scn1 = NULL;
176 : 1436 : Elf_ScnList *list;
177 : 1436 : bool first = true;
178 : :
179 [ - + ]: 1436 : assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0);
180 : :
181 [ + + ]: 1436 : if (shnum >= SHN_LORESERVE)
182 : : {
183 : : /* We have to fill in the number of sections in the header
184 : : of the zeroth section. */
185 : 38 : Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
186 : :
187 : : /* Make sure section zero header is actually loaded. */
188 [ + + ]: 38 : if (scn0->shdr.ELFW(e,LIBELFBITS) == NULL)
189 : 2 : (void) __elfw2(LIBELFBITS,getshdr_wrlock) (scn0);
190 : :
191 [ + + ]: 38 : update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
192 : : shnum, scn0->shdr_flags);
193 : : }
194 : :
195 : : /* Go over all sections and find out how large they are. */
196 : 1436 : list = &elf->state.ELFW(elf,LIBELFBITS).scns;
197 : :
198 : : /* Find the first section. */
199 [ + + ]: 1436 : if (list->cnt > 1)
200 : 1428 : scn1 = &list->data[1];
201 [ + - ]: 8 : else if (list->next != NULL)
202 : 8 : scn1 = &list->next->data[0];
203 : :
204 : : /* Load the section headers if necessary. This loads the
205 : : headers for all sections. */
206 [ + + ]: 1436 : if (scn1 != NULL && scn1->shdr.ELFW(e,LIBELFBITS) == NULL)
207 : 58 : (void) __elfw2(LIBELFBITS,getshdr_wrlock) (scn1);
208 : :
209 : 3398 : do
210 : : {
211 [ + + ]: 4098008 : for (size_t cnt = first == true; cnt < list->cnt; ++cnt)
212 : : {
213 : 4094610 : Elf_Scn *scn = &list->data[cnt];
214 : 4094610 : ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
215 : 4094610 : int64_t offset = 0;
216 : :
217 [ - + ]: 4094610 : assert (shdr != NULL);
218 : 4094610 : ElfW2(LIBELFBITS,SizeWord) sh_entsize = shdr->sh_entsize;
219 : 4094610 : ElfW2(LIBELFBITS,SizeWord) sh_align = shdr->sh_addralign ?: 1;
220 [ - + ]: 4094610 : if (unlikely (! powerof2 (sh_align)))
221 : : {
222 : 0 : __libelf_seterrno (ELF_E_INVALID_ALIGN);
223 : 0 : return -1;
224 : : }
225 : :
226 : : /* Set the sh_entsize value if we can reliably detect it. */
227 [ + + + + : 4094610 : switch (shdr->sh_type)
+ + + + -
- - + ]
228 : : {
229 : 1070 : case SHT_SYMTAB:
230 : 1070 : sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
231 : 1070 : break;
232 : 2198 : case SHT_RELA:
233 : 2198 : sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELA, 1);
234 : 2198 : break;
235 : 44052 : case SHT_GROUP:
236 : : /* Only relocatable files can contain section groups. */
237 [ - + ]: 44052 : if (ehdr->e_type != ET_REL)
238 : : {
239 : 0 : __libelf_seterrno (ELF_E_GROUP_NOT_REL);
240 : 0 : return -1;
241 : : }
242 : 44060 : FALLTHROUGH;
243 : : case SHT_SYMTAB_SHNDX:
244 : 44060 : sh_entsize = elf_typesize (32, ELF_T_WORD, 1);
245 : 44060 : break;
246 : 264 : case SHT_HASH:
247 [ + + + + : 264 : sh_entsize = SH_ENTSIZE_HASH (ehdr);
+ + ]
248 : : break;
249 : 472 : case SHT_DYNAMIC:
250 : 472 : sh_entsize = elf_typesize (LIBELFBITS, ELF_T_DYN, 1);
251 : 472 : break;
252 : 428 : case SHT_REL:
253 : 428 : sh_entsize = elf_typesize (LIBELFBITS, ELF_T_REL, 1);
254 : 428 : break;
255 : 468 : case SHT_DYNSYM:
256 : 468 : sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
257 : 468 : break;
258 : 0 : case SHT_SUNW_move:
259 : 0 : sh_entsize = elf_typesize (LIBELFBITS, ELF_T_MOVE, 1);
260 : 0 : break;
261 : 0 : case SHT_SUNW_syminfo:
262 : 0 : sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
263 : 0 : break;
264 : 0 : case SHT_RELR:
265 : 0 : sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELR, 1);
266 : 0 : break;
267 : : default:
268 : : break;
269 : : }
270 : :
271 : : /* If the section header contained the wrong entry size
272 : : correct it and mark the header as modified. */
273 [ + + ]: 4094610 : update_if_changed (shdr->sh_entsize, sh_entsize,
274 : : scn->shdr_flags);
275 : :
276 : : /* Likewise for the alignment of a compressed section.
277 : : For a SHF_COMPRESSED section set the correct
278 : : sh_addralign value, which must match the d_align of
279 : : the data (see __libelf_set_rawdata in elf_getdata.c). */
280 [ + + ]: 4094610 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
281 : : {
282 : 1000 : sh_align = __libelf_type_align (ELFW(ELFCLASS,LIBELFBITS),
283 : : ELF_T_CHDR);
284 [ + + ]: 1000 : update_if_changed (shdr->sh_addralign, sh_align,
285 : : scn->shdr_flags);
286 : : }
287 : :
288 [ + + ]: 4094610 : if (scn->data_read == 0
289 [ - + ]: 789554 : && __libelf_set_rawdata_wrlock (scn) != 0)
290 : : /* Something went wrong. The error value is already set. */
291 : : return -1;
292 : :
293 : : /* Iterate over all data blocks. */
294 [ + + ]: 4094610 : if (list->data[cnt].data_list_rear != NULL)
295 : : {
296 : 3305044 : Elf_Data_List *dl = &scn->data_list;
297 : :
298 [ + + ]: 6610452 : while (dl != NULL)
299 : : {
300 : 3305408 : Elf_Data *data = &dl->data.d;
301 [ + + + + ]: 3305408 : if (dl == &scn->data_list && data->d_buf == NULL
302 [ - + ]: 135762 : && scn->rawdata.d.d_buf != NULL)
303 : 0 : data = &scn->rawdata.d;
304 : :
305 [ - + ]: 3305408 : if (unlikely (data->d_version != EV_CURRENT))
306 : : {
307 : 0 : __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
308 : 0 : return -1;
309 : : }
310 : :
311 [ - + ]: 3305408 : if (unlikely (! powerof2 (data->d_align)))
312 : : {
313 : 0 : __libelf_seterrno (ELF_E_INVALID_ALIGN);
314 : 0 : return -1;
315 : : }
316 : :
317 : 3305408 : sh_align = MAX (sh_align, data->d_align);
318 : :
319 [ + + ]: 3305408 : if (elf->flags & ELF_F_LAYOUT)
320 : : {
321 : : /* The user specified the offset and the size.
322 : : All we have to do is check whether this block
323 : : fits in the size specified for the section. */
324 [ - + ]: 802404 : if (unlikely ((ElfW2(LIBELFBITS,SizeWord))
325 : : (data->d_off + data->d_size)
326 : : > shdr->sh_size))
327 : : {
328 : 0 : __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
329 : 0 : return -1;
330 : : }
331 : : }
332 : : else
333 : : {
334 : : /* Determine the padding. */
335 : 2503004 : offset = ((offset + data->d_align - 1)
336 : 2503004 : & ~(data->d_align - 1));
337 : :
338 [ + + ]: 2503004 : update_if_changed (data->d_off, offset, changed);
339 : :
340 : 2503004 : offset += data->d_size;
341 : : }
342 : :
343 : : /* Next data block. */
344 : 3305408 : dl = dl->next;
345 : : }
346 : : }
347 : : else
348 : : /* Get the size of the section from the raw data. If
349 : : none is available the value is zero. */
350 : 789566 : offset += scn->rawdata.d.d_size;
351 : :
352 [ + + ]: 4094610 : if (elf->flags & ELF_F_LAYOUT)
353 : : {
354 [ + + ]: 803738 : size = MAX (size,
355 : : (shdr->sh_type != SHT_NOBITS
356 : : ? shdr->sh_offset + shdr->sh_size : 0));
357 : :
358 : : /* The alignment must be a power of two. This is a
359 : : requirement from the ELF specification. Additionally
360 : : we test for the alignment of the section being large
361 : : enough for the largest alignment required by a data
362 : : block. */
363 [ + - ]: 803738 : if (unlikely (! powerof2 (shdr->sh_addralign))
364 [ - + ]: 803738 : || unlikely ((shdr->sh_addralign ?: 1) < sh_align))
365 : : {
366 : 0 : __libelf_seterrno (ELF_E_INVALID_ALIGN);
367 : 0 : return -1;
368 : : }
369 : : }
370 : : else
371 : : {
372 : : /* How much alignment do we need for this section. */
373 [ + + ]: 3290872 : update_if_changed (shdr->sh_addralign, sh_align,
374 : : scn->shdr_flags);
375 : :
376 : 3290872 : size = (size + sh_align - 1) & ~(sh_align - 1);
377 : 3290872 : int offset_changed = 0;
378 [ + + ]: 3290872 : update_if_changed (shdr->sh_offset, size, offset_changed);
379 : 5530042 : changed |= offset_changed;
380 : :
381 [ + + ]: 2239170 : if (offset_changed && scn->data_list_rear == NULL)
382 : : {
383 : : /* The position of the section in the file
384 : : changed. Create the section data list. */
385 [ - + ]: 262536 : if (__elf_getdata_rdlock (scn, NULL) == NULL)
386 : : return -1;
387 : : }
388 : :
389 : : /* See whether the section size is correct. */
390 : 3290872 : int size_changed = 0;
391 [ + + ]: 3290872 : update_if_changed (shdr->sh_size,
392 : : (ElfW2(LIBELFBITS,SizeWord)) offset,
393 : : size_changed);
394 : 3290872 : changed |= size_changed;
395 : :
396 [ + + ]: 3290872 : if (shdr->sh_type != SHT_NOBITS)
397 : 3156434 : size += offset;
398 : :
399 : 3290872 : scn->shdr_flags |= (offset_changed | size_changed);
400 : 3290872 : scn->flags |= changed;
401 : : }
402 : :
403 : : /* Check that the section size is actually a multiple of
404 : : the entry size. */
405 [ + + ]: 4094610 : if (shdr->sh_entsize != 0 && shdr->sh_entsize != 1
406 [ + - ]: 52278 : && (elf->flags & ELF_F_PERMISSIVE) == 0)
407 : : {
408 : : /* For compressed sections check the uncompressed size. */
409 : 52278 : ElfW2(LIBELFBITS,SizeWord) sh_size;
410 [ + + ]: 52278 : if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
411 : 52260 : sh_size = shdr->sh_size;
412 : : else
413 : : {
414 : 18 : ElfW2(LIBELFBITS,Chdr) *chdr;
415 : 18 : chdr = __elfw2(LIBELFBITS,getchdr_wrlock) (scn);
416 [ - + ]: 18 : if (unlikely (chdr == NULL))
417 : : return -1;
418 : 18 : sh_size = chdr->ch_size;
419 : : }
420 : :
421 [ - + ]: 52278 : if (unlikely (sh_size % shdr->sh_entsize != 0))
422 : : {
423 : 0 : __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
424 : 0 : return -1;
425 : : }
426 : : }
427 : : }
428 : :
429 [ + + - + ]: 3398 : assert (list->next == NULL || list->cnt == list->max);
430 : :
431 : 3398 : first = false;
432 : : }
433 [ + + ]: 3398 : while ((list = list->next) != NULL);
434 : :
435 : : /* Store section information. */
436 [ + + ]: 1436 : update_if_changed (ehdr->e_shentsize,
437 : : elf_typesize (LIBELFBITS, ELF_T_SHDR, 1), ehdr_flags);
438 [ + + ]: 1436 : if (elf->flags & ELF_F_LAYOUT)
439 : : {
440 : : /* The user is supposed to fill out e_shoff. Use it and
441 : : e_shnum (or sh_size of the dummy, first section header)
442 : : to determine the maximum extend. */
443 : 768 : size = MAX (size,
444 : : (ehdr->e_shoff
445 : : + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
446 : : }
447 : : else
448 : : {
449 : : /* Align for section header table.
450 : :
451 : : Yes, we use `sizeof' and not `__alignof__' since we do not
452 : : want to be surprised by architectures with less strict
453 : : alignment rules. */
454 : : #define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
455 : 668 : size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
456 : :
457 [ + + ]: 668 : update_if_changed (ehdr->e_shoff, size, elf->flags);
458 : :
459 : : /* Account for the section header size. */
460 : 668 : size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
461 : : }
462 : : }
463 : :
464 : 1466 : elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
465 : :
466 : 1466 : return size;
467 : : }
|