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