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