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