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

Generated by: LCOV version 1.12