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

Generated by: LCOV version 1.13