125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Update data structures for changes.
225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Copyright (C) 2000-2010 Red Hat, Inc.
303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is part of elfutils.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is free software; you can redistribute it and/or modify
703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   it under the terms of either
825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     * the GNU Lesser General Public License as published by the Free
1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       Software Foundation; either version 3 of the License, or (at
1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       your option) any later version
1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   or
1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     * the GNU General Public License as published by the Free
1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       Software Foundation; either version 2 of the License, or (at
1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       your option) any later version
1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   or both in parallel, as here.
2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
2103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   elfutils is distributed in the hope that it will be useful, but
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   You should have received copies of the GNU General Public License and
2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   the GNU Lesser General Public License along with this program.  If
2803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   not, see <http://www.gnu.org/licenses/>.  */
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h>
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <endian.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libelf.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h>
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h>
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h>
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libelfP.h"
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "elf-knowledge.h"
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef LIBELFBITS
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define LIBELFBITS 32
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
5125b3c049e70834cf33790a28643ab058b507b35cBen ChengELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       size_t shnum, int *change_bop)
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Always write the magic bytes.  */
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (memcmp (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Always set the file class.  */
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  update_if_changed (ehdr->e_ident[EI_CLASS], ELFW(ELFCLASS,LIBELFBITS),
6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Set the data encoding if necessary.  */
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (ehdr->e_ident[EI_DATA] == ELFDATANONE))
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ehdr->e_ident[EI_DATA] =
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	BYTE_ORDER == BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB;
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (unlikely (ehdr->e_ident[EI_DATA] >= ELFDATANUM))
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_DATA_ENCODING);
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 1;
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    *change_bop = ((BYTE_ORDER == LITTLE_ENDIAN
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    && ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   || (BYTE_ORDER == BIG_ENDIAN
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       && ehdr->e_ident[EI_DATA] != ELFDATA2MSB));
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Unconditionally overwrite the ELF version.  */
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  update_if_changed (ehdr->e_ident[EI_VERSION], EV_CURRENT,
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (ehdr->e_version == EV_NONE)
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      || unlikely (ehdr->e_version >= EV_NUM))
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 1;
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (shnum >= SHN_LORESERVE))
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      update_if_changed (ehdr->e_shnum, 0,
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    update_if_changed (ehdr->e_shnum, shnum,
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)))
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11325b3c049e70834cf33790a28643ab058b507b35cBen Chengoff_t
11425b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng__elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ElfW2(LIBELFBITS,Ehdr) *ehdr;
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int changed = 0;
11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int ehdr_flags = 0;
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Set the default values.  */
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* At least the ELF header is there.  */
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  off_t size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Set the program header position.  */
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || ehdr->e_type == ET_CORE))
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    (void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Only executables, shared objects, and core files have a program
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 header.  */
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && unlikely (ehdr->e_type != ET_CORE))
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libelf_seterrno (ELF_E_INVALID_PHDR);
14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return -1;
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t phnum;
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf->flags & ELF_F_LAYOUT)
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* The user is supposed to fill out e_phoff.  Use it and
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     e_phnum to determine the maximum extend.  */
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size = MAX ((size_t) size,
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      ehdr->e_phoff
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  update_if_changed (ehdr->e_phoff,
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     ehdr_flags);
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We need no alignment here.  */
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size += elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum);
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shnum > 0)
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_ScnList *list;
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool first = true;
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0);
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shnum >= SHN_LORESERVE)
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We have to  fill in the number of sections in the header
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     of the zeroth section.  */
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     shnum, scn0->shdr_flags);
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Go over all sections and find out how large they are.  */
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      list = &elf->state.ELFW(elf,LIBELFBITS).scns;
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Load the section headers if necessary.  This loads the
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 headers for all sections.  */
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (list->data[1].shdr.ELFW(e,LIBELFBITS) == NULL)
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	(void) __elfw2(LIBELFBITS,getshdr_wrlock) (&list->data[1]);
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (size_t cnt = first == true; cnt < list->cnt; ++cnt)
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      Elf_Scn *scn = &list->data[cnt];
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      off_t offset = 0;
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      assert (shdr != NULL);
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ElfW2(LIBELFBITS,Word) sh_entsize = shdr->sh_entsize;
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ElfW2(LIBELFBITS,Word) sh_align = shdr->sh_addralign ?: 1;
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Set the sh_entsize value if we can reliably detect it.  */
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      switch (shdr->sh_type)
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case SHT_SYMTAB:
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case SHT_RELA:
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELA, 1);
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case SHT_GROUP:
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Only relocatable files can contain section groups.  */
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (ehdr->e_type != ET_REL)
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      __libelf_seterrno (ELF_E_GROUP_NOT_REL);
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      return -1;
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* FALLTHROUGH */
22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case SHT_SYMTAB_SHNDX:
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  sh_entsize = elf_typesize (32, ELF_T_WORD, 1);
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case SHT_HASH:
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  sh_entsize = SH_ENTSIZE_HASH (ehdr);
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case SHT_DYNAMIC:
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_DYN, 1);
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case SHT_REL:
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_REL, 1);
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case SHT_DYNSYM:
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case SHT_SUNW_move:
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_MOVE, 1);
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case SHT_SUNW_syminfo:
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		default:
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* If the section header contained the wrong entry size
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 correct it and mark the header as modified.  */
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      update_if_changed (shdr->sh_entsize, sh_entsize,
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 scn->shdr_flags);
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (scn->data_read == 0
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && __libelf_set_rawdata_wrlock (scn) != 0)
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* Something went wrong.  The error value is already set.  */
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		return -1;
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Iterate over all data blocks.  */
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (list->data[cnt].data_list_rear != NULL)
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  Elf_Data_List *dl = &scn->data_list;
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  while (dl != NULL)
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      Elf_Data *data = &dl->data.d;
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (dl == &scn->data_list && data->d_buf == NULL
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  && scn->rawdata.d.d_buf != NULL)
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			data = &scn->rawdata.d;
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (unlikely (data->d_version == EV_NONE)
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  || unlikely (data->d_version >= EV_NUM))
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  return -1;
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (unlikely (! powerof2 (data->d_align)))
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  __libelf_seterrno (ELF_E_INVALID_ALIGN);
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  return -1;
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      sh_align = MAX (sh_align, data->d_align);
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (elf->flags & ELF_F_LAYOUT)
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  /* The user specified the offset and the size.
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     All we have to do is check whether this block
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     fits in the size specified for the section.  */
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  if (unlikely ((GElf_Word) (data->d_off
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng						     + data->d_size)
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					> shdr->sh_size))
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    {
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      return -1;
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    }
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      else
29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  /* Determine the padding.  */
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  offset = ((offset + data->d_align - 1)
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    & ~(data->d_align - 1));
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  update_if_changed (data->d_off, offset, changed);
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  offset += data->d_size;
30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      /* Next data block.  */
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      dl = dl->next;
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* Get the size of the section from the raw data.  If
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   none is available the value is zero.  */
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		offset += scn->rawdata.d.d_size;
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (elf->flags & ELF_F_LAYOUT)
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  size = MAX ((GElf_Word) size,
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      shdr->sh_offset
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      + (shdr->sh_type != SHT_NOBITS
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 ? shdr->sh_size : 0));
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* The alignment must be a power of two.  This is a
32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     requirement from the ELF specification.  Additionally
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     we test for the alignment of the section being large
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     enough for the largest alignment required by a data
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     block.  */
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (! powerof2 (shdr->sh_addralign))
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      || unlikely (shdr->sh_addralign < sh_align))
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      __libelf_seterrno (ELF_E_INVALID_ALIGN);
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      return -1;
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* How much alignment do we need for this section.  */
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  update_if_changed (shdr->sh_addralign, sh_align,
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     scn->shdr_flags);
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  size = (size + sh_align - 1) & ~(sh_align - 1);
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  int offset_changed = 0;
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  update_if_changed (shdr->sh_offset, (GElf_Word) size,
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     offset_changed);
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  changed |= offset_changed;
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (offset_changed && scn->data_list_rear == NULL)
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      /* The position of the section in the file
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 changed.  Create the section data list.  */
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (__elf_getdata_rdlock (scn, NULL) == NULL)
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			return -1;
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* See whether the section size is correct.  */
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  update_if_changed (shdr->sh_size, (GElf_Word) offset,
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     changed);
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (shdr->sh_type != SHT_NOBITS)
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    size += offset;
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  scn->flags |= changed;
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Check that the section size is actually a multiple of
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 the entry size.  */
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (shdr->sh_entsize != 0
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && unlikely (shdr->sh_size % shdr->sh_entsize != 0)
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && (elf->flags & ELF_F_PERMISSIVE) == 0)
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  return -1;
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (list->next == NULL || list->cnt == list->max);
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  first = false;
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while ((list = list->next) != NULL);
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Store section information.  */
38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf->flags & ELF_F_LAYOUT)
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* The user is supposed to fill out e_shoff.  Use it and
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     e_shnum (or sh_size of the dummy, first section header)
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     to determine the maximum extend.  */
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size = MAX ((GElf_Word) size,
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (ehdr->e_shoff
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Align for section header table.
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     Yes, we use `sizeof' and not `__alignof__' since we do not
39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     want to be surprised by architectures with less strict
40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     alignment rules.  */
40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  update_if_changed (ehdr->e_shoff, (GElf_Word) size, elf->flags);
40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  update_if_changed (ehdr->e_shentsize,
40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     elf_typesize (LIBELFBITS, ELF_T_SHDR, 1),
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     ehdr_flags);
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Account for the section header size.  */
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return size;
41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
418