elf32_updatenull.c revision d56e232fb8f8cd97a336ed612c89145ec121f785
1/* Update data structures for changes.
2   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
3   This file is part of Red Hat elfutils.
4   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5
6   Red Hat elfutils is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by the
8   Free Software Foundation; version 2 of the License.
9
10   Red Hat elfutils is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   General Public License for more details.
14
15   You should have received a copy of the GNU General Public License along
16   with Red Hat elfutils; if not, write to the Free Software Foundation,
17   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18
19   In addition, as a special exception, Red Hat, Inc. gives You the
20   additional right to link the code of Red Hat elfutils with code licensed
21   under any Open Source Initiative certified open source license
22   (http://www.opensource.org/licenses/index.php) which requires the
23   distribution of source code with any binary distribution and to
24   distribute linked combinations of the two.  Non-GPL Code permitted under
25   this exception must only link to the code of Red Hat elfutils through
26   those well defined interfaces identified in the file named EXCEPTION
27   found in the source code files (the "Approved Interfaces").  The files
28   of Non-GPL Code may instantiate templates or use macros or inline
29   functions from the Approved Interfaces without causing the resulting
30   work to be covered by the GNU General Public License.  Only Red Hat,
31   Inc. may make changes or additions to the list of Approved Interfaces.
32   Red Hat's grant of this exception is conditioned upon your not adding
33   any new exceptions.  If you wish to add a new Approved Interface or
34   exception, please contact Red Hat.  You must obey the GNU General Public
35   License in all respects for all of the Red Hat elfutils code and other
36   code used in conjunction with Red Hat elfutils except the Non-GPL Code
37   covered by this exception.  If you modify this file, you may extend this
38   exception to your version of the file, but you are not obligated to do
39   so.  If you do not wish to provide this exception without modification,
40   you must delete this exception statement from your version and license
41   this file solely under the GPL without exception.
42
43   Red Hat elfutils is an included package of the Open Invention Network.
44   An included package of the Open Invention Network is a package for which
45   Open Invention Network licensees cross-license their patents.  No patent
46   license is granted, either expressly or impliedly, by designation as an
47   included package.  Should you wish to participate in the Open Invention
48   Network licensing program, please visit www.openinventionnetwork.com
49   <http://www.openinventionnetwork.com>.  */
50
51#ifdef HAVE_CONFIG_H
52# include <config.h>
53#endif
54
55#include <assert.h>
56#include <endian.h>
57#include <libelf.h>
58#include <stdbool.h>
59#include <string.h>
60#include <sys/param.h>
61
62#include "libelfP.h"
63#include "elf-knowledge.h"
64
65#ifndef LIBELFBITS
66# define LIBELFBITS 32
67#endif
68
69
70
71static int
72ELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
73			       size_t shnum, int *change_bop)
74{
75  /* Always write the magic bytes.  */
76  if (memcmp (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
77    {
78      memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
79      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
80    }
81
82  /* Always set the file class.  */
83  update_if_changed (ehdr->e_ident[EI_CLASS], ELFW(ELFCLASS,LIBELFBITS),
84		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
85
86  /* Set the data encoding if necessary.  */
87  if (unlikely (ehdr->e_ident[EI_DATA] == ELFDATANONE))
88    {
89      ehdr->e_ident[EI_DATA] =
90	BYTE_ORDER == BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB;
91      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
92    }
93  else if (unlikely (ehdr->e_ident[EI_DATA] >= ELFDATANUM))
94    {
95      __libelf_seterrno (ELF_E_DATA_ENCODING);
96      return 1;
97    }
98  else
99    *change_bop = ((BYTE_ORDER == LITTLE_ENDIAN
100		    && ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
101		   || (BYTE_ORDER == BIG_ENDIAN
102		       && ehdr->e_ident[EI_DATA] != ELFDATA2MSB));
103
104  /* Unconditionally overwrite the ELF version.  */
105  update_if_changed (ehdr->e_ident[EI_VERSION], EV_CURRENT,
106		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
107
108  if (unlikely (ehdr->e_version == EV_NONE)
109      || unlikely (ehdr->e_version >= EV_NUM))
110    {
111      __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
112      return 1;
113    }
114
115  if (unlikely (shnum >= SHN_LORESERVE))
116    {
117      update_if_changed (ehdr->e_shnum, 0,
118			 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
119    }
120  else
121    update_if_changed (ehdr->e_shnum, shnum,
122		       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
123
124  if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)))
125    {
126      ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
127      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
128    }
129
130  return 0;
131}
132
133
134off_t
135internal_function
136__elfw2(LIBELFBITS,updatenull) (Elf *elf, int *change_bop,
137				size_t shnum, lockstat_t locked)
138{
139  ElfW2(LIBELFBITS,Ehdr) *ehdr;
140  int changed = 0;
141  int ehdr_flags = 0;
142
143  ehdr = __elfw2(LIBELFBITS,getehdr_internal) (elf, locked);
144
145  /* Set the default values.  */
146  if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
147    return -1;
148
149  /* At least the ELF header is there.  */
150  off_t size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
151
152  /* Set the program header position.  */
153  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL
154      && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
155	  || ehdr->e_type == ET_CORE))
156    (void) __elfw2(LIBELFBITS,getphdr_internal) (elf, locked);
157  if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
158    {
159      /* Only executables, shared objects, and core files have a program
160	 header.  */
161      if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
162	  && unlikely (ehdr->e_type != ET_CORE))
163	{
164	  __libelf_seterrno (ELF_E_INVALID_PHDR);
165	  return -1;
166	}
167
168      if (elf->flags & ELF_F_LAYOUT)
169	{
170	  /* The user is supposed to fill out e_phoff.  Use it and
171	     e_phnum to determine the maximum extend.  */
172	  size = MAX ((size_t) size,
173		      ehdr->e_phoff
174		      + elf_typesize (LIBELFBITS, ELF_T_PHDR, ehdr->e_phnum));
175	}
176      else
177	{
178	  update_if_changed (ehdr->e_phoff,
179			     elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
180			     ehdr_flags);
181
182	  /* We need no alignment here.  */
183	  size += elf_typesize (LIBELFBITS, ELF_T_PHDR, ehdr->e_phnum);
184	}
185    }
186
187  if (shnum > 0)
188    {
189      Elf_ScnList *list;
190      bool first = true;
191
192      assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0);
193
194      if (shnum >= SHN_LORESERVE)
195	{
196	  /* We have to  fill in the number of sections in the header
197	     of the zeroth section.  */
198	  Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
199
200	  update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
201			     shnum, scn0->shdr_flags);
202	}
203
204      /* Go over all sections and find out how large they are.  */
205      list = &elf->state.ELFW(elf,LIBELFBITS).scns;
206
207      /* Load the section headers if necessary.  This loads the
208	 headers for all sections.  */
209      if (list->data[1].shdr.ELFW(e,LIBELFBITS) == NULL)
210	(void) __elfw2(LIBELFBITS,getshdr_internal) (&list->data[1], locked);
211
212      do
213	{
214	  for (size_t cnt = first == true; cnt < list->cnt; ++cnt)
215	    {
216	      Elf_Scn *scn = &list->data[cnt];
217	      ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
218	      off_t offset = 0;
219
220	      assert (shdr != NULL);
221	      ElfW2(LIBELFBITS,Word) sh_entsize = shdr->sh_entsize;
222	      ElfW2(LIBELFBITS,Word) sh_align = shdr->sh_addralign ?: 1;
223
224	      /* Set the sh_entsize value if we can reliably detect it.  */
225	      switch (shdr->sh_type)
226		{
227		case SHT_SYMTAB:
228		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
229		  break;
230		case SHT_RELA:
231		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELA, 1);
232		  break;
233		case SHT_GROUP:
234		  /* Only relocatable files can contain section groups.  */
235		  if (ehdr->e_type != ET_REL)
236		    {
237		      __libelf_seterrno (ELF_E_GROUP_NOT_REL);
238		      return -1;
239		    }
240		  /* FALLTHROUGH */
241		case SHT_SYMTAB_SHNDX:
242		  sh_entsize = elf_typesize (32, ELF_T_WORD, 1);
243		  break;
244		case SHT_HASH:
245		  sh_entsize = SH_ENTSIZE_HASH (ehdr);
246		  break;
247		case SHT_DYNAMIC:
248		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_DYN, 1);
249		  break;
250		case SHT_REL:
251		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_REL, 1);
252		  break;
253		case SHT_DYNSYM:
254		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
255		  break;
256		case SHT_SUNW_move:
257		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_MOVE, 1);
258		  break;
259		case SHT_SUNW_syminfo:
260		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
261		  break;
262		default:
263		  break;
264		}
265
266	      /* If the section header contained the wrong entry size
267		 correct it and mark the header as modified.  */
268	      update_if_changed (shdr->sh_entsize, sh_entsize,
269				 scn->shdr_flags);
270
271	      if (scn->data_read == 0
272		  && __libelf_set_rawdata (scn, locked) != 0)
273		/* Something went wrong.  The error value is already set.  */
274		return -1;
275
276	      /* Iterate over all data blocks.  */
277	      if (list->data[cnt].data_list_rear != NULL)
278		{
279		  Elf_Data_List *dl = &scn->data_list;
280
281		  while (dl != NULL)
282		    {
283		      Elf_Data *data = &dl->data.d;
284		      if (dl == &scn->data_list && data->d_buf == NULL
285			  && scn->rawdata.d.d_buf != NULL)
286			data = &scn->rawdata.d;
287
288		      if (unlikely (data->d_version == EV_NONE)
289			  || unlikely (data->d_version >= EV_NUM))
290			{
291			  __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
292			  return -1;
293			}
294
295		      if (unlikely (! powerof2 (data->d_align)))
296			{
297			  __libelf_seterrno (ELF_E_INVALID_ALIGN);
298			  return -1;
299			}
300
301		      sh_align = MAX (sh_align, data->d_align);
302
303		      if (elf->flags & ELF_F_LAYOUT)
304			{
305			  /* The user specified the offset and the size.
306			     All we have to do is check whether this block
307			     fits in the size specified for the section.  */
308			  if (unlikely ((GElf_Word) (data->d_off
309						     + data->d_size)
310					> shdr->sh_size))
311			    {
312			      __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
313			      return -1;
314			    }
315			}
316		      else
317			{
318			  /* Determine the padding.  */
319			  offset = ((offset + data->d_align - 1)
320				    & ~(data->d_align - 1));
321
322			  update_if_changed (data->d_off, offset, changed);
323
324			  offset += data->d_size;
325			}
326
327		      /* Next data block.  */
328		      dl = dl->next;
329		    }
330		}
331	      else
332		/* Get the size of the section from the raw data.  If
333		   none is available the value is zero.  */
334		offset += scn->rawdata.d.d_size;
335
336	      if (elf->flags & ELF_F_LAYOUT)
337		{
338		  size = MAX ((GElf_Word) size,
339			      shdr->sh_offset
340			      + (shdr->sh_type != SHT_NOBITS
341				 ? shdr->sh_size : 0));
342
343		  /* The alignment must be a power of two.  This is a
344		     requirement from the ELF specification.  Additionally
345		     we test for the alignment of the section being large
346		     enough for the largest alignment required by a data
347		     block.  */
348		  if (unlikely (! powerof2 (shdr->sh_addralign))
349		      || unlikely (shdr->sh_addralign < sh_align))
350		    {
351		      __libelf_seterrno (ELF_E_INVALID_ALIGN);
352		      return -1;
353		    }
354		}
355	      else
356		{
357		  /* How much alignment do we need for this section.  */
358		  update_if_changed (shdr->sh_addralign, sh_align,
359				     scn->shdr_flags);
360
361		  size = (size + sh_align - 1) & ~(sh_align - 1);
362		  int offset_changed = 0;
363		  update_if_changed (shdr->sh_offset, (GElf_Word) size,
364				     offset_changed);
365		  changed |= offset_changed;
366
367		  if (offset_changed && scn->data_list_rear == NULL)
368		    {
369		      /* The position of the section in the file
370			 changed.  Create the section data list.  */
371		      if (__elf_getdata_internal (scn, NULL, locked) == NULL)
372			return -1;
373		    }
374
375		  /* See whether the section size is correct.  */
376		  update_if_changed (shdr->sh_size, (GElf_Word) offset,
377				     changed);
378
379		  if (shdr->sh_type != SHT_NOBITS)
380		    size += offset;
381
382		  scn->flags |= changed;
383		}
384
385	      /* Check that the section size is actually a multiple of
386		 the entry size.  */
387	      if (shdr->sh_entsize != 0
388		  && unlikely (shdr->sh_size % shdr->sh_entsize != 0)
389		  && (elf->flags & ELF_F_PERMISSIVE) == 0)
390		{
391		  __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
392		  return -1;
393		}
394	    }
395
396	  assert (list->next == NULL || list->cnt == list->max);
397
398	  first = false;
399	}
400      while ((list = list->next) != NULL);
401
402      /* Store section information.  */
403      if (elf->flags & ELF_F_LAYOUT)
404	{
405	  /* The user is supposed to fill out e_phoff.  Use it and
406	     e_phnum to determine the maximum extend.  */
407	  size = MAX ((GElf_Word) size,
408		      (ehdr->e_shoff
409		       + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
410	}
411      else
412	{
413	  /* Align for section header table.
414
415	     Yes, we use `sizeof' and not `__alignof__' since we do not
416	     want to be surprised by architectures with less strict
417	     alignment rules.  */
418#define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
419	  size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
420
421	  update_if_changed (ehdr->e_shoff, (GElf_Word) size, elf->flags);
422	  update_if_changed (ehdr->e_shentsize,
423			     elf_typesize (LIBELFBITS, ELF_T_SHDR, 1),
424			     ehdr_flags);
425
426	  /* Account for the section header size.  */
427	  size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
428	}
429    }
430
431  elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
432
433  return size;
434}
435