125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Write changed data structures.
225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Copyright (C) 2000-2010 Red Hat, Inc.
325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   This file is part of Red Hat elfutils.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   it under the terms of the GNU General Public License as published by the
825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Free Software Foundation; version 2 of the License.
925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   You should have received a copy of the GNU General Public License along
1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   In addition, as a special exception, Red Hat, Inc. gives You the
2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   additional right to link the code of Red Hat elfutils with code licensed
2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   under any Open Source Initiative certified open source license
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   (http://www.opensource.org/licenses/index.php) which requires the
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   distribution of source code with any binary distribution and to
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   distribute linked combinations of the two.  Non-GPL Code permitted under
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   this exception must only link to the code of Red Hat elfutils through
2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   those well defined interfaces identified in the file named EXCEPTION
2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   found in the source code files (the "Approved Interfaces").  The files
2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   of Non-GPL Code may instantiate templates or use macros or inline
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   functions from the Approved Interfaces without causing the resulting
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   work to be covered by the GNU General Public License.  Only Red Hat,
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Inc. may make changes or additions to the list of Approved Interfaces.
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat's grant of this exception is conditioned upon your not adding
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   any new exceptions.  If you wish to add a new Approved Interface or
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   exception, please contact Red Hat.  You must obey the GNU General Public
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   License in all respects for all of the Red Hat elfutils code and other
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   code used in conjunction with Red Hat elfutils except the Non-GPL Code
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   covered by this exception.  If you modify this file, you may extend this
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   exception to your version of the file, but you are not obligated to do
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   so.  If you do not wish to provide this exception without modification,
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   you must delete this exception statement from your version and license
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   this file solely under the GPL without exception.
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is an included package of the Open Invention Network.
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   An included package of the Open Invention Network is a package for which
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Open Invention Network licensees cross-license their patents.  No patent
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   license is granted, either expressly or impliedly, by designation as an
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   included package.  Should you wish to participate in the Open Invention
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Network licensing program, please visit www.openinventionnetwork.com
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   <http://www.openinventionnetwork.com>.  */
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h>
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <errno.h>
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libelf.h>
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h>
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h>
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h>
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h>
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/mman.h>
6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h>
6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h>
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libelfP.h"
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef LIBELFBITS
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define LIBELFBITS 32
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
7525b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_sections (const void *a, const void *b)
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Elf_Scn **scna = (const Elf_Scn **) a;
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Elf_Scn **scnb = (const Elf_Scn **) b;
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      < (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset)
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      > (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset)
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 1;
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_size
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      < (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_size)
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_size
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      > (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_size)
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 1;
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((*scna)->index < (*scnb)->index)
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((*scna)->index > (*scnb)->index)
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 1;
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Insert the sections in the list into the provided array and sort
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   them according to their start offsets.  For sections with equal
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   start offsets, the size is used; for sections with equal start
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   offsets and sizes, the section index is used.  Sorting by size
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   ensures that zero-length sections are processed first, which
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   is what we want since they do not advance our file writing position.  */
11225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
11325b3c049e70834cf33790a28643ab058b507b35cBen Chengsort_sections (Elf_Scn **scns, Elf_ScnList *list)
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn **scnp = scns;
11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    for (size_t cnt = 0; cnt < list->cnt; ++cnt)
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *scnp++ = &list->data[cnt];
11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((list = list->next) != NULL);
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  qsort (scns, scnp - scns, sizeof (*scns), compare_sections);
12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12525b3c049e70834cf33790a28643ab058b507b35cBen Chengint
12625b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng__elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool previous_scn_changed = false;
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We need the ELF header several times.  */
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write out the ELF header.  */
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY)
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If the type sizes should be different at some time we have to
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 rewrite this code.  */
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (sizeof (ElfW2(LIBELFBITS,Ehdr))
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      == elf_typesize (LIBELFBITS, ELF_T_EHDR, 1));
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (change_bo))
14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Today there is only one version of the ELF header.  */
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  xfct_t fctp;
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR];
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Do the real work.  */
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (*fctp) ((char *) elf->map_address + elf->start_offset, ehdr,
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	memcpy (elf->map_address + elf->start_offset, ehdr,
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		sizeof (ElfW2(LIBELFBITS,Ehdr)));
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY;
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We start writing sections after the ELF header only if there is
16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 no program header.  */
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      previous_scn_changed = elf->state.ELFW(elf,LIBELFBITS).phdr == NULL;
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t phnum;
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write out the program header table.  */
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      && ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags)
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  & ELF_F_DIRTY))
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If the type sizes should be different at some time we have to
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 rewrite this code.  */
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (sizeof (ElfW2(LIBELFBITS,Phdr))
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Maybe the user wants a gap between the ELF header and the program
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 header.  */
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ehdr->e_phoff > ehdr->e_ehsize)
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	memset (elf->map_address + elf->start_offset + ehdr->e_ehsize,
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		__libelf_fill_byte, ehdr->e_phoff - ehdr->e_ehsize);
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (change_bo))
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Today there is only one version of the ELF header.  */
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  xfct_t fctp;
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR];
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Do the real work.  */
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (*fctp) (elf->map_address + elf->start_offset + ehdr->e_phoff,
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   elf->state.ELFW(elf,LIBELFBITS).phdr,
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum, 1);
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	memcpy (elf->map_address + elf->start_offset + ehdr->e_phoff,
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		elf->state.ELFW(elf,LIBELFBITS).phdr,
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY;
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We modified the program header.  Maybe this created a gap so
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 we have to write fill bytes, if necessary.  */
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      previous_scn_changed = true;
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* From now on we have to keep track of the last position to eventually
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     fill the gaps with the prescribed fill byte.  */
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *last_position = ((char *) elf->map_address + elf->start_offset
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 + MAX (elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				ehdr->e_phoff)
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write all the sections.  Well, only those which are modified.  */
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shnum > 0)
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn **scns = (Elf_Scn **) alloca (shnum * sizeof (Elf_Scn *));
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *const shdr_start = ((char *) elf->map_address + elf->start_offset
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				+ ehdr->e_shoff);
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *const shdr_end = shdr_start + ehdr->e_shnum * ehdr->e_shentsize;
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR];
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef shdr_fctp
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define shdr_fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define shdr_dest ((ElfW2(LIBELFBITS,Shdr) *) shdr_start)
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get all sections into the array and sort them.  */
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      sort_sections (scns, list);
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We possibly have to copy the section header data because moving
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 the sections might overwrite the data.  */
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t cnt = 0; cnt < shnum; ++cnt)
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Scn *scn = scns[cnt];
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!elf->state.ELFW(elf,LIBELFBITS).shdr_malloced
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && (scn->shdr_flags & ELF_F_MALLOCED) == 0
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && scn->shdr.ELFW(e,LIBELFBITS) != &shdr_dest[scn->index])
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      assert ((char *) elf->map_address + elf->start_offset
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      < (char *) scn->shdr.ELFW(e,LIBELFBITS));
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      assert ((char *) scn->shdr.ELFW(e,LIBELFBITS)
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      < ((char *) elf->map_address + elf->start_offset
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 + elf->maximum_size));
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      void *p = alloca (sizeof (ElfW2(LIBELFBITS,Shdr)));
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      scn->shdr.ELFW(e,LIBELFBITS)
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		= memcpy (p, scn->shdr.ELFW(e,LIBELFBITS),
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  sizeof (ElfW2(LIBELFBITS,Shdr)));
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* If the file is mmaped and the original position of the
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     section in the file is lower than the new position we
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     need to save the section content since otherwise it is
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     overwritten before it can be copied.  If there are
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     multiple data segments in the list only the first can be
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     from the file.  */
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (((char *) elf->map_address + elf->start_offset
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       <= (char  *) scn->data_list.data.d.d_buf)
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && ((char *) scn->data_list.data.d.d_buf
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  < ((char *) elf->map_address + elf->start_offset
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     + elf->maximum_size))
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && (((char *) elf->map_address + elf->start_offset
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   + scn->shdr.ELFW(e,LIBELFBITS)->sh_offset)
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  > (char *) scn->data_list.data.d.d_buf))
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      void *p = malloc (scn->data_list.data.d.d_size);
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (p == NULL)
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  __libelf_seterrno (ELF_E_NOMEM);
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  return -1;
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      scn->data_list.data.d.d_buf = scn->data_base
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		= memcpy (p, scn->data_list.data.d.d_buf,
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  scn->data_list.data.d.d_size);
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Iterate over all the section in the order in which they
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 appear in the output file.  */
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t cnt = 0; cnt < shnum; ++cnt)
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Scn *scn = scns[cnt];
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (scn->index == 0)
29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* The dummy section header entry.  It should not be
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 possible to mark this "section" as dirty.  */
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      assert ((scn->flags & ELF_F_DIRTY) == 0);
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      continue;
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_type == SHT_NOBITS)
30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto next;
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *scn_start = ((char *) elf->map_address
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     + elf->start_offset + shdr->sh_offset);
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data_List *dl = &scn->data_list;
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bool scn_changed = false;
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  void fill_mmap (size_t offset)
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    size_t written = 0;
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (last_position < shdr_start)
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		written = MIN (scn_start + offset - last_position,
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       shdr_start - last_position);
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		memset (last_position, __libelf_fill_byte, written);
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (last_position + written != scn_start + offset
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		&& shdr_end < scn_start + offset)
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		char *fill_start = MAX (shdr_end, scn_start);
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		memset (fill_start, __libelf_fill_byte,
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			scn_start + offset - fill_start);
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (scn->data_list_rear != NULL)
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    do
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		assert (dl->data.d.d_off >= 0);
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		assert ((GElf_Off) dl->data.d.d_off <= shdr->sh_size);
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		assert (dl->data.d.d_size <= (shdr->sh_size
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      - (GElf_Off) dl->data.d.d_off));
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* If there is a gap, fill it.  */
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (scn_start + dl->data.d.d_off > last_position
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    && (dl->data.d.d_off == 0
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			|| ((scn->flags | dl->flags | elf->flags)
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    & ELF_F_DIRTY) != 0))
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    fill_mmap (dl->data.d.d_off);
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    last_position = scn_start + dl->data.d.d_off;
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    /* Let it go backward if the sections use a bogus
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       layout with overlaps.  We'll overwrite the stupid
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       user's section data with the latest one, rather than
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       crashing.  */
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    last_position = scn_start + dl->data.d.d_off;
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (unlikely (change_bo))
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      {
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			xfct_t fctp;
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Do the real work.  */
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(*fctp) (last_position, dl->data.d.d_buf,
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 dl->data.d.d_size, 1);
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			last_position += dl->data.d.d_size;
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      }
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    else
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      last_position = mempcpy (last_position,
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       dl->data.d.d_buf,
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       dl->data.d.d_size);
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    scn_changed = true;
38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		else
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  last_position += dl->data.d.d_size;
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		assert (scn_start + dl->data.d.d_off + dl->data.d.d_size
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			== last_position);
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		dl->flags &= ~ELF_F_DIRTY;
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		dl = dl->next;
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    while (dl != NULL);
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* If the previous section (or the ELF/program
39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 header) changed we might have to fill the gap.  */
40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (scn_start > last_position && previous_scn_changed)
40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		fill_mmap (0);
40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* We have to trust the existing section header information.  */
40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      last_position = scn_start + shdr->sh_size;
40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  previous_scn_changed = scn_changed;
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	next:
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  scn->flags &= ~ELF_F_DIRTY;
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Fill the gap between last section and section header table if
41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 necessary.  */
41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((elf->flags & ELF_F_DIRTY)
41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && last_position < ((char *) elf->map_address + elf->start_offset
41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      + ehdr->e_shoff))
41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	memset (last_position, __libelf_fill_byte,
41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(char *) elf->map_address + elf->start_offset + ehdr->e_shoff
42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		- last_position);
42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Write the section header table entry if necessary.  */
42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t cnt = 0; cnt < shnum; ++cnt)
42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Scn *scn = scns[cnt];
42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((scn->shdr_flags | elf->flags) & ELF_F_DIRTY)
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (change_bo))
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(*shdr_fctp) (&shdr_dest[scn->index],
43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      scn->shdr.ELFW(e,LIBELFBITS),
43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		memcpy (&shdr_dest[scn->index],
43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			scn->shdr.ELFW(e,LIBELFBITS),
43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			sizeof (ElfW2(LIBELFBITS,Shdr)));
43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* If we previously made a copy of the section header
43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 entry we now have to adjust the pointer again so
44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 point to new place in the mapping.  */
44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (!elf->state.ELFW(elf,LIBELFBITS).shdr_malloced
44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && (scn->shdr_flags & ELF_F_MALLOCED) == 0)
44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		scn->shdr.ELFW(e,LIBELFBITS) = &shdr_dest[scn->index];
44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      scn->shdr_flags &= ~ELF_F_DIRTY;
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* That was the last part.  Clear the overall flag.  */
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf->flags &= ~ELF_F_DIRTY;
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Make sure the content hits the disk.  */
45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *msync_start = ((char *) elf->map_address
45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       + (elf->start_offset & ~(sysconf (_SC_PAGESIZE) - 1)));
45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *msync_end = ((char *) elf->map_address
45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     + elf->start_offset + ehdr->e_shoff
45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     + ehdr->e_shentsize * shnum);
45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) msync (msync_start, msync_end - msync_start, MS_SYNC);
46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Size of the buffer we use to generate the blocks of fill bytes.  */
46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define FILLBUFSIZE	4096
46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* If we have to convert the section buffer contents we have to use
46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   temporary buffer.  Only buffers up to MAX_TMPBUF bytes are allocated
47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   on the stack.  */
47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MAX_TMPBUF	32768
47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Helper function to write out fill bytes.  */
47525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
47625b3c049e70834cf33790a28643ab058b507b35cBen Chengfill (int fd, off_t pos, size_t len, char *fillbuf, size_t *filledp)
47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t filled = *filledp;
47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t fill_len = MIN (len, FILLBUFSIZE);
48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (fill_len > filled) && filled < FILLBUFSIZE)
48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Initialize a few more bytes.  */
48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memset (fillbuf + filled, __libelf_fill_byte, fill_len - filled);
48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *filledp = filled = fill_len;
48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do
48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This many bytes we want to write in this round.  */
49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t n = MIN (filled, len);
49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely ((size_t) pwrite_retry (fd, fillbuf, n, pos) != n))
49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libelf_seterrno (ELF_E_WRITE_ERROR);
49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return 1;
49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      pos += n;
50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      len -= n;
50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (len > 0);
50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50825b3c049e70834cf33790a28643ab058b507b35cBen Chengint
50925b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function
51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng__elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char fillbuf[FILLBUFSIZE];
51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t filled = 0;
51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool previous_scn_changed = false;
51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We need the ELF header several times.  */
51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write out the ELF header.  */
52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY)
52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ElfW2(LIBELFBITS,Ehdr) tmp_ehdr;
52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ElfW2(LIBELFBITS,Ehdr) *out_ehdr = ehdr;
52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If the type sizes should be different at some time we have to
52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 rewrite this code.  */
52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (sizeof (ElfW2(LIBELFBITS,Ehdr))
52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      == elf_typesize (LIBELFBITS, ELF_T_EHDR, 1));
52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (change_bo))
53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Today there is only one version of the ELF header.  */
53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2
53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  xfct_t fctp;
53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR];
53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp
53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Write the converted ELF header in a temporary buffer.  */
54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (*fctp) (&tmp_ehdr, ehdr, sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This is the buffer we want to write.  */
54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  out_ehdr = &tmp_ehdr;
54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Write out the ELF header.  */
54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (pwrite_retry (elf->fildes, out_ehdr,
55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  sizeof (ElfW2(LIBELFBITS,Ehdr)), 0)
55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    != sizeof (ElfW2(LIBELFBITS,Ehdr))))
55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libelf_seterrno (ELF_E_WRITE_ERROR);
55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return 1;
55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY;
55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We start writing sections after the ELF header only if there is
56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 no program header.  */
56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      previous_scn_changed = elf->state.ELFW(elf,LIBELFBITS).phdr == NULL;
56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If the type sizes should be different at some time we have to
56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     rewrite this code.  */
56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (sizeof (ElfW2(LIBELFBITS,Phdr))
56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t phnum;
57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write out the program header table.  */
57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL
57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      && ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags)
57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  & ELF_F_DIRTY))
57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ElfW2(LIBELFBITS,Phdr) *tmp_phdr = NULL;
57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ElfW2(LIBELFBITS,Phdr) *out_phdr = elf->state.ELFW(elf,LIBELFBITS).phdr;
58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Maybe the user wants a gap between the ELF header and the program
58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 header.  */
58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ehdr->e_phoff > ehdr->e_ehsize
58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && unlikely (fill (elf->fildes, ehdr->e_ehsize,
58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     ehdr->e_phoff - ehdr->e_ehsize, fillbuf, &filled)
58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       != 0))
58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return 1;
58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (change_bo))
59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Today there is only one version of the ELF header.  */
59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2
59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  xfct_t fctp;
59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR];
59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp
59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Allocate sufficient memory.  */
60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  tmp_phdr = (ElfW2(LIBELFBITS,Phdr) *)
60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    malloc (sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (tmp_phdr == NULL)
60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      __libelf_seterrno (ELF_E_NOMEM);
60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return 1;
60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Write the converted ELF header in a temporary buffer.  */
61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (*fctp) (tmp_phdr, elf->state.ELFW(elf,LIBELFBITS).phdr,
61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum, 1);
61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This is the buffer we want to write.  */
61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  out_phdr = tmp_phdr;
61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Write out the ELF header.  */
61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t phdr_size = sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum;
61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely ((size_t) pwrite_retry (elf->fildes, out_phdr,
62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   phdr_size, ehdr->e_phoff)
62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    != phdr_size))
62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libelf_seterrno (ELF_E_WRITE_ERROR);
62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return 1;
62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This is a no-op we we have not allocated any memory.  */
62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      free (tmp_phdr);
62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY;
63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We modified the program header.  Maybe this created a gap so
63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 we have to write fill bytes, if necessary.  */
63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      previous_scn_changed = true;
63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* From now on we have to keep track of the last position to eventually
63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     fill the gaps with the prescribed fill byte.  */
63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  off_t last_offset;
64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    last_offset = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    last_offset = (ehdr->e_phoff + sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write all the sections.  Well, only those which are modified.  */
64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shnum > 0)
64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      off_t shdr_offset = elf->start_offset + ehdr->e_shoff;
64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2
65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR];
65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef shdr_fctp
65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define shdr_fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ElfW2(LIBELFBITS,Shdr) *shdr_data;
65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	shdr_data = (ElfW2(LIBELFBITS,Shdr) *)
65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  alloca (shnum * sizeof (ElfW2(LIBELFBITS,Shdr)));
66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	shdr_data = elf->state.ELFW(elf,LIBELFBITS).shdr;
66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int shdr_flags = elf->flags;
66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get all sections into the array and sort them.  */
66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn **scns = (Elf_Scn **) alloca (shnum * sizeof (Elf_Scn *));
66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      sort_sections (scns, list);
66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t cnt = 0; cnt < shnum; ++cnt)
67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Scn *scn = scns[cnt];
67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (scn->index == 0)
67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* The dummy section header entry.  It should not be
67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 possible to mark this "section" as dirty.  */
67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      assert ((scn->flags & ELF_F_DIRTY) == 0);
67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      goto next;
67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_type == SHT_NOBITS)
68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto next;
68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  off_t scn_start = elf->start_offset + shdr->sh_offset;
68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data_List *dl = &scn->data_list;
68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bool scn_changed = false;
68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (scn->data_list_rear != NULL)
68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    do
69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* If there is a gap, fill it.  */
69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (scn_start + dl->data.d.d_off > last_offset
69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    && ((previous_scn_changed && dl->data.d.d_off == 0)
69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			|| ((scn->flags | dl->flags | elf->flags)
69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    & ELF_F_DIRTY) != 0))
69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (unlikely (fill (elf->fildes, last_offset,
69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					(scn_start + dl->data.d.d_off)
69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng					- last_offset, fillbuf,
70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					&filled) != 0))
70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      return 1;
70225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    char tmpbuf[MAX_TMPBUF];
70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    void *buf = dl->data.d.d_buf;
70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    /* Let it go backward if the sections use a bogus
71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       layout with overlaps.  We'll overwrite the stupid
71125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       user's section data with the latest one, rather than
71225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       crashing.  */
71325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
71425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    last_offset = scn_start + dl->data.d.d_off;
71525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
71625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (unlikely (change_bo))
71725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      {
71825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2
71925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			xfct_t fctp;
72025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
72125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp
72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			buf = tmpbuf;
72725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			if (dl->data.d.d_size > MAX_TMPBUF)
72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  {
72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    buf = malloc (dl->data.d.d_size);
73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    if (buf == NULL)
73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      {
73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				__libelf_seterrno (ELF_E_NOMEM);
73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				return 1;
73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      }
73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  }
73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Do the real work.  */
73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(*fctp) (buf, dl->data.d.d_buf, dl->data.d.d_size, 1);
73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      }
74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    ssize_t n = pwrite_retry (elf->fildes, buf,
74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      dl->data.d.d_size,
74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      last_offset);
74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (unlikely ((size_t) n != dl->data.d.d_size))
74525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      {
74625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			if (buf != dl->data.d.d_buf && buf != tmpbuf)
74725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  free (buf);
74825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
74925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			__libelf_seterrno (ELF_E_WRITE_ERROR);
75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			return 1;
75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      }
75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (buf != dl->data.d.d_buf && buf != tmpbuf)
75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      free (buf);
75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    scn_changed = true;
75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		last_offset += dl->data.d.d_size;
76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		dl->flags &= ~ELF_F_DIRTY;
76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		dl = dl->next;
76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    while (dl != NULL);
76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* If the previous section (or the ELF/program
76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 header) changed we might have to fill the gap.  */
77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (scn_start > last_offset && previous_scn_changed)
77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (fill (elf->fildes, last_offset,
77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      scn_start - last_offset, fillbuf,
77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      &filled) != 0))
77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    return 1;
77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      last_offset = scn_start + shdr->sh_size;
77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  previous_scn_changed = scn_changed;
78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	next:
78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Collect the section header table information.  */
78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (change_bo))
78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    (*shdr_fctp) (&shdr_data[scn->index],
78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  scn->shdr.ELFW(e,LIBELFBITS),
78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    memcpy (&shdr_data[scn->index], scn->shdr.ELFW(e,LIBELFBITS),
79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    sizeof (ElfW2(LIBELFBITS,Shdr)));
79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr_flags |= scn->shdr_flags;
79325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  scn->shdr_flags &= ~ELF_F_DIRTY;
79425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
79525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Fill the gap between last section and section header table if
79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 necessary.  */
79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((elf->flags & ELF_F_DIRTY) && last_offset < shdr_offset
79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && unlikely (fill (elf->fildes, last_offset,
80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     shdr_offset - last_offset,
80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     fillbuf, &filled) != 0))
80225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return 1;
80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Write out the section header table.  */
80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr_flags & ELF_F_DIRTY
80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && unlikely ((size_t) pwrite_retry (elf->fildes, shdr_data,
80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      sizeof (ElfW2(LIBELFBITS,Shdr))
80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      * shnum, shdr_offset)
80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       != sizeof (ElfW2(LIBELFBITS,Shdr)) * shnum))
81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libelf_seterrno (ELF_E_WRITE_ERROR);
81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return 1;
81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
81425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* That was the last part.  Clear the overall flag.  */
81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf->flags &= ~ELF_F_DIRTY;
81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
821