xref: /aosp_15_r20/external/elfutils/libelf/elf32_updatenull.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Update data structures for changes.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2000-2010, 2015, 2016 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker    Written by Ulrich Drepper <[email protected]>, 2000.
5*7304104dSAndroid Build Coastguard Worker 
6*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker    it under the terms of either
8*7304104dSAndroid Build Coastguard Worker 
9*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker        your option) any later version
12*7304104dSAndroid Build Coastguard Worker 
13*7304104dSAndroid Build Coastguard Worker    or
14*7304104dSAndroid Build Coastguard Worker 
15*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker        your option) any later version
18*7304104dSAndroid Build Coastguard Worker 
19*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker 
21*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker 
26*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
28*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
29*7304104dSAndroid Build Coastguard Worker 
30*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
31*7304104dSAndroid Build Coastguard Worker # include <config.h>
32*7304104dSAndroid Build Coastguard Worker #endif
33*7304104dSAndroid Build Coastguard Worker 
34*7304104dSAndroid Build Coastguard Worker #include <assert.h>
35*7304104dSAndroid Build Coastguard Worker #include <libelf.h>
36*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
37*7304104dSAndroid Build Coastguard Worker #include <string.h>
38*7304104dSAndroid Build Coastguard Worker 
39*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"
40*7304104dSAndroid Build Coastguard Worker #include "elf-knowledge.h"
41*7304104dSAndroid Build Coastguard Worker 
42*7304104dSAndroid Build Coastguard Worker #ifndef LIBELFBITS
43*7304104dSAndroid Build Coastguard Worker # define LIBELFBITS 32
44*7304104dSAndroid Build Coastguard Worker #endif
45*7304104dSAndroid Build Coastguard Worker 
46*7304104dSAndroid Build Coastguard Worker /* Some fields contain 32/64 sizes.  We cannot use Elf32/64_Word for those,
47*7304104dSAndroid Build Coastguard Worker    since those are both 32bits.  Elf32/64_Xword is always 64bits.  */
48*7304104dSAndroid Build Coastguard Worker #define Elf32_SizeWord Elf32_Word
49*7304104dSAndroid Build Coastguard Worker #define Elf64_SizeWord Elf64_Xword
50*7304104dSAndroid Build Coastguard Worker 
51*7304104dSAndroid Build Coastguard Worker 
52*7304104dSAndroid Build Coastguard Worker static int
ELFW(default_ehdr,LIBELFBITS)53*7304104dSAndroid Build Coastguard Worker ELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
54*7304104dSAndroid Build Coastguard Worker 			       size_t shnum, int *change_bop)
55*7304104dSAndroid Build Coastguard Worker {
56*7304104dSAndroid Build Coastguard Worker   /* Always write the magic bytes.  */
57*7304104dSAndroid Build Coastguard Worker   if (memcmp (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
58*7304104dSAndroid Build Coastguard Worker     {
59*7304104dSAndroid Build Coastguard Worker       memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
60*7304104dSAndroid Build Coastguard Worker       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
61*7304104dSAndroid Build Coastguard Worker     }
62*7304104dSAndroid Build Coastguard Worker 
63*7304104dSAndroid Build Coastguard Worker   /* Always set the file class.  */
64*7304104dSAndroid Build Coastguard Worker   update_if_changed (ehdr->e_ident[EI_CLASS], ELFW(ELFCLASS,LIBELFBITS),
65*7304104dSAndroid Build Coastguard Worker 		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
66*7304104dSAndroid Build Coastguard Worker 
67*7304104dSAndroid Build Coastguard Worker   /* Set the data encoding if necessary.  */
68*7304104dSAndroid Build Coastguard Worker   if (unlikely (ehdr->e_ident[EI_DATA] == ELFDATANONE))
69*7304104dSAndroid Build Coastguard Worker     {
70*7304104dSAndroid Build Coastguard Worker       ehdr->e_ident[EI_DATA] =
71*7304104dSAndroid Build Coastguard Worker 	BYTE_ORDER == BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB;
72*7304104dSAndroid Build Coastguard Worker       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
73*7304104dSAndroid Build Coastguard Worker     }
74*7304104dSAndroid Build Coastguard Worker   else if (unlikely (ehdr->e_ident[EI_DATA] >= ELFDATANUM))
75*7304104dSAndroid Build Coastguard Worker     {
76*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_DATA_ENCODING);
77*7304104dSAndroid Build Coastguard Worker       return 1;
78*7304104dSAndroid Build Coastguard Worker     }
79*7304104dSAndroid Build Coastguard Worker   else
80*7304104dSAndroid Build Coastguard Worker     *change_bop = ((BYTE_ORDER == LITTLE_ENDIAN
81*7304104dSAndroid Build Coastguard Worker 		    && ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
82*7304104dSAndroid Build Coastguard Worker 		   || (BYTE_ORDER == BIG_ENDIAN
83*7304104dSAndroid Build Coastguard Worker 		       && ehdr->e_ident[EI_DATA] != ELFDATA2MSB));
84*7304104dSAndroid Build Coastguard Worker 
85*7304104dSAndroid Build Coastguard Worker   /* Unconditionally overwrite the ELF version.  */
86*7304104dSAndroid Build Coastguard Worker   update_if_changed (ehdr->e_ident[EI_VERSION], EV_CURRENT,
87*7304104dSAndroid Build Coastguard Worker 		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
88*7304104dSAndroid Build Coastguard Worker 
89*7304104dSAndroid Build Coastguard Worker   if (unlikely (ehdr->e_version == EV_NONE))
90*7304104dSAndroid Build Coastguard Worker     {
91*7304104dSAndroid Build Coastguard Worker       ehdr->e_version = EV_CURRENT;
92*7304104dSAndroid Build Coastguard Worker       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
93*7304104dSAndroid Build Coastguard Worker     }
94*7304104dSAndroid Build Coastguard Worker   else if (unlikely (ehdr->e_version != EV_CURRENT))
95*7304104dSAndroid Build Coastguard Worker     {
96*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
97*7304104dSAndroid Build Coastguard Worker       return 1;
98*7304104dSAndroid Build Coastguard Worker     }
99*7304104dSAndroid Build Coastguard Worker 
100*7304104dSAndroid Build Coastguard Worker   if (unlikely (shnum >= SHN_LORESERVE))
101*7304104dSAndroid Build Coastguard Worker     {
102*7304104dSAndroid Build Coastguard Worker       update_if_changed (ehdr->e_shnum, 0,
103*7304104dSAndroid Build Coastguard Worker 			 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
104*7304104dSAndroid Build Coastguard Worker     }
105*7304104dSAndroid Build Coastguard Worker   else
106*7304104dSAndroid Build Coastguard Worker     update_if_changed (ehdr->e_shnum, shnum,
107*7304104dSAndroid Build Coastguard Worker 		       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
108*7304104dSAndroid Build Coastguard Worker 
109*7304104dSAndroid Build Coastguard Worker   if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)))
110*7304104dSAndroid Build Coastguard Worker     {
111*7304104dSAndroid Build Coastguard Worker       ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
112*7304104dSAndroid Build Coastguard Worker       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
113*7304104dSAndroid Build Coastguard Worker     }
114*7304104dSAndroid Build Coastguard Worker 
115*7304104dSAndroid Build Coastguard Worker   /* If phnum is zero make sure e_phoff is also zero and not some random
116*7304104dSAndroid Build Coastguard Worker      value.  That would cause trouble in update_file.  */
117*7304104dSAndroid Build Coastguard Worker   if (ehdr->e_phnum == 0 && ehdr->e_phoff != 0)
118*7304104dSAndroid Build Coastguard Worker     {
119*7304104dSAndroid Build Coastguard Worker       ehdr->e_phoff = 0;
120*7304104dSAndroid Build Coastguard Worker       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
121*7304104dSAndroid Build Coastguard Worker     }
122*7304104dSAndroid Build Coastguard Worker 
123*7304104dSAndroid Build Coastguard Worker   return 0;
124*7304104dSAndroid Build Coastguard Worker }
125*7304104dSAndroid Build Coastguard Worker 
126*7304104dSAndroid Build Coastguard Worker 
127*7304104dSAndroid Build Coastguard Worker int64_t
128*7304104dSAndroid Build Coastguard Worker internal_function
__elfw2(LIBELFBITS,updatenull_wrlock)129*7304104dSAndroid Build Coastguard Worker __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
130*7304104dSAndroid Build Coastguard Worker {
131*7304104dSAndroid Build Coastguard Worker   ElfW2(LIBELFBITS,Ehdr) *ehdr;
132*7304104dSAndroid Build Coastguard Worker   int changed = 0;
133*7304104dSAndroid Build Coastguard Worker   int ehdr_flags = 0;
134*7304104dSAndroid Build Coastguard Worker 
135*7304104dSAndroid Build Coastguard Worker   ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
136*7304104dSAndroid Build Coastguard Worker 
137*7304104dSAndroid Build Coastguard Worker   /* Set the default values.  */
138*7304104dSAndroid Build Coastguard Worker   if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
139*7304104dSAndroid Build Coastguard Worker     return -1;
140*7304104dSAndroid Build Coastguard Worker 
141*7304104dSAndroid Build Coastguard Worker   /* At least the ELF header is there.  */
142*7304104dSAndroid Build Coastguard Worker   ElfW2(LIBELFBITS,SizeWord) size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
143*7304104dSAndroid Build Coastguard Worker 
144*7304104dSAndroid Build Coastguard Worker   /* Set the program header position.  */
145*7304104dSAndroid Build Coastguard Worker   if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
146*7304104dSAndroid Build Coastguard Worker     (void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
147*7304104dSAndroid Build Coastguard Worker   if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
148*7304104dSAndroid Build Coastguard Worker     {
149*7304104dSAndroid Build Coastguard Worker       size_t phnum;
150*7304104dSAndroid Build Coastguard Worker       if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
151*7304104dSAndroid Build Coastguard Worker 	return -1;
152*7304104dSAndroid Build Coastguard Worker 
153*7304104dSAndroid Build Coastguard Worker       if (elf->flags & ELF_F_LAYOUT)
154*7304104dSAndroid Build Coastguard Worker 	{
155*7304104dSAndroid Build Coastguard Worker 	  /* The user is supposed to fill out e_phoff.  Use it and
156*7304104dSAndroid Build Coastguard Worker 	     e_phnum to determine the maximum extend.  */
157*7304104dSAndroid Build Coastguard Worker 	  size = MAX (size,
158*7304104dSAndroid Build Coastguard Worker 		      ehdr->e_phoff
159*7304104dSAndroid Build Coastguard Worker 		      + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
160*7304104dSAndroid Build Coastguard Worker 	}
161*7304104dSAndroid Build Coastguard Worker       else
162*7304104dSAndroid Build Coastguard Worker 	{
163*7304104dSAndroid Build Coastguard Worker 	  update_if_changed (ehdr->e_phoff,
164*7304104dSAndroid Build Coastguard Worker 			     elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
165*7304104dSAndroid Build Coastguard Worker 			     ehdr_flags);
166*7304104dSAndroid Build Coastguard Worker 
167*7304104dSAndroid Build Coastguard Worker 	  /* We need no alignment here.  */
168*7304104dSAndroid Build Coastguard Worker 	  size += elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum);
169*7304104dSAndroid Build Coastguard Worker 	}
170*7304104dSAndroid Build Coastguard Worker     }
171*7304104dSAndroid Build Coastguard Worker 
172*7304104dSAndroid Build Coastguard Worker   if (shnum > 0)
173*7304104dSAndroid Build Coastguard Worker     {
174*7304104dSAndroid Build Coastguard Worker       struct Elf_Scn *scn1 = NULL;
175*7304104dSAndroid Build Coastguard Worker       Elf_ScnList *list;
176*7304104dSAndroid Build Coastguard Worker       bool first = true;
177*7304104dSAndroid Build Coastguard Worker 
178*7304104dSAndroid Build Coastguard Worker       assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0);
179*7304104dSAndroid Build Coastguard Worker 
180*7304104dSAndroid Build Coastguard Worker       if (shnum >= SHN_LORESERVE)
181*7304104dSAndroid Build Coastguard Worker 	{
182*7304104dSAndroid Build Coastguard Worker 	  /* We have to  fill in the number of sections in the header
183*7304104dSAndroid Build Coastguard Worker 	     of the zeroth section.  */
184*7304104dSAndroid Build Coastguard Worker 	  Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
185*7304104dSAndroid Build Coastguard Worker 
186*7304104dSAndroid Build Coastguard Worker 	  update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
187*7304104dSAndroid Build Coastguard Worker 			     shnum, scn0->shdr_flags);
188*7304104dSAndroid Build Coastguard Worker 	}
189*7304104dSAndroid Build Coastguard Worker 
190*7304104dSAndroid Build Coastguard Worker       /* Go over all sections and find out how large they are.  */
191*7304104dSAndroid Build Coastguard Worker       list = &elf->state.ELFW(elf,LIBELFBITS).scns;
192*7304104dSAndroid Build Coastguard Worker 
193*7304104dSAndroid Build Coastguard Worker       /* Find the first section. */
194*7304104dSAndroid Build Coastguard Worker       if (list->cnt > 1)
195*7304104dSAndroid Build Coastguard Worker 	scn1 = &list->data[1];
196*7304104dSAndroid Build Coastguard Worker       else if (list->next != NULL)
197*7304104dSAndroid Build Coastguard Worker 	scn1 = &list->next->data[0];
198*7304104dSAndroid Build Coastguard Worker 
199*7304104dSAndroid Build Coastguard Worker       /* Load the section headers if necessary.  This loads the
200*7304104dSAndroid Build Coastguard Worker 	 headers for all sections.  */
201*7304104dSAndroid Build Coastguard Worker       if (scn1 != NULL && scn1->shdr.ELFW(e,LIBELFBITS) == NULL)
202*7304104dSAndroid Build Coastguard Worker 	(void) __elfw2(LIBELFBITS,getshdr_wrlock) (scn1);
203*7304104dSAndroid Build Coastguard Worker 
204*7304104dSAndroid Build Coastguard Worker       do
205*7304104dSAndroid Build Coastguard Worker 	{
206*7304104dSAndroid Build Coastguard Worker 	  for (size_t cnt = first == true; cnt < list->cnt; ++cnt)
207*7304104dSAndroid Build Coastguard Worker 	    {
208*7304104dSAndroid Build Coastguard Worker 	      Elf_Scn *scn = &list->data[cnt];
209*7304104dSAndroid Build Coastguard Worker 	      ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
210*7304104dSAndroid Build Coastguard Worker 	      int64_t offset = 0;
211*7304104dSAndroid Build Coastguard Worker 
212*7304104dSAndroid Build Coastguard Worker 	      assert (shdr != NULL);
213*7304104dSAndroid Build Coastguard Worker 	      ElfW2(LIBELFBITS,SizeWord) sh_entsize = shdr->sh_entsize;
214*7304104dSAndroid Build Coastguard Worker 	      ElfW2(LIBELFBITS,SizeWord) sh_align = shdr->sh_addralign ?: 1;
215*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (! powerof2 (sh_align)))
216*7304104dSAndroid Build Coastguard Worker 		{
217*7304104dSAndroid Build Coastguard Worker 		  __libelf_seterrno (ELF_E_INVALID_ALIGN);
218*7304104dSAndroid Build Coastguard Worker 		  return -1;
219*7304104dSAndroid Build Coastguard Worker 		}
220*7304104dSAndroid Build Coastguard Worker 
221*7304104dSAndroid Build Coastguard Worker 	      /* Set the sh_entsize value if we can reliably detect it.  */
222*7304104dSAndroid Build Coastguard Worker 	      switch (shdr->sh_type)
223*7304104dSAndroid Build Coastguard Worker 		{
224*7304104dSAndroid Build Coastguard Worker 		case SHT_SYMTAB:
225*7304104dSAndroid Build Coastguard Worker 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
226*7304104dSAndroid Build Coastguard Worker 		  break;
227*7304104dSAndroid Build Coastguard Worker 		case SHT_RELA:
228*7304104dSAndroid Build Coastguard Worker 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELA, 1);
229*7304104dSAndroid Build Coastguard Worker 		  break;
230*7304104dSAndroid Build Coastguard Worker 		case SHT_GROUP:
231*7304104dSAndroid Build Coastguard Worker 		  /* Only relocatable files can contain section groups.  */
232*7304104dSAndroid Build Coastguard Worker 		  if (ehdr->e_type != ET_REL)
233*7304104dSAndroid Build Coastguard Worker 		    {
234*7304104dSAndroid Build Coastguard Worker 		      __libelf_seterrno (ELF_E_GROUP_NOT_REL);
235*7304104dSAndroid Build Coastguard Worker 		      return -1;
236*7304104dSAndroid Build Coastguard Worker 		    }
237*7304104dSAndroid Build Coastguard Worker 		  FALLTHROUGH;
238*7304104dSAndroid Build Coastguard Worker 		case SHT_SYMTAB_SHNDX:
239*7304104dSAndroid Build Coastguard Worker 		  sh_entsize = elf_typesize (32, ELF_T_WORD, 1);
240*7304104dSAndroid Build Coastguard Worker 		  break;
241*7304104dSAndroid Build Coastguard Worker 		case SHT_HASH:
242*7304104dSAndroid Build Coastguard Worker 		  sh_entsize = SH_ENTSIZE_HASH (ehdr);
243*7304104dSAndroid Build Coastguard Worker 		  break;
244*7304104dSAndroid Build Coastguard Worker 		case SHT_DYNAMIC:
245*7304104dSAndroid Build Coastguard Worker 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_DYN, 1);
246*7304104dSAndroid Build Coastguard Worker 		  break;
247*7304104dSAndroid Build Coastguard Worker 		case SHT_REL:
248*7304104dSAndroid Build Coastguard Worker 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_REL, 1);
249*7304104dSAndroid Build Coastguard Worker 		  break;
250*7304104dSAndroid Build Coastguard Worker 		case SHT_DYNSYM:
251*7304104dSAndroid Build Coastguard Worker 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
252*7304104dSAndroid Build Coastguard Worker 		  break;
253*7304104dSAndroid Build Coastguard Worker 		case SHT_SUNW_move:
254*7304104dSAndroid Build Coastguard Worker 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_MOVE, 1);
255*7304104dSAndroid Build Coastguard Worker 		  break;
256*7304104dSAndroid Build Coastguard Worker 		case SHT_SUNW_syminfo:
257*7304104dSAndroid Build Coastguard Worker 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
258*7304104dSAndroid Build Coastguard Worker 		  break;
259*7304104dSAndroid Build Coastguard Worker 		case SHT_RELR:
260*7304104dSAndroid Build Coastguard Worker 		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELR, 1);
261*7304104dSAndroid Build Coastguard Worker 		  break;
262*7304104dSAndroid Build Coastguard Worker 		default:
263*7304104dSAndroid Build Coastguard Worker 		  break;
264*7304104dSAndroid Build Coastguard Worker 		}
265*7304104dSAndroid Build Coastguard Worker 
266*7304104dSAndroid Build Coastguard Worker 	      /* If the section header contained the wrong entry size
267*7304104dSAndroid Build Coastguard Worker 		 correct it and mark the header as modified.  */
268*7304104dSAndroid Build Coastguard Worker 	      update_if_changed (shdr->sh_entsize, sh_entsize,
269*7304104dSAndroid Build Coastguard Worker 				 scn->shdr_flags);
270*7304104dSAndroid Build Coastguard Worker 
271*7304104dSAndroid Build Coastguard Worker 	      /* Likewise for the alignment of a compressed section.
272*7304104dSAndroid Build Coastguard Worker 	         For a SHF_COMPRESSED section set the correct
273*7304104dSAndroid Build Coastguard Worker 	         sh_addralign value, which must match the d_align of
274*7304104dSAndroid Build Coastguard Worker 	         the data (see __libelf_set_rawdata in elf_getdata.c).  */
275*7304104dSAndroid Build Coastguard Worker 	      if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
276*7304104dSAndroid Build Coastguard Worker 		{
277*7304104dSAndroid Build Coastguard Worker 		  sh_align = __libelf_type_align (ELFW(ELFCLASS,LIBELFBITS),
278*7304104dSAndroid Build Coastguard Worker 						  ELF_T_CHDR);
279*7304104dSAndroid Build Coastguard Worker 		  update_if_changed (shdr->sh_addralign, sh_align,
280*7304104dSAndroid Build Coastguard Worker 				     scn->shdr_flags);
281*7304104dSAndroid Build Coastguard Worker 		}
282*7304104dSAndroid Build Coastguard Worker 
283*7304104dSAndroid Build Coastguard Worker 	      if (scn->data_read == 0
284*7304104dSAndroid Build Coastguard Worker 		  && __libelf_set_rawdata_wrlock (scn) != 0)
285*7304104dSAndroid Build Coastguard Worker 		/* Something went wrong.  The error value is already set.  */
286*7304104dSAndroid Build Coastguard Worker 		return -1;
287*7304104dSAndroid Build Coastguard Worker 
288*7304104dSAndroid Build Coastguard Worker 	      /* Iterate over all data blocks.  */
289*7304104dSAndroid Build Coastguard Worker 	      if (list->data[cnt].data_list_rear != NULL)
290*7304104dSAndroid Build Coastguard Worker 		{
291*7304104dSAndroid Build Coastguard Worker 		  Elf_Data_List *dl = &scn->data_list;
292*7304104dSAndroid Build Coastguard Worker 
293*7304104dSAndroid Build Coastguard Worker 		  while (dl != NULL)
294*7304104dSAndroid Build Coastguard Worker 		    {
295*7304104dSAndroid Build Coastguard Worker 		      Elf_Data *data = &dl->data.d;
296*7304104dSAndroid Build Coastguard Worker 		      if (dl == &scn->data_list && data->d_buf == NULL
297*7304104dSAndroid Build Coastguard Worker 			  && scn->rawdata.d.d_buf != NULL)
298*7304104dSAndroid Build Coastguard Worker 			data = &scn->rawdata.d;
299*7304104dSAndroid Build Coastguard Worker 
300*7304104dSAndroid Build Coastguard Worker 		      if (unlikely (data->d_version != EV_CURRENT))
301*7304104dSAndroid Build Coastguard Worker 			{
302*7304104dSAndroid Build Coastguard Worker 			  __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
303*7304104dSAndroid Build Coastguard Worker 			  return -1;
304*7304104dSAndroid Build Coastguard Worker 			}
305*7304104dSAndroid Build Coastguard Worker 
306*7304104dSAndroid Build Coastguard Worker 		      if (unlikely (! powerof2 (data->d_align)))
307*7304104dSAndroid Build Coastguard Worker 			{
308*7304104dSAndroid Build Coastguard Worker 			  __libelf_seterrno (ELF_E_INVALID_ALIGN);
309*7304104dSAndroid Build Coastguard Worker 			  return -1;
310*7304104dSAndroid Build Coastguard Worker 			}
311*7304104dSAndroid Build Coastguard Worker 
312*7304104dSAndroid Build Coastguard Worker 		      sh_align = MAX (sh_align, data->d_align);
313*7304104dSAndroid Build Coastguard Worker 
314*7304104dSAndroid Build Coastguard Worker 		      if (elf->flags & ELF_F_LAYOUT)
315*7304104dSAndroid Build Coastguard Worker 			{
316*7304104dSAndroid Build Coastguard Worker 			  /* The user specified the offset and the size.
317*7304104dSAndroid Build Coastguard Worker 			     All we have to do is check whether this block
318*7304104dSAndroid Build Coastguard Worker 			     fits in the size specified for the section.  */
319*7304104dSAndroid Build Coastguard Worker 			  if (unlikely ((ElfW2(LIBELFBITS,SizeWord))
320*7304104dSAndroid Build Coastguard Worker 					(data->d_off + data->d_size)
321*7304104dSAndroid Build Coastguard Worker 					> shdr->sh_size))
322*7304104dSAndroid Build Coastguard Worker 			    {
323*7304104dSAndroid Build Coastguard Worker 			      __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
324*7304104dSAndroid Build Coastguard Worker 			      return -1;
325*7304104dSAndroid Build Coastguard Worker 			    }
326*7304104dSAndroid Build Coastguard Worker 			}
327*7304104dSAndroid Build Coastguard Worker 		      else
328*7304104dSAndroid Build Coastguard Worker 			{
329*7304104dSAndroid Build Coastguard Worker 			  /* Determine the padding.  */
330*7304104dSAndroid Build Coastguard Worker 			  offset = ((offset + data->d_align - 1)
331*7304104dSAndroid Build Coastguard Worker 				    & ~(data->d_align - 1));
332*7304104dSAndroid Build Coastguard Worker 
333*7304104dSAndroid Build Coastguard Worker 			  update_if_changed (data->d_off, offset, changed);
334*7304104dSAndroid Build Coastguard Worker 
335*7304104dSAndroid Build Coastguard Worker 			  offset += data->d_size;
336*7304104dSAndroid Build Coastguard Worker 			}
337*7304104dSAndroid Build Coastguard Worker 
338*7304104dSAndroid Build Coastguard Worker 		      /* Next data block.  */
339*7304104dSAndroid Build Coastguard Worker 		      dl = dl->next;
340*7304104dSAndroid Build Coastguard Worker 		    }
341*7304104dSAndroid Build Coastguard Worker 		}
342*7304104dSAndroid Build Coastguard Worker 	      else
343*7304104dSAndroid Build Coastguard Worker 		/* Get the size of the section from the raw data.  If
344*7304104dSAndroid Build Coastguard Worker 		   none is available the value is zero.  */
345*7304104dSAndroid Build Coastguard Worker 		offset += scn->rawdata.d.d_size;
346*7304104dSAndroid Build Coastguard Worker 
347*7304104dSAndroid Build Coastguard Worker 	      if (elf->flags & ELF_F_LAYOUT)
348*7304104dSAndroid Build Coastguard Worker 		{
349*7304104dSAndroid Build Coastguard Worker 		  size = MAX (size,
350*7304104dSAndroid Build Coastguard Worker 			      (shdr->sh_type != SHT_NOBITS
351*7304104dSAndroid Build Coastguard Worker 			       ? shdr->sh_offset + shdr->sh_size : 0));
352*7304104dSAndroid Build Coastguard Worker 
353*7304104dSAndroid Build Coastguard Worker 		  /* The alignment must be a power of two.  This is a
354*7304104dSAndroid Build Coastguard Worker 		     requirement from the ELF specification.  Additionally
355*7304104dSAndroid Build Coastguard Worker 		     we test for the alignment of the section being large
356*7304104dSAndroid Build Coastguard Worker 		     enough for the largest alignment required by a data
357*7304104dSAndroid Build Coastguard Worker 		     block.  */
358*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (! powerof2 (shdr->sh_addralign))
359*7304104dSAndroid Build Coastguard Worker 		      || unlikely ((shdr->sh_addralign ?: 1) < sh_align))
360*7304104dSAndroid Build Coastguard Worker 		    {
361*7304104dSAndroid Build Coastguard Worker 		      __libelf_seterrno (ELF_E_INVALID_ALIGN);
362*7304104dSAndroid Build Coastguard Worker 		      return -1;
363*7304104dSAndroid Build Coastguard Worker 		    }
364*7304104dSAndroid Build Coastguard Worker 		}
365*7304104dSAndroid Build Coastguard Worker 	      else
366*7304104dSAndroid Build Coastguard Worker 		{
367*7304104dSAndroid Build Coastguard Worker 		  /* How much alignment do we need for this section.  */
368*7304104dSAndroid Build Coastguard Worker 		  update_if_changed (shdr->sh_addralign, sh_align,
369*7304104dSAndroid Build Coastguard Worker 				     scn->shdr_flags);
370*7304104dSAndroid Build Coastguard Worker 
371*7304104dSAndroid Build Coastguard Worker 		  size = (size + sh_align - 1) & ~(sh_align - 1);
372*7304104dSAndroid Build Coastguard Worker 		  int offset_changed = 0;
373*7304104dSAndroid Build Coastguard Worker 		  update_if_changed (shdr->sh_offset, size, offset_changed);
374*7304104dSAndroid Build Coastguard Worker 		  changed |= offset_changed;
375*7304104dSAndroid Build Coastguard Worker 
376*7304104dSAndroid Build Coastguard Worker 		  if (offset_changed && scn->data_list_rear == NULL)
377*7304104dSAndroid Build Coastguard Worker 		    {
378*7304104dSAndroid Build Coastguard Worker 		      /* The position of the section in the file
379*7304104dSAndroid Build Coastguard Worker 			 changed.  Create the section data list.  */
380*7304104dSAndroid Build Coastguard Worker 		      if (__elf_getdata_rdlock (scn, NULL) == NULL)
381*7304104dSAndroid Build Coastguard Worker 			return -1;
382*7304104dSAndroid Build Coastguard Worker 		    }
383*7304104dSAndroid Build Coastguard Worker 
384*7304104dSAndroid Build Coastguard Worker 		  /* See whether the section size is correct.  */
385*7304104dSAndroid Build Coastguard Worker 		  int size_changed = 0;
386*7304104dSAndroid Build Coastguard Worker 		  update_if_changed (shdr->sh_size,
387*7304104dSAndroid Build Coastguard Worker 				     (ElfW2(LIBELFBITS,SizeWord)) offset,
388*7304104dSAndroid Build Coastguard Worker 				     size_changed);
389*7304104dSAndroid Build Coastguard Worker 		  changed |= size_changed;
390*7304104dSAndroid Build Coastguard Worker 
391*7304104dSAndroid Build Coastguard Worker 		  if (shdr->sh_type != SHT_NOBITS)
392*7304104dSAndroid Build Coastguard Worker 		    size += offset;
393*7304104dSAndroid Build Coastguard Worker 
394*7304104dSAndroid Build Coastguard Worker 		  scn->shdr_flags |= (offset_changed | size_changed);
395*7304104dSAndroid Build Coastguard Worker 		  scn->flags |= changed;
396*7304104dSAndroid Build Coastguard Worker 		}
397*7304104dSAndroid Build Coastguard Worker 
398*7304104dSAndroid Build Coastguard Worker 	      /* Check that the section size is actually a multiple of
399*7304104dSAndroid Build Coastguard Worker 		 the entry size.  */
400*7304104dSAndroid Build Coastguard Worker 	      if (shdr->sh_entsize != 0 && shdr->sh_entsize != 1
401*7304104dSAndroid Build Coastguard Worker 		  && (elf->flags & ELF_F_PERMISSIVE) == 0)
402*7304104dSAndroid Build Coastguard Worker 		{
403*7304104dSAndroid Build Coastguard Worker 		  /* For compressed sections check the uncompressed size.  */
404*7304104dSAndroid Build Coastguard Worker 		  ElfW2(LIBELFBITS,SizeWord) sh_size;
405*7304104dSAndroid Build Coastguard Worker 		  if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
406*7304104dSAndroid Build Coastguard Worker 		    sh_size = shdr->sh_size;
407*7304104dSAndroid Build Coastguard Worker 		  else
408*7304104dSAndroid Build Coastguard Worker 		    {
409*7304104dSAndroid Build Coastguard Worker 		      ElfW2(LIBELFBITS,Chdr) *chdr;
410*7304104dSAndroid Build Coastguard Worker 		      chdr = __elfw2(LIBELFBITS,getchdr_wrlock) (scn);
411*7304104dSAndroid Build Coastguard Worker 		      if (unlikely (chdr == NULL))
412*7304104dSAndroid Build Coastguard Worker 			return -1;
413*7304104dSAndroid Build Coastguard Worker 		      sh_size = chdr->ch_size;
414*7304104dSAndroid Build Coastguard Worker 		    }
415*7304104dSAndroid Build Coastguard Worker 
416*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (sh_size % shdr->sh_entsize != 0))
417*7304104dSAndroid Build Coastguard Worker 		    {
418*7304104dSAndroid Build Coastguard Worker 		      __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
419*7304104dSAndroid Build Coastguard Worker 		      return -1;
420*7304104dSAndroid Build Coastguard Worker 		    }
421*7304104dSAndroid Build Coastguard Worker 		}
422*7304104dSAndroid Build Coastguard Worker 	    }
423*7304104dSAndroid Build Coastguard Worker 
424*7304104dSAndroid Build Coastguard Worker 	  assert (list->next == NULL || list->cnt == list->max);
425*7304104dSAndroid Build Coastguard Worker 
426*7304104dSAndroid Build Coastguard Worker 	  first = false;
427*7304104dSAndroid Build Coastguard Worker 	}
428*7304104dSAndroid Build Coastguard Worker       while ((list = list->next) != NULL);
429*7304104dSAndroid Build Coastguard Worker 
430*7304104dSAndroid Build Coastguard Worker       /* Store section information.  */
431*7304104dSAndroid Build Coastguard Worker       update_if_changed (ehdr->e_shentsize,
432*7304104dSAndroid Build Coastguard Worker 			 elf_typesize (LIBELFBITS, ELF_T_SHDR, 1), ehdr_flags);
433*7304104dSAndroid Build Coastguard Worker       if (elf->flags & ELF_F_LAYOUT)
434*7304104dSAndroid Build Coastguard Worker 	{
435*7304104dSAndroid Build Coastguard Worker 	  /* The user is supposed to fill out e_shoff.  Use it and
436*7304104dSAndroid Build Coastguard Worker 	     e_shnum (or sh_size of the dummy, first section header)
437*7304104dSAndroid Build Coastguard Worker 	     to determine the maximum extend.  */
438*7304104dSAndroid Build Coastguard Worker 	  size = MAX (size,
439*7304104dSAndroid Build Coastguard Worker 		      (ehdr->e_shoff
440*7304104dSAndroid Build Coastguard Worker 		       + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
441*7304104dSAndroid Build Coastguard Worker 	}
442*7304104dSAndroid Build Coastguard Worker       else
443*7304104dSAndroid Build Coastguard Worker 	{
444*7304104dSAndroid Build Coastguard Worker 	  /* Align for section header table.
445*7304104dSAndroid Build Coastguard Worker 
446*7304104dSAndroid Build Coastguard Worker 	     Yes, we use `sizeof' and not `__alignof__' since we do not
447*7304104dSAndroid Build Coastguard Worker 	     want to be surprised by architectures with less strict
448*7304104dSAndroid Build Coastguard Worker 	     alignment rules.  */
449*7304104dSAndroid Build Coastguard Worker #define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
450*7304104dSAndroid Build Coastguard Worker 	  size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
451*7304104dSAndroid Build Coastguard Worker 
452*7304104dSAndroid Build Coastguard Worker 	  update_if_changed (ehdr->e_shoff, size, elf->flags);
453*7304104dSAndroid Build Coastguard Worker 
454*7304104dSAndroid Build Coastguard Worker 	  /* Account for the section header size.  */
455*7304104dSAndroid Build Coastguard Worker 	  size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
456*7304104dSAndroid Build Coastguard Worker 	}
457*7304104dSAndroid Build Coastguard Worker     }
458*7304104dSAndroid Build Coastguard Worker 
459*7304104dSAndroid Build Coastguard Worker   elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
460*7304104dSAndroid Build Coastguard Worker 
461*7304104dSAndroid Build Coastguard Worker   return size;
462*7304104dSAndroid Build Coastguard Worker }
463