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 <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
50 static int
ELFW(default_ehdr,LIBELFBITS)51 ELFW(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_CURRENT))
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
125 off_t
126 internal_function
__elfw2(LIBELFBITS,updatenull_wrlock)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_CURRENT))
284 {
285 __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
286 return -1;
287 }
288
289 if (unlikely (! powerof2 (data->d_align)))
290 {
291 __libelf_seterrno (ELF_E_INVALID_ALIGN);
292 return -1;
293 }
294
295 sh_align = MAX (sh_align, data->d_align);
296
297 if (elf->flags & ELF_F_LAYOUT)
298 {
299 /* The user specified the offset and the size.
300 All we have to do is check whether this block
301 fits in the size specified for the section. */
302 if (unlikely ((GElf_Word) (data->d_off
303 + data->d_size)
304 > shdr->sh_size))
305 {
306 __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
307 return -1;
308 }
309 }
310 else
311 {
312 /* Determine the padding. */
313 offset = ((offset + data->d_align - 1)
314 & ~(data->d_align - 1));
315
316 update_if_changed (data->d_off, offset, changed);
317
318 offset += data->d_size;
319 }
320
321 /* Next data block. */
322 dl = dl->next;
323 }
324 }
325 else
326 /* Get the size of the section from the raw data. If
327 none is available the value is zero. */
328 offset += scn->rawdata.d.d_size;
329
330 if (elf->flags & ELF_F_LAYOUT)
331 {
332 size = MAX ((GElf_Word) size,
333 (shdr->sh_type != SHT_NOBITS
334 ? shdr->sh_offset + shdr->sh_size : 0));
335
336 /* The alignment must be a power of two. This is a
337 requirement from the ELF specification. Additionally
338 we test for the alignment of the section being large
339 enough for the largest alignment required by a data
340 block. */
341 if (unlikely (! powerof2 (shdr->sh_addralign))
342 || unlikely ((shdr->sh_addralign ?: 1) < sh_align))
343 {
344 __libelf_seterrno (ELF_E_INVALID_ALIGN);
345 return -1;
346 }
347 }
348 else
349 {
350 /* How much alignment do we need for this section. */
351 update_if_changed (shdr->sh_addralign, sh_align,
352 scn->shdr_flags);
353
354 size = (size + sh_align - 1) & ~(sh_align - 1);
355 int offset_changed = 0;
356 update_if_changed (shdr->sh_offset, (GElf_Word) size,
357 offset_changed);
358 changed |= offset_changed;
359
360 if (offset_changed && scn->data_list_rear == NULL)
361 {
362 /* The position of the section in the file
363 changed. Create the section data list. */
364 if (__elf_getdata_rdlock (scn, NULL) == NULL)
365 return -1;
366 }
367
368 /* See whether the section size is correct. */
369 update_if_changed (shdr->sh_size, (GElf_Word) offset,
370 changed);
371
372 if (shdr->sh_type != SHT_NOBITS)
373 size += offset;
374
375 scn->flags |= changed;
376 }
377
378 /* Check that the section size is actually a multiple of
379 the entry size. */
380 if (shdr->sh_entsize != 0 && shdr->sh_entsize != 1
381 && (elf->flags & ELF_F_PERMISSIVE) == 0)
382 {
383 /* For compressed sections check the uncompressed size. */
384 ElfW2(LIBELFBITS,Word) sh_size;
385 if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
386 sh_size = shdr->sh_size;
387 else
388 {
389 ElfW2(LIBELFBITS,Chdr) *chdr;
390 chdr = elfw2(LIBELFBITS,getchdr) (scn);
391 if (unlikely (chdr == NULL))
392 return -1;
393 sh_size = chdr->ch_size;
394 }
395
396 if (unlikely (sh_size % shdr->sh_entsize != 0))
397 {
398 __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
399 return -1;
400 }
401 }
402 }
403
404 assert (list->next == NULL || list->cnt == list->max);
405
406 first = false;
407 }
408 while ((list = list->next) != NULL);
409
410 /* Store section information. */
411 update_if_changed (ehdr->e_shentsize,
412 elf_typesize (LIBELFBITS, ELF_T_SHDR, 1), ehdr_flags);
413 if (elf->flags & ELF_F_LAYOUT)
414 {
415 /* The user is supposed to fill out e_shoff. Use it and
416 e_shnum (or sh_size of the dummy, first section header)
417 to determine the maximum extend. */
418 size = MAX ((GElf_Word) size,
419 (ehdr->e_shoff
420 + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
421 }
422 else
423 {
424 /* Align for section header table.
425
426 Yes, we use `sizeof' and not `__alignof__' since we do not
427 want to be surprised by architectures with less strict
428 alignment rules. */
429 #define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
430 size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
431
432 update_if_changed (ehdr->e_shoff, (GElf_Word) size, elf->flags);
433
434 /* Account for the section header size. */
435 size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
436 }
437 }
438
439 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
440
441 return size;
442 }
443