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