• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Merge string sections.
2    Copyright (C) 2015, 2016 Red Hat, Inc.
3    This file is part of elfutils.
4 
5    This file is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9 
10    elfutils is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17 
18 #include <config.h>
19 
20 #include <assert.h>
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <inttypes.h>
29 #include <unistd.h>
30 
31 #include <system.h>
32 #include <gelf.h>
33 #include ELFUTILS_HEADER(dwelf)
34 #include "elf-knowledge.h"
35 
36 /* The original ELF file.  */
37 static int fd = -1;
38 static Elf *elf = NULL;
39 static bool replace;
40 
41 /* The new ELF file.  */
42 static char *fnew = NULL;
43 static int fdnew = -1;
44 static Elf *elfnew = NULL;
45 
46 /* The merged string table.  */
47 static Dwelf_Strtab *strings = NULL;
48 
49 /* Section name strents.  */
50 static Dwelf_Strent **scnstrents = NULL;
51 
52 /* Symbol name strends.  */
53 static Dwelf_Strent **symstrents = NULL;
54 
55 /* New ELF file buffers.  */
56 static Elf_Data newstrtabdata = { .d_buf = NULL };
57 static size_t newshnums = 0;
58 static void **newscnbufs = NULL;
59 
60 /* Release all files and resources allocated.  */
61 static void
release(void)62 release (void)
63 {
64   /* The new string table.  */
65   if (strings != NULL)
66     dwelf_strtab_free (strings);
67 
68   free (scnstrents);
69   free (symstrents);
70   free (newstrtabdata.d_buf);
71 
72   /* Any new data buffers allocated.  */
73   for (size_t i = 0; i < newshnums; i++)
74     free (newscnbufs[i]);
75   free (newscnbufs);
76 
77   /* The new ELF file.  */
78   if (fdnew != -1)
79     {
80       unlink (fnew);
81       elf_end (elfnew);
82       close (fdnew);
83     }
84   // Don't release, we might need it in the error message.
85   // if (replace)
86   //   free (fnew);
87 
88   /* The original ELF file.  */
89   elf_end (elf);
90   close (fd);
91 }
92 
93 /* The various ways we can fail... Cleanup and show some message to
94    the user.  The file name may be NULL.  */
95 static void __attribute__ ((noreturn))
fail(const char * msg,const char * fname)96 fail (const char *msg, const char *fname)
97 {
98   release ();
99   if (fname != NULL)
100     error (1, 0, "%s: %s", fname, msg);
101   else
102     error (1, 0, "%s", msg);
103   abort();
104 }
105 
106 static void __attribute__ ((noreturn))
fail_errno(const char * msg,const char * fname)107 fail_errno (const char *msg, const char *fname)
108 {
109   release ();
110   if (fname != NULL)
111     error (1, errno, "%s: %s", fname, msg);
112   else
113     error (1, errno, "%s", msg);
114   abort();
115 }
116 
117 static void __attribute__ ((noreturn))
fail_idx(const char * msg,const char * fname,size_t idx)118 fail_idx (const char *msg, const char *fname, size_t idx)
119 {
120   release ();
121   if (fname != NULL)
122     error (1, 0, "%s: %s %zd", fname, msg, idx);
123   else
124     error (1, 0, "%s %zd", msg, idx);
125   abort();
126 }
127 
128 static void __attribute__ ((noreturn))
fail_elf(const char * msg,const char * fname)129 fail_elf (const char *msg, const char *fname)
130 {
131   release ();
132   if (fname != NULL)
133     error (1, 0, "%s: %s: %s", fname, msg, elf_errmsg (-1));
134   else
135     error (1, 0, "%s: %s", msg, elf_errmsg (-1));
136   abort();
137 }
138 
139 static void __attribute__ ((noreturn))
fail_elf_idx(const char * msg,const char * fname,size_t idx)140 fail_elf_idx (const char *msg, const char *fname, size_t idx)
141 {
142   release ();
143   if (fname != NULL)
144     error (1, 0, "%s: %s %zd: %s", fname, msg, idx, elf_errmsg (-1));
145   else
146     error (1, 0, "%s %zd: %s", msg, idx, elf_errmsg (-1));
147   abort();
148 }
149 
150 /* section index mapping and sanity checking.  */
151 static size_t
newsecndx(size_t secndx,size_t shdrstrndx,size_t shdrnum,const char * fname,const char * what,size_t widx,const char * member,size_t midx)152 newsecndx (size_t secndx, size_t shdrstrndx, size_t shdrnum,
153 	   const char *fname,
154 	   const char *what, size_t widx,
155 	   const char *member, size_t midx)
156 {
157   if (unlikely (secndx == 0 || secndx == shdrstrndx || secndx >= shdrnum))
158     {
159       /* Don't use fail... too specialized messages.  Call release
160 	 outselves and then error.  Ignores midx if widx is
161 	 zero.  */
162       release ();
163       if (widx == 0)
164 	error (1, 0, "%s: bad section index %zd in %s for %s",
165 	       fname, secndx, what, member);
166       else if (midx == 0)
167 	error (1, 0, "%s: bad section index %zd in %s %zd for %s",
168 	       fname, secndx, what, widx, member);
169       else
170 	error (1, 0, "%s: bad section index %zd in %s %zd for %s %zd",
171 	       fname, secndx, what, widx, member, midx);
172     }
173 
174   return secndx < shdrstrndx ? secndx : secndx - 1;
175 }
176 
177 static void
new_data_buf(Elf_Data * d,const char * fname,size_t ndx,size_t shdrstrndx,size_t shdrnum)178 new_data_buf (Elf_Data *d, const char *fname,
179 	      size_t ndx, size_t shdrstrndx, size_t shdrnum)
180 {
181   size_t s = d->d_size;
182   if (s == 0)
183     fail_idx ("Expected data in section", fname, ndx);
184   void *b = malloc (d->d_size);
185   if (b == NULL)
186     fail_idx ("Couldn't allocated buffer for section", NULL, ndx);
187   newscnbufs[newsecndx (ndx, shdrstrndx, shdrnum, fname,
188 			"section", ndx, "d_buf", 0)] = d->d_buf = b;
189 }
190 
191 int
main(int argc,char ** argv)192 main (int argc, char **argv)
193 {
194   elf_version (EV_CURRENT);
195 
196   /* Basic command line handling.  Need to replace the input file?  */
197   if ((argc != 2 && argc != 4)
198       || (argc == 4 && strcmp (argv[1], "-o") != 0))
199     fail ("Usage argument: [-o <outputfile>] <inputfile>", NULL);
200   replace = argc == 2;
201 
202   /* Get the ELF file.  */
203   const char *fname;
204   if (replace)
205     fname = argv[1];
206   else
207     fname = argv[3];
208   fd = open (fname, O_RDONLY);
209   if (fd < 0)
210     fail_errno ("couldn't open", fname);
211 
212   elf = elf_begin (fd, ELF_C_READ, NULL);
213   if (elf == NULL)
214     fail_elf ("couldn't open ELF file for reading", fname);
215 
216   GElf_Ehdr ehdr;
217   if (gelf_getehdr (elf, &ehdr) == NULL)
218     fail_elf ("Couldn't get ehdr", fname);
219 
220   /* Get the section header string table.  */
221   size_t shdrstrndx;
222   if (elf_getshdrstrndx (elf, &shdrstrndx) != 0)
223     fail_elf ("couldn't get section header string table index", fname);
224 
225   Elf_Scn *shdrstrscn = elf_getscn (elf, shdrstrndx);
226   GElf_Shdr shdrstrshdr_mem;
227   GElf_Shdr *shdrstrshdr = gelf_getshdr (shdrstrscn, &shdrstrshdr_mem);
228   if (shdrstrshdr == NULL)
229     fail_elf ("couldn't get section header string table section", fname);
230 
231   if ((shdrstrshdr->sh_flags & SHF_ALLOC) != 0)
232     fail ("section header string table is an allocated section", fname);
233 
234   /* Get the symtab section.  */
235   size_t symtabndx = 0;
236   Elf_Scn *symtabscn = NULL;
237   GElf_Shdr symtabshdr_mem;
238   GElf_Shdr *symtabshdr = NULL;
239   while ((symtabscn = elf_nextscn (elf, symtabscn)) != NULL)
240     {
241       symtabshdr = gelf_getshdr (symtabscn, &symtabshdr_mem);
242       if (symtabshdr == NULL)
243 	fail_elf ("couldn't get shdr", fname);
244 
245       if (symtabshdr->sh_type == SHT_SYMTAB)
246 	{
247 	  /* Just pick the first, we don't expect more than one. */
248 	  symtabndx = elf_ndxscn (symtabscn);
249 	  break;
250 	}
251     }
252 
253   if (symtabshdr == NULL)
254     fail ("No symtab found", fname);
255 
256   if ((symtabshdr->sh_flags & SHF_ALLOC) != 0)
257     fail ("symtab is an allocated section", fname);
258 
259   /* Get the strtab of the symtab.  */
260   size_t strtabndx = symtabshdr->sh_link;
261   Elf_Scn *strtabscn = elf_getscn (elf, strtabndx);
262   GElf_Shdr strtabshdr_mem;
263   GElf_Shdr *strtabshdr = gelf_getshdr (strtabscn, &strtabshdr_mem);
264   if (strtabshdr == NULL)
265     fail_elf ("Couldn't get strtab section", fname);
266 
267   if (shdrstrndx == strtabndx)
268     {
269       error (0, 0, "%s: Nothing to do, shstrtab == strtab", fname);
270       release ();
271       return 0;
272     }
273 
274   if ((strtabshdr->sh_flags & SHF_ALLOC) != 0)
275     fail ("strtab is an allocated section", fname);
276 
277   size_t phnum;
278   if (elf_getphdrnum (elf, &phnum) != 0)
279     fail_elf ("Couldn't get number of phdrs", fname);
280 
281   /* If there are phdrs we want to maintain the layout of the
282      allocated sections in the file.  */
283   bool layout = phnum != 0;
284 
285   /* Create a new merged strings table that starts with the empty string.  */
286   strings = dwelf_strtab_init (true);
287   if (strings == NULL)
288     fail ("No memory to create merged string table", NULL);
289 
290   /* Add the strings from all the sections.  */
291   size_t shdrnum;
292   if (elf_getshdrnum (elf, &shdrnum) != 0)
293     fail_elf ("Couldn't get number of sections", fname);
294   scnstrents = malloc (shdrnum * sizeof (Dwelf_Strent *));
295   if (scnstrents == NULL)
296     fail ("couldn't allocate memory for section strings", NULL);
297 
298   /* While going through all sections keep track of last allocated
299      offset if needed to keep the layout.  We'll put any unallocated
300      sections behind those (strtab is unallocated and will change
301      size).  */
302   GElf_Off last_offset = 0;
303   if (layout)
304     last_offset = (ehdr.e_phoff
305 		   + gelf_fsize (elf, ELF_T_PHDR, phnum, EV_CURRENT));
306   Elf_Scn *scn = NULL;
307   while ((scn = elf_nextscn (elf, scn)) != NULL)
308     {
309       size_t scnnum = elf_ndxscn (scn);
310       GElf_Shdr shdr_mem;
311       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
312       if (shdr == NULL)
313 	fail_elf_idx ("couldn't get shdr", fname, scnnum);
314       /* Don't add the .shstrtab section itself, we'll not use it.  */
315       if (shdr->sh_name != 0 && scnnum != shdrstrndx)
316 	{
317 	  const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
318 	  if (sname == NULL)
319 	    fail_elf_idx ("couldn't get section name", fname, scnnum);
320 	  if ((scnstrents[scnnum] = dwelf_strtab_add (strings, sname)) == NULL)
321 	    fail ("No memory to add to merged string table", NULL);
322 	}
323 
324       if (layout)
325 	if ((shdr->sh_flags & SHF_ALLOC) != 0)
326 	  {
327 	    GElf_Off off = shdr->sh_offset + (shdr->sh_type != SHT_NOBITS
328 					      ? shdr->sh_size : 0);
329 	    if (last_offset < off)
330 	      last_offset = off;
331 	  }
332     }
333 
334   /* Add the strings from all the symbols.  */
335   size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
336   Elf_Data *symd = elf_getdata (symtabscn, NULL);
337   if (symd == NULL)
338     fail_elf ("couldn't get symtab data", fname);
339   size_t symsnum = symd->d_size / elsize;
340   symstrents = malloc (symsnum * sizeof (Dwelf_Strent *));
341   if (symstrents == NULL)
342     fail_errno ("Couldn't allocate memory for symbol strings", NULL);
343   for (size_t i = 0; i < symsnum; i++)
344     {
345       GElf_Sym sym_mem;
346       GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem);
347       if (sym == NULL)
348 	fail_elf_idx ("Couldn't get symbol", fname, i);
349       if (sym->st_name != 0)
350 	{
351 	  const char *sname = elf_strptr (elf, strtabndx, sym->st_name);
352 	  if (sname == NULL)
353 	    fail_elf_idx ("Couldn't get symbol name", fname, i);
354 	  if ((symstrents[i] = dwelf_strtab_add (strings, sname)) == NULL)
355 	    fail_idx ("No memory to add to merged string table symbol",
356 		      fname, i);
357 	}
358     }
359 
360   /* We got all strings, build the new string table and store it as
361      new strtab.  */
362   dwelf_strtab_finalize (strings, &newstrtabdata);
363 
364   /* We share at least the empty string so the result is at least 1
365      byte smaller.  */
366   if (newstrtabdata.d_size >= shdrstrshdr->sh_size + strtabshdr->sh_size)
367     fail ("Impossible, merged string table is larger", fname);
368 
369   struct stat st;
370   if (fstat (fd, &st) != 0)
371     fail_errno("Couldn't fstat", fname);
372 
373   /* Create a new (temporary) ELF file for the result.  */
374   if (replace)
375     {
376       size_t fname_len = strlen (fname);
377       fnew = malloc (fname_len + sizeof (".XXXXXX"));
378       if (fnew == NULL)
379 	fail_errno ("couldn't allocate memory for new file name", NULL);
380       strcpy (mempcpy (fnew, fname, fname_len), ".XXXXXX");
381 
382       fdnew = mkstemp (fnew);
383     }
384   else
385     {
386       fnew = argv[2];
387       fdnew = open (fnew, O_WRONLY | O_CREAT, st.st_mode & ALLPERMS);
388     }
389 
390   if (fdnew < 0)
391     fail_errno ("couldn't create output file", fnew);
392 
393   elfnew = elf_begin (fdnew, ELF_C_WRITE, NULL);
394   if (elfnew == NULL)
395     fail_elf ("couldn't open new ELF for writing", fnew);
396 
397   /* Create the new ELF header and copy over all the data.  */
398   if (gelf_newehdr (elfnew, gelf_getclass (elf)) == 0)
399     fail_elf ("Couldn't create new ehdr", fnew);
400   GElf_Ehdr newehdr;
401   if (gelf_getehdr (elfnew, &newehdr) == NULL)
402     fail_elf ("Couldn't get ehdr", fnew);
403 
404   newehdr.e_ident[EI_DATA] = ehdr.e_ident[EI_DATA];
405   newehdr.e_type = ehdr.e_type;
406   newehdr.e_machine = ehdr.e_machine;
407   newehdr.e_version = ehdr.e_version;
408   newehdr.e_entry = ehdr.e_entry;
409   newehdr.e_flags = ehdr.e_flags;
410 
411   /* The new file uses the new strtab as shstrtab.  */
412   size_t newstrtabndx = newsecndx (strtabndx, shdrstrndx, shdrnum,
413 				   fname, "ehdr", 0, "e_shstrndx", 0);
414   if (newstrtabndx < SHN_LORESERVE)
415     newehdr.e_shstrndx = newstrtabndx;
416   else
417     {
418       Elf_Scn *zscn = elf_getscn (elfnew, 0);
419       GElf_Shdr zshdr_mem;
420       GElf_Shdr *zshdr = gelf_getshdr (zscn, &zshdr_mem);
421       if (zshdr == NULL)
422 	fail_elf ("Couldn't get section zero", fnew);
423       zshdr->sh_link = strtabndx;
424       if (gelf_update_shdr (zscn, zshdr) == 0)
425 	fail_elf ("Couldn't update section zero", fnew);
426       newehdr.e_shstrndx = SHN_XINDEX;
427     }
428 
429   if (gelf_update_ehdr (elfnew, &newehdr) == 0)
430     fail ("Couldn't update ehdr", fnew);
431 
432   /* Copy the program headers if any.  */
433   if (phnum != 0)
434     {
435       if (gelf_newphdr (elfnew, phnum) == 0)
436 	fail_elf ("Couldn't create phdrs", fnew);
437 
438       for (size_t cnt = 0; cnt < phnum; ++cnt)
439 	{
440 	  GElf_Phdr phdr_mem;
441 	  GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
442 	  if (phdr == NULL)
443 	    fail_elf_idx ("Couldn't get phdr", fname, cnt);
444 	  if (gelf_update_phdr (elfnew, cnt, phdr) == 0)
445 	    fail_elf_idx ("Couldn't create phdr", fnew, cnt);
446 	}
447     }
448 
449   newshnums = shdrnum - 1;
450   newscnbufs = calloc (sizeof (void *), newshnums);
451   if (newscnbufs == NULL)
452     fail_errno ("Couldn't allocate memory for new section buffers", NULL);
453 
454   /* Copy the sections, except the shstrtab, fill the strtab with the
455      combined strings and adjust section references.  */
456   while ((scn = elf_nextscn (elf, scn)) != NULL)
457     {
458       size_t ndx = elf_ndxscn (scn);
459 
460       GElf_Shdr shdr_mem;
461       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
462       if (shdr == NULL)
463 	fail_elf_idx ("Couldn't get shdr", fname, ndx);
464 
465       /* Section zero is always created.  Skip the shtrtab.  */
466       if (ndx == 0 || ndx == shdrstrndx)
467 	continue;
468 
469       Elf_Scn *newscn = elf_newscn (elfnew);
470       if (newscn == NULL)
471 	fail_elf_idx ("couldn't create new section", fnew, ndx);
472 
473       GElf_Shdr newshdr;
474       newshdr.sh_name = (shdr->sh_name != 0
475 			 ? dwelf_strent_off (scnstrents[ndx]) : 0);
476       newshdr.sh_type = shdr->sh_type;
477       newshdr.sh_flags = shdr->sh_flags;
478       newshdr.sh_addr = shdr->sh_addr;
479       newshdr.sh_size = shdr->sh_size;
480       if (shdr->sh_link != 0)
481 	newshdr.sh_link = newsecndx (shdr->sh_link, shdrstrndx, shdrnum,
482 				     fname, "shdr", ndx, "sh_link", 0);
483       else
484 	newshdr.sh_link = 0;
485       if (SH_INFO_LINK_P (shdr) && shdr->sh_info != 0)
486 	newshdr.sh_info = newsecndx (shdr->sh_info, shdrstrndx, shdrnum,
487 				     fname, "shdr", ndx, "sh_info", 0);
488 
489       else
490 	newshdr.sh_info = shdr->sh_info;
491       newshdr.sh_entsize = shdr->sh_entsize;
492 
493       /* Some sections need a new data buffer because they need to
494 	 manipulate the original data.  Allocate and check here, so we
495 	 have a list of all data buffers we might need to release when
496 	 done.  */
497       Elf_Data *newdata = elf_newdata (newscn);
498       if (newdata == NULL)
499 	fail_elf_idx ("Couldn't create new data for section", fnew, ndx);
500       if (ndx == strtabndx)
501 	*newdata = newstrtabdata;
502       else
503 	{
504 	  /* The symtab, dynsym, group and symtab_shndx sections
505 	     contain section indexes. Symbol tables (symtab and
506 	     dynsym) contain indexes to strings. Update both if
507 	     necessary.  */
508 	  Elf_Data *data = elf_getdata (scn, NULL);
509 	  if (data == NULL)
510 	    fail_elf_idx ("Couldn't get data from section", fname, ndx);
511 	  *newdata = *data;
512 	  switch (shdr->sh_type)
513 	    {
514 	    case SHT_SYMTAB:
515 	    case SHT_DYNSYM:
516 	      {
517 		/* We need to update the section numbers of the
518 		   symbols and if this symbol table uses the strtab
519 		   section also the name indexes.  */
520 		const bool update_name = shdr->sh_link == strtabndx;
521 		if (update_name && ndx != symtabndx)
522 		  fail ("Only one symbol table using strtab expected", fname);
523 		new_data_buf (newdata, fname, ndx, shdrstrndx, shdrnum);
524 		size_t syms = (data->d_size
525 			       / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT));
526 		for (size_t i = 0; i < syms; i++)
527 		  {
528 		    GElf_Sym sym;
529 		    if (gelf_getsym (data, i, &sym) == NULL)
530 		      fail_elf_idx ("Couldn't get symbol", fname, i);
531 
532 		    if (GELF_ST_TYPE (sym.st_info) == STT_SECTION
533 			&& sym.st_shndx == shdrstrndx)
534 		      fprintf (stderr, "WARNING:"
535 			       " symbol table [%zd] contains section symbol %zd"
536 			       " for old shdrstrndx %zd\n", ndx, i, shdrstrndx);
537 		    else if (sym.st_shndx != SHN_UNDEF
538 			     && sym.st_shndx < SHN_LORESERVE)
539 		      sym.st_shndx = newsecndx (sym.st_shndx, shdrstrndx, shdrnum,
540 					 fname, "section", ndx, "symbol", i);
541 		    if (update_name && sym.st_name != 0)
542 		      sym.st_name = dwelf_strent_off (symstrents[i]);
543 
544 		    /* We explicitly don't update the SHNDX table at
545 		       the same time, we do that below.  */
546 		    if (gelf_update_sym (newdata, i, &sym) == 0)
547 		      fail_elf_idx ("Couldn't update symbol", fnew, i);
548 		  }
549 	      }
550 	      break;
551 
552 	    case SHT_GROUP:
553 	      {
554 		new_data_buf (newdata, fname, ndx, shdrstrndx, shdrnum);
555 		/* A section group contains Elf32_Words. The first
556 		   word is a flag value, the rest of the words are
557 		   indexes of the sections belonging to the group.  */
558 		Elf32_Word *group = (Elf32_Word *) data->d_buf;
559 		Elf32_Word *newgroup = (Elf32_Word *) newdata->d_buf;
560 		size_t words = data->d_size / sizeof (Elf32_Word);
561 		if (words == 0)
562 		  fail_idx ("Not enough data in group section", fname, ndx);
563 		newgroup[0] = group[0];
564 		for (size_t i = 1; i < words; i++)
565 		  newgroup[i] = newsecndx (group[i], shdrstrndx, shdrnum,
566 					   fname, "section", ndx, "group", i);
567 	      }
568 	      break;
569 
570 	    case SHT_SYMTAB_SHNDX:
571 	      {
572 		new_data_buf (newdata, fname, ndx, shdrstrndx, shdrnum);
573 		/* A SHNDX just contains an array of section indexes
574 		   for the corresponding symbol table.  The entry is
575 		   SHN_UNDEF unless the corresponding symbol is
576 		   SHN_XINDEX.  */
577 		Elf32_Word *shndx = (Elf32_Word *) data->d_buf;
578 		Elf32_Word *newshndx = (Elf32_Word *) newdata->d_buf;
579 		size_t words = data->d_size / sizeof (Elf32_Word);
580 		for (size_t i = 0; i < words; i++)
581 		  if (shndx[i] == SHN_UNDEF)
582 		    newshndx[i] = SHN_UNDEF;
583 		  else
584 		    newshndx[i] = newsecndx (shndx[i], shdrstrndx, shdrnum,
585 					     fname, "section", ndx, "shndx", i);
586 	      }
587 	      break;
588 
589 	    case SHT_DYNAMIC:
590 	      FALLTHROUGH;
591 	      /* There are string indexes in here, but
592 		 they (should) point to a allocated string table,
593 		 which we don't alter.  */
594 	    default:
595 	      /* Nothing to do.  Section data doesn't contain section
596 		 or strtab indexes.  */
597 	      break;
598 	    }
599 	}
600 
601       /* When we are responsible for the layout explicitly set
602 	 sh_addralign, sh_size and sh_offset.  Otherwise libelf will
603 	 calculate those from the Elf_Data.  */
604       if (layout)
605 	{
606 	  /* We have just one Elf_Data.  */
607 	  newshdr.sh_size = newdata->d_size;
608 	  newshdr.sh_addralign = newdata->d_align;
609 
610 	  /* Keep the offset of allocated sections so they are at the
611 	     same place in the file. Add unallocated ones after the
612 	     allocated ones.  */
613 	  if ((shdr->sh_flags & SHF_ALLOC) != 0)
614 	    newshdr.sh_offset = shdr->sh_offset;
615 	  else
616 	    {
617 	      /* Zero means one.  No alignment constraints.  */
618 	      size_t addralign = newshdr.sh_addralign ?: 1;
619 	      last_offset = (last_offset + addralign - 1) & ~(addralign - 1);
620 	      newshdr.sh_offset = last_offset;
621 	      if (newshdr.sh_type != SHT_NOBITS)
622 		last_offset += newshdr.sh_size;
623 	    }
624 	}
625       else
626 	{
627 	  newshdr.sh_addralign = 0;
628 	  newshdr.sh_size = 0;
629 	  newshdr.sh_offset = 0;
630 	}
631 
632       if (gelf_update_shdr (newscn, &newshdr) == 0)
633 	fail_elf_idx ("Couldn't update section header", fnew, ndx);
634     }
635 
636   /* If we have phdrs we want elf_update to layout the SHF_ALLOC
637      sections precisely as in the original file.  In that case we are
638      also responsible for setting phoff and shoff */
639   if (layout)
640     {
641       /* Position the shdrs after the last (unallocated) section.  */
642       if (gelf_getehdr (elfnew, &newehdr) == NULL)
643 	fail_elf ("Couldn't get ehdr", fnew);
644       const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
645       newehdr.e_shoff = ((last_offset + offsize - 1)
646 			 & ~((GElf_Off) (offsize - 1)));
647 
648       /* The phdrs go in the same place as in the original file.
649 	 Normally right after the ELF header.  */
650       newehdr.e_phoff = ehdr.e_phoff;
651 
652       if (gelf_update_ehdr (elfnew, &newehdr) == 0)
653 	fail_elf ("Couldn't update ehdr", fnew);
654 
655       elf_flagelf (elfnew, ELF_C_SET, ELF_F_LAYOUT);
656     }
657 
658   if (elf_update (elfnew, ELF_C_WRITE) == -1)
659     fail_elf ("Couldn't write ELF", fnew);
660 
661   elf_end (elfnew);
662   elfnew = NULL;
663 
664   /* Try to match mode and owner.group of the original file.  */
665   if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0)
666     error (0, errno, "Couldn't fchmod %s", fnew);
667   if (fchown (fdnew, st.st_uid, st.st_gid) != 0)
668     error (0, errno, "Couldn't fchown %s", fnew);
669 
670   /* Finally replace the old file with the new merged strings file.  */
671   if (replace)
672     if (rename (fnew, fname) != 0)
673       fail_errno ("rename", fnew);
674 
675   /* We are finally done with the new file, don't unlink it now.  */
676   close (fdnew);
677   if (replace)
678     free (fnew);
679   fnew = NULL;
680   fdnew = -1;
681 
682   release ();
683   return 0;
684 }
685