xref: /aosp_15_r20/external/elfutils/libelf/elf32_updatefile.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Write changed data structures.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2000-2010, 2014, 2015, 2016, 2018 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 <errno.h>
36*7304104dSAndroid Build Coastguard Worker #include <libelf.h>
37*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
38*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
39*7304104dSAndroid Build Coastguard Worker #include <string.h>
40*7304104dSAndroid Build Coastguard Worker 
41*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"
42*7304104dSAndroid Build Coastguard Worker 
43*7304104dSAndroid Build Coastguard Worker 
44*7304104dSAndroid Build Coastguard Worker #ifndef LIBELFBITS
45*7304104dSAndroid Build Coastguard Worker # define LIBELFBITS 32
46*7304104dSAndroid Build Coastguard Worker #endif
47*7304104dSAndroid Build Coastguard Worker 
48*7304104dSAndroid Build Coastguard Worker 
49*7304104dSAndroid Build Coastguard Worker static int
compare_sections(const void * a,const void * b)50*7304104dSAndroid Build Coastguard Worker compare_sections (const void *a, const void *b)
51*7304104dSAndroid Build Coastguard Worker {
52*7304104dSAndroid Build Coastguard Worker   const Elf_Scn **scna = (const Elf_Scn **) a;
53*7304104dSAndroid Build Coastguard Worker   const Elf_Scn **scnb = (const Elf_Scn **) b;
54*7304104dSAndroid Build Coastguard Worker 
55*7304104dSAndroid Build Coastguard Worker   if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset
56*7304104dSAndroid Build Coastguard Worker       < (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset)
57*7304104dSAndroid Build Coastguard Worker     return -1;
58*7304104dSAndroid Build Coastguard Worker 
59*7304104dSAndroid Build Coastguard Worker   if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset
60*7304104dSAndroid Build Coastguard Worker       > (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset)
61*7304104dSAndroid Build Coastguard Worker     return 1;
62*7304104dSAndroid Build Coastguard Worker 
63*7304104dSAndroid Build Coastguard Worker   if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_size
64*7304104dSAndroid Build Coastguard Worker       < (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_size)
65*7304104dSAndroid Build Coastguard Worker     return -1;
66*7304104dSAndroid Build Coastguard Worker 
67*7304104dSAndroid Build Coastguard Worker   if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_size
68*7304104dSAndroid Build Coastguard Worker       > (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_size)
69*7304104dSAndroid Build Coastguard Worker     return 1;
70*7304104dSAndroid Build Coastguard Worker 
71*7304104dSAndroid Build Coastguard Worker   if ((*scna)->index < (*scnb)->index)
72*7304104dSAndroid Build Coastguard Worker     return -1;
73*7304104dSAndroid Build Coastguard Worker 
74*7304104dSAndroid Build Coastguard Worker   if ((*scna)->index > (*scnb)->index)
75*7304104dSAndroid Build Coastguard Worker     return 1;
76*7304104dSAndroid Build Coastguard Worker 
77*7304104dSAndroid Build Coastguard Worker   return 0;
78*7304104dSAndroid Build Coastguard Worker }
79*7304104dSAndroid Build Coastguard Worker 
80*7304104dSAndroid Build Coastguard Worker 
81*7304104dSAndroid Build Coastguard Worker /* Insert the sections in the list into the provided array and sort
82*7304104dSAndroid Build Coastguard Worker    them according to their start offsets.  For sections with equal
83*7304104dSAndroid Build Coastguard Worker    start offsets, the size is used; for sections with equal start
84*7304104dSAndroid Build Coastguard Worker    offsets and sizes, the section index is used.  Sorting by size
85*7304104dSAndroid Build Coastguard Worker    ensures that zero-length sections are processed first, which
86*7304104dSAndroid Build Coastguard Worker    is what we want since they do not advance our file writing position.  */
87*7304104dSAndroid Build Coastguard Worker static void
sort_sections(Elf_Scn ** scns,Elf_ScnList * list)88*7304104dSAndroid Build Coastguard Worker sort_sections (Elf_Scn **scns, Elf_ScnList *list)
89*7304104dSAndroid Build Coastguard Worker {
90*7304104dSAndroid Build Coastguard Worker   Elf_Scn **scnp = scns;
91*7304104dSAndroid Build Coastguard Worker   do
92*7304104dSAndroid Build Coastguard Worker     for (size_t cnt = 0; cnt < list->cnt; ++cnt)
93*7304104dSAndroid Build Coastguard Worker       *scnp++ = &list->data[cnt];
94*7304104dSAndroid Build Coastguard Worker   while ((list = list->next) != NULL);
95*7304104dSAndroid Build Coastguard Worker 
96*7304104dSAndroid Build Coastguard Worker   qsort (scns, scnp - scns, sizeof (*scns), compare_sections);
97*7304104dSAndroid Build Coastguard Worker }
98*7304104dSAndroid Build Coastguard Worker 
99*7304104dSAndroid Build Coastguard Worker 
100*7304104dSAndroid Build Coastguard Worker static inline void
fill_mmap(size_t offset,char * last_position,char * scn_start,char * const shdr_start,char * const shdr_end)101*7304104dSAndroid Build Coastguard Worker fill_mmap (size_t offset, char *last_position, char *scn_start,
102*7304104dSAndroid Build Coastguard Worker            char *const shdr_start, char *const shdr_end)
103*7304104dSAndroid Build Coastguard Worker {
104*7304104dSAndroid Build Coastguard Worker   size_t written = 0;
105*7304104dSAndroid Build Coastguard Worker 
106*7304104dSAndroid Build Coastguard Worker   if (last_position < shdr_start)
107*7304104dSAndroid Build Coastguard Worker     {
108*7304104dSAndroid Build Coastguard Worker       written = MIN (scn_start + offset - last_position,
109*7304104dSAndroid Build Coastguard Worker                      shdr_start - last_position);
110*7304104dSAndroid Build Coastguard Worker 
111*7304104dSAndroid Build Coastguard Worker       memset (last_position, __libelf_fill_byte, written);
112*7304104dSAndroid Build Coastguard Worker     }
113*7304104dSAndroid Build Coastguard Worker 
114*7304104dSAndroid Build Coastguard Worker   if (last_position + written != scn_start + offset
115*7304104dSAndroid Build Coastguard Worker       && shdr_end < scn_start + offset)
116*7304104dSAndroid Build Coastguard Worker     {
117*7304104dSAndroid Build Coastguard Worker       char *fill_start = MAX (shdr_end, scn_start);
118*7304104dSAndroid Build Coastguard Worker       memset (fill_start, __libelf_fill_byte,
119*7304104dSAndroid Build Coastguard Worker               scn_start + offset - fill_start);
120*7304104dSAndroid Build Coastguard Worker     }
121*7304104dSAndroid Build Coastguard Worker }
122*7304104dSAndroid Build Coastguard Worker 
123*7304104dSAndroid Build Coastguard Worker int
124*7304104dSAndroid Build Coastguard Worker internal_function
__elfw2(LIBELFBITS,updatemmap)125*7304104dSAndroid Build Coastguard Worker __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
126*7304104dSAndroid Build Coastguard Worker {
127*7304104dSAndroid Build Coastguard Worker   bool previous_scn_changed = false;
128*7304104dSAndroid Build Coastguard Worker 
129*7304104dSAndroid Build Coastguard Worker   /* We need the ELF header several times.  */
130*7304104dSAndroid Build Coastguard Worker   ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
131*7304104dSAndroid Build Coastguard Worker 
132*7304104dSAndroid Build Coastguard Worker   /* Write out the ELF header.  */
133*7304104dSAndroid Build Coastguard Worker   if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY)
134*7304104dSAndroid Build Coastguard Worker     {
135*7304104dSAndroid Build Coastguard Worker       /* If the type sizes should be different at some time we have to
136*7304104dSAndroid Build Coastguard Worker 	 rewrite this code.  */
137*7304104dSAndroid Build Coastguard Worker       assert (sizeof (ElfW2(LIBELFBITS,Ehdr))
138*7304104dSAndroid Build Coastguard Worker 	      == elf_typesize (LIBELFBITS, ELF_T_EHDR, 1));
139*7304104dSAndroid Build Coastguard Worker 
140*7304104dSAndroid Build Coastguard Worker       if (unlikely (change_bo))
141*7304104dSAndroid Build Coastguard Worker 	{
142*7304104dSAndroid Build Coastguard Worker 	  /* Today there is only one version of the ELF header.  */
143*7304104dSAndroid Build Coastguard Worker #undef fctp
144*7304104dSAndroid Build Coastguard Worker #define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
145*7304104dSAndroid Build Coastguard Worker 
146*7304104dSAndroid Build Coastguard Worker 	  /* Do the real work.  */
147*7304104dSAndroid Build Coastguard Worker 	  (*fctp) ((char *) elf->map_address + elf->start_offset, ehdr,
148*7304104dSAndroid Build Coastguard Worker 		   sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
149*7304104dSAndroid Build Coastguard Worker 	}
150*7304104dSAndroid Build Coastguard Worker       else if (elf->map_address + elf->start_offset != ehdr)
151*7304104dSAndroid Build Coastguard Worker 	memcpy (elf->map_address + elf->start_offset, ehdr,
152*7304104dSAndroid Build Coastguard Worker 		sizeof (ElfW2(LIBELFBITS,Ehdr)));
153*7304104dSAndroid Build Coastguard Worker 
154*7304104dSAndroid Build Coastguard Worker       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY;
155*7304104dSAndroid Build Coastguard Worker 
156*7304104dSAndroid Build Coastguard Worker       /* We start writing sections after the ELF header only if there is
157*7304104dSAndroid Build Coastguard Worker 	 no program header.  */
158*7304104dSAndroid Build Coastguard Worker       previous_scn_changed = elf->state.ELFW(elf,LIBELFBITS).phdr == NULL;
159*7304104dSAndroid Build Coastguard Worker     }
160*7304104dSAndroid Build Coastguard Worker 
161*7304104dSAndroid Build Coastguard Worker   size_t phnum;
162*7304104dSAndroid Build Coastguard Worker   if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
163*7304104dSAndroid Build Coastguard Worker     return -1;
164*7304104dSAndroid Build Coastguard Worker 
165*7304104dSAndroid Build Coastguard Worker   /* Write out the program header table.  */
166*7304104dSAndroid Build Coastguard Worker   if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL
167*7304104dSAndroid Build Coastguard Worker       && ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags)
168*7304104dSAndroid Build Coastguard Worker 	  & ELF_F_DIRTY))
169*7304104dSAndroid Build Coastguard Worker     {
170*7304104dSAndroid Build Coastguard Worker       /* If the type sizes should be different at some time we have to
171*7304104dSAndroid Build Coastguard Worker 	 rewrite this code.  */
172*7304104dSAndroid Build Coastguard Worker       assert (sizeof (ElfW2(LIBELFBITS,Phdr))
173*7304104dSAndroid Build Coastguard Worker 	      == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
174*7304104dSAndroid Build Coastguard Worker 
175*7304104dSAndroid Build Coastguard Worker       /* Maybe the user wants a gap between the ELF header and the program
176*7304104dSAndroid Build Coastguard Worker 	 header.  */
177*7304104dSAndroid Build Coastguard Worker       if (ehdr->e_phoff > ehdr->e_ehsize)
178*7304104dSAndroid Build Coastguard Worker 	memset (elf->map_address + elf->start_offset + ehdr->e_ehsize,
179*7304104dSAndroid Build Coastguard Worker 		__libelf_fill_byte, ehdr->e_phoff - ehdr->e_ehsize);
180*7304104dSAndroid Build Coastguard Worker 
181*7304104dSAndroid Build Coastguard Worker       if (unlikely (change_bo))
182*7304104dSAndroid Build Coastguard Worker 	{
183*7304104dSAndroid Build Coastguard Worker 	  /* Today there is only one version of the ELF header.  */
184*7304104dSAndroid Build Coastguard Worker #undef fctp
185*7304104dSAndroid Build Coastguard Worker #define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
186*7304104dSAndroid Build Coastguard Worker 
187*7304104dSAndroid Build Coastguard Worker 	  /* Do the real work.  */
188*7304104dSAndroid Build Coastguard Worker 	  (*fctp) (elf->map_address + elf->start_offset + ehdr->e_phoff,
189*7304104dSAndroid Build Coastguard Worker 		   elf->state.ELFW(elf,LIBELFBITS).phdr,
190*7304104dSAndroid Build Coastguard Worker 		   sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum, 1);
191*7304104dSAndroid Build Coastguard Worker 	}
192*7304104dSAndroid Build Coastguard Worker       else
193*7304104dSAndroid Build Coastguard Worker 	memmove (elf->map_address + elf->start_offset + ehdr->e_phoff,
194*7304104dSAndroid Build Coastguard Worker 		elf->state.ELFW(elf,LIBELFBITS).phdr,
195*7304104dSAndroid Build Coastguard Worker 		sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
196*7304104dSAndroid Build Coastguard Worker 
197*7304104dSAndroid Build Coastguard Worker       elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY;
198*7304104dSAndroid Build Coastguard Worker 
199*7304104dSAndroid Build Coastguard Worker       /* We modified the program header.  Maybe this created a gap so
200*7304104dSAndroid Build Coastguard Worker 	 we have to write fill bytes, if necessary.  */
201*7304104dSAndroid Build Coastguard Worker       previous_scn_changed = true;
202*7304104dSAndroid Build Coastguard Worker     }
203*7304104dSAndroid Build Coastguard Worker 
204*7304104dSAndroid Build Coastguard Worker   /* From now on we have to keep track of the last position to eventually
205*7304104dSAndroid Build Coastguard Worker      fill the gaps with the prescribed fill byte.  */
206*7304104dSAndroid Build Coastguard Worker   char *last_position = ((char *) elf->map_address + elf->start_offset
207*7304104dSAndroid Build Coastguard Worker 			 + MAX (elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
208*7304104dSAndroid Build Coastguard Worker 				ehdr->e_phoff)
209*7304104dSAndroid Build Coastguard Worker 			 + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
210*7304104dSAndroid Build Coastguard Worker 
211*7304104dSAndroid Build Coastguard Worker   /* Write all the sections.  Well, only those which are modified.  */
212*7304104dSAndroid Build Coastguard Worker   if (shnum > 0)
213*7304104dSAndroid Build Coastguard Worker     {
214*7304104dSAndroid Build Coastguard Worker       if (unlikely (shnum > SIZE_MAX / sizeof (Elf_Scn *)))
215*7304104dSAndroid Build Coastguard Worker 	return 1;
216*7304104dSAndroid Build Coastguard Worker 
217*7304104dSAndroid Build Coastguard Worker       Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
218*7304104dSAndroid Build Coastguard Worker       Elf_Scn **scns = malloc (shnum * sizeof (Elf_Scn *));
219*7304104dSAndroid Build Coastguard Worker       if (unlikely (scns == NULL))
220*7304104dSAndroid Build Coastguard Worker 	{
221*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_NOMEM);
222*7304104dSAndroid Build Coastguard Worker 	  return -1;
223*7304104dSAndroid Build Coastguard Worker 	}
224*7304104dSAndroid Build Coastguard Worker       char *const shdr_start = ((char *) elf->map_address + elf->start_offset
225*7304104dSAndroid Build Coastguard Worker 				+ ehdr->e_shoff);
226*7304104dSAndroid Build Coastguard Worker       char *const shdr_end = shdr_start + shnum * ehdr->e_shentsize;
227*7304104dSAndroid Build Coastguard Worker 
228*7304104dSAndroid Build Coastguard Worker #undef shdr_fctp
229*7304104dSAndroid Build Coastguard Worker #define shdr_fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
230*7304104dSAndroid Build Coastguard Worker #define shdr_dest ((ElfW2(LIBELFBITS,Shdr) *) shdr_start)
231*7304104dSAndroid Build Coastguard Worker 
232*7304104dSAndroid Build Coastguard Worker       /* Get all sections into the array and sort them.  */
233*7304104dSAndroid Build Coastguard Worker       sort_sections (scns, list);
234*7304104dSAndroid Build Coastguard Worker 
235*7304104dSAndroid Build Coastguard Worker       /* We possibly have to copy the section header data because moving
236*7304104dSAndroid Build Coastguard Worker 	 the sections might overwrite the data.  */
237*7304104dSAndroid Build Coastguard Worker       for (size_t cnt = 0; cnt < shnum; ++cnt)
238*7304104dSAndroid Build Coastguard Worker 	{
239*7304104dSAndroid Build Coastguard Worker 	  Elf_Scn *scn = scns[cnt];
240*7304104dSAndroid Build Coastguard Worker 
241*7304104dSAndroid Build Coastguard Worker 	  if (!elf->state.ELFW(elf,LIBELFBITS).shdr_malloced
242*7304104dSAndroid Build Coastguard Worker 	      && (scn->shdr_flags & ELF_F_MALLOCED) == 0
243*7304104dSAndroid Build Coastguard Worker 	      && scn->shdr.ELFW(e,LIBELFBITS) != &shdr_dest[scn->index])
244*7304104dSAndroid Build Coastguard Worker 	    {
245*7304104dSAndroid Build Coastguard Worker 	      assert ((char *) elf->map_address + elf->start_offset
246*7304104dSAndroid Build Coastguard Worker 		      < (char *) scn->shdr.ELFW(e,LIBELFBITS));
247*7304104dSAndroid Build Coastguard Worker 	      assert ((char *) scn->shdr.ELFW(e,LIBELFBITS)
248*7304104dSAndroid Build Coastguard Worker 		      < ((char *) elf->map_address + elf->start_offset
249*7304104dSAndroid Build Coastguard Worker 			 + elf->maximum_size));
250*7304104dSAndroid Build Coastguard Worker 
251*7304104dSAndroid Build Coastguard Worker 	      void *p = malloc (sizeof (ElfW2(LIBELFBITS,Shdr)));
252*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (p == NULL))
253*7304104dSAndroid Build Coastguard Worker 		{
254*7304104dSAndroid Build Coastguard Worker 		  free (scns);
255*7304104dSAndroid Build Coastguard Worker 		  __libelf_seterrno (ELF_E_NOMEM);
256*7304104dSAndroid Build Coastguard Worker 		  return -1;
257*7304104dSAndroid Build Coastguard Worker 		}
258*7304104dSAndroid Build Coastguard Worker 	      scn->shdr.ELFW(e,LIBELFBITS)
259*7304104dSAndroid Build Coastguard Worker 		= memcpy (p, scn->shdr.ELFW(e,LIBELFBITS),
260*7304104dSAndroid Build Coastguard Worker 			  sizeof (ElfW2(LIBELFBITS,Shdr)));
261*7304104dSAndroid Build Coastguard Worker 	    }
262*7304104dSAndroid Build Coastguard Worker 
263*7304104dSAndroid Build Coastguard Worker 	  /* If the file is mmaped and the original position of the
264*7304104dSAndroid Build Coastguard Worker 	     section in the file is lower than the new position we
265*7304104dSAndroid Build Coastguard Worker 	     need to save the section content since otherwise it is
266*7304104dSAndroid Build Coastguard Worker 	     overwritten before it can be copied.  If there are
267*7304104dSAndroid Build Coastguard Worker 	     multiple data segments in the list only the first can be
268*7304104dSAndroid Build Coastguard Worker 	     from the file.  */
269*7304104dSAndroid Build Coastguard Worker 	  if (((char *) elf->map_address + elf->start_offset
270*7304104dSAndroid Build Coastguard Worker 	       <= (char  *) scn->data_list.data.d.d_buf)
271*7304104dSAndroid Build Coastguard Worker 	      && ((char *) scn->data_list.data.d.d_buf
272*7304104dSAndroid Build Coastguard Worker 		  < ((char *) elf->map_address + elf->start_offset
273*7304104dSAndroid Build Coastguard Worker 		     + elf->maximum_size))
274*7304104dSAndroid Build Coastguard Worker 	      && (((char *) elf->map_address + elf->start_offset
275*7304104dSAndroid Build Coastguard Worker 		   + scn->shdr.ELFW(e,LIBELFBITS)->sh_offset)
276*7304104dSAndroid Build Coastguard Worker 		  > (char *) scn->data_list.data.d.d_buf))
277*7304104dSAndroid Build Coastguard Worker 	    {
278*7304104dSAndroid Build Coastguard Worker 	      void *p = malloc (scn->data_list.data.d.d_size);
279*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (p == NULL))
280*7304104dSAndroid Build Coastguard Worker 		{
281*7304104dSAndroid Build Coastguard Worker 		  free (scns);
282*7304104dSAndroid Build Coastguard Worker 		  __libelf_seterrno (ELF_E_NOMEM);
283*7304104dSAndroid Build Coastguard Worker 		  return -1;
284*7304104dSAndroid Build Coastguard Worker 		}
285*7304104dSAndroid Build Coastguard Worker 	      scn->data_list.data.d.d_buf = scn->data_base
286*7304104dSAndroid Build Coastguard Worker 		= memcpy (p, scn->data_list.data.d.d_buf,
287*7304104dSAndroid Build Coastguard Worker 			  scn->data_list.data.d.d_size);
288*7304104dSAndroid Build Coastguard Worker 	    }
289*7304104dSAndroid Build Coastguard Worker 	}
290*7304104dSAndroid Build Coastguard Worker 
291*7304104dSAndroid Build Coastguard Worker       /* Iterate over all the section in the order in which they
292*7304104dSAndroid Build Coastguard Worker 	 appear in the output file.  */
293*7304104dSAndroid Build Coastguard Worker       for (size_t cnt = 0; cnt < shnum; ++cnt)
294*7304104dSAndroid Build Coastguard Worker 	{
295*7304104dSAndroid Build Coastguard Worker 	  Elf_Scn *scn = scns[cnt];
296*7304104dSAndroid Build Coastguard Worker 	  if (scn->index == 0)
297*7304104dSAndroid Build Coastguard Worker 	    {
298*7304104dSAndroid Build Coastguard Worker 	      /* The dummy section header entry.  It should not be
299*7304104dSAndroid Build Coastguard Worker 		 possible to mark this "section" as dirty.  */
300*7304104dSAndroid Build Coastguard Worker 	      assert ((scn->flags & ELF_F_DIRTY) == 0);
301*7304104dSAndroid Build Coastguard Worker 	      continue;
302*7304104dSAndroid Build Coastguard Worker 	    }
303*7304104dSAndroid Build Coastguard Worker 
304*7304104dSAndroid Build Coastguard Worker 	  ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
305*7304104dSAndroid Build Coastguard Worker 	  if (shdr->sh_type == SHT_NOBITS)
306*7304104dSAndroid Build Coastguard Worker 	    goto next;
307*7304104dSAndroid Build Coastguard Worker 
308*7304104dSAndroid Build Coastguard Worker 	  char *scn_start = ((char *) elf->map_address
309*7304104dSAndroid Build Coastguard Worker 			     + elf->start_offset + shdr->sh_offset);
310*7304104dSAndroid Build Coastguard Worker 	  Elf_Data_List *dl = &scn->data_list;
311*7304104dSAndroid Build Coastguard Worker 	  bool scn_changed = false;
312*7304104dSAndroid Build Coastguard Worker 
313*7304104dSAndroid Build Coastguard Worker 	  if (scn->data_list_rear != NULL)
314*7304104dSAndroid Build Coastguard Worker 	    do
315*7304104dSAndroid Build Coastguard Worker 	      {
316*7304104dSAndroid Build Coastguard Worker 		assert (dl->data.d.d_off >= 0);
317*7304104dSAndroid Build Coastguard Worker 		assert ((GElf_Off) dl->data.d.d_off <= shdr->sh_size);
318*7304104dSAndroid Build Coastguard Worker 		assert (dl->data.d.d_size <= (shdr->sh_size
319*7304104dSAndroid Build Coastguard Worker 					      - (GElf_Off) dl->data.d.d_off));
320*7304104dSAndroid Build Coastguard Worker 
321*7304104dSAndroid Build Coastguard Worker 		/* If there is a gap, fill it.  */
322*7304104dSAndroid Build Coastguard Worker 		if (scn_start + dl->data.d.d_off > last_position
323*7304104dSAndroid Build Coastguard Worker 		    && (dl->data.d.d_off == 0
324*7304104dSAndroid Build Coastguard Worker 			|| ((scn->flags | dl->flags | elf->flags)
325*7304104dSAndroid Build Coastguard Worker 			    & ELF_F_DIRTY) != 0))
326*7304104dSAndroid Build Coastguard Worker 		  {
327*7304104dSAndroid Build Coastguard Worker 		    fill_mmap (dl->data.d.d_off, last_position, scn_start,
328*7304104dSAndroid Build Coastguard Worker 		               shdr_start, shdr_end);
329*7304104dSAndroid Build Coastguard Worker 		  }
330*7304104dSAndroid Build Coastguard Worker 
331*7304104dSAndroid Build Coastguard Worker 		last_position = scn_start + dl->data.d.d_off;
332*7304104dSAndroid Build Coastguard Worker 
333*7304104dSAndroid Build Coastguard Worker 		if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
334*7304104dSAndroid Build Coastguard Worker 		  {
335*7304104dSAndroid Build Coastguard Worker 		    /* Let it go backward if the sections use a bogus
336*7304104dSAndroid Build Coastguard Worker 		       layout with overlaps.  We'll overwrite the stupid
337*7304104dSAndroid Build Coastguard Worker 		       user's section data with the latest one, rather than
338*7304104dSAndroid Build Coastguard Worker 		       crashing.  */
339*7304104dSAndroid Build Coastguard Worker 
340*7304104dSAndroid Build Coastguard Worker 		    if (unlikely (change_bo
341*7304104dSAndroid Build Coastguard Worker 				  && dl->data.d.d_size != 0
342*7304104dSAndroid Build Coastguard Worker 				  && dl->data.d.d_type != ELF_T_BYTE))
343*7304104dSAndroid Build Coastguard Worker 		      {
344*7304104dSAndroid Build Coastguard Worker #undef fctp
345*7304104dSAndroid Build Coastguard Worker #define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
346*7304104dSAndroid Build Coastguard Worker 
347*7304104dSAndroid Build Coastguard Worker 			size_t align;
348*7304104dSAndroid Build Coastguard Worker 			align = __libelf_type_align (ELFW(ELFCLASS,LIBELFBITS),
349*7304104dSAndroid Build Coastguard Worker 						     dl->data.d.d_type);
350*7304104dSAndroid Build Coastguard Worker 			if ((((uintptr_t) last_position)
351*7304104dSAndroid Build Coastguard Worker 			     & (uintptr_t) (align - 1)) == 0)
352*7304104dSAndroid Build Coastguard Worker 			  {
353*7304104dSAndroid Build Coastguard Worker 			    /* No need to copy, we can convert directly.  */
354*7304104dSAndroid Build Coastguard Worker 			    (*fctp) (last_position, dl->data.d.d_buf,
355*7304104dSAndroid Build Coastguard Worker 				     dl->data.d.d_size, 1);
356*7304104dSAndroid Build Coastguard Worker 			  }
357*7304104dSAndroid Build Coastguard Worker 			else
358*7304104dSAndroid Build Coastguard Worker 			  {
359*7304104dSAndroid Build Coastguard Worker 			    /* We have to do the conversion on properly
360*7304104dSAndroid Build Coastguard Worker 			       aligned memory first.  align is a power of 2,
361*7304104dSAndroid Build Coastguard Worker 			       but posix_memalign only works for alignments
362*7304104dSAndroid Build Coastguard Worker 			       which are a multiple of sizeof (void *).
363*7304104dSAndroid Build Coastguard Worker 			       So use normal malloc for smaller alignments.  */
364*7304104dSAndroid Build Coastguard Worker 			    size_t size = dl->data.d.d_size;
365*7304104dSAndroid Build Coastguard Worker 			    void *converted;
366*7304104dSAndroid Build Coastguard Worker 			    if (align < sizeof (void *))
367*7304104dSAndroid Build Coastguard Worker 			      converted = malloc (size);
368*7304104dSAndroid Build Coastguard Worker 			    else
369*7304104dSAndroid Build Coastguard Worker 			      {
370*7304104dSAndroid Build Coastguard Worker 				int res;
371*7304104dSAndroid Build Coastguard Worker 				res = posix_memalign (&converted, align, size);
372*7304104dSAndroid Build Coastguard Worker 				if (res != 0)
373*7304104dSAndroid Build Coastguard Worker 				  converted = NULL;
374*7304104dSAndroid Build Coastguard Worker 			      }
375*7304104dSAndroid Build Coastguard Worker 
376*7304104dSAndroid Build Coastguard Worker 			    if (converted == NULL)
377*7304104dSAndroid Build Coastguard Worker 			      {
378*7304104dSAndroid Build Coastguard Worker 				free (scns);
379*7304104dSAndroid Build Coastguard Worker 				__libelf_seterrno (ELF_E_NOMEM);
380*7304104dSAndroid Build Coastguard Worker 				return 1;
381*7304104dSAndroid Build Coastguard Worker 			      }
382*7304104dSAndroid Build Coastguard Worker 
383*7304104dSAndroid Build Coastguard Worker 			    (*fctp) (converted, dl->data.d.d_buf, size, 1);
384*7304104dSAndroid Build Coastguard Worker 
385*7304104dSAndroid Build Coastguard Worker 			    /* And then write it to the mmapped file.  */
386*7304104dSAndroid Build Coastguard Worker 			    memcpy (last_position, converted, size);
387*7304104dSAndroid Build Coastguard Worker 			    free (converted);
388*7304104dSAndroid Build Coastguard Worker 			  }
389*7304104dSAndroid Build Coastguard Worker 
390*7304104dSAndroid Build Coastguard Worker 			last_position += dl->data.d.d_size;
391*7304104dSAndroid Build Coastguard Worker 		      }
392*7304104dSAndroid Build Coastguard Worker 		    else if (dl->data.d.d_size != 0)
393*7304104dSAndroid Build Coastguard Worker 		      {
394*7304104dSAndroid Build Coastguard Worker 			memmove (last_position, dl->data.d.d_buf,
395*7304104dSAndroid Build Coastguard Worker 				 dl->data.d.d_size);
396*7304104dSAndroid Build Coastguard Worker 			last_position += dl->data.d.d_size;
397*7304104dSAndroid Build Coastguard Worker 		      }
398*7304104dSAndroid Build Coastguard Worker 
399*7304104dSAndroid Build Coastguard Worker 		    scn_changed = true;
400*7304104dSAndroid Build Coastguard Worker 		  }
401*7304104dSAndroid Build Coastguard Worker 		else
402*7304104dSAndroid Build Coastguard Worker 		  last_position += dl->data.d.d_size;
403*7304104dSAndroid Build Coastguard Worker 
404*7304104dSAndroid Build Coastguard Worker 		assert (scn_start + dl->data.d.d_off + dl->data.d.d_size
405*7304104dSAndroid Build Coastguard Worker 			== last_position);
406*7304104dSAndroid Build Coastguard Worker 
407*7304104dSAndroid Build Coastguard Worker 		dl->flags &= ~ELF_F_DIRTY;
408*7304104dSAndroid Build Coastguard Worker 
409*7304104dSAndroid Build Coastguard Worker 		dl = dl->next;
410*7304104dSAndroid Build Coastguard Worker 	      }
411*7304104dSAndroid Build Coastguard Worker 	    while (dl != NULL);
412*7304104dSAndroid Build Coastguard Worker 	  else
413*7304104dSAndroid Build Coastguard Worker 	    {
414*7304104dSAndroid Build Coastguard Worker 	      /* If the previous section (or the ELF/program
415*7304104dSAndroid Build Coastguard Worker 		 header) changed we might have to fill the gap.  */
416*7304104dSAndroid Build Coastguard Worker 	      if (scn_start > last_position && previous_scn_changed)
417*7304104dSAndroid Build Coastguard Worker 		fill_mmap (0, last_position, scn_start,
418*7304104dSAndroid Build Coastguard Worker 		           shdr_start, shdr_end);
419*7304104dSAndroid Build Coastguard Worker 
420*7304104dSAndroid Build Coastguard Worker 	      /* We have to trust the existing section header information.  */
421*7304104dSAndroid Build Coastguard Worker 	      last_position = scn_start + shdr->sh_size;
422*7304104dSAndroid Build Coastguard Worker 	    }
423*7304104dSAndroid Build Coastguard Worker 
424*7304104dSAndroid Build Coastguard Worker 
425*7304104dSAndroid Build Coastguard Worker 	  previous_scn_changed = scn_changed;
426*7304104dSAndroid Build Coastguard Worker 	next:
427*7304104dSAndroid Build Coastguard Worker 	  scn->flags &= ~ELF_F_DIRTY;
428*7304104dSAndroid Build Coastguard Worker 	}
429*7304104dSAndroid Build Coastguard Worker 
430*7304104dSAndroid Build Coastguard Worker       /* Fill the gap between last section and section header table if
431*7304104dSAndroid Build Coastguard Worker 	 necessary.  */
432*7304104dSAndroid Build Coastguard Worker       if ((elf->flags & ELF_F_DIRTY)
433*7304104dSAndroid Build Coastguard Worker 	  && last_position < ((char *) elf->map_address + elf->start_offset
434*7304104dSAndroid Build Coastguard Worker 			      + ehdr->e_shoff))
435*7304104dSAndroid Build Coastguard Worker 	memset (last_position, __libelf_fill_byte,
436*7304104dSAndroid Build Coastguard Worker 		(char *) elf->map_address + elf->start_offset + ehdr->e_shoff
437*7304104dSAndroid Build Coastguard Worker 		- last_position);
438*7304104dSAndroid Build Coastguard Worker 
439*7304104dSAndroid Build Coastguard Worker       /* Write the section header table entry if necessary.  */
440*7304104dSAndroid Build Coastguard Worker       for (size_t cnt = 0; cnt < shnum; ++cnt)
441*7304104dSAndroid Build Coastguard Worker 	{
442*7304104dSAndroid Build Coastguard Worker 	  Elf_Scn *scn = scns[cnt];
443*7304104dSAndroid Build Coastguard Worker 
444*7304104dSAndroid Build Coastguard Worker 	  if ((scn->shdr_flags | elf->flags) & ELF_F_DIRTY)
445*7304104dSAndroid Build Coastguard Worker 	    {
446*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (change_bo))
447*7304104dSAndroid Build Coastguard Worker 		(*shdr_fctp) (&shdr_dest[scn->index],
448*7304104dSAndroid Build Coastguard Worker 			      scn->shdr.ELFW(e,LIBELFBITS),
449*7304104dSAndroid Build Coastguard Worker 			      sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
450*7304104dSAndroid Build Coastguard Worker 	      else
451*7304104dSAndroid Build Coastguard Worker 		memcpy (&shdr_dest[scn->index],
452*7304104dSAndroid Build Coastguard Worker 			scn->shdr.ELFW(e,LIBELFBITS),
453*7304104dSAndroid Build Coastguard Worker 			sizeof (ElfW2(LIBELFBITS,Shdr)));
454*7304104dSAndroid Build Coastguard Worker 
455*7304104dSAndroid Build Coastguard Worker 	      /* If we previously made a copy of the section header
456*7304104dSAndroid Build Coastguard Worker 		 entry we now have to adjust the pointer again so
457*7304104dSAndroid Build Coastguard Worker 		 point to new place in the mapping.  */
458*7304104dSAndroid Build Coastguard Worker 	      if (!elf->state.ELFW(elf,LIBELFBITS).shdr_malloced
459*7304104dSAndroid Build Coastguard Worker 		  && (scn->shdr_flags & ELF_F_MALLOCED) == 0
460*7304104dSAndroid Build Coastguard Worker 		  && scn->shdr.ELFW(e,LIBELFBITS) != &shdr_dest[scn->index])
461*7304104dSAndroid Build Coastguard Worker 		{
462*7304104dSAndroid Build Coastguard Worker 		  free (scn->shdr.ELFW(e,LIBELFBITS));
463*7304104dSAndroid Build Coastguard Worker 		  scn->shdr.ELFW(e,LIBELFBITS) = &shdr_dest[scn->index];
464*7304104dSAndroid Build Coastguard Worker 		}
465*7304104dSAndroid Build Coastguard Worker 
466*7304104dSAndroid Build Coastguard Worker 	      scn->shdr_flags &= ~ELF_F_DIRTY;
467*7304104dSAndroid Build Coastguard Worker 	    }
468*7304104dSAndroid Build Coastguard Worker 	}
469*7304104dSAndroid Build Coastguard Worker       free (scns);
470*7304104dSAndroid Build Coastguard Worker     }
471*7304104dSAndroid Build Coastguard Worker 
472*7304104dSAndroid Build Coastguard Worker   /* That was the last part.  Clear the overall flag.  */
473*7304104dSAndroid Build Coastguard Worker   elf->flags &= ~ELF_F_DIRTY;
474*7304104dSAndroid Build Coastguard Worker 
475*7304104dSAndroid Build Coastguard Worker   /* Make sure the content hits the disk.  */
476*7304104dSAndroid Build Coastguard Worker   char *msync_start = ((char *) elf->map_address
477*7304104dSAndroid Build Coastguard Worker 		       + (elf->start_offset & ~(sysconf (_SC_PAGESIZE) - 1)));
478*7304104dSAndroid Build Coastguard Worker   char *msync_end = ((char *) elf->map_address
479*7304104dSAndroid Build Coastguard Worker 		     + elf->start_offset + ehdr->e_shoff
480*7304104dSAndroid Build Coastguard Worker 		     + ehdr->e_shentsize * shnum);
481*7304104dSAndroid Build Coastguard Worker   (void) msync (msync_start, msync_end - msync_start, MS_SYNC);
482*7304104dSAndroid Build Coastguard Worker 
483*7304104dSAndroid Build Coastguard Worker   return 0;
484*7304104dSAndroid Build Coastguard Worker }
485*7304104dSAndroid Build Coastguard Worker 
486*7304104dSAndroid Build Coastguard Worker 
487*7304104dSAndroid Build Coastguard Worker /* Size of the buffer we use to generate the blocks of fill bytes.  */
488*7304104dSAndroid Build Coastguard Worker #define FILLBUFSIZE	4096
489*7304104dSAndroid Build Coastguard Worker 
490*7304104dSAndroid Build Coastguard Worker /* If we have to convert the section buffer contents we have to use
491*7304104dSAndroid Build Coastguard Worker    temporary buffer.  Only buffers up to MAX_TMPBUF bytes are allocated
492*7304104dSAndroid Build Coastguard Worker    on the stack.  */
493*7304104dSAndroid Build Coastguard Worker #define MAX_TMPBUF	32768
494*7304104dSAndroid Build Coastguard Worker 
495*7304104dSAndroid Build Coastguard Worker 
496*7304104dSAndroid Build Coastguard Worker /* Helper function to write out fill bytes.  */
497*7304104dSAndroid Build Coastguard Worker static int
fill(int fd,int64_t pos,size_t len,char * fillbuf,size_t * filledp)498*7304104dSAndroid Build Coastguard Worker fill (int fd, int64_t pos, size_t len, char *fillbuf, size_t *filledp)
499*7304104dSAndroid Build Coastguard Worker {
500*7304104dSAndroid Build Coastguard Worker   size_t filled = *filledp;
501*7304104dSAndroid Build Coastguard Worker   size_t fill_len = MIN (len, FILLBUFSIZE);
502*7304104dSAndroid Build Coastguard Worker 
503*7304104dSAndroid Build Coastguard Worker   if (unlikely (fill_len > filled) && filled < FILLBUFSIZE)
504*7304104dSAndroid Build Coastguard Worker     {
505*7304104dSAndroid Build Coastguard Worker       /* Initialize a few more bytes.  */
506*7304104dSAndroid Build Coastguard Worker       memset (fillbuf + filled, __libelf_fill_byte, fill_len - filled);
507*7304104dSAndroid Build Coastguard Worker       *filledp = filled = fill_len;
508*7304104dSAndroid Build Coastguard Worker     }
509*7304104dSAndroid Build Coastguard Worker 
510*7304104dSAndroid Build Coastguard Worker   do
511*7304104dSAndroid Build Coastguard Worker     {
512*7304104dSAndroid Build Coastguard Worker       /* This many bytes we want to write in this round.  */
513*7304104dSAndroid Build Coastguard Worker       size_t n = MIN (filled, len);
514*7304104dSAndroid Build Coastguard Worker 
515*7304104dSAndroid Build Coastguard Worker       if (unlikely ((size_t) pwrite_retry (fd, fillbuf, n, pos) != n))
516*7304104dSAndroid Build Coastguard Worker 	{
517*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_WRITE_ERROR);
518*7304104dSAndroid Build Coastguard Worker 	  return 1;
519*7304104dSAndroid Build Coastguard Worker 	}
520*7304104dSAndroid Build Coastguard Worker 
521*7304104dSAndroid Build Coastguard Worker       pos += n;
522*7304104dSAndroid Build Coastguard Worker       len -= n;
523*7304104dSAndroid Build Coastguard Worker     }
524*7304104dSAndroid Build Coastguard Worker   while (len > 0);
525*7304104dSAndroid Build Coastguard Worker 
526*7304104dSAndroid Build Coastguard Worker   return 0;
527*7304104dSAndroid Build Coastguard Worker }
528*7304104dSAndroid Build Coastguard Worker 
529*7304104dSAndroid Build Coastguard Worker 
530*7304104dSAndroid Build Coastguard Worker int
531*7304104dSAndroid Build Coastguard Worker internal_function
__elfw2(LIBELFBITS,updatefile)532*7304104dSAndroid Build Coastguard Worker __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
533*7304104dSAndroid Build Coastguard Worker {
534*7304104dSAndroid Build Coastguard Worker   char fillbuf[FILLBUFSIZE];
535*7304104dSAndroid Build Coastguard Worker   size_t filled = 0;
536*7304104dSAndroid Build Coastguard Worker   bool previous_scn_changed = false;
537*7304104dSAndroid Build Coastguard Worker 
538*7304104dSAndroid Build Coastguard Worker   /* We need the ELF header several times.  */
539*7304104dSAndroid Build Coastguard Worker   ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
540*7304104dSAndroid Build Coastguard Worker 
541*7304104dSAndroid Build Coastguard Worker   /* Write out the ELF header.  */
542*7304104dSAndroid Build Coastguard Worker   if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY)
543*7304104dSAndroid Build Coastguard Worker     {
544*7304104dSAndroid Build Coastguard Worker       ElfW2(LIBELFBITS,Ehdr) tmp_ehdr;
545*7304104dSAndroid Build Coastguard Worker       ElfW2(LIBELFBITS,Ehdr) *out_ehdr = ehdr;
546*7304104dSAndroid Build Coastguard Worker 
547*7304104dSAndroid Build Coastguard Worker       /* If the type sizes should be different at some time we have to
548*7304104dSAndroid Build Coastguard Worker 	 rewrite this code.  */
549*7304104dSAndroid Build Coastguard Worker       assert (sizeof (ElfW2(LIBELFBITS,Ehdr))
550*7304104dSAndroid Build Coastguard Worker 	      == elf_typesize (LIBELFBITS, ELF_T_EHDR, 1));
551*7304104dSAndroid Build Coastguard Worker 
552*7304104dSAndroid Build Coastguard Worker       if (unlikely (change_bo))
553*7304104dSAndroid Build Coastguard Worker 	{
554*7304104dSAndroid Build Coastguard Worker 	  /* Today there is only one version of the ELF header.  */
555*7304104dSAndroid Build Coastguard Worker #undef fctp
556*7304104dSAndroid Build Coastguard Worker #define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
557*7304104dSAndroid Build Coastguard Worker 
558*7304104dSAndroid Build Coastguard Worker 	  /* Write the converted ELF header in a temporary buffer.  */
559*7304104dSAndroid Build Coastguard Worker 	  (*fctp) (&tmp_ehdr, ehdr, sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
560*7304104dSAndroid Build Coastguard Worker 
561*7304104dSAndroid Build Coastguard Worker 	  /* This is the buffer we want to write.  */
562*7304104dSAndroid Build Coastguard Worker 	  out_ehdr = &tmp_ehdr;
563*7304104dSAndroid Build Coastguard Worker 	}
564*7304104dSAndroid Build Coastguard Worker 
565*7304104dSAndroid Build Coastguard Worker       /* Write out the ELF header.  */
566*7304104dSAndroid Build Coastguard Worker       if (unlikely (pwrite_retry (elf->fildes, out_ehdr,
567*7304104dSAndroid Build Coastguard Worker 				  sizeof (ElfW2(LIBELFBITS,Ehdr)), 0)
568*7304104dSAndroid Build Coastguard Worker 		    != sizeof (ElfW2(LIBELFBITS,Ehdr))))
569*7304104dSAndroid Build Coastguard Worker 	{
570*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_WRITE_ERROR);
571*7304104dSAndroid Build Coastguard Worker 	  return 1;
572*7304104dSAndroid Build Coastguard Worker 	}
573*7304104dSAndroid Build Coastguard Worker 
574*7304104dSAndroid Build Coastguard Worker       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY;
575*7304104dSAndroid Build Coastguard Worker 
576*7304104dSAndroid Build Coastguard Worker       /* We start writing sections after the ELF header only if there is
577*7304104dSAndroid Build Coastguard Worker 	 no program header.  */
578*7304104dSAndroid Build Coastguard Worker       previous_scn_changed = elf->state.ELFW(elf,LIBELFBITS).phdr == NULL;
579*7304104dSAndroid Build Coastguard Worker     }
580*7304104dSAndroid Build Coastguard Worker 
581*7304104dSAndroid Build Coastguard Worker   /* If the type sizes should be different at some time we have to
582*7304104dSAndroid Build Coastguard Worker      rewrite this code.  */
583*7304104dSAndroid Build Coastguard Worker   assert (sizeof (ElfW2(LIBELFBITS,Phdr))
584*7304104dSAndroid Build Coastguard Worker 	  == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
585*7304104dSAndroid Build Coastguard Worker 
586*7304104dSAndroid Build Coastguard Worker   size_t phnum;
587*7304104dSAndroid Build Coastguard Worker   if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
588*7304104dSAndroid Build Coastguard Worker     return -1;
589*7304104dSAndroid Build Coastguard Worker 
590*7304104dSAndroid Build Coastguard Worker   /* Write out the program header table.  */
591*7304104dSAndroid Build Coastguard Worker   if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL
592*7304104dSAndroid Build Coastguard Worker       && ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags)
593*7304104dSAndroid Build Coastguard Worker 	  & ELF_F_DIRTY))
594*7304104dSAndroid Build Coastguard Worker     {
595*7304104dSAndroid Build Coastguard Worker       ElfW2(LIBELFBITS,Phdr) *tmp_phdr = NULL;
596*7304104dSAndroid Build Coastguard Worker       ElfW2(LIBELFBITS,Phdr) *out_phdr = elf->state.ELFW(elf,LIBELFBITS).phdr;
597*7304104dSAndroid Build Coastguard Worker 
598*7304104dSAndroid Build Coastguard Worker       /* Maybe the user wants a gap between the ELF header and the program
599*7304104dSAndroid Build Coastguard Worker 	 header.  */
600*7304104dSAndroid Build Coastguard Worker       if (ehdr->e_phoff > ehdr->e_ehsize
601*7304104dSAndroid Build Coastguard Worker 	  && unlikely (fill (elf->fildes, ehdr->e_ehsize,
602*7304104dSAndroid Build Coastguard Worker 			     ehdr->e_phoff - ehdr->e_ehsize, fillbuf, &filled)
603*7304104dSAndroid Build Coastguard Worker 		       != 0))
604*7304104dSAndroid Build Coastguard Worker 	return 1;
605*7304104dSAndroid Build Coastguard Worker 
606*7304104dSAndroid Build Coastguard Worker       if (unlikely (change_bo))
607*7304104dSAndroid Build Coastguard Worker 	{
608*7304104dSAndroid Build Coastguard Worker 	  /* Today there is only one version of the ELF header.  */
609*7304104dSAndroid Build Coastguard Worker #undef fctp
610*7304104dSAndroid Build Coastguard Worker #define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
611*7304104dSAndroid Build Coastguard Worker 
612*7304104dSAndroid Build Coastguard Worker 	  /* Allocate sufficient memory.  */
613*7304104dSAndroid Build Coastguard Worker 	  tmp_phdr = (ElfW2(LIBELFBITS,Phdr) *)
614*7304104dSAndroid Build Coastguard Worker 	    malloc (sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
615*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (tmp_phdr == NULL))
616*7304104dSAndroid Build Coastguard Worker 	    {
617*7304104dSAndroid Build Coastguard Worker 	      __libelf_seterrno (ELF_E_NOMEM);
618*7304104dSAndroid Build Coastguard Worker 	      return 1;
619*7304104dSAndroid Build Coastguard Worker 	    }
620*7304104dSAndroid Build Coastguard Worker 
621*7304104dSAndroid Build Coastguard Worker 	  /* Write the converted ELF header in a temporary buffer.  */
622*7304104dSAndroid Build Coastguard Worker 	  (*fctp) (tmp_phdr, elf->state.ELFW(elf,LIBELFBITS).phdr,
623*7304104dSAndroid Build Coastguard Worker 		   sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum, 1);
624*7304104dSAndroid Build Coastguard Worker 
625*7304104dSAndroid Build Coastguard Worker 	  /* This is the buffer we want to write.  */
626*7304104dSAndroid Build Coastguard Worker 	  out_phdr = tmp_phdr;
627*7304104dSAndroid Build Coastguard Worker 	}
628*7304104dSAndroid Build Coastguard Worker 
629*7304104dSAndroid Build Coastguard Worker       /* Write out the ELF header.  */
630*7304104dSAndroid Build Coastguard Worker       size_t phdr_size = sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum;
631*7304104dSAndroid Build Coastguard Worker       if (unlikely ((size_t) pwrite_retry (elf->fildes, out_phdr,
632*7304104dSAndroid Build Coastguard Worker 					   phdr_size, ehdr->e_phoff)
633*7304104dSAndroid Build Coastguard Worker 		    != phdr_size))
634*7304104dSAndroid Build Coastguard Worker 	{
635*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_WRITE_ERROR);
636*7304104dSAndroid Build Coastguard Worker 	  return 1;
637*7304104dSAndroid Build Coastguard Worker 	}
638*7304104dSAndroid Build Coastguard Worker 
639*7304104dSAndroid Build Coastguard Worker       /* This is a no-op we we have not allocated any memory.  */
640*7304104dSAndroid Build Coastguard Worker       free (tmp_phdr);
641*7304104dSAndroid Build Coastguard Worker 
642*7304104dSAndroid Build Coastguard Worker       elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY;
643*7304104dSAndroid Build Coastguard Worker 
644*7304104dSAndroid Build Coastguard Worker       /* We modified the program header.  Maybe this created a gap so
645*7304104dSAndroid Build Coastguard Worker 	 we have to write fill bytes, if necessary.  */
646*7304104dSAndroid Build Coastguard Worker       previous_scn_changed = true;
647*7304104dSAndroid Build Coastguard Worker     }
648*7304104dSAndroid Build Coastguard Worker 
649*7304104dSAndroid Build Coastguard Worker   /* From now on we have to keep track of the last position to eventually
650*7304104dSAndroid Build Coastguard Worker      fill the gaps with the prescribed fill byte.  */
651*7304104dSAndroid Build Coastguard Worker   int64_t last_offset;
652*7304104dSAndroid Build Coastguard Worker   if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
653*7304104dSAndroid Build Coastguard Worker     last_offset = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
654*7304104dSAndroid Build Coastguard Worker   else
655*7304104dSAndroid Build Coastguard Worker     last_offset = (ehdr->e_phoff + sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
656*7304104dSAndroid Build Coastguard Worker 
657*7304104dSAndroid Build Coastguard Worker   /* Write all the sections.  Well, only those which are modified.  */
658*7304104dSAndroid Build Coastguard Worker   if (shnum > 0)
659*7304104dSAndroid Build Coastguard Worker     {
660*7304104dSAndroid Build Coastguard Worker       if (unlikely (shnum > SIZE_MAX / (sizeof (Elf_Scn *)
661*7304104dSAndroid Build Coastguard Worker 					+ sizeof (ElfW2(LIBELFBITS,Shdr)))))
662*7304104dSAndroid Build Coastguard Worker 	return 1;
663*7304104dSAndroid Build Coastguard Worker 
664*7304104dSAndroid Build Coastguard Worker       int64_t shdr_offset = elf->start_offset + ehdr->e_shoff;
665*7304104dSAndroid Build Coastguard Worker #undef shdr_fctp
666*7304104dSAndroid Build Coastguard Worker #define shdr_fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
667*7304104dSAndroid Build Coastguard Worker 
668*7304104dSAndroid Build Coastguard Worker       ElfW2(LIBELFBITS,Shdr) *shdr_data;
669*7304104dSAndroid Build Coastguard Worker       ElfW2(LIBELFBITS,Shdr) *shdr_data_mem = NULL;
670*7304104dSAndroid Build Coastguard Worker       if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL
671*7304104dSAndroid Build Coastguard Worker 	  || (elf->flags & ELF_F_DIRTY))
672*7304104dSAndroid Build Coastguard Worker 	{
673*7304104dSAndroid Build Coastguard Worker 	  shdr_data_mem = (ElfW2(LIBELFBITS,Shdr) *)
674*7304104dSAndroid Build Coastguard Worker 	    malloc (shnum * sizeof (ElfW2(LIBELFBITS,Shdr)));
675*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (shdr_data_mem == NULL))
676*7304104dSAndroid Build Coastguard Worker 	    {
677*7304104dSAndroid Build Coastguard Worker 	      __libelf_seterrno (ELF_E_NOMEM);
678*7304104dSAndroid Build Coastguard Worker 	      return -1;
679*7304104dSAndroid Build Coastguard Worker 	    }
680*7304104dSAndroid Build Coastguard Worker 	  shdr_data = shdr_data_mem;
681*7304104dSAndroid Build Coastguard Worker 	}
682*7304104dSAndroid Build Coastguard Worker       else
683*7304104dSAndroid Build Coastguard Worker 	shdr_data = elf->state.ELFW(elf,LIBELFBITS).shdr;
684*7304104dSAndroid Build Coastguard Worker       int shdr_flags = elf->flags;
685*7304104dSAndroid Build Coastguard Worker 
686*7304104dSAndroid Build Coastguard Worker       /* Get all sections into the array and sort them.  */
687*7304104dSAndroid Build Coastguard Worker       Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
688*7304104dSAndroid Build Coastguard Worker       Elf_Scn **scns = malloc (shnum * sizeof (Elf_Scn *));
689*7304104dSAndroid Build Coastguard Worker       if (unlikely (scns == NULL))
690*7304104dSAndroid Build Coastguard Worker 	{
691*7304104dSAndroid Build Coastguard Worker 	  free (shdr_data_mem);
692*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_NOMEM);
693*7304104dSAndroid Build Coastguard Worker 	  return -1;
694*7304104dSAndroid Build Coastguard Worker 	}
695*7304104dSAndroid Build Coastguard Worker       sort_sections (scns, list);
696*7304104dSAndroid Build Coastguard Worker 
697*7304104dSAndroid Build Coastguard Worker       for (size_t cnt = 0; cnt < shnum; ++cnt)
698*7304104dSAndroid Build Coastguard Worker 	{
699*7304104dSAndroid Build Coastguard Worker 	  Elf_Scn *scn = scns[cnt];
700*7304104dSAndroid Build Coastguard Worker 	  if (scn->index == 0)
701*7304104dSAndroid Build Coastguard Worker 	    {
702*7304104dSAndroid Build Coastguard Worker 	      /* The dummy section header entry.  It should not be
703*7304104dSAndroid Build Coastguard Worker 		 possible to mark this "section" as dirty.  */
704*7304104dSAndroid Build Coastguard Worker 	      assert ((scn->flags & ELF_F_DIRTY) == 0);
705*7304104dSAndroid Build Coastguard Worker 	      goto next;
706*7304104dSAndroid Build Coastguard Worker 	    }
707*7304104dSAndroid Build Coastguard Worker 
708*7304104dSAndroid Build Coastguard Worker 	  ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
709*7304104dSAndroid Build Coastguard Worker 	  if (shdr->sh_type == SHT_NOBITS)
710*7304104dSAndroid Build Coastguard Worker 	    goto next;
711*7304104dSAndroid Build Coastguard Worker 
712*7304104dSAndroid Build Coastguard Worker 	  int64_t scn_start = elf->start_offset + shdr->sh_offset;
713*7304104dSAndroid Build Coastguard Worker 	  Elf_Data_List *dl = &scn->data_list;
714*7304104dSAndroid Build Coastguard Worker 	  bool scn_changed = false;
715*7304104dSAndroid Build Coastguard Worker 
716*7304104dSAndroid Build Coastguard Worker 	  if (scn->data_list_rear != NULL)
717*7304104dSAndroid Build Coastguard Worker 	    do
718*7304104dSAndroid Build Coastguard Worker 	      {
719*7304104dSAndroid Build Coastguard Worker 		/* If there is a gap, fill it.  */
720*7304104dSAndroid Build Coastguard Worker 		if (scn_start + dl->data.d.d_off > last_offset
721*7304104dSAndroid Build Coastguard Worker 		    && ((previous_scn_changed && dl->data.d.d_off == 0)
722*7304104dSAndroid Build Coastguard Worker 			|| ((scn->flags | dl->flags | elf->flags)
723*7304104dSAndroid Build Coastguard Worker 			    & ELF_F_DIRTY) != 0))
724*7304104dSAndroid Build Coastguard Worker 		  {
725*7304104dSAndroid Build Coastguard Worker 		    if (unlikely (fill (elf->fildes, last_offset,
726*7304104dSAndroid Build Coastguard Worker 					(scn_start + dl->data.d.d_off)
727*7304104dSAndroid Build Coastguard Worker 					- last_offset, fillbuf,
728*7304104dSAndroid Build Coastguard Worker 					&filled) != 0))
729*7304104dSAndroid Build Coastguard Worker 		      {
730*7304104dSAndroid Build Coastguard Worker 		      fail_free:
731*7304104dSAndroid Build Coastguard Worker 			free (shdr_data_mem);
732*7304104dSAndroid Build Coastguard Worker 			free (scns);
733*7304104dSAndroid Build Coastguard Worker 			return 1;
734*7304104dSAndroid Build Coastguard Worker 		      }
735*7304104dSAndroid Build Coastguard Worker 		  }
736*7304104dSAndroid Build Coastguard Worker 
737*7304104dSAndroid Build Coastguard Worker 		last_offset = scn_start + dl->data.d.d_off;
738*7304104dSAndroid Build Coastguard Worker 
739*7304104dSAndroid Build Coastguard Worker 		if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
740*7304104dSAndroid Build Coastguard Worker 		  {
741*7304104dSAndroid Build Coastguard Worker 		    char tmpbuf[MAX_TMPBUF];
742*7304104dSAndroid Build Coastguard Worker 		    void *buf = dl->data.d.d_buf;
743*7304104dSAndroid Build Coastguard Worker 
744*7304104dSAndroid Build Coastguard Worker 		    /* Let it go backward if the sections use a bogus
745*7304104dSAndroid Build Coastguard Worker 		       layout with overlaps.  We'll overwrite the stupid
746*7304104dSAndroid Build Coastguard Worker 		       user's section data with the latest one, rather than
747*7304104dSAndroid Build Coastguard Worker 		       crashing.  */
748*7304104dSAndroid Build Coastguard Worker 
749*7304104dSAndroid Build Coastguard Worker 		    if (unlikely (change_bo))
750*7304104dSAndroid Build Coastguard Worker 		      {
751*7304104dSAndroid Build Coastguard Worker #undef fctp
752*7304104dSAndroid Build Coastguard Worker #define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
753*7304104dSAndroid Build Coastguard Worker 
754*7304104dSAndroid Build Coastguard Worker 			buf = tmpbuf;
755*7304104dSAndroid Build Coastguard Worker 			if (dl->data.d.d_size > MAX_TMPBUF)
756*7304104dSAndroid Build Coastguard Worker 			  {
757*7304104dSAndroid Build Coastguard Worker 			    buf = malloc (dl->data.d.d_size);
758*7304104dSAndroid Build Coastguard Worker 			    if (unlikely (buf == NULL))
759*7304104dSAndroid Build Coastguard Worker 			      {
760*7304104dSAndroid Build Coastguard Worker 				__libelf_seterrno (ELF_E_NOMEM);
761*7304104dSAndroid Build Coastguard Worker 				goto fail_free;
762*7304104dSAndroid Build Coastguard Worker 			      }
763*7304104dSAndroid Build Coastguard Worker 			  }
764*7304104dSAndroid Build Coastguard Worker 
765*7304104dSAndroid Build Coastguard Worker 			/* Do the real work.  */
766*7304104dSAndroid Build Coastguard Worker 			(*fctp) (buf, dl->data.d.d_buf, dl->data.d.d_size, 1);
767*7304104dSAndroid Build Coastguard Worker 		      }
768*7304104dSAndroid Build Coastguard Worker 
769*7304104dSAndroid Build Coastguard Worker 		    ssize_t n = pwrite_retry (elf->fildes, buf,
770*7304104dSAndroid Build Coastguard Worker 					      dl->data.d.d_size,
771*7304104dSAndroid Build Coastguard Worker 					      last_offset);
772*7304104dSAndroid Build Coastguard Worker 		    if (unlikely ((size_t) n != dl->data.d.d_size))
773*7304104dSAndroid Build Coastguard Worker 		      {
774*7304104dSAndroid Build Coastguard Worker 			if (buf != dl->data.d.d_buf && buf != tmpbuf)
775*7304104dSAndroid Build Coastguard Worker 			  free (buf);
776*7304104dSAndroid Build Coastguard Worker 
777*7304104dSAndroid Build Coastguard Worker 			__libelf_seterrno (ELF_E_WRITE_ERROR);
778*7304104dSAndroid Build Coastguard Worker 			goto fail_free;
779*7304104dSAndroid Build Coastguard Worker 		      }
780*7304104dSAndroid Build Coastguard Worker 
781*7304104dSAndroid Build Coastguard Worker 		    if (buf != dl->data.d.d_buf && buf != tmpbuf)
782*7304104dSAndroid Build Coastguard Worker 		      free (buf);
783*7304104dSAndroid Build Coastguard Worker 
784*7304104dSAndroid Build Coastguard Worker 		    scn_changed = true;
785*7304104dSAndroid Build Coastguard Worker 		  }
786*7304104dSAndroid Build Coastguard Worker 
787*7304104dSAndroid Build Coastguard Worker 		last_offset += dl->data.d.d_size;
788*7304104dSAndroid Build Coastguard Worker 
789*7304104dSAndroid Build Coastguard Worker 		dl->flags &= ~ELF_F_DIRTY;
790*7304104dSAndroid Build Coastguard Worker 
791*7304104dSAndroid Build Coastguard Worker 		dl = dl->next;
792*7304104dSAndroid Build Coastguard Worker 	      }
793*7304104dSAndroid Build Coastguard Worker 	    while (dl != NULL);
794*7304104dSAndroid Build Coastguard Worker 	  else
795*7304104dSAndroid Build Coastguard Worker 	    {
796*7304104dSAndroid Build Coastguard Worker 	      /* If the previous section (or the ELF/program
797*7304104dSAndroid Build Coastguard Worker 		 header) changed we might have to fill the gap.  */
798*7304104dSAndroid Build Coastguard Worker 	      if (scn_start > last_offset && previous_scn_changed)
799*7304104dSAndroid Build Coastguard Worker 		{
800*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (fill (elf->fildes, last_offset,
801*7304104dSAndroid Build Coastguard Worker 				      scn_start - last_offset, fillbuf,
802*7304104dSAndroid Build Coastguard Worker 				      &filled) != 0))
803*7304104dSAndroid Build Coastguard Worker 		    goto fail_free;
804*7304104dSAndroid Build Coastguard Worker 		}
805*7304104dSAndroid Build Coastguard Worker 
806*7304104dSAndroid Build Coastguard Worker 	      last_offset = scn_start + shdr->sh_size;
807*7304104dSAndroid Build Coastguard Worker 	    }
808*7304104dSAndroid Build Coastguard Worker 
809*7304104dSAndroid Build Coastguard Worker 	  previous_scn_changed = scn_changed;
810*7304104dSAndroid Build Coastguard Worker 	next:
811*7304104dSAndroid Build Coastguard Worker 	  /* Collect the section header table information.  */
812*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (change_bo))
813*7304104dSAndroid Build Coastguard Worker 	    (*shdr_fctp) (&shdr_data[scn->index],
814*7304104dSAndroid Build Coastguard Worker 			  scn->shdr.ELFW(e,LIBELFBITS),
815*7304104dSAndroid Build Coastguard Worker 			  sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
816*7304104dSAndroid Build Coastguard Worker 	  else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL
817*7304104dSAndroid Build Coastguard Worker 		   || (elf->flags & ELF_F_DIRTY))
818*7304104dSAndroid Build Coastguard Worker 	    memcpy (&shdr_data[scn->index], scn->shdr.ELFW(e,LIBELFBITS),
819*7304104dSAndroid Build Coastguard Worker 		    sizeof (ElfW2(LIBELFBITS,Shdr)));
820*7304104dSAndroid Build Coastguard Worker 
821*7304104dSAndroid Build Coastguard Worker 	  shdr_flags |= scn->shdr_flags;
822*7304104dSAndroid Build Coastguard Worker 	  scn->shdr_flags &= ~ELF_F_DIRTY;
823*7304104dSAndroid Build Coastguard Worker 	}
824*7304104dSAndroid Build Coastguard Worker 
825*7304104dSAndroid Build Coastguard Worker       /* Fill the gap between last section and section header table if
826*7304104dSAndroid Build Coastguard Worker 	 necessary.  */
827*7304104dSAndroid Build Coastguard Worker       if ((elf->flags & ELF_F_DIRTY) && last_offset < shdr_offset
828*7304104dSAndroid Build Coastguard Worker 	  && unlikely (fill (elf->fildes, last_offset,
829*7304104dSAndroid Build Coastguard Worker 			     shdr_offset - last_offset,
830*7304104dSAndroid Build Coastguard Worker 			     fillbuf, &filled) != 0))
831*7304104dSAndroid Build Coastguard Worker 	goto fail_free;
832*7304104dSAndroid Build Coastguard Worker 
833*7304104dSAndroid Build Coastguard Worker       /* Write out the section header table.  */
834*7304104dSAndroid Build Coastguard Worker       if (shdr_flags & ELF_F_DIRTY
835*7304104dSAndroid Build Coastguard Worker 	  && unlikely ((size_t) pwrite_retry (elf->fildes, shdr_data,
836*7304104dSAndroid Build Coastguard Worker 					      sizeof (ElfW2(LIBELFBITS,Shdr))
837*7304104dSAndroid Build Coastguard Worker 					      * shnum, shdr_offset)
838*7304104dSAndroid Build Coastguard Worker 		       != sizeof (ElfW2(LIBELFBITS,Shdr)) * shnum))
839*7304104dSAndroid Build Coastguard Worker 	{
840*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_WRITE_ERROR);
841*7304104dSAndroid Build Coastguard Worker 	  goto fail_free;
842*7304104dSAndroid Build Coastguard Worker 	}
843*7304104dSAndroid Build Coastguard Worker 
844*7304104dSAndroid Build Coastguard Worker       free (shdr_data_mem);
845*7304104dSAndroid Build Coastguard Worker       free (scns);
846*7304104dSAndroid Build Coastguard Worker     }
847*7304104dSAndroid Build Coastguard Worker 
848*7304104dSAndroid Build Coastguard Worker   /* That was the last part.  Clear the overall flag.  */
849*7304104dSAndroid Build Coastguard Worker   elf->flags &= ~ELF_F_DIRTY;
850*7304104dSAndroid Build Coastguard Worker 
851*7304104dSAndroid Build Coastguard Worker   return 0;
852*7304104dSAndroid Build Coastguard Worker }
853