LCOV - code coverage report
Current view: top level - src - strip.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 659 908 72.6 %
Date: 2017-01-05 09:15:16 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Discard section not used at runtime from object files.
       2             :    Copyright (C) 2000-2012, 2014, 2015, 2016 Red Hat, Inc.
       3             :    This file is part of elfutils.
       4             :    Written by Ulrich Drepper <drepper@redhat.com>, 2000.
       5             : 
       6             :    This file is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    elfutils is distributed in the hope that it will be useful, but
      12             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      18             : 
      19             : #ifdef HAVE_CONFIG_H
      20             : # include <config.h>
      21             : #endif
      22             : 
      23             : #include <argp.h>
      24             : #include <assert.h>
      25             : #include <byteswap.h>
      26             : #include <endian.h>
      27             : #include <error.h>
      28             : #include <fcntl.h>
      29             : #include <gelf.h>
      30             : #include <libelf.h>
      31             : #include <libintl.h>
      32             : #include <locale.h>
      33             : #include <stdbool.h>
      34             : #include <stdio.h>
      35             : #include <stdio_ext.h>
      36             : #include <stdlib.h>
      37             : #include <string.h>
      38             : #include <unistd.h>
      39             : #include <sys/stat.h>
      40             : #include <sys/time.h>
      41             : 
      42             : #include <elf-knowledge.h>
      43             : #include <libebl.h>
      44             : #include "libdwelf.h"
      45             : #include <libeu.h>
      46             : #include <system.h>
      47             : 
      48             : typedef uint8_t GElf_Byte;
      49             : 
      50             : /* Name and version of program.  */
      51             : ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
      52             : 
      53             : /* Bug report address.  */
      54             : ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
      55             : 
      56             : 
      57             : /* Values for the parameters which have no short form.  */
      58             : #define OPT_REMOVE_COMMENT      0x100
      59             : #define OPT_PERMISSIVE          0x101
      60             : #define OPT_STRIP_SECTIONS      0x102
      61             : #define OPT_RELOC_DEBUG         0x103
      62             : 
      63             : 
      64             : /* Definitions of arguments for argp functions.  */
      65             : static const struct argp_option options[] =
      66             : {
      67             :   { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
      68             :   { "output", 'o', "FILE", 0, N_("Place stripped output into FILE"), 0 },
      69             :   { NULL, 'f', "FILE", 0, N_("Extract the removed sections into FILE"), 0 },
      70             :   { NULL, 'F', "FILE", 0, N_("Embed name FILE instead of -f argument"), 0 },
      71             : 
      72             :   { NULL, 0, NULL, 0, N_("Output options:"), 0 },
      73             :   { "strip-all", 's', NULL, OPTION_HIDDEN, NULL, 0 },
      74             :   { "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols"), 0 },
      75             :   { NULL, 'd', NULL, OPTION_ALIAS, NULL, 0 },
      76             :   { NULL, 'S', NULL, OPTION_ALIAS, NULL, 0 },
      77             :   { "strip-sections", OPT_STRIP_SECTIONS, NULL, 0,
      78             :     N_("Remove section headers (not recommended)"), 0 },
      79             :   { "preserve-dates", 'p', NULL, 0,
      80             :     N_("Copy modified/access timestamps to the output"), 0 },
      81             :   { "reloc-debug-sections", OPT_RELOC_DEBUG, NULL, 0,
      82             :     N_("Resolve all trivial relocations between debug sections if the removed sections are placed in a debug file (only relevant for ET_REL files, operation is not reversable, needs -f)"), 0 },
      83             :   { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
      84             :     N_("Remove .comment section"), 0 },
      85             :   { "remove-section", 'R', "SECTION", OPTION_HIDDEN, NULL, 0 },
      86             :   { "permissive", OPT_PERMISSIVE, NULL, 0,
      87             :     N_("Relax a few rules to handle slightly broken ELF files"), 0 },
      88             :   { NULL, 0, NULL, 0, NULL, 0 }
      89             : };
      90             : 
      91             : /* Short description of program.  */
      92             : static const char doc[] = N_("Discard symbols from object files.");
      93             : 
      94             : /* Strings for arguments in help texts.  */
      95             : static const char args_doc[] = N_("[FILE...]");
      96             : 
      97             : /* Prototype for option handler.  */
      98             : static error_t parse_opt (int key, char *arg, struct argp_state *state);
      99             : 
     100             : /* Data structure to communicate with argp functions.  */
     101             : static struct argp argp =
     102             : {
     103             :   options, parse_opt, args_doc, doc, NULL, NULL, NULL
     104             : };
     105             : 
     106             : 
     107             : /* Print symbols in file named FNAME.  */
     108             : static int process_file (const char *fname);
     109             : 
     110             : /* Handle one ELF file.  */
     111             : static int handle_elf (int fd, Elf *elf, const char *prefix,
     112             :                        const char *fname, mode_t mode, struct timespec tvp[2]);
     113             : 
     114             : /* Handle all files contained in the archive.  */
     115             : static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
     116             :                       struct timespec tvp[2]) __attribute__ ((unused));
     117             : 
     118             : static int debug_fd = -1;
     119             : static char *tmp_debug_fname = NULL;
     120             : 
     121             : /* Close debug file descriptor, if opened. And remove temporary debug file.  */
     122             : static void cleanup_debug (void);
     123             : 
     124             : #define INTERNAL_ERROR(fname) \
     125             :   do { \
     126             :     cleanup_debug (); \
     127             :     error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s): %s"),      \
     128             :            fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1)); \
     129             :   } while (0)
     130             : 
     131             : 
     132             : /* Name of the output file.  */
     133             : static const char *output_fname;
     134             : 
     135             : /* Name of the debug output file.  */
     136             : static const char *debug_fname;
     137             : 
     138             : /* Name to pretend the debug output file has.  */
     139             : static const char *debug_fname_embed;
     140             : 
     141             : /* If true output files shall have same date as the input file.  */
     142             : static bool preserve_dates;
     143             : 
     144             : /* If true .comment sections will be removed.  */
     145             : static bool remove_comment;
     146             : 
     147             : /* If true remove all debug sections.  */
     148             : static bool remove_debug;
     149             : 
     150             : /* If true remove all section headers.  */
     151             : static bool remove_shdrs;
     152             : 
     153             : /* If true relax some ELF rules for input files.  */
     154             : static bool permissive;
     155             : 
     156             : /* If true perform relocations between debug sections.  */
     157             : static bool reloc_debug;
     158             : 
     159             : 
     160             : int
     161          48 : main (int argc, char *argv[])
     162             : {
     163             :   int remaining;
     164          48 :   int result = 0;
     165             : 
     166             :   /* We use no threads here which can interfere with handling a stream.  */
     167          48 :   __fsetlocking (stdin, FSETLOCKING_BYCALLER);
     168          48 :   __fsetlocking (stdout, FSETLOCKING_BYCALLER);
     169          48 :   __fsetlocking (stderr, FSETLOCKING_BYCALLER);
     170             : 
     171             :   /* Set locale.  */
     172          48 :   setlocale (LC_ALL, "");
     173             : 
     174             :   /* Make sure the message catalog can be found.  */
     175          48 :   bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
     176             : 
     177             :   /* Initialize the message catalog.  */
     178          48 :   textdomain (PACKAGE_TARNAME);
     179             : 
     180             :   /* Parse and process arguments.  */
     181          48 :   if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
     182             :     return EXIT_FAILURE;
     183             : 
     184          48 :   if (reloc_debug && debug_fname == NULL)
     185             :     error (EXIT_FAILURE, 0,
     186           0 :            gettext ("--reloc-debug-sections used without -f"));
     187             : 
     188             :   /* Tell the library which version we are expecting.  */
     189          48 :   elf_version (EV_CURRENT);
     190             : 
     191          48 :   if (remaining == argc)
     192             :     /* The user didn't specify a name so we use a.out.  */
     193           0 :     result = process_file ("a.out");
     194             :   else
     195             :     {
     196             :       /* If we have seen the '-o' or '-f' option there must be exactly one
     197             :          input file.  */
     198          48 :       if ((output_fname != NULL || debug_fname != NULL)
     199          36 :           && remaining + 1 < argc)
     200           0 :         error (EXIT_FAILURE, 0, gettext ("\
     201             : Only one input file allowed together with '-o' and '-f'"));
     202             : 
     203             :       /* Process all the remaining files.  */
     204             :       do
     205          48 :         result |= process_file (argv[remaining]);
     206          48 :       while (++remaining < argc);
     207             :     }
     208             : 
     209             :   return result;
     210             : }
     211             : 
     212             : 
     213             : /* Handle program arguments.  */
     214             : static error_t
     215         322 : parse_opt (int key, char *arg, struct argp_state *state)
     216             : {
     217         322 :   switch (key)
     218             :     {
     219             :     case 'f':
     220          30 :       if (debug_fname != NULL)
     221             :         {
     222           0 :           error (0, 0, gettext ("-f option specified twice"));
     223           0 :           return EINVAL;
     224             :         }
     225          30 :       debug_fname = arg;
     226          30 :       break;
     227             : 
     228             :     case 'F':
     229           6 :       if (debug_fname_embed != NULL)
     230             :         {
     231           0 :           error (0, 0, gettext ("-F option specified twice"));
     232           0 :           return EINVAL;
     233             :         }
     234           6 :       debug_fname_embed = arg;
     235           6 :       break;
     236             : 
     237             :     case 'o':
     238          36 :       if (output_fname != NULL)
     239             :         {
     240           0 :           error (0, 0, gettext ("-o option specified twice"));
     241           0 :           return EINVAL;
     242             :         }
     243          36 :       output_fname = arg;
     244          36 :       break;
     245             : 
     246             :     case 'p':
     247           0 :       preserve_dates = true;
     248           0 :       break;
     249             : 
     250             :     case OPT_RELOC_DEBUG:
     251          10 :       reloc_debug = true;
     252          10 :       break;
     253             : 
     254             :     case OPT_REMOVE_COMMENT:
     255           0 :       remove_comment = true;
     256           0 :       break;
     257             : 
     258             :     case 'R':
     259           0 :       if (!strcmp (arg, ".comment"))
     260           0 :         remove_comment = true;
     261             :       else
     262             :         {
     263           0 :           argp_error (state,
     264           0 :                       gettext ("-R option supports only .comment section"));
     265           0 :           return EINVAL;
     266             :         }
     267           0 :       break;
     268             : 
     269             :     case 'g':
     270             :     case 'd':
     271             :     case 'S':
     272           0 :       remove_debug = true;
     273           0 :       break;
     274             : 
     275             :     case OPT_STRIP_SECTIONS:
     276           0 :       remove_shdrs = true;
     277           0 :       break;
     278             : 
     279             :     case OPT_PERMISSIVE:
     280           0 :       permissive = true;
     281           0 :       break;
     282             : 
     283             :     case 's':                   /* Ignored for compatibility.  */
     284             :       break;
     285             : 
     286             :     default:
     287             :       return ARGP_ERR_UNKNOWN;
     288             :     }
     289             :   return 0;
     290             : }
     291             : 
     292             : 
     293             : static int
     294          48 : process_file (const char *fname)
     295             : {
     296             :   /* If we have to preserve the modify and access timestamps get them
     297             :      now.  We cannot use fstat() after opening the file since the open
     298             :      would change the access time.  */
     299             :   struct stat pre_st;
     300             :   struct timespec tv[2];
     301             :  again:
     302          48 :   if (preserve_dates)
     303             :     {
     304           0 :       if (stat (fname, &pre_st) != 0)
     305             :         {
     306           0 :           error (0, errno, gettext ("cannot stat input file '%s'"), fname);
     307           0 :           return 1;
     308             :         }
     309             : 
     310             :       /* If we have to preserve the timestamp, we need it in the
     311             :          format utimes() understands.  */
     312           0 :       tv[0] = pre_st.st_atim;
     313           0 :       tv[1] = pre_st.st_mtim;
     314             :     }
     315             : 
     316             :   /* Open the file.  */
     317          48 :   int fd = open (fname, output_fname == NULL ? O_RDWR : O_RDONLY);
     318          48 :   if (fd == -1)
     319             :     {
     320           0 :       error (0, errno, gettext ("while opening '%s'"), fname);
     321           0 :       return 1;
     322             :     }
     323             : 
     324             :   /* We always use fstat() even if we called stat() before.  This is
     325             :      done to make sure the information returned by stat() is for the
     326             :      same file.  */
     327             :   struct stat st;
     328          48 :   if (fstat (fd, &st) != 0)
     329             :     {
     330           0 :       error (0, errno, gettext ("cannot stat input file '%s'"), fname);
     331           0 :       return 1;
     332             :     }
     333             :   /* Paranoid mode on.  */
     334          48 :   if (preserve_dates
     335           0 :       && (st.st_ino != pre_st.st_ino || st.st_dev != pre_st.st_dev))
     336             :     {
     337             :       /* We detected a race.  Try again.  */
     338           0 :       close (fd);
     339           0 :       goto again;
     340             :     }
     341             : 
     342             :   /* Now get the ELF descriptor.  */
     343          48 :   Elf *elf = elf_begin (fd, output_fname == NULL ? ELF_C_RDWR : ELF_C_READ,
     344             :                         NULL);
     345             :   int result;
     346          48 :   switch (elf_kind (elf))
     347             :     {
     348             :     case ELF_K_ELF:
     349          48 :       result = handle_elf (fd, elf, NULL, fname, st.st_mode & ACCESSPERMS,
     350          48 :                            preserve_dates ? tv : NULL);
     351          48 :       break;
     352             : 
     353             :     case ELF_K_AR:
     354             :       /* It is not possible to strip the content of an archive direct
     355             :          the output to a specific file.  */
     356           0 :       if (unlikely (output_fname != NULL || debug_fname != NULL))
     357             :         {
     358           0 :           error (0, 0, gettext ("%s: cannot use -o or -f when stripping archive"),
     359             :                  fname);
     360           0 :           result = 1;
     361             :         }
     362             :       else
     363             :         {
     364             :           /* We would like to support ar archives, but currently it just
     365             :              doesn't work at all since we call elf_clone on the members
     366             :              which doesn't really support ar members.
     367             :              result = handle_ar (fd, elf, NULL, fname,
     368             :                                  preserve_dates ? tv : NULL);
     369             :            */
     370           0 :           error (0, 0, gettext ("%s: no support for stripping archive"),
     371             :                  fname);
     372           0 :           result = 1;
     373             :         }
     374             :       break;
     375             : 
     376             :     default:
     377           0 :       error (0, 0, gettext ("%s: File format not recognized"), fname);
     378           0 :       result = 1;
     379           0 :       break;
     380             :     }
     381             : 
     382          48 :   if (unlikely (elf_end (elf) != 0))
     383           0 :     INTERNAL_ERROR (fname);
     384             : 
     385          48 :   close (fd);
     386             : 
     387          48 :   return result;
     388             : }
     389             : 
     390             : 
     391             : /* Maximum size of array allocated on stack.  */
     392             : #define MAX_STACK_ALLOC (400 * 1024)
     393             : 
     394             : static int
     395          48 : handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
     396             :             mode_t mode, struct timespec tvp[2])
     397             : {
     398          48 :   size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
     399          48 :   size_t fname_len = strlen (fname) + 1;
     400          48 :   char *fullname = alloca (prefix_len + 1 + fname_len);
     401          48 :   char *cp = fullname;
     402          48 :   Elf *debugelf = NULL;
     403          48 :   tmp_debug_fname = NULL;
     404          48 :   int result = 0;
     405          48 :   size_t shdridx = 0;
     406             :   size_t shstrndx;
     407             :   struct shdr_info
     408             :   {
     409             :     Elf_Scn *scn;
     410             :     GElf_Shdr shdr;
     411             :     Elf_Data *data;
     412             :     Elf_Data *debug_data;
     413             :     const char *name;
     414             :     Elf32_Word idx;             /* Index in new file.  */
     415             :     Elf32_Word old_sh_link;     /* Original value of shdr.sh_link.  */
     416             :     Elf32_Word symtab_idx;
     417             :     Elf32_Word version_idx;
     418             :     Elf32_Word group_idx;
     419             :     Elf32_Word group_cnt;
     420             :     Elf_Scn *newscn;
     421             :     Dwelf_Strent *se;
     422             :     Elf32_Word *newsymidx;
     423          48 :   } *shdr_info = NULL;
     424             :   Elf_Scn *scn;
     425             :   size_t cnt;
     426             :   size_t idx;
     427             :   bool changes;
     428             :   GElf_Ehdr newehdr_mem;
     429             :   GElf_Ehdr *newehdr;
     430             :   GElf_Ehdr debugehdr_mem;
     431             :   GElf_Ehdr *debugehdr;
     432          48 :   Dwelf_Strtab *shst = NULL;
     433             :   Elf_Data debuglink_crc_data;
     434          48 :   bool any_symtab_changes = false;
     435          48 :   Elf_Data *shstrtab_data = NULL;
     436          48 :   void *debuglink_buf = NULL;
     437             : 
     438             :   /* Create the full name of the file.  */
     439          48 :   if (prefix != NULL)
     440             :     {
     441           0 :       cp = mempcpy (cp, prefix, prefix_len);
     442           0 :       *cp++ = ':';
     443             :     }
     444          48 :   memcpy (cp, fname, fname_len);
     445             : 
     446             :   /* If we are not replacing the input file open a new file here.  */
     447          48 :   if (output_fname != NULL)
     448             :     {
     449          36 :       fd = open (output_fname, O_RDWR | O_CREAT, mode);
     450          36 :       if (unlikely (fd == -1))
     451             :         {
     452           0 :           error (0, errno, gettext ("cannot open '%s'"), output_fname);
     453           0 :           return 1;
     454             :         }
     455             :     }
     456             : 
     457          48 :   debug_fd = -1;
     458             : 
     459             :   /* Get the EBL handling.  Removing all debugging symbols with the -g
     460             :      option or resolving all relocations between debug sections with
     461             :      the --reloc-debug-sections option are currently the only reasons
     462             :      we need EBL so don't open the backend unless necessary.  */
     463          48 :   Ebl *ebl = NULL;
     464          48 :   if (remove_debug || reloc_debug)
     465             :     {
     466          10 :       ebl = ebl_openbackend (elf);
     467          10 :       if (ebl == NULL)
     468             :         {
     469           0 :           error (0, errno, gettext ("cannot open EBL backend"));
     470           0 :           result = 1;
     471           0 :           goto fail;
     472             :         }
     473             :     }
     474             : 
     475             :   /* Open the additional file the debug information will be stored in.  */
     476          48 :   if (debug_fname != NULL)
     477             :     {
     478             :       /* Create a temporary file name.  We do not want to overwrite
     479             :          the debug file if the file would not contain any
     480             :          information.  */
     481          30 :       size_t debug_fname_len = strlen (debug_fname);
     482          30 :       tmp_debug_fname = (char *) xmalloc (debug_fname_len + sizeof (".XXXXXX"));
     483          30 :       strcpy (mempcpy (tmp_debug_fname, debug_fname, debug_fname_len),
     484             :               ".XXXXXX");
     485             : 
     486          30 :       debug_fd = mkstemp (tmp_debug_fname);
     487          30 :       if (unlikely (debug_fd == -1))
     488             :         {
     489           0 :           error (0, errno, gettext ("cannot open '%s'"), debug_fname);
     490           0 :           result = 1;
     491           0 :           goto fail;
     492             :         }
     493             :     }
     494             : 
     495             :   /* Get the information from the old file.  */
     496             :   GElf_Ehdr ehdr_mem;
     497          48 :   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
     498          48 :   if (ehdr == NULL)
     499           0 :     INTERNAL_ERROR (fname);
     500             : 
     501             :   /* Get the section header string table index.  */
     502          48 :   if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0))
     503             :     {
     504           0 :       cleanup_debug ();
     505             :       error (EXIT_FAILURE, 0,
     506           0 :              gettext ("cannot get section header string table index"));
     507             :     }
     508             : 
     509             :   /* Get the number of phdrs in the old file.  */
     510             :   size_t phnum;
     511          48 :   if (elf_getphdrnum (elf, &phnum) != 0)
     512             :     {
     513           0 :       cleanup_debug ();
     514           0 :       error (EXIT_FAILURE, 0, gettext ("cannot get number of phdrs"));
     515             :     }
     516             : 
     517             :   /* We now create a new ELF descriptor for the same file.  We
     518             :      construct it almost exactly in the same way with some information
     519             :      dropped.  */
     520             :   Elf *newelf;
     521          48 :   if (output_fname != NULL)
     522          36 :     newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
     523             :   else
     524          12 :     newelf = elf_clone (elf, ELF_C_EMPTY);
     525             : 
     526          48 :   if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0)
     527          48 :       || (ehdr->e_type != ET_REL
     528          22 :           && unlikely (gelf_newphdr (newelf, phnum) == 0)))
     529             :     {
     530           0 :       error (0, 0, gettext ("cannot create new file '%s': %s"),
     531           0 :              output_fname ?: fname, elf_errmsg (-1));
     532             :       goto fail;
     533             :     }
     534             : 
     535             :   /* Copy over the old program header if needed.  */
     536          48 :   if (ehdr->e_type != ET_REL)
     537         180 :     for (cnt = 0; cnt < phnum; ++cnt)
     538             :       {
     539             :         GElf_Phdr phdr_mem;
     540         158 :         GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
     541         158 :         if (phdr == NULL
     542         158 :             || unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
     543           0 :           INTERNAL_ERROR (fname);
     544             :       }
     545             : 
     546          48 :   if (debug_fname != NULL)
     547             :     {
     548             :       /* Also create an ELF descriptor for the debug file */
     549          30 :       debugelf = elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL);
     550          30 :       if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0)
     551          30 :           || (ehdr->e_type != ET_REL
     552           8 :               && unlikely (gelf_newphdr (debugelf, phnum) == 0)))
     553             :         {
     554           0 :           error (0, 0, gettext ("cannot create new file '%s': %s"),
     555             :                  debug_fname, elf_errmsg (-1));
     556             :           goto fail_close;
     557             :         }
     558             : 
     559             :       /* Copy over the old program header if needed.  */
     560          30 :       if (ehdr->e_type != ET_REL)
     561          68 :         for (cnt = 0; cnt < phnum; ++cnt)
     562             :           {
     563             :             GElf_Phdr phdr_mem;
     564          60 :             GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
     565          60 :             if (phdr == NULL
     566          60 :                 || unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
     567           0 :               INTERNAL_ERROR (fname);
     568             :           }
     569             :     }
     570             : 
     571             :   /* Number of sections.  */
     572             :   size_t shnum;
     573          48 :   if (unlikely (elf_getshdrnum (elf, &shnum) < 0))
     574             :     {
     575           0 :       error (0, 0, gettext ("cannot determine number of sections: %s"),
     576             :              elf_errmsg (-1));
     577             :       goto fail_close;
     578             :     }
     579             : 
     580          48 :   if (shstrndx >= shnum)
     581             :     goto illformed;
     582             : 
     583             : #define elf_assert(test) do { if (!(test)) goto illformed; } while (0)
     584             : 
     585             :   /* Storage for section information.  We leave room for two more
     586             :      entries since we unconditionally create a section header string
     587             :      table.  Maybe some weird tool created an ELF file without one.
     588             :      The other one is used for the debug link section.  */
     589          48 :   if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
     590           0 :     shdr_info = (struct shdr_info *) xcalloc (shnum + 2,
     591             :                                               sizeof (struct shdr_info));
     592             :   else
     593             :     {
     594          48 :       shdr_info = (struct shdr_info *) alloca ((shnum + 2)
     595             :                                                * sizeof (struct shdr_info));
     596          48 :       memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
     597             :     }
     598             : 
     599             :   /* Prepare section information data structure.  */
     600          48 :   scn = NULL;
     601          48 :   cnt = 1;
     602        1622 :   while ((scn = elf_nextscn (elf, scn)) != NULL)
     603             :     {
     604             :       /* This should always be true (i.e., there should not be any
     605             :          holes in the numbering).  */
     606        1526 :       elf_assert (elf_ndxscn (scn) == cnt);
     607             : 
     608        1526 :       shdr_info[cnt].scn = scn;
     609             : 
     610             :       /* Get the header.  */
     611        1526 :       if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL)
     612           0 :         INTERNAL_ERROR (fname);
     613             : 
     614             :       /* Get the name of the section.  */
     615        3052 :       shdr_info[cnt].name = elf_strptr (elf, shstrndx,
     616        1526 :                                         shdr_info[cnt].shdr.sh_name);
     617        1526 :       if (shdr_info[cnt].name == NULL)
     618             :         {
     619             :         illformed:
     620           0 :           error (0, 0, gettext ("illformed file '%s'"), fname);
     621             :           goto fail_close;
     622             :         }
     623             : 
     624             :       /* Mark them as present but not yet investigated.  */
     625        1526 :       shdr_info[cnt].idx = 1;
     626             : 
     627             :       /* Remember the shdr.sh_link value.  */
     628        1526 :       shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link;
     629        1526 :       if (shdr_info[cnt].old_sh_link >= shnum)
     630             :         goto illformed;
     631             : 
     632             :       /* Sections in files other than relocatable object files which
     633             :          not loaded can be freely moved by us.  In theory we can also
     634             :          freely move around allocated nobits sections.  But we don't
     635             :          to keep the layout of all allocated sections as similar as
     636             :          possible to the original file.  In relocatable object files
     637             :          everything can be moved.  */
     638        1526 :       if (ehdr->e_type == ET_REL
     639         763 :           || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
     640        1009 :         shdr_info[cnt].shdr.sh_offset = 0;
     641             : 
     642             :       /* If this is an extended section index table store an
     643             :          appropriate reference.  */
     644        1526 :       if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
     645             :         {
     646           0 :           elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
     647           0 :           shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
     648             :         }
     649        1526 :       else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
     650             :         {
     651             :           /* Cross-reference the sections contained in the section
     652             :              group.  */
     653           3 :           shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
     654           3 :           if (shdr_info[cnt].data == NULL
     655           3 :               || shdr_info[cnt].data->d_size < sizeof (Elf32_Word))
     656           0 :             INTERNAL_ERROR (fname);
     657             : 
     658             :           /* XXX Fix for unaligned access.  */
     659           3 :           Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
     660             :           size_t inner;
     661           9 :           for (inner = 1;
     662           6 :                inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
     663           3 :                ++inner)
     664             :             {
     665           3 :               if (grpref[inner] < shnum)
     666           3 :                 shdr_info[grpref[inner]].group_idx = cnt;
     667             :               else
     668             :                 goto illformed;
     669             :             }
     670             : 
     671           3 :           if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
     672             :             /* If the section group contains only one element and this
     673             :                is n COMDAT section we can drop it right away.  */
     674           0 :             shdr_info[cnt].idx = 0;
     675             :           else
     676           3 :             shdr_info[cnt].group_cnt = inner - 1;
     677             :         }
     678        1523 :       else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
     679             :         {
     680          22 :           elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
     681          22 :           shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
     682             :         }
     683             : 
     684             :       /* If this section is part of a group make sure it is not
     685             :          discarded right away.  */
     686        1526 :       if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
     687             :         {
     688           3 :           elf_assert (shdr_info[cnt].group_idx != 0);
     689             : 
     690           3 :           if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
     691             :             {
     692             :               /* The section group section will be removed.  */
     693           0 :               shdr_info[cnt].group_idx = 0;
     694           0 :               shdr_info[cnt].shdr.sh_flags &= ~SHF_GROUP;
     695             :             }
     696             :         }
     697             : 
     698             :       /* Increment the counter.  */
     699        1526 :       ++cnt;
     700             :     }
     701             : 
     702             :   /* Now determine which sections can go away.  The general rule is that
     703             :      all sections which are not used at runtime are stripped out.  But
     704             :      there are a few exceptions:
     705             : 
     706             :      - special sections named ".comment" and ".note" are kept
     707             :      - OS or architecture specific sections are kept since we might not
     708             :        know how to handle them
     709             :      - if a section is referred to from a section which is not removed
     710             :        in the sh_link or sh_info element it cannot be removed either
     711             :   */
     712        1574 :   for (cnt = 1; cnt < shnum; ++cnt)
     713             :     /* Check whether the section can be removed.  */
     714        3052 :     if (remove_shdrs ? !(shdr_info[cnt].shdr.sh_flags & SHF_ALLOC)
     715        3052 :         : ebl_section_strip_p (ebl, ehdr, &shdr_info[cnt].shdr,
     716        1526 :                                shdr_info[cnt].name, remove_comment,
     717             :                                remove_debug))
     718             :       {
     719             :         /* For now assume this section will be removed.  */
     720         744 :         shdr_info[cnt].idx = 0;
     721             : 
     722         744 :         idx = shdr_info[cnt].group_idx;
     723        1489 :         while (idx != 0)
     724             :           {
     725             :             /* The section group data is already loaded.  */
     726           1 :             elf_assert (shdr_info[idx].data != NULL
     727             :                         && shdr_info[idx].data->d_buf != NULL
     728             :                         && shdr_info[idx].data->d_size >= sizeof (Elf32_Word));
     729             : 
     730             :             /* If the references section group is a normal section
     731             :                group and has one element remaining, or if it is an
     732             :                empty COMDAT section group it is removed.  */
     733           2 :             bool is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
     734           1 :                               & GRP_COMDAT) != 0;
     735             : 
     736           1 :             --shdr_info[idx].group_cnt;
     737           1 :             if ((!is_comdat && shdr_info[idx].group_cnt == 1)
     738           1 :                 || (is_comdat && shdr_info[idx].group_cnt == 0))
     739             :               {
     740           1 :                 shdr_info[idx].idx = 0;
     741             :                 /* Continue recursively.  */
     742           1 :                 idx = shdr_info[idx].group_idx;
     743             :               }
     744             :             else
     745             :               break;
     746             :           }
     747             :       }
     748             : 
     749             :   /* Mark the SHT_NULL section as handled.  */
     750          48 :   shdr_info[0].idx = 2;
     751             : 
     752             : 
     753             :   /* Handle exceptions: section groups and cross-references.  We might
     754             :      have to repeat this a few times since the resetting of the flag
     755             :      might propagate.  */
     756             :   do
     757             :     {
     758          48 :       changes = false;
     759             : 
     760        1574 :       for (cnt = 1; cnt < shnum; ++cnt)
     761             :         {
     762        1526 :           if (shdr_info[cnt].idx == 0)
     763             :             {
     764             :               /* If a relocation section is marked as being removed make
     765             :                  sure the section it is relocating is removed, too.  */
     766        1384 :               if (shdr_info[cnt].shdr.sh_type == SHT_REL
     767         692 :                    || shdr_info[cnt].shdr.sh_type == SHT_RELA)
     768             :                 {
     769         234 :                   if (shdr_info[cnt].shdr.sh_info >= shnum)
     770             :                     goto illformed;
     771         234 :                   else if (shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
     772         104 :                     shdr_info[cnt].idx = 1;
     773             :                 }
     774             : 
     775             :               /* If a group section is marked as being removed make
     776             :                  sure all the sections it contains are being removed, too.  */
     777         692 :               if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
     778             :                 {
     779             :                   Elf32_Word *grpref;
     780           3 :                   grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
     781           7 :                   for (size_t in = 1;
     782           4 :                        in < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
     783           1 :                        ++in)
     784           3 :                     if (grpref[in] < shnum)
     785             :                       {
     786           3 :                         if (shdr_info[grpref[in]].idx != 0)
     787             :                           {
     788           2 :                             shdr_info[cnt].idx = 1;
     789           2 :                             break;
     790             :                           }
     791             :                       }
     792             :                     else
     793             :                       goto illformed;
     794             :                 }
     795             :             }
     796             : 
     797        1526 :           if (shdr_info[cnt].idx == 1)
     798             :             {
     799             :               /* The content of symbol tables we don't remove must not
     800             :                  reference any section which we do remove.  Otherwise
     801             :                  we cannot remove the section.  */
     802         940 :               if (debug_fname != NULL
     803         554 :                   && shdr_info[cnt].debug_data == NULL
     804        1020 :                   && (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
     805         510 :                       || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB))
     806             :                 {
     807             :                   /* Make sure the data is loaded.  */
     808           8 :                   if (shdr_info[cnt].data == NULL)
     809             :                     {
     810             :                       shdr_info[cnt].data
     811           8 :                         = elf_getdata (shdr_info[cnt].scn, NULL);
     812           8 :                       if (shdr_info[cnt].data == NULL)
     813           0 :                         INTERNAL_ERROR (fname);
     814             :                     }
     815           8 :                   Elf_Data *symdata = shdr_info[cnt].data;
     816             : 
     817             :                   /* If there is an extended section index table load it
     818             :                      as well.  */
     819           8 :                   if (shdr_info[cnt].symtab_idx != 0
     820           0 :                       && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
     821             :                     {
     822           0 :                       elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
     823             : 
     824             :                       shdr_info[shdr_info[cnt].symtab_idx].data
     825           0 :                         = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
     826             :                                        NULL);
     827           0 :                       if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
     828           0 :                         INTERNAL_ERROR (fname);
     829             :                     }
     830           8 :                   Elf_Data *xndxdata
     831           8 :                     = shdr_info[shdr_info[cnt].symtab_idx].data;
     832             : 
     833             :                   /* Go through all symbols and make sure the section they
     834             :                      reference is not removed.  */
     835           8 :                   size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
     836             : 
     837         371 :                   for (size_t inner = 0;
     838         363 :                        inner < shdr_info[cnt].data->d_size / elsize;
     839         355 :                        ++inner)
     840             :                     {
     841             :                       GElf_Sym sym_mem;
     842             :                       Elf32_Word xndx;
     843         355 :                       GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
     844             :                                                         inner, &sym_mem,
     845             :                                                         &xndx);
     846         355 :                       if (sym == NULL)
     847           0 :                         INTERNAL_ERROR (fname);
     848             : 
     849         355 :                       size_t scnidx = sym->st_shndx;
     850         355 :                       if (scnidx == SHN_UNDEF || scnidx >= shnum
     851          82 :                           || (scnidx >= SHN_LORESERVE
     852             :                               && scnidx <= SHN_HIRESERVE
     853          82 :                               && scnidx != SHN_XINDEX)
     854             :                           /* Don't count in the section symbols.  */
     855          82 :                           || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
     856             :                         /* This is no section index, leave it alone.  */
     857         305 :                         continue;
     858          50 :                       else if (scnidx == SHN_XINDEX)
     859           0 :                         scnidx = xndx;
     860             : 
     861          50 :                       if (scnidx >= shnum)
     862             :                         goto illformed;
     863             : 
     864          50 :                       if (shdr_info[scnidx].idx == 0)
     865             :                         /* This symbol table has a real symbol in
     866             :                            a discarded section.  So preserve the
     867             :                            original table in the debug file.  */
     868           0 :                         shdr_info[cnt].debug_data = symdata;
     869             :                     }
     870             :                 }
     871             : 
     872             :               /* Cross referencing happens:
     873             :                  - for the cases the ELF specification says.  That are
     874             :                    + SHT_DYNAMIC in sh_link to string table
     875             :                    + SHT_HASH in sh_link to symbol table
     876             :                    + SHT_REL and SHT_RELA in sh_link to symbol table
     877             :                    + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
     878             :                    + SHT_GROUP in sh_link to symbol table
     879             :                    + SHT_SYMTAB_SHNDX in sh_link to symbol table
     880             :                    Other (OS or architecture-specific) sections might as
     881             :                    well use this field so we process it unconditionally.
     882             :                  - references inside section groups
     883             :                  - specially marked references in sh_info if the SHF_INFO_LINK
     884             :                  flag is set
     885             :               */
     886             : 
     887         940 :               if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
     888             :                 {
     889          52 :                   shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
     890          52 :                   changes |= shdr_info[cnt].shdr.sh_link < cnt;
     891             :                 }
     892             : 
     893             :               /* Handle references through sh_info.  */
     894         940 :               if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
     895             :                 {
     896         146 :                   if (shdr_info[cnt].shdr.sh_info >= shnum)
     897             :                     goto illformed;
     898         146 :                   else if ( shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
     899             :                     {
     900           0 :                       shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
     901           0 :                       changes |= shdr_info[cnt].shdr.sh_info < cnt;
     902             :                     }
     903             :                 }
     904             : 
     905             :               /* Mark the section as investigated.  */
     906         940 :               shdr_info[cnt].idx = 2;
     907             :             }
     908             : 
     909        1526 :           if (debug_fname != NULL
     910         940 :               && (shdr_info[cnt].idx == 0 || shdr_info[cnt].debug_data != NULL))
     911             :             {
     912             :               /* This section is being preserved in the debug file.
     913             :                  Sections it refers to must be preserved there too.
     914             : 
     915             :                  In this pass we mark sections to be preserved in both
     916             :                  files by setting the .debug_data pointer to the original
     917             :                  file's .data pointer.  Below, we'll copy the section
     918             :                  contents.  */
     919             : 
     920         540 :               inline void check_preserved (size_t i)
     921             :               {
     922         540 :                 if (i != 0 && i < shnum + 2 && shdr_info[i].idx != 0
     923         133 :                     && shdr_info[i].debug_data == NULL)
     924             :                   {
     925          44 :                     if (shdr_info[i].data == NULL)
     926          44 :                       shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
     927          44 :                     if (shdr_info[i].data == NULL)
     928           0 :                       INTERNAL_ERROR (fname);
     929             : 
     930          44 :                     shdr_info[i].debug_data = shdr_info[i].data;
     931          44 :                     changes |= i < cnt;
     932             :                   }
     933         540 :               }
     934             : 
     935         430 :               check_preserved (shdr_info[cnt].shdr.sh_link);
     936         430 :               if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
     937         110 :                 check_preserved (shdr_info[cnt].shdr.sh_info);
     938             :             }
     939             :         }
     940             :     }
     941          48 :   while (changes);
     942             : 
     943             :   /* Copy the removed sections to the debug output file.
     944             :      The ones that are not removed in the stripped file are SHT_NOBITS.  */
     945          48 :   if (debug_fname != NULL)
     946             :     {
     947         970 :       for (cnt = 1; cnt < shnum; ++cnt)
     948             :         {
     949         940 :           scn = elf_newscn (debugelf);
     950         940 :           if (scn == NULL)
     951             :             {
     952           0 :               cleanup_debug ();
     953           0 :               error (EXIT_FAILURE, 0,
     954           0 :                      gettext ("while generating output file: %s"),
     955             :                      elf_errmsg (-1));
     956             :             }
     957             : 
     958        1880 :           bool discard_section = (shdr_info[cnt].idx > 0
     959         554 :                                   && shdr_info[cnt].debug_data == NULL
     960         510 :                                   && shdr_info[cnt].shdr.sh_type != SHT_NOTE
     961         486 :                                   && shdr_info[cnt].shdr.sh_type != SHT_GROUP
     962        1424 :                                   && cnt != ehdr->e_shstrndx);
     963             : 
     964             :           /* Set the section header in the new file.  */
     965         940 :           GElf_Shdr debugshdr = shdr_info[cnt].shdr;
     966         940 :           if (discard_section)
     967         484 :             debugshdr.sh_type = SHT_NOBITS;
     968             : 
     969         940 :           if (unlikely (gelf_update_shdr (scn, &debugshdr) == 0))
     970             :             /* There cannot be any overflows.  */
     971           0 :             INTERNAL_ERROR (fname);
     972             : 
     973             :           /* Get the data from the old file if necessary. */
     974         940 :           if (shdr_info[cnt].data == NULL)
     975             :             {
     976         885 :               shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
     977         885 :               if (shdr_info[cnt].data == NULL)
     978           0 :                 INTERNAL_ERROR (fname);
     979             :             }
     980             : 
     981             :           /* Set the data.  This is done by copying from the old file.  */
     982         940 :           Elf_Data *debugdata = elf_newdata (scn);
     983         940 :           if (debugdata == NULL)
     984           0 :             INTERNAL_ERROR (fname);
     985             : 
     986             :           /* Copy the structure.  This data may be modified in place
     987             :              before we write out the file.  */
     988         940 :           *debugdata = *shdr_info[cnt].data;
     989         940 :           if (discard_section)
     990         484 :             debugdata->d_buf = NULL;
     991         456 :           else if (shdr_info[cnt].debug_data != NULL
     992         412 :                    || shdr_info[cnt].shdr.sh_type == SHT_GROUP)
     993             :             {
     994             :               /* Copy the original data before it gets modified.  */
     995          47 :               shdr_info[cnt].debug_data = debugdata;
     996          47 :               if (debugdata->d_buf == NULL)
     997           0 :                 INTERNAL_ERROR (fname);
     998          47 :               debugdata->d_buf = memcpy (xmalloc (debugdata->d_size),
     999             :                                          debugdata->d_buf, debugdata->d_size);
    1000             :             }
    1001             :         }
    1002             : 
    1003             :       /* Finish the ELF header.  Fill in the fields not handled by
    1004             :          libelf from the old file.  */
    1005          30 :       debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
    1006          30 :       if (debugehdr == NULL)
    1007           0 :         INTERNAL_ERROR (fname);
    1008             : 
    1009          30 :       memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
    1010          30 :       debugehdr->e_type = ehdr->e_type;
    1011          30 :       debugehdr->e_machine = ehdr->e_machine;
    1012          30 :       debugehdr->e_version = ehdr->e_version;
    1013          30 :       debugehdr->e_entry = ehdr->e_entry;
    1014          30 :       debugehdr->e_flags = ehdr->e_flags;
    1015          30 :       debugehdr->e_shstrndx = ehdr->e_shstrndx;
    1016             : 
    1017          30 :       if (unlikely (gelf_update_ehdr (debugelf, debugehdr) == 0))
    1018             :         {
    1019           0 :           error (0, 0, gettext ("%s: error while creating ELF header: %s"),
    1020             :                  debug_fname, elf_errmsg (-1));
    1021           0 :           result = 1;
    1022           0 :           goto fail_close;
    1023             :         }
    1024             :     }
    1025             : 
    1026             :   /* Although we always create a new section header string table we
    1027             :      don't explicitly mark the existing one as unused.  It can still
    1028             :      be used through a symbol table section we are keeping.  If not it
    1029             :      will already be marked as unused.  */
    1030             : 
    1031             :   /* We need a string table for the section headers.  */
    1032          48 :   shst = dwelf_strtab_init (true);
    1033          48 :   if (shst == NULL)
    1034             :     {
    1035           0 :       cleanup_debug ();
    1036           0 :       error (EXIT_FAILURE, errno, gettext ("while preparing output for '%s'"),
    1037           0 :              output_fname ?: fname);
    1038             :     }
    1039             : 
    1040             :   /* Assign new section numbers.  */
    1041          48 :   shdr_info[0].idx = 0;
    1042        1574 :   for (cnt = idx = 1; cnt < shnum; ++cnt)
    1043        1526 :     if (shdr_info[cnt].idx > 0)
    1044             :       {
    1045         940 :         shdr_info[cnt].idx = idx++;
    1046             : 
    1047             :         /* Create a new section.  */
    1048         940 :         shdr_info[cnt].newscn = elf_newscn (newelf);
    1049         940 :         if (shdr_info[cnt].newscn == NULL)
    1050             :           {
    1051           0 :             cleanup_debug ();
    1052           0 :             error (EXIT_FAILURE, 0,
    1053           0 :                    gettext ("while generating output file: %s"),
    1054             :                    elf_errmsg (-1));
    1055             :           }
    1056             : 
    1057         940 :         elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
    1058             : 
    1059             :         /* Add this name to the section header string table.  */
    1060         940 :         shdr_info[cnt].se = dwelf_strtab_add (shst, shdr_info[cnt].name);
    1061             :       }
    1062             : 
    1063             :   /* Test whether we are doing anything at all.  */
    1064          48 :   if (cnt == idx)
    1065             :     /* Nope, all removable sections are already gone.  */
    1066             :     goto fail_close;
    1067             : 
    1068             :   /* Create the reference to the file with the debug info.  */
    1069          48 :   if (debug_fname != NULL && !remove_shdrs)
    1070             :     {
    1071             :       /* Add the section header string table section name.  */
    1072          30 :       shdr_info[cnt].se = dwelf_strtab_add_len (shst, ".gnu_debuglink", 15);
    1073          30 :       shdr_info[cnt].idx = idx++;
    1074             : 
    1075             :       /* Create the section header.  */
    1076          30 :       shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
    1077          30 :       shdr_info[cnt].shdr.sh_flags = 0;
    1078          30 :       shdr_info[cnt].shdr.sh_addr = 0;
    1079          30 :       shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
    1080          30 :       shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
    1081          30 :       shdr_info[cnt].shdr.sh_entsize = 0;
    1082          30 :       shdr_info[cnt].shdr.sh_addralign = 4;
    1083             :       /* We set the offset to zero here.  Before we write the ELF file the
    1084             :          field must have the correct value.  This is done in the final
    1085             :          loop over all section.  Then we have all the information needed.  */
    1086          30 :       shdr_info[cnt].shdr.sh_offset = 0;
    1087             : 
    1088             :       /* Create the section.  */
    1089          30 :       shdr_info[cnt].newscn = elf_newscn (newelf);
    1090          30 :       if (shdr_info[cnt].newscn == NULL)
    1091             :         {
    1092           0 :           cleanup_debug ();
    1093           0 :           error (EXIT_FAILURE, 0,
    1094           0 :                  gettext ("while create section header section: %s"),
    1095             :                  elf_errmsg (-1));
    1096             :         }
    1097          30 :       elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
    1098             : 
    1099          30 :       shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
    1100          30 :       if (shdr_info[cnt].data == NULL)
    1101             :         {
    1102           0 :           cleanup_debug ();
    1103           0 :           error (EXIT_FAILURE, 0, gettext ("cannot allocate section data: %s"),
    1104             :                  elf_errmsg (-1));
    1105             :         }
    1106             : 
    1107          30 :       char *debug_basename = basename (debug_fname_embed ?: debug_fname);
    1108          30 :       off_t crc_offset = strlen (debug_basename) + 1;
    1109             :       /* Align to 4 byte boundary */
    1110          30 :       crc_offset = ((crc_offset - 1) & ~3) + 4;
    1111             : 
    1112          30 :       shdr_info[cnt].data->d_align = 4;
    1113          30 :       shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
    1114          30 :         = crc_offset + 4;
    1115          30 :       debuglink_buf = xcalloc (1, shdr_info[cnt].data->d_size);
    1116          30 :       shdr_info[cnt].data->d_buf = debuglink_buf;
    1117             : 
    1118          30 :       strcpy (shdr_info[cnt].data->d_buf, debug_basename);
    1119             : 
    1120             :       /* Cache this Elf_Data describing the CRC32 word in the section.
    1121             :          We'll fill this in when we have written the debug file.  */
    1122          30 :       debuglink_crc_data = *shdr_info[cnt].data;
    1123          60 :       debuglink_crc_data.d_buf = ((char *) debuglink_crc_data.d_buf
    1124          30 :                                   + crc_offset);
    1125          30 :       debuglink_crc_data.d_size = 4;
    1126             : 
    1127             :       /* One more section done.  */
    1128          30 :       ++cnt;
    1129             :     }
    1130             : 
    1131             :   /* Index of the section header table in the shdr_info array.  */
    1132          48 :   shdridx = cnt;
    1133             : 
    1134             :   /* Add the section header string table section name.  */
    1135          48 :   shdr_info[cnt].se = dwelf_strtab_add_len (shst, ".shstrtab", 10);
    1136          48 :   shdr_info[cnt].idx = idx;
    1137             : 
    1138             :   /* Create the section header.  */
    1139          48 :   shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
    1140          48 :   shdr_info[cnt].shdr.sh_flags = 0;
    1141          48 :   shdr_info[cnt].shdr.sh_addr = 0;
    1142          48 :   shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
    1143          48 :   shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
    1144          48 :   shdr_info[cnt].shdr.sh_entsize = 0;
    1145             :   /* We set the offset to zero here.  Before we write the ELF file the
    1146             :      field must have the correct value.  This is done in the final
    1147             :      loop over all section.  Then we have all the information needed.  */
    1148          48 :   shdr_info[cnt].shdr.sh_offset = 0;
    1149          48 :   shdr_info[cnt].shdr.sh_addralign = 1;
    1150             : 
    1151             :   /* Create the section.  */
    1152          48 :   shdr_info[cnt].newscn = elf_newscn (newelf);
    1153          48 :   if (shdr_info[cnt].newscn == NULL)
    1154             :     {
    1155           0 :       cleanup_debug ();
    1156           0 :       error (EXIT_FAILURE, 0,
    1157           0 :              gettext ("while create section header section: %s"),
    1158             :              elf_errmsg (-1));
    1159             :     }
    1160          48 :   elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
    1161             : 
    1162             :   /* Finalize the string table and fill in the correct indices in the
    1163             :      section headers.  */
    1164          48 :   shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
    1165          48 :   if (shstrtab_data == NULL)
    1166             :     {
    1167           0 :       cleanup_debug ();
    1168           0 :       error (EXIT_FAILURE, 0,
    1169           0 :              gettext ("while create section header string table: %s"),
    1170             :              elf_errmsg (-1));
    1171             :     }
    1172          48 :   if (dwelf_strtab_finalize (shst, shstrtab_data) == NULL)
    1173             :     {
    1174           0 :       cleanup_debug ();
    1175             :       error (EXIT_FAILURE, 0,
    1176           0 :              gettext ("no memory to create section header string table"));
    1177             :     }
    1178             : 
    1179             :   /* We have to set the section size.  */
    1180          48 :   shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
    1181             : 
    1182             :   /* Update the section information.  */
    1183          48 :   GElf_Off lastoffset = 0;
    1184        1652 :   for (cnt = 1; cnt <= shdridx; ++cnt)
    1185        1604 :     if (shdr_info[cnt].idx > 0)
    1186             :       {
    1187             :         Elf_Data *newdata;
    1188             : 
    1189        1018 :         scn = elf_getscn (newelf, shdr_info[cnt].idx);
    1190        1018 :         elf_assert (scn != NULL);
    1191             : 
    1192             :         /* Update the name.  */
    1193        1018 :         shdr_info[cnt].shdr.sh_name = dwelf_strent_off (shdr_info[cnt].se);
    1194             : 
    1195             :         /* Update the section header from the input file.  Some fields
    1196             :            might be section indeces which now have to be adjusted.  */
    1197        1018 :         if (shdr_info[cnt].shdr.sh_link != 0)
    1198         286 :           shdr_info[cnt].shdr.sh_link =
    1199         286 :             shdr_info[shdr_info[cnt].shdr.sh_link].idx;
    1200             : 
    1201        1018 :         if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
    1202             :           {
    1203           2 :             elf_assert (shdr_info[cnt].data != NULL
    1204             :                         && shdr_info[cnt].data->d_buf != NULL);
    1205             : 
    1206             :             Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
    1207           6 :             for (size_t inner = 0;
    1208           6 :                  inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
    1209           4 :                  ++inner)
    1210           4 :               if (grpref[inner] < shnum)
    1211           4 :                 grpref[inner] = shdr_info[grpref[inner]].idx;
    1212             :               else
    1213             :                 goto illformed;
    1214             :           }
    1215             : 
    1216             :         /* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag.  */
    1217        1018 :         if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
    1218         146 :           shdr_info[cnt].shdr.sh_info =
    1219         146 :             shdr_info[shdr_info[cnt].shdr.sh_info].idx;
    1220             : 
    1221             :         /* Get the data from the old file if necessary.  We already
    1222             :            created the data for the section header string table.  */
    1223        1018 :         if (cnt < shnum)
    1224             :           {
    1225         940 :             if (shdr_info[cnt].data == NULL)
    1226             :               {
    1227         386 :                 shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
    1228         386 :                 if (shdr_info[cnt].data == NULL)
    1229           0 :                   INTERNAL_ERROR (fname);
    1230             :               }
    1231             : 
    1232             :             /* Set the data.  This is done by copying from the old file.  */
    1233         940 :             newdata = elf_newdata (scn);
    1234         940 :             if (newdata == NULL)
    1235           0 :               INTERNAL_ERROR (fname);
    1236             : 
    1237             :             /* Copy the structure.  */
    1238         940 :             *newdata = *shdr_info[cnt].data;
    1239             : 
    1240             :             /* We know the size.  */
    1241         940 :             shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
    1242             : 
    1243             :             /* We have to adjust symbol tables.  The st_shndx member might
    1244             :                have to be updated.  */
    1245        1880 :             if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
    1246         940 :                 || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
    1247             :               {
    1248          48 :                 Elf_Data *versiondata = NULL;
    1249          48 :                 Elf_Data *shndxdata = NULL;
    1250             : 
    1251          48 :                 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
    1252             : 
    1253          48 :                 if (shdr_info[cnt].symtab_idx != 0)
    1254             :                   {
    1255           0 :                     elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
    1256             :                     /* This section has extended section information.
    1257             :                        We have to modify that information, too.  */
    1258           0 :                     shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
    1259             :                                              NULL);
    1260             : 
    1261           0 :                     elf_assert (shndxdata != NULL
    1262             :                                 && shndxdata->d_buf != NULL
    1263             :                                 && ((shndxdata->d_size / sizeof (Elf32_Word))
    1264             :                                     >= shdr_info[cnt].data->d_size / elsize));
    1265             :                   }
    1266             : 
    1267          48 :                 if (shdr_info[cnt].version_idx != 0)
    1268             :                   {
    1269          22 :                     elf_assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
    1270             :                     /* This section has associated version
    1271             :                        information.  We have to modify that
    1272             :                        information, too.  */
    1273          22 :                     versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
    1274             :                                                NULL);
    1275             : 
    1276          22 :                     elf_assert (versiondata != NULL
    1277             :                                 && versiondata->d_buf != NULL
    1278             :                                 && ((versiondata->d_size / sizeof (GElf_Versym))
    1279             :                                     >= shdr_info[cnt].data->d_size / elsize));
    1280             :                   }
    1281             : 
    1282          48 :                 shdr_info[cnt].newsymidx
    1283          48 :                   = (Elf32_Word *) xcalloc (shdr_info[cnt].data->d_size
    1284             :                                             / elsize, sizeof (Elf32_Word));
    1285             : 
    1286          48 :                 bool last_was_local = true;
    1287             :                 size_t destidx;
    1288             :                 size_t inner;
    1289       12789 :                 for (destidx = inner = 1;
    1290       12741 :                      inner < shdr_info[cnt].data->d_size / elsize;
    1291       12693 :                      ++inner)
    1292             :                   {
    1293             :                     Elf32_Word sec;
    1294             :                     GElf_Sym sym_mem;
    1295             :                     Elf32_Word xshndx;
    1296       12693 :                     GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
    1297             :                                                       shndxdata, inner,
    1298             :                                                       &sym_mem, &xshndx);
    1299       12693 :                     if (sym == NULL)
    1300           0 :                       INTERNAL_ERROR (fname);
    1301             : 
    1302       12693 :                     if (sym->st_shndx == SHN_UNDEF
    1303       11492 :                         || (sym->st_shndx >= shnum
    1304          79 :                             && sym->st_shndx != SHN_XINDEX))
    1305             :                       {
    1306             :                         /* This is no section index, leave it alone
    1307             :                            unless it is moved.  */
    1308        1280 :                         if (destidx != inner
    1309         943 :                             && gelf_update_symshndx (shdr_info[cnt].data,
    1310             :                                                      shndxdata,
    1311             :                                                      destidx, sym,
    1312             :                                                      xshndx) == 0)
    1313           0 :                           INTERNAL_ERROR (fname);
    1314             : 
    1315        1280 :                         shdr_info[cnt].newsymidx[inner] = destidx++;
    1316             : 
    1317        1280 :                         if (last_was_local
    1318          81 :                             && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
    1319             :                           {
    1320          27 :                             last_was_local = false;
    1321          27 :                             shdr_info[cnt].shdr.sh_info = destidx - 1;
    1322             :                           }
    1323             : 
    1324        1280 :                         continue;
    1325             :                       }
    1326             : 
    1327             :                     /* Get the full section index, if necessary from the
    1328             :                        XINDEX table.  */
    1329       11413 :                     if (sym->st_shndx == SHN_XINDEX)
    1330           0 :                       elf_assert (shndxdata != NULL
    1331             :                                   && shndxdata->d_buf != NULL);
    1332       11413 :                     size_t sidx = (sym->st_shndx != SHN_XINDEX
    1333       11413 :                                    ? sym->st_shndx : xshndx);
    1334       11413 :                     sec = shdr_info[sidx].idx;
    1335             : 
    1336       11413 :                     if (sec != 0)
    1337             :                       {
    1338             :                         GElf_Section nshndx;
    1339             :                         Elf32_Word nxshndx;
    1340             : 
    1341         907 :                         if (sec < SHN_LORESERVE)
    1342             :                           {
    1343         907 :                             nshndx = sec;
    1344         907 :                             nxshndx = 0;
    1345             :                           }
    1346             :                         else
    1347             :                           {
    1348             :                             nshndx = SHN_XINDEX;
    1349             :                             nxshndx = sec;
    1350             :                           }
    1351             : 
    1352         907 :                         elf_assert (sec < SHN_LORESERVE || shndxdata != NULL);
    1353             : 
    1354         907 :                         if ((inner != destidx || nshndx != sym->st_shndx
    1355         666 :                              || (shndxdata != NULL && nxshndx != xshndx))
    1356         482 :                             && (sym->st_shndx = nshndx,
    1357         241 :                                 gelf_update_symshndx (shdr_info[cnt].data,
    1358             :                                                       shndxdata,
    1359             :                                                       destidx, sym,
    1360             :                                                       nxshndx) == 0))
    1361           0 :                           INTERNAL_ERROR (fname);
    1362             : 
    1363         907 :                         shdr_info[cnt].newsymidx[inner] = destidx++;
    1364             : 
    1365         907 :                         if (last_was_local
    1366         756 :                             && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
    1367             :                           {
    1368          21 :                             last_was_local = false;
    1369          21 :                             shdr_info[cnt].shdr.sh_info = destidx - 1;
    1370             :                           }
    1371             :                       }
    1372       10506 :                     else if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0
    1373          32 :                              && GELF_ST_TYPE (sym->st_info) != STT_SECTION
    1374           0 :                              && shdr_info[sidx].shdr.sh_type != SHT_GROUP)
    1375             :                       {
    1376             :                         /* Removing a real symbol from an allocated
    1377             :                            symbol table is hard and probably a
    1378             :                            mistake.  Really removing it means
    1379             :                            rewriting the dynamic segment and hash
    1380             :                            sections.  Just warn and set the symbol
    1381             :                            section to UNDEF.  */
    1382           0 :                         error (0, 0,
    1383           0 :                                gettext ("Cannot remove symbol [%zd] from allocated symbol table [%zd]"), inner, cnt);
    1384           0 :                         sym->st_shndx = SHN_UNDEF;
    1385           0 :                         if (gelf_update_sym (shdr_info[cnt].data, destidx,
    1386             :                                              sym) == 0)
    1387           0 :                           INTERNAL_ERROR (fname);
    1388           0 :                         shdr_info[cnt].newsymidx[inner] = destidx++;
    1389             :                       }
    1390       10506 :                     else if (debug_fname != NULL
    1391       10446 :                              && shdr_info[cnt].debug_data == NULL)
    1392             :                       /* The symbol points to a section that is discarded
    1393             :                          but isn't preserved in the debug file. Check that
    1394             :                          this is a section or group signature symbol
    1395             :                          for a section which has been removed.  */
    1396             :                       {
    1397           8 :                         elf_assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION
    1398             :                                     || ((shdr_info[sidx].shdr.sh_type
    1399             :                                          == SHT_GROUP)
    1400             :                                         && (shdr_info[sidx].shdr.sh_info
    1401             :                                             == inner)));
    1402             :                       }
    1403             :                   }
    1404             : 
    1405          48 :                 if (destidx != inner)
    1406             :                   {
    1407             :                     /* The size of the symbol table changed.  */
    1408          30 :                     shdr_info[cnt].shdr.sh_size = newdata->d_size
    1409          30 :                       = destidx * elsize;
    1410          30 :                     any_symtab_changes = true;
    1411             :                   }
    1412             :                 else
    1413             :                   {
    1414             :                     /* The symbol table didn't really change.  */
    1415          18 :                     free (shdr_info[cnt].newsymidx);
    1416          18 :                     shdr_info[cnt].newsymidx = NULL;
    1417             :                   }
    1418             :               }
    1419             :           }
    1420             : 
    1421             :         /* If we have to, compute the offset of the section.  */
    1422        1018 :         if (shdr_info[cnt].shdr.sh_offset == 0)
    1423             :           shdr_info[cnt].shdr.sh_offset
    1424        1002 :             = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
    1425         501 :                & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
    1426             : 
    1427             :         /* Set the section header in the new file.  */
    1428        1018 :         if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
    1429             :           /* There cannot be any overflows.  */
    1430           0 :           INTERNAL_ERROR (fname);
    1431             : 
    1432             :         /* Remember the last section written so far.  */
    1433        2036 :         GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
    1434        1018 :                            ? shdr_info[cnt].shdr.sh_size : 0);
    1435        1018 :         if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
    1436         967 :           lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
    1437             :       }
    1438             : 
    1439             :   /* Adjust symbol references if symbol tables changed.  */
    1440          48 :   if (any_symtab_changes)
    1441             :     /* Find all relocation sections which use this symbol table.  */
    1442         978 :     for (cnt = 1; cnt <= shdridx; ++cnt)
    1443             :       {
    1444             :         /* Update section headers when the data size has changed.
    1445             :            We also update the SHT_NOBITS section in the debug
    1446             :            file so that the section headers match in sh_size.  */
    1447           8 :         inline void update_section_size (const Elf_Data *newdata)
    1448             :         {
    1449             :           GElf_Shdr shdr_mem;
    1450           8 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1451           8 :           shdr->sh_size = newdata->d_size;
    1452           8 :           (void) gelf_update_shdr (scn, shdr);
    1453           8 :           if (debugelf != NULL)
    1454             :             {
    1455             :               /* libelf will use d_size to set sh_size.  */
    1456           2 :               Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
    1457             :                                                              cnt), NULL);
    1458           2 :               if (debugdata == NULL)
    1459           0 :                 INTERNAL_ERROR (fname);
    1460           2 :               debugdata->d_size = newdata->d_size;
    1461             :             }
    1462           8 :         }
    1463             : 
    1464         948 :         if (shdr_info[cnt].idx == 0 && debug_fname == NULL)
    1465             :           /* Ignore sections which are discarded.  When we are saving a
    1466             :              relocation section in a separate debug file, we must fix up
    1467             :              the symbol table references.  */
    1468          89 :           continue;
    1469             : 
    1470         859 :         const Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
    1471         859 :         elf_assert (symtabidx < shnum + 2);
    1472         859 :         const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
    1473         859 :         switch (shdr_info[cnt].shdr.sh_type)
    1474             :           {
    1475             :             inline bool no_symtab_updates (void)
    1476             :             {
    1477             :               /* If the symbol table hasn't changed, do not do anything.  */
    1478         233 :               if (shdr_info[symtabidx].newsymidx == NULL)
    1479             :                 return true;
    1480             : 
    1481             :               /* If the symbol table is not discarded, but additionally
    1482             :                  duplicated in the separate debug file and this section
    1483             :                  is discarded, don't adjust anything.  */
    1484             :               return (shdr_info[cnt].idx == 0
    1485         233 :                       && shdr_info[symtabidx].debug_data != NULL);
    1486             :             }
    1487             : 
    1488             :           case SHT_REL:
    1489             :           case SHT_RELA:
    1490         222 :             if (no_symtab_updates ())
    1491             :               break;
    1492             : 
    1493         224 :             Elf_Data *d = elf_getdata (shdr_info[cnt].idx == 0
    1494             :                                        ? elf_getscn (debugelf, cnt)
    1495         112 :                                        : elf_getscn (newelf,
    1496             :                                                      shdr_info[cnt].idx),
    1497             :                                        NULL);
    1498         112 :             elf_assert (d != NULL && d->d_buf != NULL
    1499             :                         && shdr_info[cnt].shdr.sh_entsize != 0);
    1500         112 :             size_t nrels = (shdr_info[cnt].shdr.sh_size
    1501             :                             / shdr_info[cnt].shdr.sh_entsize);
    1502             : 
    1503         112 :             size_t symsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
    1504         224 :             const Elf32_Word symidxn = (shdr_info[symtabidx].data->d_size
    1505         112 :                                         / symsize);
    1506         112 :             if (shdr_info[cnt].shdr.sh_type == SHT_REL)
    1507        1608 :               for (size_t relidx = 0; relidx < nrels; ++relidx)
    1508             :                 {
    1509             :                   GElf_Rel rel_mem;
    1510        1608 :                   if (gelf_getrel (d, relidx, &rel_mem) == NULL)
    1511           0 :                     INTERNAL_ERROR (fname);
    1512             : 
    1513        1608 :                   size_t symidx = GELF_R_SYM (rel_mem.r_info);
    1514        1608 :                   elf_assert (symidx < symidxn);
    1515        1608 :                   if (newsymidx[symidx] != symidx)
    1516             :                     {
    1517             :                       rel_mem.r_info
    1518        1472 :                         = GELF_R_INFO (newsymidx[symidx],
    1519             :                                        GELF_R_TYPE (rel_mem.r_info));
    1520             : 
    1521        1472 :                       if (gelf_update_rel (d, relidx, &rel_mem) == 0)
    1522           0 :                         INTERNAL_ERROR (fname);
    1523             :                     }
    1524             :                 }
    1525             :             else
    1526       10179 :               for (size_t relidx = 0; relidx < nrels; ++relidx)
    1527             :                 {
    1528             :                   GElf_Rela rel_mem;
    1529       10179 :                   if (gelf_getrela (d, relidx, &rel_mem) == NULL)
    1530           0 :                     INTERNAL_ERROR (fname);
    1531             : 
    1532       10179 :                   size_t symidx = GELF_R_SYM (rel_mem.r_info);
    1533       10179 :                   elf_assert (symidx < symidxn);
    1534       10179 :                   if (newsymidx[symidx] != symidx)
    1535             :                     {
    1536             :                       rel_mem.r_info
    1537        2449 :                         = GELF_R_INFO (newsymidx[symidx],
    1538             :                                        GELF_R_TYPE (rel_mem.r_info));
    1539             : 
    1540        2449 :                       if (gelf_update_rela (d, relidx, &rel_mem) == 0)
    1541           0 :                         INTERNAL_ERROR (fname);
    1542             :                     }
    1543             :                 }
    1544             :             break;
    1545             : 
    1546             :           case SHT_HASH:
    1547           4 :             if (no_symtab_updates ())
    1548             :               break;
    1549             : 
    1550             :             /* We have to recompute the hash table.  */
    1551             : 
    1552           4 :             elf_assert (shdr_info[cnt].idx > 0);
    1553             : 
    1554             :             /* The hash section in the new file.  */
    1555           4 :             scn = elf_getscn (newelf, shdr_info[cnt].idx);
    1556             : 
    1557             :             /* The symbol table data.  */
    1558           4 :             Elf_Data *symd = elf_getdata (elf_getscn (newelf,
    1559           4 :                                                       shdr_info[symtabidx].idx),
    1560             :                                           NULL);
    1561           4 :             elf_assert (symd != NULL && symd->d_buf != NULL);
    1562             : 
    1563             :             /* The hash table data.  */
    1564           4 :             Elf_Data *hashd = elf_getdata (scn, NULL);
    1565           4 :             elf_assert (hashd != NULL && hashd->d_buf != NULL);
    1566             : 
    1567           4 :             if (shdr_info[cnt].shdr.sh_entsize == sizeof (Elf32_Word))
    1568             :               {
    1569             :                 /* Sane arches first.  */
    1570           4 :                 elf_assert (hashd->d_size >= 2 * sizeof (Elf32_Word));
    1571           4 :                 Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
    1572             : 
    1573           4 :                 size_t strshndx = shdr_info[symtabidx].old_sh_link;
    1574           4 :                 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
    1575             : 
    1576           4 :                 Elf32_Word nchain = bucket[1];
    1577           4 :                 Elf32_Word nbucket = bucket[0];
    1578           8 :                 uint64_t used_buf = ((2ULL + nchain + nbucket)
    1579           4 :                                      * sizeof (Elf32_Word));
    1580           4 :                 elf_assert (used_buf <= hashd->d_size);
    1581             : 
    1582             :                 /* Adjust the nchain value.  The symbol table size
    1583             :                    changed.  We keep the same size for the bucket array.  */
    1584           4 :                 bucket[1] = symd->d_size / elsize;
    1585           4 :                 bucket += 2;
    1586           4 :                 Elf32_Word *chain = bucket + nbucket;
    1587             : 
    1588             :                 /* New size of the section.  */
    1589           8 :                 size_t n_size = ((2 + symd->d_size / elsize + nbucket)
    1590           4 :                                  * sizeof (Elf32_Word));
    1591           4 :                 elf_assert (n_size <= hashd->d_size);
    1592           4 :                 hashd->d_size = n_size;
    1593           4 :                 update_section_size (hashd);
    1594             : 
    1595             :                 /* Clear the arrays.  */
    1596           4 :                 memset (bucket, '\0',
    1597           4 :                         (symd->d_size / elsize + nbucket)
    1598             :                         * sizeof (Elf32_Word));
    1599             : 
    1600          56 :                 for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
    1601          48 :                      inner < symd->d_size / elsize; ++inner)
    1602             :                   {
    1603             :                     GElf_Sym sym_mem;
    1604          48 :                     GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
    1605          48 :                     elf_assert (sym != NULL);
    1606             : 
    1607          48 :                     const char *name = elf_strptr (elf, strshndx,
    1608          48 :                                                    sym->st_name);
    1609          48 :                     elf_assert (name != NULL && nbucket != 0);
    1610          48 :                     size_t hidx = elf_hash (name) % nbucket;
    1611             : 
    1612          48 :                     if (bucket[hidx] == 0)
    1613          40 :                       bucket[hidx] = inner;
    1614             :                     else
    1615             :                       {
    1616           8 :                         hidx = bucket[hidx];
    1617             : 
    1618          16 :                         while (chain[hidx] != 0 && chain[hidx] < nchain)
    1619           0 :                           hidx = chain[hidx];
    1620             : 
    1621           8 :                         chain[hidx] = inner;
    1622             :                       }
    1623             :                   }
    1624             :               }
    1625             :             else
    1626             :               {
    1627             :                 /* Alpha and S390 64-bit use 64-bit SHT_HASH entries.  */
    1628           0 :                 elf_assert (shdr_info[cnt].shdr.sh_entsize
    1629             :                             == sizeof (Elf64_Xword));
    1630             : 
    1631           0 :                 Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
    1632             : 
    1633           0 :                 size_t strshndx = shdr_info[symtabidx].old_sh_link;
    1634           0 :                 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
    1635             : 
    1636           0 :                 elf_assert (symd->d_size >= 2 * sizeof (Elf64_Xword));
    1637           0 :                 Elf64_Xword nbucket = bucket[0];
    1638           0 :                 Elf64_Xword nchain = bucket[1];
    1639           0 :                 uint64_t maxwords = hashd->d_size / sizeof (Elf64_Xword);
    1640           0 :                 elf_assert (maxwords >= 2
    1641             :                             && maxwords - 2 >= nbucket
    1642             :                             && maxwords - 2 - nbucket >= nchain);
    1643             : 
    1644             :                 /* Adjust the nchain value.  The symbol table size
    1645             :                    changed.  We keep the same size for the bucket array.  */
    1646           0 :                 bucket[1] = symd->d_size / elsize;
    1647           0 :                 bucket += 2;
    1648           0 :                 Elf64_Xword *chain = bucket + nbucket;
    1649             : 
    1650             :                 /* New size of the section.  */
    1651           0 :                 size_t n_size = ((2 + symd->d_size / elsize + nbucket)
    1652           0 :                                  * sizeof (Elf64_Xword));
    1653           0 :                 elf_assert (n_size <= hashd->d_size);
    1654           0 :                 hashd->d_size = n_size;
    1655           0 :                 update_section_size (hashd);
    1656             : 
    1657             :                 /* Clear the arrays.  */
    1658           0 :                 memset (bucket, '\0',
    1659           0 :                         (symd->d_size / elsize + nbucket)
    1660             :                         * sizeof (Elf64_Xword));
    1661             : 
    1662           0 :                 for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
    1663           0 :                      inner < symd->d_size / elsize; ++inner)
    1664             :                   {
    1665             :                     GElf_Sym sym_mem;
    1666           0 :                     GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
    1667           0 :                     elf_assert (sym != NULL);
    1668             : 
    1669           0 :                     const char *name = elf_strptr (elf, strshndx,
    1670           0 :                                                    sym->st_name);
    1671           0 :                     elf_assert (name != NULL && nbucket != 0);
    1672           0 :                     size_t hidx = elf_hash (name) % nbucket;
    1673             : 
    1674           0 :                     if (bucket[hidx] == 0)
    1675           0 :                       bucket[hidx] = inner;
    1676             :                     else
    1677             :                       {
    1678             :                         hidx = bucket[hidx];
    1679             : 
    1680           0 :                         while (chain[hidx] != 0 && chain[hidx] < nchain)
    1681             :                           hidx = chain[hidx];
    1682             : 
    1683           0 :                         chain[hidx] = inner;
    1684             :                       }
    1685             :                   }
    1686             :               }
    1687             :             break;
    1688             : 
    1689             :           case SHT_GNU_versym:
    1690             :             /* If the symbol table changed we have to adjust the entries.  */
    1691           4 :             if (no_symtab_updates ())
    1692             :               break;
    1693             : 
    1694           4 :             elf_assert (shdr_info[cnt].idx > 0);
    1695             : 
    1696             :             /* The symbol version section in the new file.  */
    1697           4 :             scn = elf_getscn (newelf, shdr_info[cnt].idx);
    1698             : 
    1699             :             /* The symbol table data.  */
    1700           4 :             symd = elf_getdata (elf_getscn (newelf, shdr_info[symtabidx].idx),
    1701             :                                 NULL);
    1702           4 :             elf_assert (symd != NULL && symd->d_buf != NULL);
    1703           4 :             size_t symz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
    1704           4 :             const Elf32_Word syms = (shdr_info[symtabidx].data->d_size / symz);
    1705             : 
    1706             :             /* The version symbol data.  */
    1707           4 :             Elf_Data *verd = elf_getdata (scn, NULL);
    1708           4 :             elf_assert (verd != NULL && verd->d_buf != NULL);
    1709             : 
    1710             :             /* The symbol version array.  */
    1711           4 :             GElf_Half *verstab = (GElf_Half *) verd->d_buf;
    1712             : 
    1713             :             /* Walk through the list and */
    1714           4 :             size_t elsize = gelf_fsize (elf, verd->d_type, 1, EV_CURRENT);
    1715           4 :             Elf32_Word vers = verd->d_size / elsize;
    1716         172 :             for (size_t inner = 1; inner < vers && inner < syms; ++inner)
    1717         168 :               if (newsymidx[inner] != 0 && newsymidx[inner] < vers)
    1718             :                 /* Overwriting the same array works since the
    1719             :                    reordering can only move entries to lower indices
    1720             :                    in the array.  */
    1721         136 :                 verstab[newsymidx[inner]] = verstab[inner];
    1722             : 
    1723             :             /* New size of the section.  */
    1724           4 :             verd->d_size = gelf_fsize (newelf, verd->d_type,
    1725           4 :                                        symd->d_size
    1726           4 :                                        / gelf_fsize (elf, symd->d_type, 1,
    1727             :                                                      EV_CURRENT),
    1728             :                                        EV_CURRENT);
    1729           4 :             update_section_size (verd);
    1730           4 :             break;
    1731             : 
    1732             :           case SHT_GROUP:
    1733           3 :             if (no_symtab_updates ())
    1734             :               break;
    1735             : 
    1736             :             /* Yes, the symbol table changed.
    1737             :                Update the section header of the section group.  */
    1738           2 :             scn = elf_getscn (newelf, shdr_info[cnt].idx);
    1739             :             GElf_Shdr shdr_mem;
    1740           2 :             GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1741           2 :             elf_assert (shdr != NULL);
    1742             : 
    1743           2 :             size_t symsz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
    1744           4 :             const Elf32_Word symn = (shdr_info[symtabidx].data->d_size
    1745           2 :                                      / symsz);
    1746           2 :             elf_assert (shdr->sh_info < symn);
    1747           2 :             shdr->sh_info = newsymidx[shdr->sh_info];
    1748             : 
    1749           2 :             (void) gelf_update_shdr (scn, shdr);
    1750           2 :             break;
    1751             :           }
    1752             :       }
    1753             : 
    1754             :   /* Remove any relocations between debug sections in ET_REL
    1755             :      for the debug file when requested.  These relocations are always
    1756             :      zero based between the unallocated sections.  */
    1757          48 :   if (debug_fname != NULL && reloc_debug && ehdr->e_type == ET_REL)
    1758             :     {
    1759           9 :       scn = NULL;
    1760           9 :       cnt = 0;
    1761         294 :       while ((scn = elf_nextscn (debugelf, scn)) != NULL)
    1762             :         {
    1763         276 :           cnt++;
    1764             :           /* We need the actual section and header from the debugelf
    1765             :              not just the cached original in shdr_info because we
    1766             :              might want to change the size.  */
    1767             :           GElf_Shdr shdr_mem;
    1768         276 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1769         276 :           if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
    1770             :             {
    1771             :               /* Make sure that this relocation section points to a
    1772             :                  section to relocate with contents, that isn't
    1773             :                  allocated and that is a debug section.  */
    1774          44 :               Elf_Scn *tscn = elf_getscn (debugelf, shdr->sh_info);
    1775             :               GElf_Shdr tshdr_mem;
    1776          44 :               GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
    1777          44 :               if (tshdr->sh_type == SHT_NOBITS
    1778          44 :                   || tshdr->sh_size == 0
    1779          44 :                   || (tshdr->sh_flags & SHF_ALLOC) != 0)
    1780           0 :                 continue;
    1781             : 
    1782          44 :               const char *tname =  elf_strptr (debugelf, shstrndx,
    1783          44 :                                                tshdr->sh_name);
    1784          44 :               if (! tname || ! ebl_debugscn_p (ebl, tname))
    1785           0 :                 continue;
    1786             : 
    1787             :               /* OK, lets relocate all trivial cross debug section
    1788             :                  relocations. */
    1789          44 :               Elf_Data *reldata = elf_getdata (scn, NULL);
    1790          44 :               if (reldata == NULL || reldata->d_buf == NULL)
    1791           0 :                 INTERNAL_ERROR (fname);
    1792             : 
    1793             :               /* Make sure we adjust the uncompressed debug data
    1794             :                  (and recompress if necessary at the end).  */
    1795             :               GElf_Chdr tchdr;
    1796          44 :               int tcompress_type = 0;
    1797          44 :               if (gelf_getchdr (tscn, &tchdr) != NULL)
    1798             :                 {
    1799           5 :                   tcompress_type = tchdr.ch_type;
    1800           5 :                   if (elf_compress (tscn, 0, 0) != 1)
    1801           0 :                     INTERNAL_ERROR (fname);
    1802             :                 }
    1803             : 
    1804          44 :               Elf_Data *tdata = elf_getdata (tscn, NULL);
    1805          44 :               if (tdata == NULL || tdata->d_buf == NULL
    1806          44 :                   || tdata->d_type != ELF_T_BYTE)
    1807           0 :                 INTERNAL_ERROR (fname);
    1808             : 
    1809             :               /* Pick up the symbol table and shndx table to
    1810             :                  resolve relocation symbol indexes.  */
    1811          44 :               Elf64_Word symt = shdr->sh_link;
    1812             :               Elf_Data *symdata, *xndxdata;
    1813          44 :               elf_assert (symt < shnum + 2);
    1814          44 :               elf_assert (shdr_info[symt].symtab_idx < shnum + 2);
    1815          88 :               symdata = (shdr_info[symt].debug_data
    1816          44 :                          ?: shdr_info[symt].data);
    1817          88 :               xndxdata = (shdr_info[shdr_info[symt].symtab_idx].debug_data
    1818          44 :                           ?: shdr_info[shdr_info[symt].symtab_idx].data);
    1819             : 
    1820             :               /* Apply one relocation.  Returns true when trivial
    1821             :                  relocation actually done.  */
    1822       30548 :               bool relocate (GElf_Addr offset, const GElf_Sxword addend,
    1823             :                              bool is_rela, int rtype, int symndx)
    1824             :               {
    1825             :                 /* R_*_NONE relocs can always just be removed.  */
    1826       30548 :                 if (rtype == 0)
    1827             :                   return true;
    1828             : 
    1829             :                 /* We only do simple absolute relocations.  */
    1830       30548 :                 Elf_Type type = ebl_reloc_simple_type (ebl, rtype);
    1831       30548 :                 if (type == ELF_T_NUM)
    1832             :                   return false;
    1833             : 
    1834             :                 /* These are the types we can relocate.  */
    1835             : #define TYPES   DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half);             \
    1836             :                 DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword);           \
    1837             :                 DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
    1838             : 
    1839             :                 /* And only for relocations against other debug sections.  */
    1840             :                 GElf_Sym sym_mem;
    1841             :                 Elf32_Word xndx;
    1842       30548 :                 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
    1843             :                                                   symndx, &sym_mem,
    1844             :                                                   &xndx);
    1845       61096 :                 Elf32_Word sec = (sym->st_shndx == SHN_XINDEX
    1846       30548 :                                   ? xndx : sym->st_shndx);
    1847       30548 :                 if (sec >= shnum + 2)
    1848           0 :                   INTERNAL_ERROR (fname);
    1849             : 
    1850       30548 :                 if (ebl_debugscn_p (ebl, shdr_info[sec].name))
    1851             :                   {
    1852             :                     size_t size;
    1853             : 
    1854             : #define DO_TYPE(NAME, Name) GElf_##Name Name;
    1855             :                     union { TYPES; } tmpbuf;
    1856             : #undef DO_TYPE
    1857             : 
    1858       21657 :                     switch (type)
    1859             :                       {
    1860             : #define DO_TYPE(NAME, Name)                             \
    1861             :                         case ELF_T_##NAME:              \
    1862             :                           size = sizeof (GElf_##Name);  \
    1863             :                           tmpbuf.Name = 0;              \
    1864             :                           break;
    1865           0 :                         TYPES;
    1866             : #undef DO_TYPE
    1867             :                       default:
    1868             :                         return false;
    1869             :                       }
    1870             : 
    1871       21657 :                     if (offset > tdata->d_size
    1872       21657 :                         || tdata->d_size - offset < size)
    1873             :                       {
    1874           0 :                         cleanup_debug ();
    1875           0 :                         error (EXIT_FAILURE, 0, gettext ("bad relocation"));
    1876             :                       }
    1877             : 
    1878             :                     /* When the symbol value is zero then for SHT_REL
    1879             :                        sections this is all that needs to be checked.
    1880             :                        The addend is contained in the original data at
    1881             :                        the offset already.  So if the (section) symbol
    1882             :                        address is zero and the given addend is zero
    1883             :                        just remove the relocation, it isn't needed
    1884             :                        anymore.  */
    1885       21657 :                     if (addend == 0 && sym->st_value == 0)
    1886             :                       return true;
    1887             : 
    1888       18415 :                     Elf_Data tmpdata =
    1889             :                       {
    1890             :                         .d_type = type,
    1891             :                         .d_buf = &tmpbuf,
    1892             :                         .d_size = size,
    1893             :                         .d_version = EV_CURRENT,
    1894             :                       };
    1895       36830 :                     Elf_Data rdata =
    1896             :                       {
    1897             :                         .d_type = type,
    1898       18415 :                         .d_buf = tdata->d_buf + offset,
    1899             :                         .d_size = size,
    1900             :                         .d_version = EV_CURRENT,
    1901             :                       };
    1902             : 
    1903       18415 :                     GElf_Addr value = sym->st_value;
    1904       18415 :                     if (is_rela)
    1905             :                       {
    1906             :                         /* For SHT_RELA sections we just take the
    1907             :                            given addend and add it to the value.  */
    1908       18415 :                         value += addend;
    1909             :                       }
    1910             :                     else
    1911             :                       {
    1912             :                         /* For SHT_REL sections we have to peek at
    1913             :                            what is already in the section at the given
    1914             :                            offset to get the addend.  */
    1915           0 :                         Elf_Data *d = gelf_xlatetom (debugelf, &tmpdata,
    1916             :                                                      &rdata,
    1917           0 :                                                      ehdr->e_ident[EI_DATA]);
    1918           0 :                         if (d == NULL)
    1919           0 :                           INTERNAL_ERROR (fname);
    1920           0 :                         assert (d == &tmpdata);
    1921             :                       }
    1922             : 
    1923       18415 :                     switch (type)
    1924             :                       {
    1925             : #define DO_TYPE(NAME, Name)                                     \
    1926             :                         case ELF_T_##NAME:                      \
    1927             :                           tmpbuf.Name += (GElf_##Name) value;   \
    1928             :                           break;
    1929           0 :                         TYPES;
    1930             : #undef DO_TYPE
    1931             :                       default:
    1932           0 :                         abort ();
    1933             :                       }
    1934             : 
    1935             :                     /* Now finally put in the new value.  */
    1936       18415 :                     Elf_Data *s = gelf_xlatetof (debugelf, &rdata,
    1937             :                                                  &tmpdata,
    1938       18415 :                                                  ehdr->e_ident[EI_DATA]);
    1939       18415 :                     if (s == NULL)
    1940           0 :                       INTERNAL_ERROR (fname);
    1941       18415 :                     assert (s == &rdata);
    1942             : 
    1943             :                     return true;
    1944             :                   }
    1945             :                 return false;
    1946             :               }
    1947             : 
    1948          44 :               if (shdr->sh_entsize == 0)
    1949           0 :                 INTERNAL_ERROR (fname);
    1950             : 
    1951          44 :               size_t nrels = shdr->sh_size / shdr->sh_entsize;
    1952          44 :               size_t next = 0;
    1953          44 :               if (shdr->sh_type == SHT_REL)
    1954        3212 :                 for (size_t relidx = 0; relidx < nrels; ++relidx)
    1955             :                   {
    1956             :                     GElf_Rel rel_mem;
    1957        3212 :                     GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
    1958        3212 :                     if (! relocate (r->r_offset, 0, false,
    1959             :                                     GELF_R_TYPE (r->r_info),
    1960        3212 :                                     GELF_R_SYM (r->r_info)))
    1961             :                       {
    1962          18 :                         if (relidx != next)
    1963          16 :                           gelf_update_rel (reldata, next, r);
    1964          18 :                         ++next;
    1965             :                       }
    1966             :                   }
    1967             :               else
    1968       27336 :                 for (size_t relidx = 0; relidx < nrels; ++relidx)
    1969             :                   {
    1970             :                     GElf_Rela rela_mem;
    1971       27336 :                     GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
    1972       27336 :                     if (! relocate (r->r_offset, r->r_addend, true,
    1973             :                                     GELF_R_TYPE (r->r_info),
    1974       27336 :                                     GELF_R_SYM (r->r_info)))
    1975             :                       {
    1976        8873 :                         if (relidx != next)
    1977        2051 :                           gelf_update_rela (reldata, next, r);
    1978        8873 :                         ++next;
    1979             :                       }
    1980             :                   }
    1981             : 
    1982          44 :               nrels = next;
    1983          44 :               shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
    1984          44 :               gelf_update_shdr (scn, shdr);
    1985             : 
    1986          44 :               if (tcompress_type != 0)
    1987           5 :                 if (elf_compress (tscn, tcompress_type, ELF_CHF_FORCE) != 1)
    1988           0 :                   INTERNAL_ERROR (fname);
    1989             :             }
    1990             :         }
    1991             :     }
    1992             : 
    1993             :   /* Now that we have done all adjustments to the data,
    1994             :      we can actually write out the debug file.  */
    1995          48 :   if (debug_fname != NULL)
    1996             :     {
    1997             :       /* Finally write the file.  */
    1998          30 :       if (unlikely (elf_update (debugelf, ELF_C_WRITE) == -1))
    1999             :         {
    2000           0 :           error (0, 0, gettext ("while writing '%s': %s"),
    2001             :                  tmp_debug_fname, elf_errmsg (-1));
    2002           0 :           result = 1;
    2003           0 :           goto fail_close;
    2004             :         }
    2005             : 
    2006             :       /* Create the real output file.  First rename, then change the
    2007             :          mode.  */
    2008          30 :       if (rename (tmp_debug_fname, debug_fname) != 0
    2009          30 :           || fchmod (debug_fd, mode) != 0)
    2010             :         {
    2011           0 :           error (0, errno, gettext ("while creating '%s'"), debug_fname);
    2012           0 :           result = 1;
    2013           0 :           goto fail_close;
    2014             :         }
    2015             : 
    2016             :       /* The temporary file does not exist anymore.  */
    2017          30 :       free (tmp_debug_fname);
    2018          30 :       tmp_debug_fname = NULL;
    2019             : 
    2020          30 :       if (!remove_shdrs)
    2021             :         {
    2022             :           uint32_t debug_crc;
    2023          30 :           Elf_Data debug_crc_data =
    2024             :             {
    2025             :               .d_type = ELF_T_WORD,
    2026             :               .d_buf = &debug_crc,
    2027             :               .d_size = sizeof (debug_crc),
    2028             :               .d_version = EV_CURRENT
    2029             :             };
    2030             : 
    2031             :           /* Compute the checksum which we will add to the executable.  */
    2032          30 :           if (crc32_file (debug_fd, &debug_crc) != 0)
    2033             :             {
    2034           0 :               error (0, errno, gettext ("\
    2035             : while computing checksum for debug information"));
    2036           0 :               unlink (debug_fname);
    2037           0 :               result = 1;
    2038           0 :               goto fail_close;
    2039             :             }
    2040             : 
    2041             :           /* Store it in the debuglink section data.  */
    2042          30 :           if (unlikely (gelf_xlatetof (newelf, &debuglink_crc_data,
    2043             :                                        &debug_crc_data, ehdr->e_ident[EI_DATA])
    2044             :                         != &debuglink_crc_data))
    2045           0 :             INTERNAL_ERROR (fname);
    2046             :         }
    2047             :     }
    2048             : 
    2049             :   /* Finally finish the ELF header.  Fill in the fields not handled by
    2050             :      libelf from the old file.  */
    2051          48 :   newehdr = gelf_getehdr (newelf, &newehdr_mem);
    2052          48 :   if (newehdr == NULL)
    2053           0 :     INTERNAL_ERROR (fname);
    2054             : 
    2055          48 :   memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
    2056          48 :   newehdr->e_type = ehdr->e_type;
    2057          48 :   newehdr->e_machine = ehdr->e_machine;
    2058          48 :   newehdr->e_version = ehdr->e_version;
    2059          48 :   newehdr->e_entry = ehdr->e_entry;
    2060          48 :   newehdr->e_flags = ehdr->e_flags;
    2061          48 :   newehdr->e_phoff = ehdr->e_phoff;
    2062             : 
    2063             :   /* We need to position the section header table.  */
    2064          48 :   const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
    2065          96 :   newehdr->e_shoff = ((shdr_info[shdridx].shdr.sh_offset
    2066          48 :                        + shdr_info[shdridx].shdr.sh_size + offsize - 1)
    2067          48 :                       & ~((GElf_Off) (offsize - 1)));
    2068          48 :   newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
    2069             : 
    2070             :   /* The new section header string table index.  */
    2071          48 :   if (likely (idx < SHN_HIRESERVE) && likely (idx != SHN_XINDEX))
    2072          48 :     newehdr->e_shstrndx = idx;
    2073             :   else
    2074             :     {
    2075             :       /* The index does not fit in the ELF header field.  */
    2076           0 :       shdr_info[0].scn = elf_getscn (elf, 0);
    2077             : 
    2078           0 :       if (gelf_getshdr (shdr_info[0].scn, &shdr_info[0].shdr) == NULL)
    2079           0 :         INTERNAL_ERROR (fname);
    2080             : 
    2081           0 :       shdr_info[0].shdr.sh_link = idx;
    2082           0 :       (void) gelf_update_shdr (shdr_info[0].scn, &shdr_info[0].shdr);
    2083             : 
    2084           0 :       newehdr->e_shstrndx = SHN_XINDEX;
    2085             :     }
    2086             : 
    2087          48 :   if (gelf_update_ehdr (newelf, newehdr) == 0)
    2088             :     {
    2089           0 :       error (0, 0, gettext ("%s: error while creating ELF header: %s"),
    2090           0 :              output_fname ?: fname, elf_errmsg (-1));
    2091           0 :       cleanup_debug ();
    2092           0 :       return 1;
    2093             :     }
    2094             : 
    2095             :   /* We have everything from the old file.  */
    2096          48 :   if (elf_cntl (elf, ELF_C_FDDONE) != 0)
    2097             :     {
    2098           0 :       error (0, 0, gettext ("%s: error while reading the file: %s"),
    2099             :              fname, elf_errmsg (-1));
    2100           0 :       cleanup_debug ();
    2101           0 :       return 1;
    2102             :     }
    2103             : 
    2104             :   /* The ELF library better follows our layout when this is not a
    2105             :      relocatable object file.  */
    2106          48 :   elf_flagelf (newelf, ELF_C_SET,
    2107          48 :                (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0)
    2108          48 :                | (permissive ? ELF_F_PERMISSIVE : 0));
    2109             : 
    2110             :   /* Finally write the file.  */
    2111          48 :   if (elf_update (newelf, ELF_C_WRITE) == -1)
    2112             :     {
    2113           0 :       error (0, 0, gettext ("while writing '%s': %s"),
    2114           0 :              output_fname ?: fname, elf_errmsg (-1));
    2115           0 :       result = 1;
    2116             :     }
    2117             : 
    2118          48 :   if (remove_shdrs)
    2119             :     {
    2120             :       /* libelf can't cope without the section headers being properly intact.
    2121             :          So we just let it write them normally, and then we nuke them later.  */
    2122             : 
    2123           0 :       if (newehdr->e_ident[EI_CLASS] == ELFCLASS32)
    2124             :         {
    2125             :           assert (offsetof (Elf32_Ehdr, e_shentsize) + sizeof (Elf32_Half)
    2126             :                   == offsetof (Elf32_Ehdr, e_shnum));
    2127             :           assert (offsetof (Elf32_Ehdr, e_shnum) + sizeof (Elf32_Half)
    2128             :                   == offsetof (Elf32_Ehdr, e_shstrndx));
    2129           0 :           const Elf32_Off zero_off = 0;
    2130           0 :           const Elf32_Half zero[3] = { 0, 0, SHN_UNDEF };
    2131           0 :           if (pwrite_retry (fd, &zero_off, sizeof zero_off,
    2132             :                             offsetof (Elf32_Ehdr, e_shoff)) != sizeof zero_off
    2133           0 :               || (pwrite_retry (fd, zero, sizeof zero,
    2134             :                                 offsetof (Elf32_Ehdr, e_shentsize))
    2135             :                   != sizeof zero)
    2136           0 :               || ftruncate (fd, shdr_info[shdridx].shdr.sh_offset) < 0)
    2137             :             {
    2138           0 :               error (0, errno, gettext ("while writing '%s'"),
    2139           0 :                      output_fname ?: fname);
    2140           0 :               result = 1;
    2141             :             }
    2142             :         }
    2143             :       else
    2144             :         {
    2145             :           assert (offsetof (Elf64_Ehdr, e_shentsize) + sizeof (Elf64_Half)
    2146             :                   == offsetof (Elf64_Ehdr, e_shnum));
    2147             :           assert (offsetof (Elf64_Ehdr, e_shnum) + sizeof (Elf64_Half)
    2148             :                   == offsetof (Elf64_Ehdr, e_shstrndx));
    2149           0 :           const Elf64_Off zero_off = 0;
    2150           0 :           const Elf64_Half zero[3] = { 0, 0, SHN_UNDEF };
    2151           0 :           if (pwrite_retry (fd, &zero_off, sizeof zero_off,
    2152             :                             offsetof (Elf64_Ehdr, e_shoff)) != sizeof zero_off
    2153           0 :               || (pwrite_retry (fd, zero, sizeof zero,
    2154             :                                 offsetof (Elf64_Ehdr, e_shentsize))
    2155             :                   != sizeof zero)
    2156           0 :               || ftruncate (fd, shdr_info[shdridx].shdr.sh_offset) < 0)
    2157             :             {
    2158           0 :               error (0, errno, gettext ("while writing '%s'"),
    2159           0 :                      output_fname ?: fname);
    2160           0 :               result = 1;
    2161             :             }
    2162             :         }
    2163             :     }
    2164             : 
    2165             :  fail_close:
    2166          48 :   if (shdr_info != NULL)
    2167             :     {
    2168             :       /* For some sections we might have created an table to map symbol
    2169             :          table indices.  */
    2170          48 :       if (any_symtab_changes)
    2171         978 :         for (cnt = 1; cnt <= shdridx; ++cnt)
    2172             :           {
    2173         948 :             free (shdr_info[cnt].newsymidx);
    2174         948 :             if (shdr_info[cnt].debug_data != NULL)
    2175          47 :               free (shdr_info[cnt].debug_data->d_buf);
    2176             :           }
    2177             : 
    2178             :       /* Free data we allocated for the .gnu_debuglink section. */
    2179          48 :       free (debuglink_buf);
    2180             : 
    2181             :       /* Free the memory.  */
    2182          48 :       if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
    2183           0 :         free (shdr_info);
    2184             :     }
    2185             : 
    2186             :   /* Free other resources.  */
    2187          48 :   if (shstrtab_data != NULL)
    2188          48 :     free (shstrtab_data->d_buf);
    2189          48 :   if (shst != NULL)
    2190          48 :     dwelf_strtab_free (shst);
    2191             : 
    2192             :   /* That was it.  Close the descriptors.  */
    2193          48 :   if (elf_end (newelf) != 0)
    2194             :     {
    2195           0 :       error (0, 0, gettext ("error while finishing '%s': %s"),
    2196           0 :              output_fname ?: fname, elf_errmsg (-1));
    2197           0 :       result = 1;
    2198             :     }
    2199             : 
    2200          48 :   if (debugelf != NULL && elf_end (debugelf) != 0)
    2201             :     {
    2202           0 :       error (0, 0, gettext ("error while finishing '%s': %s"), debug_fname,
    2203             :              elf_errmsg (-1));
    2204           0 :       result = 1;
    2205             :     }
    2206             : 
    2207             :  fail:
    2208             :   /* Close the EBL backend.  */
    2209          48 :   if (ebl != NULL)
    2210          10 :     ebl_closebackend (ebl);
    2211             : 
    2212          48 :   cleanup_debug ();
    2213             : 
    2214             :   /* If requested, preserve the timestamp.  */
    2215          48 :   if (tvp != NULL)
    2216             :     {
    2217           0 :       if (futimens (fd, tvp) != 0)
    2218             :         {
    2219           0 :           error (0, errno, gettext ("\
    2220             : cannot set access and modification date of '%s'"),
    2221           0 :                  output_fname ?: fname);
    2222           0 :           result = 1;
    2223             :         }
    2224             :     }
    2225             : 
    2226             :   /* Close the file descriptor if we created a new file.  */
    2227          48 :   if (output_fname != NULL)
    2228          36 :     close (fd);
    2229             : 
    2230             :   return result;
    2231             : }
    2232             : 
    2233             : static void
    2234          48 : cleanup_debug (void)
    2235             : {
    2236          48 :   if (debug_fd >= 0)
    2237             :     {
    2238          30 :       if (tmp_debug_fname != NULL)
    2239             :         {
    2240           0 :           unlink (tmp_debug_fname);
    2241           0 :           free (tmp_debug_fname);
    2242           0 :           tmp_debug_fname = NULL;
    2243             :         }
    2244          30 :       close (debug_fd);
    2245          30 :       debug_fd = -1;
    2246             :     }
    2247          48 : }
    2248             : 
    2249             : static int
    2250             : handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
    2251             :            struct timespec tvp[2])
    2252             : {
    2253             :   size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
    2254             :   size_t fname_len = strlen (fname) + 1;
    2255             :   char new_prefix[prefix_len + 1 + fname_len];
    2256             :   char *cp = new_prefix;
    2257             : 
    2258             :   /* Create the full name of the file.  */
    2259             :   if (prefix != NULL)
    2260             :     {
    2261             :       cp = mempcpy (cp, prefix, prefix_len);
    2262             :       *cp++ = ':';
    2263             :     }
    2264             :   memcpy (cp, fname, fname_len);
    2265             : 
    2266             : 
    2267             :   /* Process all the files contained in the archive.  */
    2268             :   Elf *subelf;
    2269             :   Elf_Cmd cmd = ELF_C_RDWR;
    2270             :   int result = 0;
    2271             :   while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
    2272             :     {
    2273             :       /* The the header for this element.  */
    2274             :       Elf_Arhdr *arhdr = elf_getarhdr (subelf);
    2275             : 
    2276             :       if (elf_kind (subelf) == ELF_K_ELF)
    2277             :         result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
    2278             :       else if (elf_kind (subelf) == ELF_K_AR)
    2279             :         result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
    2280             : 
    2281             :       /* Get next archive element.  */
    2282             :       cmd = elf_next (subelf);
    2283             :       if (unlikely (elf_end (subelf) != 0))
    2284             :         INTERNAL_ERROR (fname);
    2285             :     }
    2286             : 
    2287             :   if (tvp != NULL)
    2288             :     {
    2289             :       if (unlikely (futimens (fd, tvp) != 0))
    2290             :         {
    2291             :           error (0, errno, gettext ("\
    2292             : cannot set access and modification date of '%s'"), fname);
    2293             :           result = 1;
    2294             :         }
    2295             :     }
    2296             : 
    2297             :   if (unlikely (close (fd) != 0))
    2298             :     error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
    2299             : 
    2300             :   return result;
    2301             : }
    2302             : 
    2303             : 
    2304             : #include "debugpred.h"

Generated by: LCOV version 1.12