1441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Update data structures for changes.
2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   This file is part of Red Hat elfutils.
4441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
7cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   it under the terms of the GNU General Public License as published by the
8cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Free Software Foundation; version 2 of the License.
9cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
10cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
11cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
12cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   General Public License for more details.
14cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
15cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   You should have received a copy of the GNU General Public License along
16cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
17cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
19cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   In addition, as a special exception, Red Hat, Inc. gives You the
20cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   additional right to link the code of Red Hat elfutils with code licensed
21cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   under any Open Source Initiative certified open source license
22cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   (http://www.opensource.org/licenses/index.php) which requires the
23cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   distribution of source code with any binary distribution and to
24cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   distribute linked combinations of the two.  Non-GPL Code permitted under
25cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   this exception must only link to the code of Red Hat elfutils through
26cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   those well defined interfaces identified in the file named EXCEPTION
27cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   found in the source code files (the "Approved Interfaces").  The files
28cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   of Non-GPL Code may instantiate templates or use macros or inline
29cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   functions from the Approved Interfaces without causing the resulting
30cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   work to be covered by the GNU General Public License.  Only Red Hat,
31cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Inc. may make changes or additions to the list of Approved Interfaces.
32cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat's grant of this exception is conditioned upon your not adding
33cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   any new exceptions.  If you wish to add a new Approved Interface or
34cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   exception, please contact Red Hat.  You must obey the GNU General Public
35cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   License in all respects for all of the Red Hat elfutils code and other
36cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   code used in conjunction with Red Hat elfutils except the Non-GPL Code
37cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   covered by this exception.  If you modify this file, you may extend this
38cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   exception to your version of the file, but you are not obligated to do
39cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   so.  If you do not wish to provide this exception without modification,
40cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   you must delete this exception statement from your version and license
41cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   this file solely under the GPL without exception.
42cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
43cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is an included package of the Open Invention Network.
44cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   An included package of the Open Invention Network is a package for which
45cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Open Invention Network licensees cross-license their patents.  No patent
46cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   license is granted, either expressly or impliedly, by designation as an
47cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   included package.  Should you wish to participate in the Open Invention
48cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Network licensing program, please visit www.openinventionnetwork.com
49cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   <http://www.openinventionnetwork.com>.  */
50441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
51441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifdef HAVE_CONFIG_H
52441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project# include <config.h>
53441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif
54441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
55441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <assert.h>
56cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <endian.h>
57441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libelf.h>
58441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdbool.h>
59441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <string.h>
60441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <sys/param.h>
61441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
62441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include "libelfP.h"
63441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include "elf-knowledge.h"
64441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
65441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifndef LIBELFBITS
66441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project# define LIBELFBITS 32
67441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif
68441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
69441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
70441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
71441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int
72441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
73441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       size_t shnum, int *change_bop)
74441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
75441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Always write the magic bytes.  */
76441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (memcmp (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
77441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
78441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
79441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
80441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
81441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
82441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Always set the file class.  */
83441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  update_if_changed (ehdr->e_ident[EI_CLASS], ELFW(ELFCLASS,LIBELFBITS),
84441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
85441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
86441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Set the data encoding if necessary.  */
87441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (ehdr->e_ident[EI_DATA] == ELFDATANONE))
88441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
89441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ehdr->e_ident[EI_DATA] =
90441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	BYTE_ORDER == BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB;
91441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
92441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
93441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else if (unlikely (ehdr->e_ident[EI_DATA] >= ELFDATANUM))
94441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
95441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      __libelf_seterrno (ELF_E_DATA_ENCODING);
96441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return 1;
97441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
98441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
99441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    *change_bop = ((BYTE_ORDER == LITTLE_ENDIAN
100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    && ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   || (BYTE_ORDER == BIG_ENDIAN
102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       && ehdr->e_ident[EI_DATA] != ELFDATA2MSB));
103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Unconditionally overwrite the ELF version.  */
105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  update_if_changed (ehdr->e_ident[EI_VERSION], EV_CURRENT,
106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (ehdr->e_version == EV_NONE)
109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      || unlikely (ehdr->e_version >= EV_NUM))
110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return 1;
113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (shnum >= SHN_LORESERVE))
116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      update_if_changed (ehdr->e_shnum, 0,
118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    update_if_changed (ehdr->e_shnum, shnum,
122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)))
125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return 0;
131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectoff_t
135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenginternal_function
136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng__elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  ElfW2(LIBELFBITS,Ehdr) *ehdr;
139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int changed = 0;
140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int ehdr_flags = 0;
141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Set the default values.  */
145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return -1;
147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* At least the ELF header is there.  */
149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  off_t size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Set the program header position.  */
152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL
153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  || ehdr->e_type == ET_CORE))
155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    (void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Only executables, shared objects, and core files have a program
159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 header.  */
160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  && unlikely (ehdr->e_type != ET_CORE))
162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  __libelf_seterrno (ELF_E_INVALID_PHDR);
164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  return -1;
165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (elf->flags & ELF_F_LAYOUT)
168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* The user is supposed to fill out e_phoff.  Use it and
170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     e_phnum to determine the maximum extend.  */
171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  size = MAX ((size_t) size,
172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ehdr->e_phoff
173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      + elf_typesize (LIBELFBITS, ELF_T_PHDR, ehdr->e_phnum));
174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  update_if_changed (ehdr->e_phoff,
178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     ehdr_flags);
180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* We need no alignment here.  */
182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  size += elf_typesize (LIBELFBITS, ELF_T_PHDR, ehdr->e_phnum);
183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shnum > 0)
187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Elf_ScnList *list;
189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      bool first = true;
190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0);
192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shnum >= SHN_LORESERVE)
194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* We have to  fill in the number of sections in the header
196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     of the zeroth section.  */
197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     shnum, scn0->shdr_flags);
201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Go over all sections and find out how large they are.  */
204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      list = &elf->state.ELFW(elf,LIBELFBITS).scns;
205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Load the section headers if necessary.  This loads the
207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 headers for all sections.  */
208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (list->data[1].shdr.ELFW(e,LIBELFBITS) == NULL)
209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	(void) __elfw2(LIBELFBITS,getshdr_wrlock) (&list->data[1]);
210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      do
212441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  for (size_t cnt = first == true; cnt < list->cnt; ++cnt)
214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      Elf_Scn *scn = &list->data[cnt];
216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      off_t offset = 0;
218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      assert (shdr != NULL);
220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      ElfW2(LIBELFBITS,Word) sh_entsize = shdr->sh_entsize;
221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      ElfW2(LIBELFBITS,Word) sh_align = shdr->sh_addralign ?: 1;
222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Set the sh_entsize value if we can reliably detect it.  */
224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      switch (shdr->sh_type)
225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case SHT_SYMTAB:
227441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case SHT_RELA:
230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELA, 1);
231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case SHT_GROUP:
233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Only relocatable files can contain section groups.  */
234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (ehdr->e_type != ET_REL)
235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      __libelf_seterrno (ELF_E_GROUP_NOT_REL);
237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      return -1;
238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* FALLTHROUGH */
240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case SHT_SYMTAB_SHNDX:
241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  sh_entsize = elf_typesize (32, ELF_T_WORD, 1);
242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case SHT_HASH:
244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  sh_entsize = SH_ENTSIZE_HASH (ehdr);
245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case SHT_DYNAMIC:
247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_DYN, 1);
248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case SHT_REL:
250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_REL, 1);
251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case SHT_DYNSYM:
253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case SHT_SUNW_move:
256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_MOVE, 1);
257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case SHT_SUNW_syminfo:
259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		default:
262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* If the section header contained the wrong entry size
266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 correct it and mark the header as modified.  */
267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      update_if_changed (shdr->sh_entsize, sh_entsize,
268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				 scn->shdr_flags);
269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (scn->data_read == 0
271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  && __libelf_set_rawdata_wrlock (scn) != 0)
272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* Something went wrong.  The error value is already set.  */
273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		return -1;
274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Iterate over all data blocks.  */
276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (list->data[cnt].data_list_rear != NULL)
277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  Elf_Data_List *dl = &scn->data_list;
279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  while (dl != NULL)
281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      Elf_Data *data = &dl->data.d;
283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (dl == &scn->data_list && data->d_buf == NULL
284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  && scn->rawdata.d.d_buf != NULL)
285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			data = &scn->rawdata.d;
286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (unlikely (data->d_version == EV_NONE)
288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  || unlikely (data->d_version >= EV_NUM))
289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			{
290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  return -1;
292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			}
293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (unlikely (! powerof2 (data->d_align)))
295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			{
296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  __libelf_seterrno (ELF_E_INVALID_ALIGN);
297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  return -1;
298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			}
299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      sh_align = MAX (sh_align, data->d_align);
301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (elf->flags & ELF_F_LAYOUT)
303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			{
304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  /* The user specified the offset and the size.
305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     All we have to do is check whether this block
306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     fits in the size specified for the section.  */
307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  if (unlikely ((GElf_Word) (data->d_off
308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						     + data->d_size)
309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					> shdr->sh_size))
310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    {
311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      return -1;
313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    }
314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			}
315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      else
316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			{
317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  /* Determine the padding.  */
318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  offset = ((offset + data->d_align - 1)
319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				    & ~(data->d_align - 1));
320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  update_if_changed (data->d_off, offset, changed);
322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  offset += data->d_size;
324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			}
325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      /* Next data block.  */
327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      dl = dl->next;
328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else
331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* Get the size of the section from the raw data.  If
332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   none is available the value is zero.  */
333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		offset += scn->rawdata.d.d_size;
334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (elf->flags & ELF_F_LAYOUT)
336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  size = MAX ((GElf_Word) size,
338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      shdr->sh_offset
339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      + (shdr->sh_type != SHT_NOBITS
340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				 ? shdr->sh_size : 0));
341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* The alignment must be a power of two.  This is a
343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     requirement from the ELF specification.  Additionally
344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     we test for the alignment of the section being large
345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     enough for the largest alignment required by a data
346441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     block.  */
347441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (unlikely (! powerof2 (shdr->sh_addralign))
348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      || unlikely (shdr->sh_addralign < sh_align))
349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      __libelf_seterrno (ELF_E_INVALID_ALIGN);
351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      return -1;
352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else
355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* How much alignment do we need for this section.  */
357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  update_if_changed (shdr->sh_addralign, sh_align,
358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     scn->shdr_flags);
359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  size = (size + sh_align - 1) & ~(sh_align - 1);
361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  int offset_changed = 0;
362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  update_if_changed (shdr->sh_offset, (GElf_Word) size,
363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				     offset_changed);
364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  changed |= offset_changed;
365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (offset_changed && scn->data_list_rear == NULL)
367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    {
368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      /* The position of the section in the file
369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 changed.  Create the section data list.  */
370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (__elf_getdata_rdlock (scn, NULL) == NULL)
371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			return -1;
372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    }
373441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
374441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* See whether the section size is correct.  */
375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  update_if_changed (shdr->sh_size, (GElf_Word) offset,
376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     changed);
377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (shdr->sh_type != SHT_NOBITS)
379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    size += offset;
380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  scn->flags |= changed;
382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Check that the section size is actually a multiple of
385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 the entry size.  */
386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr->sh_entsize != 0
387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  && unlikely (shdr->sh_size % shdr->sh_entsize != 0)
388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  && (elf->flags & ELF_F_PERMISSIVE) == 0)
389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  return -1;
392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  assert (list->next == NULL || list->cnt == list->max);
396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  first = false;
398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      while ((list = list->next) != NULL);
400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Store section information.  */
402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (elf->flags & ELF_F_LAYOUT)
403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* The user is supposed to fill out e_phoff.  Use it and
405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     e_phnum to determine the maximum extend.  */
406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  size = MAX ((GElf_Word) size,
407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      (ehdr->e_shoff
408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Align for section header table.
413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     Yes, we use `sizeof' and not `__alignof__' since we do not
415441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     want to be surprised by architectures with less strict
416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     alignment rules.  */
417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  update_if_changed (ehdr->e_shoff, (GElf_Word) size, elf->flags);
421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  update_if_changed (ehdr->e_shentsize,
422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     elf_typesize (LIBELFBITS, ELF_T_SHDR, 1),
423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     ehdr_flags);
424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Account for the section header size.  */
426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
430441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
432441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return size;
433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
434