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