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
52static int
53ELFW(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
127int64_t
128internal_function
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		default:
260		  break;
261		}
262
263	      /* If the section header contained the wrong entry size
264		 correct it and mark the header as modified.  */
265	      update_if_changed (shdr->sh_entsize, sh_entsize,
266				 scn->shdr_flags);
267
268	      /* Likewise for the alignment of a compressed section.
269	         For a SHF_COMPRESSED section set the correct
270	         sh_addralign value, which must match the d_align of
271	         the data (see __libelf_set_rawdata in elf_getdata.c).  */
272	      if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
273		{
274		  sh_align = __libelf_type_align (ELFW(ELFCLASS,LIBELFBITS),
275						  ELF_T_CHDR);
276		  update_if_changed (shdr->sh_addralign, sh_align,
277				     scn->shdr_flags);
278		}
279
280	      if (scn->data_read == 0
281		  && __libelf_set_rawdata_wrlock (scn) != 0)
282		/* Something went wrong.  The error value is already set.  */
283		return -1;
284
285	      /* Iterate over all data blocks.  */
286	      if (list->data[cnt].data_list_rear != NULL)
287		{
288		  Elf_Data_List *dl = &scn->data_list;
289
290		  while (dl != NULL)
291		    {
292		      Elf_Data *data = &dl->data.d;
293		      if (dl == &scn->data_list && data->d_buf == NULL
294			  && scn->rawdata.d.d_buf != NULL)
295			data = &scn->rawdata.d;
296
297		      if (unlikely (data->d_version != EV_CURRENT))
298			{
299			  __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
300			  return -1;
301			}
302
303		      if (unlikely (! powerof2 (data->d_align)))
304			{
305			  __libelf_seterrno (ELF_E_INVALID_ALIGN);
306			  return -1;
307			}
308
309		      sh_align = MAX (sh_align, data->d_align);
310
311		      if (elf->flags & ELF_F_LAYOUT)
312			{
313			  /* The user specified the offset and the size.
314			     All we have to do is check whether this block
315			     fits in the size specified for the section.  */
316			  if (unlikely ((ElfW2(LIBELFBITS,SizeWord))
317					(data->d_off + data->d_size)
318					> shdr->sh_size))
319			    {
320			      __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
321			      return -1;
322			    }
323			}
324		      else
325			{
326			  /* Determine the padding.  */
327			  offset = ((offset + data->d_align - 1)
328				    & ~(data->d_align - 1));
329
330			  update_if_changed (data->d_off, offset, changed);
331
332			  offset += data->d_size;
333			}
334
335		      /* Next data block.  */
336		      dl = dl->next;
337		    }
338		}
339	      else
340		/* Get the size of the section from the raw data.  If
341		   none is available the value is zero.  */
342		offset += scn->rawdata.d.d_size;
343
344	      if (elf->flags & ELF_F_LAYOUT)
345		{
346		  size = MAX (size,
347			      (shdr->sh_type != SHT_NOBITS
348			       ? shdr->sh_offset + shdr->sh_size : 0));
349
350		  /* The alignment must be a power of two.  This is a
351		     requirement from the ELF specification.  Additionally
352		     we test for the alignment of the section being large
353		     enough for the largest alignment required by a data
354		     block.  */
355		  if (unlikely (! powerof2 (shdr->sh_addralign))
356		      || unlikely ((shdr->sh_addralign ?: 1) < sh_align))
357		    {
358		      __libelf_seterrno (ELF_E_INVALID_ALIGN);
359		      return -1;
360		    }
361		}
362	      else
363		{
364		  /* How much alignment do we need for this section.  */
365		  update_if_changed (shdr->sh_addralign, sh_align,
366				     scn->shdr_flags);
367
368		  size = (size + sh_align - 1) & ~(sh_align - 1);
369		  int offset_changed = 0;
370		  update_if_changed (shdr->sh_offset, size, offset_changed);
371		  changed |= offset_changed;
372
373		  if (offset_changed && scn->data_list_rear == NULL)
374		    {
375		      /* The position of the section in the file
376			 changed.  Create the section data list.  */
377		      if (__elf_getdata_rdlock (scn, NULL) == NULL)
378			return -1;
379		    }
380
381		  /* See whether the section size is correct.  */
382		  int size_changed = 0;
383		  update_if_changed (shdr->sh_size,
384				     (ElfW2(LIBELFBITS,SizeWord)) offset,
385				     size_changed);
386		  changed |= size_changed;
387
388		  if (shdr->sh_type != SHT_NOBITS)
389		    size += offset;
390
391		  scn->shdr_flags |= (offset_changed | size_changed);
392		  scn->flags |= changed;
393		}
394
395	      /* Check that the section size is actually a multiple of
396		 the entry size.  */
397	      if (shdr->sh_entsize != 0 && shdr->sh_entsize != 1
398		  && (elf->flags & ELF_F_PERMISSIVE) == 0)
399		{
400		  /* For compressed sections check the uncompressed size.  */
401		  ElfW2(LIBELFBITS,SizeWord) sh_size;
402		  if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
403		    sh_size = shdr->sh_size;
404		  else
405		    {
406		      ElfW2(LIBELFBITS,Chdr) *chdr;
407		      chdr = elfw2(LIBELFBITS,getchdr) (scn);
408		      if (unlikely (chdr == NULL))
409			return -1;
410		      sh_size = chdr->ch_size;
411		    }
412
413		  if (unlikely (sh_size % shdr->sh_entsize != 0))
414		    {
415		      __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
416		      return -1;
417		    }
418		}
419	    }
420
421	  assert (list->next == NULL || list->cnt == list->max);
422
423	  first = false;
424	}
425      while ((list = list->next) != NULL);
426
427      /* Store section information.  */
428      update_if_changed (ehdr->e_shentsize,
429			 elf_typesize (LIBELFBITS, ELF_T_SHDR, 1), ehdr_flags);
430      if (elf->flags & ELF_F_LAYOUT)
431	{
432	  /* The user is supposed to fill out e_shoff.  Use it and
433	     e_shnum (or sh_size of the dummy, first section header)
434	     to determine the maximum extend.  */
435	  size = MAX (size,
436		      (ehdr->e_shoff
437		       + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
438	}
439      else
440	{
441	  /* Align for section header table.
442
443	     Yes, we use `sizeof' and not `__alignof__' since we do not
444	     want to be surprised by architectures with less strict
445	     alignment rules.  */
446#define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
447	  size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
448
449	  update_if_changed (ehdr->e_shoff, size, elf->flags);
450
451	  /* Account for the section header size.  */
452	  size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
453	}
454    }
455
456  elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
457
458  return size;
459}
460