• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Discard section not used at runtime from object files.
2    Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@redhat.com>, 2000.
4 
5    This program is Open Source software; you can redistribute it and/or
6    modify it under the terms of the Open Software License version 1.0 as
7    published by the Open Source Initiative.
8 
9    You should have received a copy of the Open Software License along
10    with this program; if not, you may obtain a copy of the Open Software
11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13    3001 King Ranch Road, Ukiah, CA 95482.   */
14 
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
18 
19 #include <argp.h>
20 #include <assert.h>
21 #include <byteswap.h>
22 #include <endian.h>
23 #include <error.h>
24 #include <fcntl.h>
25 #include <gelf.h>
26 #include <libelf.h>
27 #include <libintl.h>
28 #include <locale.h>
29 #include <mcheck.h>
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <stdio_ext.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <sys/param.h>
37 #include <sys/time.h>
38 
39 #include <elf-knowledge.h>
40 #include <libebl.h>
41 #include <system.h>
42 
43 
44 /* Name and version of program.  */
45 static void print_version (FILE *stream, struct argp_state *state);
46 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
47 
48 
49 /* Values for the parameters which have no short form.  */
50 #define OPT_REMOVE_COMMENT	0x100
51 #define OPT_PERMISSIVE		0x101
52 
53 
54 /* Definitions of arguments for argp functions.  */
55 static const struct argp_option options[] =
56 {
57   { NULL, 0, NULL, 0, N_("Output selection:") },
58   { NULL, 'o', "FILE", 0, N_("Place stripped output into FILE") },
59   { NULL, 'f', "FILE", 0, N_("Extract the removed sections into FILE") },
60 
61   { NULL, 0, NULL, 0, N_("Output options:") },
62   { "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols") },
63   { "preserve-dates", 'p', NULL, 0,
64     N_("Copy modified/access timestamps to the output") },
65   { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
66     N_("Remove .comment section") },
67   { "permissive", OPT_PERMISSIVE, NULL, 0,
68     N_("Relax a few rules to handle slightly broken ELF files") },
69   { NULL, 0, NULL, 0, NULL }
70 };
71 
72 /* Short description of program.  */
73 static const char doc[] = N_("Discard symbols from object files.");
74 
75 /* Strings for arguments in help texts.  */
76 static const char args_doc[] = N_("[FILE...]");
77 
78 /* Prototype for option handler.  */
79 static error_t parse_opt (int key, char *arg, struct argp_state *state);
80 
81 /* Function to print some extra text in the help message.  */
82 static char *more_help (int key, const char *text, void *input);
83 
84 /* Data structure to communicate with argp functions.  */
85 static struct argp argp =
86 {
87   options, parse_opt, args_doc, doc, NULL, more_help
88 };
89 
90 
91 /* Print symbols in file named FNAME.  */
92 static int process_file (const char *fname);
93 
94 /* Handle one ELF file.  */
95 static int handle_elf (int fd, Elf *elf, const char *prefix,
96 		       const char *fname, mode_t mode, struct timeval tvp[2]);
97 
98 /* Handle all files contained in the archive.  */
99 static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
100 		      struct timeval tvp[2]);
101 
102 #define INTERNAL_ERROR(fname) \
103   error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"),      \
104 	 fname, __LINE__, VERSION, __DATE__, elf_errmsg (-1))
105 
106 
107 /* Name of the output file.  */
108 static const char *output_fname;
109 
110 /* Name of the debug output file.  */
111 static const char *debug_fname;
112 
113 /* If true output files shall have same date as the input file.  */
114 static bool preserve_dates;
115 
116 /* If true .comment sections will be removed.  */
117 static bool remove_comment;
118 
119 /* If true remove all debug sections.  */
120 static bool remove_debug;
121 
122 /* If true relax some ELF rules for input files.  */
123 static bool permissive;
124 
125 
126 int
main(int argc,char * argv[])127 main (int argc, char *argv[])
128 {
129   int remaining;
130   int result = 0;
131 
132   /* Make memory leak detection possible.  */
133   mtrace ();
134 
135   /* We use no threads here which can interfere with handling a stream.  */
136   __fsetlocking (stdin, FSETLOCKING_BYCALLER);
137   __fsetlocking (stdout, FSETLOCKING_BYCALLER);
138   __fsetlocking (stderr, FSETLOCKING_BYCALLER);
139 
140   /* Set locale.  */
141   setlocale (LC_ALL, "");
142 
143   /* Make sure the message catalog can be found.  */
144   bindtextdomain (PACKAGE, LOCALEDIR);
145 
146   /* Initialize the message catalog.  */
147   textdomain (PACKAGE);
148 
149   /* Parse and process arguments.  */
150   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
151 
152   /* Tell the library which version we are expecting.  */
153   elf_version (EV_CURRENT);
154 
155   if (remaining == argc)
156     /* The user didn't specify a name so we use a.out.  */
157     result = process_file ("a.out");
158   else
159     {
160       /* If we have seen the `-o' or '-f' option there must be exactly one
161 	 input file.  */
162       if ((output_fname != NULL || debug_fname != NULL)
163 	  && remaining + 1 < argc)
164 	error (EXIT_FAILURE, 0, gettext ("\
165 Only one input file allowed together with '-o' and '-f'"));
166 
167       /* Process all the remaining files.  */
168       do
169 	result |= process_file (argv[remaining]);
170       while (++remaining < argc);
171     }
172 
173   return result;
174 }
175 
176 
177 /* Print the version information.  */
178 static void
print_version(FILE * stream,struct argp_state * state)179 print_version (FILE *stream, struct argp_state *state)
180 {
181   fprintf (stream, "strip (%s) %s\n", PACKAGE_NAME, VERSION);
182   fprintf (stream, gettext ("\
183 Copyright (C) %s Red Hat, Inc.\n\
184 This is free software; see the source for copying conditions.  There is NO\n\
185 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
186 "), "2004");
187   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
188 }
189 
190 
191 /* Handle program arguments.  */
192 static error_t
parse_opt(int key,char * arg,struct argp_state * state)193 parse_opt (int key, char *arg, struct argp_state *state)
194 {
195   switch (key)
196     {
197     case 'f':
198       debug_fname = arg;
199       break;
200 
201     case 'o':
202       output_fname = arg;
203       break;
204 
205     case 'p':
206       preserve_dates = true;
207       break;
208 
209     case OPT_REMOVE_COMMENT:
210       remove_comment = true;
211       break;
212 
213     case 'g':
214       remove_debug = true;
215       break;
216 
217     case OPT_PERMISSIVE:
218       permissive = true;
219       break;
220 
221     default:
222       return ARGP_ERR_UNKNOWN;
223     }
224   return 0;
225 }
226 
227 
228 static char *
more_help(int key,const char * text,void * input)229 more_help (int key, const char *text, void *input)
230 {
231   char *buf;
232 
233   switch (key)
234     {
235     case ARGP_KEY_HELP_EXTRA:
236       /* We print some extra information.  */
237       if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
238 		    PACKAGE_BUGREPORT) < 0)
239 	buf = NULL;
240       return buf;
241 
242     default:
243       break;
244     }
245   return (char *) text;
246 }
247 
248 
249 static int
process_file(const char * fname)250 process_file (const char *fname)
251 {
252   /* If we have to preserve the modify and access timestamps get them
253      now.  We cannot use fstat() after opening the file since the open
254      would change the access time.  */
255   struct stat64 pre_st;
256   struct timeval tv[2];
257  again:
258   if (preserve_dates)
259     {
260       if (stat64 (fname, &pre_st) != 0)
261 	{
262 	  error (0, errno, gettext ("cannot stat input file \"%s\""), fname);
263 	  return 1;
264 	}
265 
266       /* If we have to preserve the timestamp, we need it in the
267 	 format utimes() understands.  */
268       TIMESPEC_TO_TIMEVAL (&tv[0], &pre_st.st_atim);
269       TIMESPEC_TO_TIMEVAL (&tv[1], &pre_st.st_mtim);
270     }
271 
272   /* Open the file.  */
273   int fd = open (fname, O_RDWR);
274   if (fd == -1)
275     {
276       error (0, errno, gettext ("while opening \"%s\""), fname);
277       return 1;
278     }
279 
280   /* We always use fstat() even if we called stat() before.  This is
281      done to make sure the information returned by stat() is for the
282      same file.  */
283   struct stat64 st;
284   if (fstat64 (fd, &st) != 0)
285     {
286       error (0, errno, gettext ("cannot stat input file \"%s\""), fname);
287       return 1;
288     }
289   /* Paranoid mode on.  */
290   if (preserve_dates
291       && (st.st_ino != pre_st.st_ino || st.st_dev != pre_st.st_dev))
292     {
293       /* We detected a race.  Try again.  */
294       close (fd);
295       goto again;
296     }
297 
298   /* Now get the ELF descriptor.  */
299   Elf *elf = elf_begin (fd, ELF_C_RDWR, NULL);
300   int result;
301   switch (elf_kind (elf))
302     {
303     case ELF_K_ELF:
304       result = handle_elf (fd, elf, NULL, fname, st.st_mode & ACCESSPERMS,
305 			   preserve_dates ? tv : NULL);
306       break;
307 
308     case ELF_K_AR:
309       /* It is not possible to strip the content of an archive direct
310 	 the output to a specific file.  */
311       if (unlikely (output_fname != NULL))
312 	{
313 	  error (0, 0, gettext ("%s: cannot use -o when stripping archive"),
314 		 fname);
315 	  result = 1;
316 	}
317       else
318 	result = handle_ar (fd, elf, NULL, fname, preserve_dates ? tv : NULL);
319       break;
320 
321     default:
322       error (0, 0, gettext ("%s: File format not recognized"), fname);
323       result = 1;
324       break;
325     }
326 
327   if (unlikely (elf_end (elf) != 0))
328     INTERNAL_ERROR (fname);
329 
330   close (fd);
331 
332   return result;
333 }
334 
335 
336 /* Maximum size of array allocated on stack.  */
337 #define MAX_STACK_ALLOC	(400 * 1024)
338 
339 
340 static uint32_t
crc32_file(int fd,uint32_t * resp)341 crc32_file (int fd, uint32_t *resp)
342 {
343   unsigned char buffer[1024 * 8];
344   uint32_t crc = 0;
345   ssize_t count;
346 
347   /* We have to rewind.  */
348   if (lseek (fd, 0, SEEK_SET) < 0)
349     return 1;
350 
351   while ((count = TEMP_FAILURE_RETRY (read (fd, buffer, sizeof (buffer)))) > 0)
352     crc = crc32 (crc, buffer, count);
353 
354   *resp = crc;
355 
356   return count != 0;
357 }
358 
359 
360 static int
handle_elf(int fd,Elf * elf,const char * prefix,const char * fname,mode_t mode,struct timeval tvp[2])361 handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
362 	    mode_t mode, struct timeval tvp[2])
363 {
364   size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
365   size_t fname_len = strlen (fname) + 1;
366   char *fullname = alloca (prefix_len + 1 + fname_len);
367   char *cp = fullname;
368   Elf *newelf;
369   Elf *debugelf = NULL;
370   char *tmp_debug_fname = NULL;
371   int result = 0;
372   GElf_Ehdr ehdr_mem;
373   GElf_Ehdr *ehdr;
374   size_t shstrndx;
375   size_t shnum;
376   struct shdr_info
377   {
378     Elf_Scn *scn;
379     GElf_Shdr shdr;
380     Elf_Data *data;
381     const char *name;
382     Elf32_Word idx;		/* Index in new file.  */
383     Elf32_Word old_sh_link;	/* Original value of shdr.sh_link.  */
384     Elf32_Word symtab_idx;
385     Elf32_Word version_idx;
386     Elf32_Word group_idx;
387     Elf32_Word group_cnt;
388     Elf_Scn *newscn;
389     struct Ebl_Strent *se;
390     Elf32_Word *newsymidx;
391   } *shdr_info = NULL;
392   Elf_Scn *scn;
393   size_t cnt;
394   size_t idx;
395   bool changes;
396   GElf_Ehdr newehdr_mem;
397   GElf_Ehdr *newehdr;
398   GElf_Ehdr debugehdr_mem;
399   GElf_Ehdr *debugehdr;
400   struct Ebl_Strtab *shst = NULL;
401   uint32_t debug_crc;
402   bool any_symtab_changes = false;
403   Elf_Data *shstrtab_data = NULL;
404 
405   /* Create the full name of the file.  */
406   if (prefix != NULL)
407     {
408       cp = mempcpy (cp, prefix, prefix_len);
409       *cp++ = ':';
410     }
411   memcpy (cp, fname, fname_len);
412 
413   /* If we are not replacing the input file open a new file here.  */
414   if (output_fname != NULL)
415     {
416       fd = open (output_fname, O_RDWR | O_CREAT, mode);
417       if (unlikely (fd == -1))
418 	{
419 	  error (0, errno, gettext ("cannot open `%s'"), output_fname);
420 	  return 1;
421 	}
422     }
423 
424   int debug_fd = -1;
425 
426   /* Get the EBL handling.  The -g option is currently the only reason
427      we need EBL so dont open the backend unless necessary.  */
428   Ebl *ebl = NULL;
429   if (remove_debug)
430     {
431       ebl = ebl_openbackend (elf);
432       if (ebl == NULL)
433 	{
434 	  error (0, errno, gettext ("cannot open EBL backend"));
435 	  result = 1;
436 	  goto fail;
437 	}
438     }
439 
440   /* Open the additional file the debug information will be stored in.  */
441   if (debug_fname != NULL)
442     {
443       /* Create a temporary file name.  We do not want to overwrite
444 	 the debug file if the file would not contain any
445 	 information.  */
446       size_t debug_fname_len = strlen (debug_fname);
447       tmp_debug_fname = (char *) alloca (debug_fname_len + sizeof (".XXXXXX"));
448       strcpy (mempcpy (tmp_debug_fname, debug_fname, debug_fname_len),
449 	      ".XXXXXX");
450 
451       debug_fd = mkstemp (tmp_debug_fname);
452       if (unlikely (debug_fd == -1))
453 	{
454 	  error (0, errno, gettext ("cannot open `%s'"), debug_fname);
455 	  result = 1;
456 	  goto fail;
457 	}
458     }
459 
460   /* Get the information from the old file.  */
461   ehdr = gelf_getehdr (elf, &ehdr_mem);
462   if (ehdr == NULL)
463     INTERNAL_ERROR (fname);
464 
465   /* Get the section header string table index.  */
466   if (unlikely (elf_getshstrndx (elf, &shstrndx) < 0))
467     error (EXIT_FAILURE, 0,
468 	   gettext ("cannot get section header string table index"));
469 
470   /* We now create a new ELF descriptor for the same file.  We
471      construct it almost exactly in the same way with some information
472      dropped.  */
473   if (output_fname != NULL)
474     newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
475   else
476     newelf = elf_clone (elf, ELF_C_EMPTY);
477 
478   if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0)
479       || (ehdr->e_type != ET_REL
480 	  && unlikely (gelf_newphdr (newelf, ehdr->e_phnum) == 0)))
481     {
482       error (0, 0, gettext ("cannot create new file `%s': %s"),
483 	     output_fname, elf_errmsg (-1));
484       goto fail;
485     }
486 
487   /* Copy over the old program header if needed.  */
488   if (ehdr->e_type != ET_REL)
489     for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
490       {
491 	GElf_Phdr phdr_mem;
492 	GElf_Phdr *phdr;
493 
494 	phdr = gelf_getphdr (elf, cnt, &phdr_mem);
495 	if (phdr == NULL
496 	    || unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
497 	  INTERNAL_ERROR (fname);
498       }
499 
500   if (debug_fname != NULL)
501     {
502       /* Also create an ELF descriptor for the debug file */
503       debugelf = elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL);
504       if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0)
505 	  || (ehdr->e_type != ET_REL
506 	      && unlikely (gelf_newphdr (debugelf, ehdr->e_phnum) == 0)))
507 	{
508 	  error (0, 0, gettext ("cannot create new file `%s': %s"),
509 		 debug_fname, elf_errmsg (-1));
510 	  goto fail_close;
511 	}
512 
513       /* Copy over the old program header if needed.  */
514       if (ehdr->e_type != ET_REL)
515 	for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
516 	  {
517 	    GElf_Phdr phdr_mem;
518 	    GElf_Phdr *phdr;
519 
520 	    phdr = gelf_getphdr (elf, cnt, &phdr_mem);
521 	    if (phdr == NULL
522 		|| unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
523 	      INTERNAL_ERROR (fname);
524 	  }
525     }
526 
527   /* Number of sections.  */
528   if (unlikely (elf_getshnum (elf, &shnum) < 0))
529     {
530       error (0, 0, gettext ("cannot determine number of sections: %s"),
531 	     elf_errmsg (-1));
532       goto fail_close;
533     }
534 
535   /* Storage for section information.  We leave room for two more
536      entries since we unconditionally create a section header string
537      table.  Maybe some weird tool created an ELF file without one.
538      The other one is used for the debug link section.  */
539   if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
540     shdr_info = (struct shdr_info *) xcalloc (shnum + 2,
541 					      sizeof (struct shdr_info));
542   else
543     {
544       shdr_info = (struct shdr_info *) alloca ((shnum + 2)
545 					       * sizeof (struct shdr_info));
546       memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
547     }
548 
549   /* Prepare section information data structure.  */
550   scn = NULL;
551   cnt = 1;
552   while ((scn = elf_nextscn (elf, scn)) != NULL)
553     {
554       /* This should always be true (i.e., there should not be any
555 	 holes in the numbering).  */
556       assert (elf_ndxscn (scn) == cnt);
557 
558       shdr_info[cnt].scn = scn;
559 
560       /* Get the header.  */
561       if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL)
562 	INTERNAL_ERROR (fname);
563 
564       /* Get the name of the section.  */
565       shdr_info[cnt].name = elf_strptr (elf, shstrndx,
566 					shdr_info[cnt].shdr.sh_name);
567       if (shdr_info[cnt].name == NULL)
568 	{
569 	  error (0, 0, gettext ("illformed file `%s'"), fname);
570 	  goto fail_close;
571 	}
572 
573       /* Mark them as present but not yet investigated.  */
574       shdr_info[cnt].idx = 1;
575 
576       /* Remember the shdr.sh_link value.  */
577       shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link;
578 
579       /* Sections in files other than relocatable object files which
580 	 are not loaded can be freely moved by us.  In relocatable
581 	 object files everything can be moved.  */
582       if (ehdr->e_type == ET_REL
583 	  || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
584 	shdr_info[cnt].shdr.sh_offset = 0;
585 
586       /* If this is an extended section index table store an
587 	 appropriate reference.  */
588       if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
589 	{
590 	  assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
591 	  shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
592 	}
593       else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
594 	{
595 	  Elf32_Word *grpref;
596 	  size_t inner;
597 
598 	  /* Cross-reference the sections contained in the section
599 	     group.  */
600 	  shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
601 	  if (shdr_info[cnt].data == NULL)
602 	    INTERNAL_ERROR (fname);
603 
604 	  /* XXX Fix for unaligned access.  */
605 	  grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
606 	  for (inner = 1;
607 	       inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
608 	       ++inner)
609 	    shdr_info[grpref[inner]].group_idx = cnt;
610 
611 	  if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
612 	    /* If the section group contains only one element and this
613 	       is n COMDAT section we can drop it right away.  */
614 	    shdr_info[cnt].idx = 0;
615 	  else
616 	    shdr_info[cnt].group_cnt = inner - 1;
617 	}
618       else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
619 	{
620 	  assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
621 	  shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
622 	}
623 
624       /* If this section is part of a group make sure it is not
625 	 discarded right away.  */
626       if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
627 	{
628 	  assert (shdr_info[cnt].group_idx != 0);
629 
630 	  if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
631 	    {
632 	      /* The section group section will be removed.  */
633 	      shdr_info[cnt].group_idx = 0;
634 	      shdr_info[cnt].shdr.sh_flags &= ~SHF_GROUP;
635 	    }
636 	}
637 
638       /* Increment the counter.  */
639       ++cnt;
640     }
641 
642   /* Now determine which sections can go away.  The general rule is that
643      all sections which are not used at runtime are stripped out.  But
644      there are a few exceptions:
645 
646      - special sections named ".comment" and ".note" are kept
647      - OS or architecture specific sections are kept since we might not
648        know how to handle them
649      - if a section is referred to from a section which is not removed
650        in the sh_link or sh_info element it cannot be removed either
651   */
652   for (cnt = 1; cnt < shnum; ++cnt)
653     /* Check whether the section can be removed.  */
654     if (SECTION_STRIP_P (ebl, elf, ehdr, &shdr_info[cnt].shdr,
655 			 shdr_info[cnt].name, remove_comment, remove_debug))
656       {
657 	/* For now assume this section will be removed.  */
658 	shdr_info[cnt].idx = 0;
659 
660 	idx = shdr_info[cnt].group_idx;
661 	while (idx != 0)
662 	  {
663 	    /* If the references section group is a normal section
664 	       group and has one element remaining, or if it is an
665 	       empty COMDAT section group it is removed.  */
666 	    bool is_comdat;
667 
668 	    /* The section group data is already loaded.  */
669 	    assert (shdr_info[idx].data != NULL);
670 
671 	    is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
672 			 & GRP_COMDAT) != 0;
673 
674 	    --shdr_info[idx].group_cnt;
675 	    if ((!is_comdat && shdr_info[idx].group_cnt == 1)
676 		|| (is_comdat && shdr_info[idx].group_cnt == 0))
677 	      {
678 		shdr_info[idx].idx = 0;
679 		/* Continue recursively.  */
680 		idx = shdr_info[idx].group_idx;
681 	      }
682 	    else
683 	      break;
684 	  }
685       }
686 
687   /* Mark the SHT_NULL section as handled.  */
688   shdr_info[0].idx = 2;
689 
690 
691   /* Handle exceptions: section groups and cross-references.  We might
692      have to repeat this a few times since the resetting of the flag
693      might propagate.  */
694   do
695     {
696       changes = false;
697 
698       for (cnt = 1; cnt < shnum; ++cnt)
699 	{
700 	  if (shdr_info[cnt].idx == 0)
701 	    {
702 	      /* If a relocation section is marked as being removed make
703 		 sure the section it is relocating is removed, too.  */
704 	      if ((shdr_info[cnt].shdr.sh_type == SHT_REL
705 		   || shdr_info[cnt].shdr.sh_type == SHT_RELA)
706 		  && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
707 		shdr_info[cnt].idx = 1;
708 	    }
709 
710 	  if (shdr_info[cnt].idx == 1)
711 	    {
712 	      /* The content of symbol tables we don't remove must not
713 		 reference any section which we do remove.  Otherwise
714 		 we cannot remove the section.  */
715 	      if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
716 		  || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
717 		{
718 		  Elf_Data *symdata;
719 		  Elf_Data *xndxdata;
720 		  size_t elsize;
721 
722 		  /* Make sure the data is loaded.  */
723 		  if (shdr_info[cnt].data == NULL)
724 		    {
725 		      shdr_info[cnt].data
726 			= elf_getdata (shdr_info[cnt].scn, NULL);
727 		      if (shdr_info[cnt].data == NULL)
728 			INTERNAL_ERROR (fname);
729 		    }
730 		  symdata = shdr_info[cnt].data;
731 
732 		  /* If there is an extended section index table load it
733 		     as well.  */
734 		  if (shdr_info[cnt].symtab_idx != 0
735 		      && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
736 		    {
737 		      assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
738 
739 		      shdr_info[shdr_info[cnt].symtab_idx].data
740 			= elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
741 				       NULL);
742 		      if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
743 			INTERNAL_ERROR (fname);
744 		    }
745 		  xndxdata = shdr_info[shdr_info[cnt].symtab_idx].data;
746 
747 		  /* Go through all symbols and make sure the section they
748 		     reference is not removed.  */
749 		  elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
750 
751 		  for (size_t inner = 0;
752 		       inner < shdr_info[cnt].data->d_size / elsize;
753 		       ++inner)
754 		    {
755 		      GElf_Sym sym_mem;
756 		      Elf32_Word xndx;
757 		      GElf_Sym *sym;
758 		      size_t scnidx;
759 
760 		      sym = gelf_getsymshndx (symdata, xndxdata, inner,
761 					      &sym_mem, &xndx);
762 		      if (sym == NULL)
763 			INTERNAL_ERROR (fname);
764 
765 		      scnidx = sym->st_shndx;
766 		      if (scnidx == SHN_UNDEF || scnidx >= shnum
767 			  || (scnidx >= SHN_LORESERVE
768 			      && scnidx <= SHN_HIRESERVE
769 			      && scnidx != SHN_XINDEX)
770 			  /* Don't count in the section symbols.  */
771 			  || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
772 			/* This is no section index, leave it alone.  */
773 			continue;
774 		      else if (scnidx == SHN_XINDEX)
775 			scnidx = xndx;
776 
777 		      if (shdr_info[scnidx].idx == 0)
778 			{
779 			  /* Mark this section as used.  */
780 			  shdr_info[scnidx].idx = 1;
781 			  changes |= scnidx < cnt;
782 			}
783 		    }
784 		}
785 
786 	      /* Cross referencing happens:
787 		 - for the cases the ELF specification says.  That are
788 		 + SHT_DYNAMIC in sh_link to string table
789 		 + SHT_HASH in sh_link to symbol table
790 		 + SHT_REL and SHT_RELA in sh_link to symbol table
791 		 + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
792 		 + SHT_GROUP in sh_link to symbol table
793 		 + SHT_SYMTAB_SHNDX in sh_link to symbol table
794 		 Other (OS or architecture-specific) sections might as
795 		 well use this field so we process it unconditionally.
796 		 - references inside section groups
797 		 - specially marked references in sh_info if the SHF_INFO_LINK
798 		 flag is set
799 	      */
800 
801 	      if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
802 		{
803 		  shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
804 		  changes |= shdr_info[cnt].shdr.sh_link < cnt;
805 		}
806 
807 	      /* Handle references through sh_info.  */
808 	      if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)
809 		  && shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
810 		{
811 		  shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
812 		  changes |= shdr_info[cnt].shdr.sh_info < cnt;
813 		}
814 
815 	      /* Mark the section as investigated.  */
816 	      shdr_info[cnt].idx = 2;
817 	    }
818 	}
819     }
820   while (changes);
821 
822   /* Write out a copy of all the sections to the debug output file.
823      The ones that are not removed in the stripped file are SHT_NOBITS */
824   if (debug_fname != NULL)
825     {
826       for (cnt = 1; cnt < shnum; ++cnt)
827 	{
828 	  Elf_Data *debugdata;
829 	  GElf_Shdr debugshdr;
830 	  int discard_section;
831 
832 	  scn = elf_newscn (debugelf);
833 	  if (scn == NULL)
834 	    error (EXIT_FAILURE, 0,
835 		   gettext ("while generating output file: %s"),
836 		   elf_errmsg (-1));
837 
838 	  discard_section = shdr_info[cnt].idx > 0 && cnt != ehdr->e_shstrndx;
839 
840 	  /* Set the section header in the new file.  */
841 	  debugshdr = shdr_info[cnt].shdr;
842 	  if (discard_section)
843 	    debugshdr.sh_type = SHT_NOBITS;
844 
845 	  if (unlikely (gelf_update_shdr (scn, &debugshdr)) == 0)
846 	    /* There cannot be any overflows.  */
847 	    INTERNAL_ERROR (fname);
848 
849 	  /* Get the data from the old file if necessary. */
850 	  if (shdr_info[cnt].data == NULL)
851 	    {
852 	      shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
853 	      if (shdr_info[cnt].data == NULL)
854 		INTERNAL_ERROR (fname);
855 	    }
856 
857 	  /* Set the data.  This is done by copying from the old file.  */
858 	  debugdata = elf_newdata (scn);
859 	  if (debugdata == NULL)
860 	    INTERNAL_ERROR (fname);
861 
862 	  /* Copy the structure.  */
863 	  *debugdata = *shdr_info[cnt].data;
864 	  if (discard_section)
865 	    debugdata->d_buf = NULL;
866 	}
867 
868       /* Finish the ELF header.  Fill in the fields not handled by
869 	 libelf from the old file.  */
870       debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
871       if (debugehdr == NULL)
872 	INTERNAL_ERROR (fname);
873 
874       memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
875       debugehdr->e_type = ehdr->e_type;
876       debugehdr->e_machine = ehdr->e_machine;
877       debugehdr->e_version = ehdr->e_version;
878       debugehdr->e_entry = ehdr->e_entry;
879       debugehdr->e_flags = ehdr->e_flags;
880       debugehdr->e_shstrndx = ehdr->e_shstrndx;
881 
882       if (unlikely (gelf_update_ehdr (debugelf, debugehdr)) == 0)
883 	{
884 	  error (0, 0, gettext ("%s: error while creating ELF header: %s"),
885 		 debug_fname, elf_errmsg (-1));
886 	  result = 1;
887 	  goto fail_close;
888 	}
889 
890       /* Finally write the file.  */
891       if (unlikely (elf_update (debugelf, ELF_C_WRITE)) == -1)
892 	{
893 	  error (0, 0, gettext ("while writing `%s': %s"),
894 		 debug_fname, elf_errmsg (-1));
895 	  result = 1;
896 	  goto fail_close;
897 	}
898 
899       /* Create the real output file.  First rename, then change the
900 	 mode.  */
901       if (rename (tmp_debug_fname, debug_fname) != 0
902 	  || fchmod (debug_fd, mode) != 0)
903 	{
904 	  error (0, errno, gettext ("while creating '%s'"), debug_fname);
905 	  result = 1;
906 	  goto fail_close;
907 	}
908 
909       /* The temporary file does not exist anymore.  */
910       tmp_debug_fname = NULL;
911 
912       /* Compute the checksum which we will add to the executable.  */
913       if (crc32_file (debug_fd, &debug_crc) != 0)
914 	{
915 	  error (0, errno,
916 		 gettext ("while computing checksum for debug information"));
917 	  unlink (debug_fname);
918 	  result = 1;
919 	  goto fail_close;
920 	}
921 
922     }
923 
924   /* Mark the section header string table as unused, we will create
925      a new one.  */
926   shdr_info[shstrndx].idx = 0;
927 
928   /* We need a string table for the section headers.  */
929   shst = ebl_strtabinit (true);
930   if (shst == NULL)
931     error (EXIT_FAILURE, errno, gettext ("while preparing output for `%s'"),
932 	   output_fname ?: fname);
933 
934   /* Assign new section numbers.  */
935   shdr_info[0].idx = 0;
936   for (cnt = idx = 1; cnt < shnum; ++cnt)
937     if (shdr_info[cnt].idx > 0)
938       {
939 	shdr_info[cnt].idx = idx++;
940 
941 	/* Create a new section.  */
942 	shdr_info[cnt].newscn = elf_newscn (newelf);
943 	if (shdr_info[cnt].newscn == NULL)
944 	  error (EXIT_FAILURE, 0, gettext ("while generating output file: %s"),
945 		 elf_errmsg (-1));
946 
947 	assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
948 
949 	/* Add this name to the section header string table.  */
950 	shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);
951       }
952 
953   /* Test whether we are doing anything at all.  */
954   if (cnt == idx)
955     /* Nope, all removable sections are already gone.  */
956     goto fail_close;
957 
958   /* Create the reference to the file with the debug info.  */
959   if (debug_fname != NULL)
960     {
961       char *debug_basename;
962       off_t crc_offset;
963 
964       /* Add the section header string table section name.  */
965       shdr_info[cnt].se = ebl_strtabadd (shst, ".gnu_debuglink", 15);
966       shdr_info[cnt].idx = idx++;
967 
968       /* Create the section header.  */
969       shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
970       shdr_info[cnt].shdr.sh_flags = 0;
971       shdr_info[cnt].shdr.sh_addr = 0;
972       shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
973       shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
974       shdr_info[cnt].shdr.sh_entsize = 0;
975       shdr_info[cnt].shdr.sh_addralign = 4;
976       /* We set the offset to zero here.  Before we write the ELF file the
977 	 field must have the correct value.  This is done in the final
978 	 loop over all section.  Then we have all the information needed.  */
979       shdr_info[cnt].shdr.sh_offset = 0;
980 
981       /* Create the section.  */
982       shdr_info[cnt].newscn = elf_newscn (newelf);
983       if (shdr_info[cnt].newscn == NULL)
984 	error (EXIT_FAILURE, 0,
985 	       gettext ("while create section header section: %s"),
986 	       elf_errmsg (-1));
987       assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
988 
989       shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
990       if (shdr_info[cnt].data == NULL)
991 	error (EXIT_FAILURE, 0, gettext ("cannot allocate section data: %s"),
992 	       elf_errmsg (-1));
993 
994       debug_basename = basename (debug_fname);
995       crc_offset = strlen (debug_basename) + 1;
996       /* Align to 4 byte boundary */
997       crc_offset = ((crc_offset - 1) & ~3) + 4;
998 
999       shdr_info[cnt].data->d_align = 4;
1000       shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
1001 	= crc_offset + 4;
1002       shdr_info[cnt].data->d_buf = xcalloc (1, shdr_info[cnt].data->d_size);
1003 
1004       strcpy (shdr_info[cnt].data->d_buf, debug_basename);
1005       /* Store the crc value in the correct byteorder */
1006       if ((__BYTE_ORDER == __LITTLE_ENDIAN
1007 	   && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
1008 	  || (__BYTE_ORDER == __BIG_ENDIAN
1009 	      && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
1010 	debug_crc = bswap_32 (debug_crc);
1011       memcpy ((char *)shdr_info[cnt].data->d_buf + crc_offset,
1012 	      (char *) &debug_crc, 4);
1013 
1014       /* One more section done.  */
1015       ++cnt;
1016     }
1017 
1018   /* Index of the section header table in the shdr_info array.  */
1019   size_t shdridx = cnt;
1020 
1021   /* Add the section header string table section name.  */
1022   shdr_info[cnt].se = ebl_strtabadd (shst, ".shstrtab", 10);
1023   shdr_info[cnt].idx = idx;
1024 
1025   /* Create the section header.  */
1026   shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
1027   shdr_info[cnt].shdr.sh_flags = 0;
1028   shdr_info[cnt].shdr.sh_addr = 0;
1029   shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1030   shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1031   shdr_info[cnt].shdr.sh_entsize = 0;
1032   /* We set the offset to zero here.  Before we write the ELF file the
1033      field must have the correct value.  This is done in the final
1034      loop over all section.  Then we have all the information needed.  */
1035   shdr_info[cnt].shdr.sh_offset = 0;
1036   shdr_info[cnt].shdr.sh_addralign = 1;
1037 
1038   /* Create the section.  */
1039   shdr_info[cnt].newscn = elf_newscn (newelf);
1040   if (shdr_info[cnt].newscn == NULL)
1041     error (EXIT_FAILURE, 0,
1042 	   gettext ("while create section header section: %s"),
1043 	   elf_errmsg (-1));
1044   assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
1045 
1046   /* Finalize the string table and fill in the correct indices in the
1047      section headers.  */
1048   shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
1049   if (shstrtab_data == NULL)
1050     error (EXIT_FAILURE, 0,
1051 	   gettext ("while create section header string table: %s"),
1052 	   elf_errmsg (-1));
1053   ebl_strtabfinalize (shst, shstrtab_data);
1054 
1055   /* We have to set the section size.  */
1056   shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
1057 
1058   /* Update the section information.  */
1059   GElf_Off lastoffset = 0;
1060   for (cnt = 1; cnt <= shdridx; ++cnt)
1061     if (shdr_info[cnt].idx > 0)
1062       {
1063 	Elf_Data *newdata;
1064 
1065 	scn = elf_getscn (newelf, shdr_info[cnt].idx);
1066 	assert (scn != NULL);
1067 
1068 	/* Update the name.  */
1069 	shdr_info[cnt].shdr.sh_name = ebl_strtaboffset (shdr_info[cnt].se);
1070 
1071 	/* Update the section header from the input file.  Some fields
1072 	   might be section indeces which now have to be adjusted.  */
1073 	if (shdr_info[cnt].shdr.sh_link != 0)
1074 	  shdr_info[cnt].shdr.sh_link =
1075 	    shdr_info[shdr_info[cnt].shdr.sh_link].idx;
1076 
1077 	if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1078 	  {
1079 	    assert (shdr_info[cnt].data != NULL);
1080 
1081 	    Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1082 	    for (size_t inner = 0;
1083 		 inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1084 		 ++inner)
1085 	      grpref[inner] = shdr_info[grpref[inner]].idx;
1086 	  }
1087 
1088 	/* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag.  */
1089 	if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1090 	  shdr_info[cnt].shdr.sh_info =
1091 	    shdr_info[shdr_info[cnt].shdr.sh_info].idx;
1092 
1093 	/* Get the data from the old file if necessary.  We already
1094            created the data for the section header string table.  */
1095 	if (cnt < shnum)
1096 	  {
1097 	    if (shdr_info[cnt].data == NULL)
1098 	      {
1099 		shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1100 		if (shdr_info[cnt].data == NULL)
1101 		  INTERNAL_ERROR (fname);
1102 	      }
1103 
1104 	    /* Set the data.  This is done by copying from the old file.  */
1105 	    newdata = elf_newdata (scn);
1106 	    if (newdata == NULL)
1107 	      INTERNAL_ERROR (fname);
1108 
1109 	    /* Copy the structure.  */
1110 	    *newdata = *shdr_info[cnt].data;
1111 
1112 	    /* We know the size.  */
1113 	    shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
1114 
1115 	    /* We have to adjust symtol tables.  The st_shndx member might
1116 	       have to be updated.  */
1117 	    if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
1118 		|| shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
1119 	      {
1120 		Elf_Data *versiondata = NULL;
1121 		Elf_Data *shndxdata = NULL;
1122 
1123 		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1124 					    ehdr->e_version);
1125 
1126 		if (shdr_info[cnt].symtab_idx != 0)
1127 		  {
1128 		    assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
1129 		    /* This section has extended section information.
1130 		       We have to modify that information, too.  */
1131 		    shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
1132 					     NULL);
1133 
1134 		    assert ((versiondata->d_size / sizeof (Elf32_Word))
1135 			    >= shdr_info[cnt].data->d_size / elsize);
1136 		  }
1137 
1138 		if (shdr_info[cnt].version_idx != 0)
1139 		  {
1140 		    assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
1141 		    /* This section has associated version
1142 		       information.  We have to modify that
1143 		       information, too.  */
1144 		    versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
1145 					       NULL);
1146 
1147 		    assert ((versiondata->d_size / sizeof (GElf_Versym))
1148 			    >= shdr_info[cnt].data->d_size / elsize);
1149 		  }
1150 
1151 		shdr_info[cnt].newsymidx
1152 		  = (Elf32_Word *) xcalloc (shdr_info[cnt].data->d_size
1153 					    / elsize, sizeof (Elf32_Word));
1154 
1155 		bool last_was_local = true;
1156 		size_t destidx;
1157 		size_t inner;
1158 		for (destidx = inner = 1;
1159 		     inner < shdr_info[cnt].data->d_size / elsize;
1160 		     ++inner)
1161 		  {
1162 		    Elf32_Word sec;
1163 		    GElf_Sym sym_mem;
1164 		    Elf32_Word xshndx;
1165 		    GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
1166 						      shndxdata, inner,
1167 						      &sym_mem, &xshndx);
1168 		    if (sym == NULL)
1169 		      INTERNAL_ERROR (fname);
1170 
1171 		    if (sym->st_shndx == SHN_UNDEF
1172 			|| (sym->st_shndx >= shnum
1173 			    && sym->st_shndx != SHN_XINDEX))
1174 		      {
1175 			/* This is no section index, leave it alone
1176 			   unless it is moved.  */
1177 			if (destidx != inner
1178 			    && gelf_update_symshndx (shdr_info[cnt].data,
1179 						     shndxdata,
1180 						     destidx, sym,
1181 						     xshndx) == 0)
1182 			  INTERNAL_ERROR (fname);
1183 
1184 			shdr_info[cnt].newsymidx[inner] = destidx++;
1185 
1186 			if (last_was_local
1187 			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1188 			  {
1189 			    last_was_local = false;
1190 			    shdr_info[cnt].shdr.sh_info = destidx - 1;
1191 			  }
1192 
1193 			continue;
1194 		      }
1195 
1196 		    /* Get the full section index, if necessary from the
1197 		       XINDEX table.  */
1198 		    if (sym->st_shndx != SHN_XINDEX)
1199 		      sec = shdr_info[sym->st_shndx].idx;
1200 		    else
1201 		      {
1202 			assert (shndxdata != NULL);
1203 
1204 			sec = shdr_info[xshndx].idx;
1205 		      }
1206 
1207 		    if (sec != 0)
1208 		      {
1209 			GElf_Section nshndx;
1210 			Elf32_Word nxshndx;
1211 
1212 			if (sec < SHN_LORESERVE)
1213 			  {
1214 			    nshndx = sec;
1215 			    nxshndx = 0;
1216 			  }
1217 			else
1218 			  {
1219 			    nshndx = SHN_XINDEX;
1220 			    nxshndx = sec;
1221 			  }
1222 
1223 			assert (sec < SHN_LORESERVE || shndxdata != NULL);
1224 
1225 			if ((inner != destidx || nshndx != sym->st_shndx
1226 			     || (shndxdata != NULL && nxshndx != xshndx))
1227 			    && (sym->st_shndx = nshndx,
1228 				gelf_update_symshndx (shdr_info[cnt].data,
1229 						      shndxdata,
1230 						      destidx, sym,
1231 						      nxshndx) == 0))
1232 			  INTERNAL_ERROR (fname);
1233 
1234 			shdr_info[cnt].newsymidx[inner] = destidx++;
1235 
1236 			if (last_was_local
1237 			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1238 			  {
1239 			    last_was_local = false;
1240 			    shdr_info[cnt].shdr.sh_info = destidx - 1;
1241 			  }
1242 		      }
1243 		    else
1244 		      /* This is a section symbol for a section which has
1245 			 been removed.  */
1246 		      assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION);
1247 		  }
1248 
1249 		if (destidx != inner)
1250 		  {
1251 		    /* The size of the symbol table changed.  */
1252 		    shdr_info[cnt].shdr.sh_size = newdata->d_size
1253 		      = destidx * elsize;
1254 		    any_symtab_changes = true;
1255 		  }
1256 		else
1257 		  {
1258 		    /* The symbol table didn't really change.  */
1259 		    free (shdr_info[cnt].newsymidx);
1260 		    shdr_info[cnt].newsymidx = NULL;
1261 		  }
1262 	      }
1263 	  }
1264 
1265 	/* If we have to, compute the offset of the section.  */
1266 	if (shdr_info[cnt].shdr.sh_offset == 0)
1267 	  shdr_info[cnt].shdr.sh_offset
1268 	    = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
1269 	       & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
1270 
1271 	/* Set the section header in the new file.  */
1272 	if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
1273 	  /* There cannot be any overflows.  */
1274 	  INTERNAL_ERROR (fname);
1275 
1276 	/* Remember the last section written so far.  */
1277 	GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
1278 			   ? shdr_info[cnt].shdr.sh_size : 0);
1279 	if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
1280 	  lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
1281       }
1282 
1283   /* Adjust symbol references if symbol tables changed.  */
1284   if (any_symtab_changes)
1285     {
1286       /* Find all relocation sections which use this
1287 	 symbol table.  */
1288       for (cnt = 1; cnt <= shdridx; ++cnt)
1289 	{
1290 	  if (shdr_info[cnt].idx == 0)
1291 	    /* Ignore sections which are discarded.  */
1292 	    continue;
1293 
1294 	  if (shdr_info[cnt].shdr.sh_type == SHT_REL
1295 	      || shdr_info[cnt].shdr.sh_type == SHT_RELA)
1296 	    {
1297 	      /* If the symbol table hasn't changed, do not do anything.  */
1298 	      if (shdr_info[shdr_info[cnt].old_sh_link].newsymidx == NULL)
1299 		continue;
1300 
1301 	      Elf32_Word *newsymidx
1302 		= shdr_info[shdr_info[cnt].old_sh_link].newsymidx;
1303 	      Elf_Data *d = elf_getdata (elf_getscn (newelf,
1304 						     shdr_info[cnt].idx),
1305 					 NULL);
1306 	      assert (d != NULL);
1307 	      size_t nrels = (shdr_info[cnt].shdr.sh_size
1308 			      / shdr_info[cnt].shdr.sh_entsize);
1309 
1310 	      if (shdr_info[cnt].shdr.sh_type == SHT_REL)
1311 		for (size_t relidx = 0; relidx < nrels; ++relidx)
1312 		  {
1313 		    GElf_Rel rel_mem;
1314 		    if (gelf_getrel (d, relidx, &rel_mem) == NULL)
1315 		      INTERNAL_ERROR (fname);
1316 
1317 		    size_t symidx = GELF_R_SYM (rel_mem.r_info);
1318 		    if (newsymidx[symidx] != symidx)
1319 		      {
1320 			rel_mem.r_info
1321 			  = GELF_R_INFO (newsymidx[symidx],
1322 					 GELF_R_TYPE (rel_mem.r_info));
1323 
1324 			if (gelf_update_rel (d, relidx, &rel_mem) == 0)
1325 			  INTERNAL_ERROR (fname);
1326 		      }
1327 		  }
1328 	      else
1329 		for (size_t relidx = 0; relidx < nrels; ++relidx)
1330 		  {
1331 		    GElf_Rela rel_mem;
1332 		    if (gelf_getrela (d, relidx, &rel_mem) == NULL)
1333 		      INTERNAL_ERROR (fname);
1334 
1335 		    size_t symidx = GELF_R_SYM (rel_mem.r_info);
1336 		    if (newsymidx[symidx] != symidx)
1337 		      {
1338 			rel_mem.r_info
1339 			  = GELF_R_INFO (newsymidx[symidx],
1340 					 GELF_R_TYPE (rel_mem.r_info));
1341 
1342 			if (gelf_update_rela (d, relidx, &rel_mem) == 0)
1343 			  INTERNAL_ERROR (fname);
1344 		      }
1345 		  }
1346 	    }
1347 	  else if (shdr_info[cnt].shdr.sh_type == SHT_HASH)
1348 	    {
1349 	      /* We have to recompute the hash table.  */
1350 	      Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
1351 
1352 	      /* We do not have to do anything if the symbol table was
1353 		 not changed.  */
1354 	      if (shdr_info[symtabidx].newsymidx == NULL)
1355 		continue;
1356 
1357 	      /* The symbol version section in the new file.  */
1358 	      scn = elf_getscn (newelf, shdr_info[cnt].idx);
1359 
1360 	      /* The symbol table data.  */
1361 	      Elf_Data *symd = elf_getdata (elf_getscn (newelf,
1362 							shdr_info[symtabidx].idx),
1363 					    NULL);
1364 	      assert (symd != NULL);
1365 
1366 	      /* The hash table data.  */
1367 	      Elf_Data *hashd = elf_getdata (scn, NULL);
1368 	      assert (hashd != NULL);
1369 
1370 	      if (shdr_info[cnt].shdr.sh_entsize == sizeof (Elf32_Word))
1371 		{
1372 		  /* Sane arches first.  */
1373 		  Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
1374 
1375 		  size_t strshndx = shdr_info[symtabidx].old_sh_link;
1376 		  size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1377 					      ehdr->e_version);
1378 
1379 		  /* Convert to the correct byte order.  */
1380 		  if (gelf_xlatetom (newelf, hashd, hashd,
1381 				     BYTE_ORDER == LITTLE_ENDIAN
1382 				     ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
1383 		    INTERNAL_ERROR (fname);
1384 
1385 		  /* Adjust the nchain value.  The symbol table size
1386 		     changed.  We keep the same size for the bucket array.  */
1387 		  bucket[1] = symd->d_size / elsize;
1388 		  Elf32_Word nbucket = bucket[0];
1389 		  bucket += 2;
1390 		  Elf32_Word *chain = bucket + nbucket;
1391 
1392 		  /* New size of the section.  */
1393 		  GElf_Shdr shdr_mem;
1394 		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1395 		  shdr->sh_size = hashd->d_size
1396 		    = (2 + symd->d_size / elsize + nbucket)
1397 		      * sizeof (Elf32_Word);
1398 		  (void) gelf_update_shdr (scn, shdr);
1399 
1400 		  /* Clear the arrays.  */
1401 		  memset (bucket, '\0',
1402 			  (symd->d_size / elsize + nbucket)
1403 			  * sizeof (Elf32_Word));
1404 
1405 		  for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1406 		       inner < symd->d_size / elsize; ++inner)
1407 		    {
1408 		      GElf_Sym sym_mem;
1409 		      GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
1410 		      assert (sym != NULL);
1411 
1412 		      const char *name = elf_strptr (elf, strshndx,
1413 						     sym->st_name);
1414 		      assert (name != NULL);
1415 		      size_t hidx = elf_hash (name) % nbucket;
1416 
1417 		      if (bucket[hidx] == 0)
1418 			bucket[hidx] = inner;
1419 		      else
1420 			{
1421 			  hidx = bucket[hidx];
1422 
1423 			  while (chain[hidx] != 0)
1424 			    hidx = chain[hidx];
1425 
1426 			  chain[hidx] = inner;
1427 			}
1428 		    }
1429 		}
1430 	      else
1431 		{
1432 		  /* Alpha and S390 64-bit use 64-bit SHT_HASH entries.  */
1433 		  assert (shdr_info[cnt].shdr.sh_entsize
1434 			  == sizeof (Elf64_Xword));
1435 
1436 		  Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
1437 
1438 		  size_t strshndx = shdr_info[symtabidx].old_sh_link;
1439 		  size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1440 					      ehdr->e_version);
1441 
1442 		  /* Convert to the correct byte order.  */
1443 		  if (gelf_xlatetom (newelf, hashd, hashd,
1444 				     BYTE_ORDER == LITTLE_ENDIAN
1445 				     ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
1446 		    INTERNAL_ERROR (fname);
1447 
1448 		  /* Adjust the nchain value.  The symbol table size
1449 		     changed.  We keep the same size for the bucket array.  */
1450 		  bucket[1] = symd->d_size / elsize;
1451 		  Elf64_Xword nbucket = bucket[0];
1452 		  bucket += 2;
1453 		  Elf64_Xword *chain = bucket + nbucket;
1454 
1455 		  /* New size of the section.  */
1456 		  GElf_Shdr shdr_mem;
1457 		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1458 		  shdr->sh_size = hashd->d_size
1459 		    = (2 + symd->d_size / elsize + nbucket)
1460 		      * sizeof (Elf64_Xword);
1461 		  (void) gelf_update_shdr (scn, shdr);
1462 
1463 		  /* Clear the arrays.  */
1464 		  memset (bucket, '\0',
1465 			  (symd->d_size / elsize + nbucket)
1466 			  * sizeof (Elf64_Xword));
1467 
1468 		  for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1469 		       inner < symd->d_size / elsize; ++inner)
1470 		    {
1471 		      GElf_Sym sym_mem;
1472 		      GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
1473 		      assert (sym != NULL);
1474 
1475 		      const char *name = elf_strptr (elf, strshndx,
1476 						     sym->st_name);
1477 		      assert (name != NULL);
1478 		      size_t hidx = elf_hash (name) % nbucket;
1479 
1480 		      if (bucket[hidx] == 0)
1481 			bucket[hidx] = inner;
1482 		      else
1483 			{
1484 			  hidx = bucket[hidx];
1485 
1486 			  while (chain[hidx] != 0)
1487 			    hidx = chain[hidx];
1488 
1489 			  chain[hidx] = inner;
1490 			}
1491 		    }
1492 	        }
1493 
1494 	      /* Convert back to the file byte order.  */
1495 	      if (gelf_xlatetof (newelf, hashd, hashd,
1496 				 BYTE_ORDER == LITTLE_ENDIAN
1497 				 ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
1498 		INTERNAL_ERROR (fname);
1499 	    }
1500 	  else if (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym)
1501 	    {
1502 	      /* If the symbol table changed we have to adjust the
1503 		 entries.  */
1504 	      Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
1505 
1506 	      /* We do not have to do anything if the symbol table was
1507 		 not changed.  */
1508 	      if (shdr_info[symtabidx].newsymidx == NULL)
1509 		continue;
1510 
1511 	      /* The symbol version section in the new file.  */
1512 	      scn = elf_getscn (newelf, shdr_info[cnt].idx);
1513 
1514 	      /* The symbol table data.  */
1515 	      Elf_Data *symd = elf_getdata (elf_getscn (newelf,
1516 							shdr_info[symtabidx].idx),
1517 					    NULL);
1518 	      assert (symd != NULL);
1519 
1520 	      /* The version symbol data.  */
1521 	      Elf_Data *verd = elf_getdata (scn, NULL);
1522 	      assert (verd != NULL);
1523 
1524 	      /* Convert to the correct byte order.  */
1525 	      if (gelf_xlatetom (newelf, verd, verd,
1526 				 BYTE_ORDER == LITTLE_ENDIAN
1527 				 ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
1528 		INTERNAL_ERROR (fname);
1529 
1530 	      /* The symbol version array.  */
1531 	      GElf_Half *verstab = (GElf_Half *) verd->d_buf;
1532 
1533 	      /* New indices of the symbols.  */
1534 	      Elf32_Word *newsymidx = shdr_info[symtabidx].newsymidx;
1535 
1536 	      /* Walk through the list and */
1537 	      size_t elsize = gelf_fsize (elf, verd->d_type, 1,
1538 					  ehdr->e_version);
1539 	      for (size_t inner = 1; inner < verd->d_size / elsize; ++inner)
1540 		if (newsymidx[inner] != 0)
1541 		  /* Overwriting the same array works since the
1542 		     reordering can only move entries to lower indices
1543 		     in the array.  */
1544 		  verstab[newsymidx[inner]] = verstab[inner];
1545 
1546 	      /* New size of the section.  */
1547 	      GElf_Shdr shdr_mem;
1548 	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1549 	      shdr->sh_size = verd->d_size
1550 		= gelf_fsize (newelf, verd->d_type,
1551 			      symd->d_size / gelf_fsize (elf, symd->d_type, 1,
1552 							 ehdr->e_version),
1553 			      ehdr->e_version);
1554 	      (void) gelf_update_shdr (scn, shdr);
1555 
1556 	      /* Convert back to the file byte order.  */
1557 	      if (gelf_xlatetof (newelf, verd, verd,
1558 				 BYTE_ORDER == LITTLE_ENDIAN
1559 				 ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
1560 		INTERNAL_ERROR (fname);
1561 	    }
1562 	  else if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1563 	    {
1564 	      /* Check whether the associated symbol table changed.  */
1565 	      if (shdr_info[shdr_info[cnt].old_sh_link].newsymidx != NULL)
1566 		{
1567 		  /* Yes the symbol table changed.  Update the section
1568 		     header of the section group.  */
1569 		  scn = elf_getscn (newelf, shdr_info[cnt].idx);
1570 		  GElf_Shdr shdr_mem;
1571 		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1572 		  assert (shdr != NULL);
1573 
1574 		  size_t stabidx = shdr_info[cnt].old_sh_link;
1575 		  shdr->sh_info = shdr_info[stabidx].newsymidx[shdr->sh_info];
1576 
1577 		  (void) gelf_update_shdr (scn, shdr);
1578 		}
1579 	    }
1580 	}
1581     }
1582 
1583   /* Finally finish the ELF header.  Fill in the fields not handled by
1584      libelf from the old file.  */
1585   newehdr = gelf_getehdr (newelf, &newehdr_mem);
1586   if (newehdr == NULL)
1587     INTERNAL_ERROR (fname);
1588 
1589   memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
1590   newehdr->e_type = ehdr->e_type;
1591   newehdr->e_machine = ehdr->e_machine;
1592   newehdr->e_version = ehdr->e_version;
1593   newehdr->e_entry = ehdr->e_entry;
1594   newehdr->e_flags = ehdr->e_flags;
1595   newehdr->e_phoff = ehdr->e_phoff;
1596   /* We need to position the section header table.  */
1597   const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
1598   newehdr->e_shoff = ((shdr_info[shdridx].shdr.sh_offset
1599 		       + shdr_info[shdridx].shdr.sh_size + offsize - 1)
1600 		      & ~((GElf_Off) (offsize - 1)));
1601   newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
1602 
1603   /* The new section header string table index.  */
1604   if (likely (idx < SHN_HIRESERVE) && likely (idx != SHN_XINDEX))
1605     newehdr->e_shstrndx = idx;
1606   else
1607     {
1608       /* The index does not fit in the ELF header field.  */
1609       shdr_info[0].scn = elf_getscn (elf, 0);
1610 
1611       if (gelf_getshdr (shdr_info[0].scn, &shdr_info[0].shdr) == NULL)
1612 	INTERNAL_ERROR (fname);
1613 
1614       shdr_info[0].shdr.sh_link = idx;
1615       (void) gelf_update_shdr (shdr_info[0].scn, &shdr_info[0].shdr);
1616 
1617       newehdr->e_shstrndx = SHN_XINDEX;
1618     }
1619 
1620   if (gelf_update_ehdr (newelf, newehdr) == 0)
1621     {
1622       error (0, 0, gettext ("%s: error while creating ELF header: %s"),
1623 	     fname, elf_errmsg (-1));
1624       return 1;
1625     }
1626 
1627   /* We have everything from the old file.  */
1628   if (elf_cntl (elf, ELF_C_FDDONE) != 0)
1629     {
1630       error (0, 0, gettext ("%s: error while reading the file: %s"),
1631 	     fname, elf_errmsg (-1));
1632       return 1;
1633     }
1634 
1635   /* The ELF library better follows our layout when this is not a
1636      relocatable object file.  */
1637   elf_flagelf (newelf, ELF_C_SET,
1638 	       (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0)
1639 	       | (permissive ? ELF_F_PERMISSIVE : 0));
1640 
1641   /* Finally write the file.  */
1642   if (elf_update (newelf, ELF_C_WRITE) == -1)
1643     {
1644       error (0, 0, gettext ("while writing `%s': %s"),
1645 	     fname, elf_errmsg (-1));
1646       result = 1;
1647     }
1648 
1649  fail_close:
1650   if (shdr_info != NULL)
1651     {
1652       /* For some sections we might have created an table to map symbol
1653 	 table indices.  */
1654       if (any_symtab_changes)
1655 	for (cnt = 1; cnt <= shdridx; ++cnt)
1656 	  free (shdr_info[cnt].newsymidx);
1657 
1658       /* Free the memory.  */
1659       if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
1660 	free (shdr_info);
1661     }
1662 
1663   /* Free other resources.  */
1664   if (shstrtab_data != NULL)
1665     free (shstrtab_data->d_buf);
1666   if (shst != NULL)
1667     ebl_strtabfree (shst);
1668 
1669   /* That was it.  Close the descriptors.  */
1670   if (elf_end (newelf) != 0)
1671     {
1672       error (0, 0, gettext ("error while finishing `%s': %s"), fname,
1673 	     elf_errmsg (-1));
1674       result = 1;
1675     }
1676 
1677   if (debugelf != NULL && elf_end (debugelf) != 0)
1678     {
1679       error (0, 0, gettext ("error while finishing `%s': %s"), debug_fname,
1680 	     elf_errmsg (-1));
1681       result = 1;
1682     }
1683 
1684  fail:
1685   /* Close the EBL backend.  */
1686   if (ebl != NULL)
1687     ebl_closebackend (ebl);
1688 
1689   /* Close debug file descriptor, if opened */
1690   if (debug_fd >= 0)
1691     {
1692       if (tmp_debug_fname != NULL)
1693 	unlink (tmp_debug_fname);
1694       close (debug_fd);
1695     }
1696 
1697   /* If requested, preserve the timestamp.  */
1698   if (tvp != NULL)
1699     {
1700       if (futimes (fd, tvp) != 0)
1701 	{
1702 	  error (0, errno, gettext ("\
1703 cannot set access and modification date of \"%s\""),
1704 		 output_fname ?: fname);
1705 	  result = 1;
1706 	}
1707     }
1708 
1709   /* Close the file descriptor if we created a new file.  */
1710   if (output_fname != NULL)
1711     close (fd);
1712 
1713   return result;
1714 }
1715 
1716 
1717 static int
handle_ar(int fd,Elf * elf,const char * prefix,const char * fname,struct timeval tvp[2])1718 handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
1719 	   struct timeval tvp[2])
1720 {
1721   size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
1722   size_t fname_len = strlen (fname) + 1;
1723   char new_prefix[prefix_len + 1 + fname_len];
1724   char *cp = new_prefix;
1725 
1726   /* Create the full name of the file.  */
1727   if (prefix != NULL)
1728     {
1729       cp = mempcpy (cp, prefix, prefix_len);
1730       *cp++ = ':';
1731     }
1732   memcpy (cp, fname, fname_len);
1733 
1734 
1735   /* Process all the files contained in the archive.  */
1736   Elf *subelf;
1737   Elf_Cmd cmd = ELF_C_RDWR;
1738   int result = 0;
1739   while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
1740     {
1741       /* The the header for this element.  */
1742       Elf_Arhdr *arhdr = elf_getarhdr (subelf);
1743 
1744       if (elf_kind (subelf) == ELF_K_ELF)
1745 	result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
1746       else if (elf_kind (subelf) == ELF_K_AR)
1747 	result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
1748 
1749       /* Get next archive element.  */
1750       cmd = elf_next (subelf);
1751       if (unlikely (elf_end (subelf) != 0))
1752 	INTERNAL_ERROR (fname);
1753     }
1754 
1755   if (tvp != NULL)
1756     {
1757       if (unlikely (futimes (fd, tvp) != 0))
1758 	{
1759 	  error (0, errno, gettext ("\
1760 cannot set access and modification date of \"%s\""), fname);
1761 	  result = 1;
1762 	}
1763     }
1764 
1765   if (unlikely (close (fd) != 0))
1766     error (EXIT_FAILURE, errno, gettext ("while closing `%s'"), fname);
1767 
1768   return result;
1769 }
1770