strip.c revision 1ccdfb683ad6c7e59793136c3a657ddf131cafd1
1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Discard section not used at runtime from object files.
2587c4b3e94c6ef877137d067d5d0f574f69b1391Mark Wielaard   Copyright (C) 2000-2012, 2014, 2015 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of the GNU General Public License as published by
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the Free Software Foundation; either version 3 of the License, or
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   (at your option) any later version.
10b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
12361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   GNU General Public License for more details.
15361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received a copy of the GNU General Public License
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
19b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#ifdef HAVE_CONFIG_H
20b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper# include <config.h>
21b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
22b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
23b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <argp.h>
24b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <assert.h>
25b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <byteswap.h>
26b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <endian.h>
27b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <error.h>
28b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <fcntl.h>
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <gelf.h>
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libelf.h>
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libintl.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <locale.h>
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdbool.h>
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdio.h>
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdio_ext.h>
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdlib.h>
37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <string.h>
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <unistd.h>
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/param.h>
40b337b1fd5f3b3410fe522a690ccee70bce8519eeRoland McGrath#include <sys/stat.h>
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/time.h>
42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <elf-knowledge.h>
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libebl.h>
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <system.h>
46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
471662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaardtypedef uint8_t GElf_Byte;
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Name and version of program.  */
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void print_version (FILE *stream, struct argp_state *state);
51fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
52b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Bug report address.  */
54fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Values for the parameters which have no short form.  */
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define OPT_REMOVE_COMMENT	0x100
59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define OPT_PERMISSIVE		0x101
600b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath#define OPT_STRIP_SECTIONS	0x102
611662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard#define OPT_RELOC_DEBUG 	0x103
62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Definitions of arguments for argp functions.  */
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const struct argp_option options[] =
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
684be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  { "output", 'o', "FILE", 0, N_("Place stripped output into FILE"), 0 },
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 'f', "FILE", 0, N_("Extract the removed sections into FILE"), 0 },
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 'F', "FILE", 0, N_("Embed name FILE instead of -f argument"), 0 },
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, N_("Output options:"), 0 },
738f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath  { "strip-all", 's', NULL, OPTION_HIDDEN, NULL, 0 },
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols"), 0 },
758f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath  { NULL, 'd', NULL, OPTION_ALIAS, NULL, 0 },
768f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath  { NULL, 'S', NULL, OPTION_ALIAS, NULL, 0 },
770b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath  { "strip-sections", OPT_STRIP_SECTIONS, NULL, 0,
780b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath    N_("Remove section headers (not recommended)"), 0 },
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "preserve-dates", 'p', NULL, 0,
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Copy modified/access timestamps to the output"), 0 },
811662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard  { "reloc-debug-sections", OPT_RELOC_DEBUG, NULL, 0,
821662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard    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 },
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Remove .comment section"), 0 },
858f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath  { "remove-section", 'R', "SECTION", OPTION_HIDDEN, NULL, 0 },
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "permissive", OPT_PERMISSIVE, NULL, 0,
87b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Relax a few rules to handle slightly broken ELF files"), 0 },
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, NULL, 0 }
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Short description of program.  */
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char doc[] = N_("Discard symbols from object files.");
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Strings for arguments in help texts.  */
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char args_doc[] = N_("[FILE...]");
96b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Prototype for option handler.  */
98b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Data structure to communicate with argp functions.  */
101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic struct argp argp =
102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  options, parse_opt, args_doc, doc, NULL, NULL, NULL
104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print symbols in file named FNAME.  */
108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int process_file (const char *fname);
109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle one ELF file.  */
111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int handle_elf (int fd, Elf *elf, const char *prefix,
1128c4aa0ef998191ed828a37190dc179b91649938aMax Filippov		       const char *fname, mode_t mode, struct timespec tvp[2]);
113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle all files contained in the archive.  */
115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
116cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard		      struct timespec tvp[2]) __attribute__ ((unused));
117b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1186d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaardstatic int debug_fd = -1;
1196d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaardstatic char *tmp_debug_fname = NULL;
1206d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard
1216d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard/* Close debug file descriptor, if opened. And remove temporary debug file.  */
1221ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaardstatic void cleanup_debug (void);
1236d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard
124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define INTERNAL_ERROR(fname) \
1256d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard  do { \
1266d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    cleanup_debug (); \
1276d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s): %s"),      \
1286d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	   fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1)); \
1296d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard  } while (0)
130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Name of the output file.  */
133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *output_fname;
134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Name of the debug output file.  */
136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *debug_fname;
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Name to pretend the debug output file has.  */
139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *debug_fname_embed;
140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* If true output files shall have same date as the input file.  */
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool preserve_dates;
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* If true .comment sections will be removed.  */
145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool remove_comment;
146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* If true remove all debug sections.  */
148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool remove_debug;
149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1500b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath/* If true remove all section headers.  */
1510b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrathstatic bool remove_shdrs;
1520b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath
153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* If true relax some ELF rules for input files.  */
154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool permissive;
155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1561662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard/* If true perform relocations between debug sections.  */
1571662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaardstatic bool reloc_debug;
1581662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermain (int argc, char *argv[])
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int remaining;
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result = 0;
165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We use no threads here which can interfere with handling a stream.  */
167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Set locale.  */
172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  setlocale (LC_ALL, "");
173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Make sure the message catalog can be found.  */
175b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Initialize the message catalog.  */
178b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  textdomain (PACKAGE_TARNAME);
179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Parse and process arguments.  */
181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return EXIT_FAILURE;
183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1841662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard  if (reloc_debug && debug_fname == NULL)
1851662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard    error (EXIT_FAILURE, 0,
1861662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	   gettext ("--reloc-debug-sections used without -f"));
1871662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Tell the library which version we are expecting.  */
189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_version (EV_CURRENT);
190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (remaining == argc)
192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* The user didn't specify a name so we use a.out.  */
193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    result = process_file ("a.out");
194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If we have seen the '-o' or '-f' option there must be exactly one
197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 input file.  */
198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((output_fname != NULL || debug_fname != NULL)
199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && remaining + 1 < argc)
200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	error (EXIT_FAILURE, 0, gettext ("\
201b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperOnly one input file allowed together with '-o' and '-f'"));
202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Process all the remaining files.  */
204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      do
205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	result |= process_file (argv[remaining]);
206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      while (++remaining < argc);
207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print the version information.  */
214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
217b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  fprintf (stream, "strip (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("\
219b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperCopyright (C) %s Red Hat, Inc.\n\
220b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperThis is free software; see the source for copying conditions.  There is NO\n\
221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
2223a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper"), "2012");
223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle program arguments.  */
228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t
2291c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrathparse_opt (int key, char *arg, struct argp_state *state)
230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (key)
232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'f':
234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (debug_fname != NULL)
235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, 0, gettext ("-f option specified twice"));
237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return EINVAL;
238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debug_fname = arg;
240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'F':
243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (debug_fname_embed != NULL)
244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, 0, gettext ("-F option specified twice"));
246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return EINVAL;
247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debug_fname_embed = arg;
249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'o':
252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (output_fname != NULL)
253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, 0, gettext ("-o option specified twice"));
255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return EINVAL;
256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      output_fname = arg;
258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'p':
261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      preserve_dates = true;
262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2641662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard    case OPT_RELOC_DEBUG:
2651662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard      reloc_debug = true;
2661662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard      break;
2671662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case OPT_REMOVE_COMMENT:
269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      remove_comment = true;
270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2728f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath    case 'R':
2738f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath      if (!strcmp (arg, ".comment"))
2748f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath	remove_comment = true;
2758f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath      else
2768f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath	{
2778f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath	  argp_error (state,
2788f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath		      gettext ("-R option supports only .comment section"));
2798f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath	  return EINVAL;
2808f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath	}
2818f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath      break;
2828f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath
283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'g':
2848f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath    case 'd':
2858f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath    case 'S':
286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      remove_debug = true;
287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2890b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath    case OPT_STRIP_SECTIONS:
2900b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath      remove_shdrs = true;
2910b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath      break;
2920b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath
293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case OPT_PERMISSIVE:
294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      permissive = true;
295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2978f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath    case 's':			/* Ignored for compatibility.  */
2988f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath      break;
2998f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath
300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ARGP_ERR_UNKNOWN;
302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
307b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
308b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprocess_file (const char *fname)
309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If we have to preserve the modify and access timestamps get them
311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     now.  We cannot use fstat() after opening the file since the open
312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     would change the access time.  */
313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct stat64 pre_st;
3148c4aa0ef998191ed828a37190dc179b91649938aMax Filippov  struct timespec tv[2];
315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper again:
316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (preserve_dates)
317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (stat64 (fname, &pre_st) != 0)
319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
320e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	  error (0, errno, gettext ("cannot stat input file '%s'"), fname);
321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return 1;
322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If we have to preserve the timestamp, we need it in the
325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 format utimes() understands.  */
3268c4aa0ef998191ed828a37190dc179b91649938aMax Filippov      tv[0] = pre_st.st_atim;
3278c4aa0ef998191ed828a37190dc179b91649938aMax Filippov      tv[1] = pre_st.st_mtim;
328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Open the file.  */
331095a01b14c2562a33615f079f300ac86da95bc56Roland McGrath  int fd = open (fname, output_fname == NULL ? O_RDWR : O_RDONLY);
332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (fd == -1)
333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
334e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper      error (0, errno, gettext ("while opening '%s'"), fname);
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 1;
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We always use fstat() even if we called stat() before.  This is
339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     done to make sure the information returned by stat() is for the
340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     same file.  */
341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct stat64 st;
342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (fstat64 (fd, &st) != 0)
343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
344e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper      error (0, errno, gettext ("cannot stat input file '%s'"), fname);
345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 1;
346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Paranoid mode on.  */
348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (preserve_dates
349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (st.st_ino != pre_st.st_ino || st.st_dev != pre_st.st_dev))
350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We detected a race.  Try again.  */
352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      close (fd);
353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      goto again;
354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now get the ELF descriptor.  */
357095a01b14c2562a33615f079f300ac86da95bc56Roland McGrath  Elf *elf = elf_begin (fd, output_fname == NULL ? ELF_C_RDWR : ELF_C_READ,
358095a01b14c2562a33615f079f300ac86da95bc56Roland McGrath			NULL);
359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result;
360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (elf_kind (elf))
361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_ELF:
363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = handle_elf (fd, elf, NULL, fname, st.st_mode & ACCESSPERMS,
364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   preserve_dates ? tv : NULL);
365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_AR:
368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* It is not possible to strip the content of an archive direct
369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 the output to a specific file.  */
3708190db6a86a37aec86c81626ab1b083c96aff891Roland McGrath      if (unlikely (output_fname != NULL || debug_fname != NULL))
371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3728190db6a86a37aec86c81626ab1b083c96aff891Roland McGrath	  error (0, 0, gettext ("%s: cannot use -o or -f when stripping archive"),
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 fname);
374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
377cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard	{
378cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard	  /* We would like to support ar archives, but currently it just
379cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard	     doesn't work at all since we call elf_clone on the members
380cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard	     which doesn't really support ar members.
381cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard	     result = handle_ar (fd, elf, NULL, fname,
382cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard				 preserve_dates ? tv : NULL);
383cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard	   */
384cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard	  error (0, 0, gettext ("%s: no support for stripping archive"),
385cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard		 fname);
386cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard	  result = 1;
387cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard	}
388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("%s: File format not recognized"), fname);
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = 1;
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (unlikely (elf_end (elf) != 0))
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    INTERNAL_ERROR (fname);
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  close (fd);
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Maximum size of array allocated on stack.  */
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define MAX_STACK_ALLOC	(400 * 1024)
407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperhandle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
4108c4aa0ef998191ed828a37190dc179b91649938aMax Filippov	    mode_t mode, struct timespec tvp[2])
411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t fname_len = strlen (fname) + 1;
414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *fullname = alloca (prefix_len + 1 + fname_len);
415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *cp = fullname;
416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *debugelf = NULL;
4176d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard  tmp_debug_fname = NULL;
418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result = 0;
419e219f1c1b2a5a2e4f248714fdc93d031cdc5ee6aUlrich Drepper  size_t shdridx = 0;
420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t shstrndx;
421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct shdr_info
422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf_Scn *scn;
424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    GElf_Shdr shdr;
425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf_Data *data;
426521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath    Elf_Data *debug_data;
427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    const char *name;
428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf32_Word idx;		/* Index in new file.  */
429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf32_Word old_sh_link;	/* Original value of shdr.sh_link.  */
430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf32_Word symtab_idx;
431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf32_Word version_idx;
432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf32_Word group_idx;
433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf32_Word group_cnt;
434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf_Scn *newscn;
435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    struct Ebl_Strent *se;
436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf32_Word *newsymidx;
437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  } *shdr_info = NULL;
438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn;
439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cnt;
440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t idx;
441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool changes;
442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr newehdr_mem;
443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr *newehdr;
444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr debugehdr_mem;
445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr *debugehdr;
446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct Ebl_Strtab *shst = NULL;
447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data debuglink_crc_data;
448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool any_symtab_changes = false;
449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *shstrtab_data = NULL;
450a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard  void *debuglink_buf = NULL;
451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Create the full name of the file.  */
453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (prefix != NULL)
454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      cp = mempcpy (cp, prefix, prefix_len);
456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      *cp++ = ':';
457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  memcpy (cp, fname, fname_len);
459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If we are not replacing the input file open a new file here.  */
461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (output_fname != NULL)
462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      fd = open (output_fname, O_RDWR | O_CREAT, mode);
464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (unlikely (fd == -1))
465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("cannot open '%s'"), output_fname);
467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return 1;
468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4716d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard  debug_fd = -1;
472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4731662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard  /* Get the EBL handling.  Removing all debugging symbols with the -g
4741662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard     option or resolving all relocations between debug sections with
4751662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard     the --reloc-debug-sections option are currently the only reasons
4766cbd7adf7eeb3f30632b53c8a68c470e0e47252bUlrich Drepper     we need EBL so don't open the backend unless necessary.  */
477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Ebl *ebl = NULL;
4781662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard  if (remove_debug || reloc_debug)
479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ebl = ebl_openbackend (elf);
481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ebl == NULL)
482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("cannot open EBL backend"));
484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto fail;
486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Open the additional file the debug information will be stored in.  */
490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (debug_fname != NULL)
491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Create a temporary file name.  We do not want to overwrite
493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 the debug file if the file would not contain any
494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 information.  */
495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t debug_fname_len = strlen (debug_fname);
4966d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      tmp_debug_fname = (char *) xmalloc (debug_fname_len + sizeof (".XXXXXX"));
497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      strcpy (mempcpy (tmp_debug_fname, debug_fname, debug_fname_len),
498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ".XXXXXX");
499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debug_fd = mkstemp (tmp_debug_fname);
501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (unlikely (debug_fd == -1))
502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("cannot open '%s'"), debug_fname);
504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto fail;
506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Get the information from the old file.  */
5101c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath  GElf_Ehdr ehdr_mem;
5111c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr == NULL)
513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    INTERNAL_ERROR (fname);
514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Get the section header string table index.  */
516f189493154d0041deced00e6a99cc5426dc9d260Ulrich Drepper  if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0))
5176d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    {
5186d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
5196d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      error (EXIT_FAILURE, 0,
5206d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     gettext ("cannot get section header string table index"));
5216d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    }
522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
523712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard  /* Get the number of phdrs in the old file.  */
524712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard  size_t phnum;
525712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard  if (elf_getphdrnum (elf, &phnum) != 0)
5266d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    {
5276d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
5286d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      error (EXIT_FAILURE, 0, gettext ("cannot get number of phdrs"));
5296d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    }
530712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard
531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We now create a new ELF descriptor for the same file.  We
532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     construct it almost exactly in the same way with some information
533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     dropped.  */
5341c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath  Elf *newelf;
535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (output_fname != NULL)
536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    newelf = elf_clone (elf, ELF_C_EMPTY);
539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0)
541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      || (ehdr->e_type != ET_REL
542712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard	  && unlikely (gelf_newphdr (newelf, phnum) == 0)))
543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("cannot create new file '%s': %s"),
5456d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     output_fname ?: fname, elf_errmsg (-1));
546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      goto fail;
547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Copy over the old program header if needed.  */
550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_REL)
551712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard    for (cnt = 0; cnt < phnum; ++cnt)
552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	GElf_Phdr phdr_mem;
5541c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (phdr == NULL
556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    || unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  INTERNAL_ERROR (fname);
558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (debug_fname != NULL)
561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Also create an ELF descriptor for the debug file */
563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugelf = elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL);
564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0)
565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || (ehdr->e_type != ET_REL
566712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard	      && unlikely (gelf_newphdr (debugelf, phnum) == 0)))
567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, 0, gettext ("cannot create new file '%s': %s"),
569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 debug_fname, elf_errmsg (-1));
570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto fail_close;
571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Copy over the old program header if needed.  */
574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type != ET_REL)
575712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard	for (cnt = 0; cnt < phnum; ++cnt)
576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    GElf_Phdr phdr_mem;
5781c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	    GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (phdr == NULL
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		|| unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      INTERNAL_ERROR (fname);
582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Number of sections.  */
5861c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath  size_t shnum;
587f189493154d0041deced00e6a99cc5426dc9d260Ulrich Drepper  if (unlikely (elf_getshdrnum (elf, &shnum) < 0))
588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("cannot determine number of sections: %s"),
590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     elf_errmsg (-1));
591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      goto fail_close;
592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
59458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath  if (shstrndx >= shnum)
59558d3619facfb708f4998d73270ca4082b20853b9Roland McGrath    goto illformed;
59658d3619facfb708f4998d73270ca4082b20853b9Roland McGrath
59758d3619facfb708f4998d73270ca4082b20853b9Roland McGrath#define elf_assert(test) do { if (!(test)) goto illformed; } while (0)
59858d3619facfb708f4998d73270ca4082b20853b9Roland McGrath
599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Storage for section information.  We leave room for two more
600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     entries since we unconditionally create a section header string
601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     table.  Maybe some weird tool created an ELF file without one.
602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     The other one is used for the debug link section.  */
603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    shdr_info = (struct shdr_info *) xcalloc (shnum + 2,
605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      sizeof (struct shdr_info));
606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info = (struct shdr_info *) alloca ((shnum + 2)
609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					       * sizeof (struct shdr_info));
610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Prepare section information data structure.  */
614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  scn = NULL;
615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  cnt = 1;
616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((scn = elf_nextscn (elf, scn)) != NULL)
617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This should always be true (i.e., there should not be any
619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 holes in the numbering).  */
62058d3619facfb708f4998d73270ca4082b20853b9Roland McGrath      elf_assert (elf_ndxscn (scn) == cnt);
621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].scn = scn;
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Get the header.  */
625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL)
626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	INTERNAL_ERROR (fname);
627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Get the name of the section.  */
629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].name = elf_strptr (elf, shstrndx,
630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					shdr_info[cnt].shdr.sh_name);
631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr_info[cnt].name == NULL)
632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
63358d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	illformed:
634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, 0, gettext ("illformed file '%s'"), fname);
635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto fail_close;
636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Mark them as present but not yet investigated.  */
639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].idx = 1;
640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Remember the shdr.sh_link value.  */
642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link;
64358d3619facfb708f4998d73270ca4082b20853b9Roland McGrath      if (shdr_info[cnt].old_sh_link >= shnum)
64458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	goto illformed;
645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Sections in files other than relocatable object files which
6476d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	 don't contain any file content or are not loaded can be freely
6486d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	 moved by us.  In relocatable object files everything can be moved.  */
649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type == ET_REL
6506d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  || shdr_info[cnt].shdr.sh_type == SHT_NOBITS
651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].shdr.sh_offset = 0;
653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If this is an extended section index table store an
655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 appropriate reference.  */
656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
65858d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	  elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Cross-reference the sections contained in the section
664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     group.  */
665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
6666d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  if (shdr_info[cnt].data == NULL
6676d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      || shdr_info[cnt].data->d_size < sizeof (Elf32_Word))
668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    INTERNAL_ERROR (fname);
669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* XXX Fix for unaligned access.  */
6711c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	  Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
6721c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	  size_t inner;
673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (inner = 1;
674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ++inner)
67658d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	    {
67758d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	      if (grpref[inner] < shnum)
67858d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		shdr_info[grpref[inner]].group_idx = cnt;
67958d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	      else
68058d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		goto illformed;
68158d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	    }
682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* If the section group contains only one element and this
685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       is n COMDAT section we can drop it right away.  */
686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    shdr_info[cnt].idx = 0;
687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    shdr_info[cnt].group_cnt = inner - 1;
689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
69258d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	  elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If this section is part of a group make sure it is not
697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 discarded right away.  */
698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
70058d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	  elf_assert (shdr_info[cnt].group_idx != 0);
701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* The section group section will be removed.  */
705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      shdr_info[cnt].group_idx = 0;
706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      shdr_info[cnt].shdr.sh_flags &= ~SHF_GROUP;
707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Increment the counter.  */
711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ++cnt;
712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now determine which sections can go away.  The general rule is that
715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     all sections which are not used at runtime are stripped out.  But
716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     there are a few exceptions:
717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     - special sections named ".comment" and ".note" are kept
719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     - OS or architecture specific sections are kept since we might not
720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper       know how to handle them
721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     - if a section is referred to from a section which is not removed
722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper       in the sh_link or sh_info element it cannot be removed either
723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  */
724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 1; cnt < shnum; ++cnt)
725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Check whether the section can be removed.  */
726f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath    if (remove_shdrs ? !(shdr_info[cnt].shdr.sh_flags & SHF_ALLOC)
727f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	: ebl_section_strip_p (ebl, ehdr, &shdr_info[cnt].shdr,
728f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath			       shdr_info[cnt].name, remove_comment,
729f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath			       remove_debug))
730b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
731b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* For now assume this section will be removed.  */
732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].idx = 0;
733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	idx = shdr_info[cnt].group_idx;
735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	while (idx != 0)
736b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
737ce4550aefd57ab68f6f279a5b662eb1716d7b361Roland McGrath	    /* The section group data is already loaded.  */
7386d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr_info[idx].data != NULL
7396d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			&& shdr_info[idx].data->d_buf != NULL
7406d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			&& shdr_info[idx].data->d_size >= sizeof (Elf32_Word));
741ce4550aefd57ab68f6f279a5b662eb1716d7b361Roland McGrath
7421c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	    /* If the references section group is a normal section
7431c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	       group and has one element remaining, or if it is an
7441c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	       empty COMDAT section group it is removed.  */
7451c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	    bool is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
7461c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath			      & GRP_COMDAT) != 0;
747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    --shdr_info[idx].group_cnt;
749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if ((!is_comdat && shdr_info[idx].group_cnt == 1)
750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		|| (is_comdat && shdr_info[idx].group_cnt == 0))
751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		shdr_info[idx].idx = 0;
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* Continue recursively.  */
754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		idx = shdr_info[idx].group_idx;
755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    else
757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      break;
758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Mark the SHT_NULL section as handled.  */
762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[0].idx = 2;
763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Handle exceptions: section groups and cross-references.  We might
766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     have to repeat this a few times since the resetting of the flag
767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     might propagate.  */
768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  do
769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      changes = false;
771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = 1; cnt < shnum; ++cnt)
773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr_info[cnt].idx == 0)
775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* If a relocation section is marked as being removed make
777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 sure the section it is relocating is removed, too.  */
77858d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	      if (shdr_info[cnt].shdr.sh_type == SHT_REL
779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   || shdr_info[cnt].shdr.sh_type == SHT_RELA)
78058d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		{
78158d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		  if (shdr_info[cnt].shdr.sh_info >= shnum)
78258d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    goto illformed;
78358d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		  else if (shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
78458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    shdr_info[cnt].idx = 1;
78558d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		}
7867a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard
7877a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard	      /* If a group section is marked as being removed make
7887a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		 sure all the sections it contains are being removed, too.  */
7897a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard	      if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
7907a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		{
7917a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		  Elf32_Word *grpref;
7927a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		  grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
7937a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		  for (size_t in = 1;
7947a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		       in < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
7957a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		       ++in)
7966d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    if (grpref[in] < shnum)
7977a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		      {
7986d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			if (shdr_info[grpref[in]].idx != 0)
7996d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			  {
8006d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			    shdr_info[cnt].idx = 1;
8016d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			    break;
8026d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			  }
8037a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		      }
8046d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    else
8056d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		      goto illformed;
8067a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		}
807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr_info[cnt].idx == 1)
810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* The content of symbol tables we don't remove must not
812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 reference any section which we do remove.  Otherwise
813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 we cannot remove the section.  */
814521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      if (debug_fname != NULL
815521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  && shdr_info[cnt].debug_data == NULL
816521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  && (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
817521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB))
818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Make sure the data is loaded.  */
820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (shdr_info[cnt].data == NULL)
821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      shdr_info[cnt].data
823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			= elf_getdata (shdr_info[cnt].scn, NULL);
824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (shdr_info[cnt].data == NULL)
825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			INTERNAL_ERROR (fname);
826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
8271c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath		  Elf_Data *symdata = shdr_info[cnt].data;
828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* If there is an extended section index table load it
830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     as well.  */
831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (shdr_info[cnt].symtab_idx != 0
832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
83458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		      elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
836b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      shdr_info[shdr_info[cnt].symtab_idx].data
837b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			= elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				       NULL);
839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
840b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			INTERNAL_ERROR (fname);
841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
8421c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath		  Elf_Data *xndxdata
8431c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath		    = shdr_info[shdr_info[cnt].symtab_idx].data;
844b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
845b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Go through all symbols and make sure the section they
846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     reference is not removed.  */
847a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard		  size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  for (size_t inner = 0;
850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       inner < shdr_info[cnt].data->d_size / elsize;
851b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       ++inner)
852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
853b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Sym sym_mem;
854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      Elf32_Word xndx;
8551c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath		      GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
8561c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath							inner, &sym_mem,
8571c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath							&xndx);
858b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (sym == NULL)
859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			INTERNAL_ERROR (fname);
860b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
8611c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath		      size_t scnidx = sym->st_shndx;
862b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (scnidx == SHN_UNDEF || scnidx >= shnum
863b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  || (scnidx >= SHN_LORESERVE
864b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      && scnidx <= SHN_HIRESERVE
865b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      && scnidx != SHN_XINDEX)
866b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  /* Don't count in the section symbols.  */
867b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
868b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			/* This is no section index, leave it alone.  */
869b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			continue;
870b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      else if (scnidx == SHN_XINDEX)
871b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			scnidx = xndx;
872b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
87358d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		      if (scnidx >= shnum)
87458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath			goto illformed;
87558d3619facfb708f4998d73270ca4082b20853b9Roland McGrath
876b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (shdr_info[scnidx].idx == 0)
877521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			/* This symbol table has a real symbol in
878521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			   a discarded section.  So preserve the
879521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			   original table in the debug file.  */
880521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			shdr_info[cnt].debug_data = symdata;
881b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
882b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
883b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
884b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Cross referencing happens:
885b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 - for the cases the ELF specification says.  That are
886b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_DYNAMIC in sh_link to string table
887b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_HASH in sh_link to symbol table
888b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_REL and SHT_RELA in sh_link to symbol table
889b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
890b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_GROUP in sh_link to symbol table
891b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_SYMTAB_SHNDX in sh_link to symbol table
892b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   Other (OS or architecture-specific) sections might as
893b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   well use this field so we process it unconditionally.
894b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 - references inside section groups
895b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 - specially marked references in sh_info if the SHF_INFO_LINK
896b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 flag is set
897b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      */
898b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
899b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
900b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
901b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
902b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  changes |= shdr_info[cnt].shdr.sh_link < cnt;
903b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
904b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Handle references through sh_info.  */
90658d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	      if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
907b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
90858d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		  if (shdr_info[cnt].shdr.sh_info >= shnum)
90958d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    goto illformed;
91058d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		  else if ( shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
91158d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    {
91258d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		      shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
91358d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		      changes |= shdr_info[cnt].shdr.sh_info < cnt;
91458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    }
915b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
916b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
917b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Mark the section as investigated.  */
918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      shdr_info[cnt].idx = 2;
919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
920521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
921521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  if (debug_fname != NULL
922521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      && (shdr_info[cnt].idx == 0 || shdr_info[cnt].debug_data != NULL))
923521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    {
924521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      /* This section is being preserved in the debug file.
925521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 Sections it refers to must be preserved there too.
926521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
927521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 In this pass we mark sections to be preserved in both
928521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 files by setting the .debug_data pointer to the original
929521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 file's .data pointer.  Below, we'll copy the section
930521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 contents.  */
931521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
932521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      inline void check_preserved (size_t i)
933521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      {
9346d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		if (i != 0 && i < shnum + 2 && shdr_info[i].idx != 0
93504a14163323bc4d2d335909a2af7259bc53ddf8bRoland McGrath		    && shdr_info[i].debug_data == NULL)
936521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  {
937521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    if (shdr_info[i].data == NULL)
938521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
939521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    if (shdr_info[i].data == NULL)
940521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      INTERNAL_ERROR (fname);
941521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
942521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    shdr_info[i].debug_data = shdr_info[i].data;
943521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    changes |= i < cnt;
944521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  }
945521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      }
946521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
947521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      check_preserved (shdr_info[cnt].shdr.sh_link);
948521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
949521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		check_preserved (shdr_info[cnt].shdr.sh_info);
950521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    }
951b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
952b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
953b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (changes);
954b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
955b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Copy the removed sections to the debug output file.
956b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     The ones that are not removed in the stripped file are SHT_NOBITS.  */
957b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (debug_fname != NULL)
958b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = 1; cnt < shnum; ++cnt)
960b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
961b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  scn = elf_newscn (debugelf);
962b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (scn == NULL)
9636d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    {
9646d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      cleanup_debug ();
9656d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      error (EXIT_FAILURE, 0,
9666d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		     gettext ("while generating output file: %s"),
9676d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		     elf_errmsg (-1));
9686d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    }
969b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
9701c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	  bool discard_section = (shdr_info[cnt].idx > 0
971521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				  && shdr_info[cnt].debug_data == NULL
9729aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath				  && shdr_info[cnt].shdr.sh_type != SHT_NOTE
9737a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard				  && shdr_info[cnt].shdr.sh_type != SHT_GROUP
9741c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath				  && cnt != ehdr->e_shstrndx);
975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
976b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Set the section header in the new file.  */
9771c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	  GElf_Shdr debugshdr = shdr_info[cnt].shdr;
978b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (discard_section)
979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    debugshdr.sh_type = SHT_NOBITS;
980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
9813cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	  if (unlikely (gelf_update_shdr (scn, &debugshdr) == 0))
982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* There cannot be any overflows.  */
983b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    INTERNAL_ERROR (fname);
984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
985b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Get the data from the old file if necessary. */
986b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr_info[cnt].data == NULL)
987b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
988b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (shdr_info[cnt].data == NULL)
990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		INTERNAL_ERROR (fname);
991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
992b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
993b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Set the data.  This is done by copying from the old file.  */
9941c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	  Elf_Data *debugdata = elf_newdata (scn);
995b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (debugdata == NULL)
996b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    INTERNAL_ERROR (fname);
997b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
998b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Copy the structure.  This data may be modified in place
999b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     before we write out the file.  */
1000b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  *debugdata = *shdr_info[cnt].data;
1001b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (discard_section)
1002b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    debugdata->d_buf = NULL;
10037a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard	  else if (shdr_info[cnt].debug_data != NULL
10047a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		   || shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1005521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    {
1006521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      /* Copy the original data before it gets modified.  */
1007521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      shdr_info[cnt].debug_data = debugdata;
10086d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (debugdata->d_buf == NULL)
10096d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		INTERNAL_ERROR (fname);
1010521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      debugdata->d_buf = memcpy (xmalloc (debugdata->d_size),
1011521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath					 debugdata->d_buf, debugdata->d_size);
1012521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    }
1013b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1014b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1015b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Finish the ELF header.  Fill in the fields not handled by
1016b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 libelf from the old file.  */
1017b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
1018b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (debugehdr == NULL)
1019b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	INTERNAL_ERROR (fname);
1020b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1021b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
1022b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_type = ehdr->e_type;
1023b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_machine = ehdr->e_machine;
1024b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_version = ehdr->e_version;
1025b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_entry = ehdr->e_entry;
1026b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_flags = ehdr->e_flags;
1027b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_shstrndx = ehdr->e_shstrndx;
1028b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
10293cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper      if (unlikely (gelf_update_ehdr (debugelf, debugehdr) == 0))
1030b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1031b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, 0, gettext ("%s: error while creating ELF header: %s"),
1032b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 debug_fname, elf_errmsg (-1));
1033b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
1034b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto fail_close;
1035b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1036b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1037b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1038b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Mark the section header string table as unused, we will create
1039b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     a new one.  */
1040b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[shstrndx].idx = 0;
1041b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1042b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We need a string table for the section headers.  */
1043b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shst = ebl_strtabinit (true);
1044b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shst == NULL)
10456d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    {
10466d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
10476d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      error (EXIT_FAILURE, errno, gettext ("while preparing output for '%s'"),
10486d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     output_fname ?: fname);
10496d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    }
1050b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Assign new section numbers.  */
1052b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[0].idx = 0;
1053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = idx = 1; cnt < shnum; ++cnt)
1054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (shdr_info[cnt].idx > 0)
1055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].idx = idx++;
1057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Create a new section.  */
1059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].newscn = elf_newscn (newelf);
1060b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (shdr_info[cnt].newscn == NULL)
10616d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  {
10626d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    cleanup_debug ();
10636d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    error (EXIT_FAILURE, 0,
10646d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		   gettext ("while generating output file: %s"),
10656d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		   elf_errmsg (-1));
10666d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  }
1067b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
106858d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
1069b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Add this name to the section header string table.  */
1071b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);
1072b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1073b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1074b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Test whether we are doing anything at all.  */
1075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (cnt == idx)
1076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Nope, all removable sections are already gone.  */
1077b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    goto fail_close;
1078b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Create the reference to the file with the debug info.  */
1080f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath  if (debug_fname != NULL && !remove_shdrs)
1081b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1082b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Add the section header string table section name.  */
1083b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].se = ebl_strtabadd (shst, ".gnu_debuglink", 15);
1084b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].idx = idx++;
1085b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1086b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Create the section header.  */
1087b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
1088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_flags = 0;
1089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_addr = 0;
1090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1091b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1092b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_entsize = 0;
1093b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_addralign = 4;
1094b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We set the offset to zero here.  Before we write the ELF file the
1095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 field must have the correct value.  This is done in the final
1096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 loop over all section.  Then we have all the information needed.  */
1097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_offset = 0;
1098b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1099b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Create the section.  */
1100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].newscn = elf_newscn (newelf);
1101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr_info[cnt].newscn == NULL)
11026d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	{
11036d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  cleanup_debug ();
11046d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  error (EXIT_FAILURE, 0,
11056d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		 gettext ("while create section header section: %s"),
11066d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		 elf_errmsg (-1));
11076d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	}
110858d3619facfb708f4998d73270ca4082b20853b9Roland McGrath      elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
1109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
1111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr_info[cnt].data == NULL)
11126d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	{
11136d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  cleanup_debug ();
11146d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  error (EXIT_FAILURE, 0, gettext ("cannot allocate section data: %s"),
11156d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		 elf_errmsg (-1));
11166d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	}
1117b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
11181c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath      char *debug_basename = basename (debug_fname_embed ?: debug_fname);
11191c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath      off_t crc_offset = strlen (debug_basename) + 1;
1120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Align to 4 byte boundary */
1121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      crc_offset = ((crc_offset - 1) & ~3) + 4;
1122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].data->d_align = 4;
1124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
1125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	= crc_offset + 4;
1126a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard      debuglink_buf = xcalloc (1, shdr_info[cnt].data->d_size);
1127a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard      shdr_info[cnt].data->d_buf = debuglink_buf;
1128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      strcpy (shdr_info[cnt].data->d_buf, debug_basename);
1130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Cache this Elf_Data describing the CRC32 word in the section.
1132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 We'll fill this in when we have written the debug file.  */
1133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debuglink_crc_data = *shdr_info[cnt].data;
1134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debuglink_crc_data.d_buf = ((char *) debuglink_crc_data.d_buf
1135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				  + crc_offset);
1136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debuglink_crc_data.d_size = 4;
1137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* One more section done.  */
1139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ++cnt;
1140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Index of the section header table in the shdr_info array.  */
1143e219f1c1b2a5a2e4f248714fdc93d031cdc5ee6aUlrich Drepper  shdridx = cnt;
1144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Add the section header string table section name.  */
1146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].se = ebl_strtabadd (shst, ".shstrtab", 10);
1147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].idx = idx;
1148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Create the section header.  */
1150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
1151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_flags = 0;
1152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_addr = 0;
1153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_entsize = 0;
1156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We set the offset to zero here.  Before we write the ELF file the
1157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     field must have the correct value.  This is done in the final
1158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     loop over all section.  Then we have all the information needed.  */
1159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_offset = 0;
1160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_addralign = 1;
1161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Create the section.  */
1163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].newscn = elf_newscn (newelf);
1164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr_info[cnt].newscn == NULL)
11656d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    {
11666d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
11676d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      error (EXIT_FAILURE, 0,
11686d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     gettext ("while create section header section: %s"),
11696d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     elf_errmsg (-1));
11706d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    }
117158d3619facfb708f4998d73270ca4082b20853b9Roland McGrath  elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
1172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Finalize the string table and fill in the correct indices in the
1174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     section headers.  */
1175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
1176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shstrtab_data == NULL)
11776d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    {
11786d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
11796d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      error (EXIT_FAILURE, 0,
11806d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     gettext ("while create section header string table: %s"),
11816d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     elf_errmsg (-1));
11826d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    }
1183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl_strtabfinalize (shst, shstrtab_data);
1184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We have to set the section size.  */
1186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
1187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Update the section information.  */
1189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Off lastoffset = 0;
1190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 1; cnt <= shdridx; ++cnt)
1191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (shdr_info[cnt].idx > 0)
1192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf_Data *newdata;
1194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	scn = elf_getscn (newelf, shdr_info[cnt].idx);
11966d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	elf_assert (scn != NULL);
1197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Update the name.  */
1199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].shdr.sh_name = ebl_strtaboffset (shdr_info[cnt].se);
1200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Update the section header from the input file.  Some fields
1202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   might be section indeces which now have to be adjusted.  */
1203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (shdr_info[cnt].shdr.sh_link != 0)
1204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[cnt].shdr.sh_link =
1205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    shdr_info[shdr_info[cnt].shdr.sh_link].idx;
1206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
12096d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr_info[cnt].data != NULL
12106d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			&& shdr_info[cnt].data->d_buf != NULL);
1211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    for (size_t inner = 0;
1214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 ++inner)
12166d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (grpref[inner] < shnum)
12176d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		grpref[inner] = shdr_info[grpref[inner]].idx;
12186d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      else
12196d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		goto illformed;
1220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
1221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag.  */
1223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[cnt].shdr.sh_info =
1225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    shdr_info[shdr_info[cnt].shdr.sh_info].idx;
1226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Get the data from the old file if necessary.  We already
12283a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper	   created the data for the section header string table.  */
1229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (cnt < shnum)
1230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
1231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (shdr_info[cnt].data == NULL)
1232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
1233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (shdr_info[cnt].data == NULL)
1235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  INTERNAL_ERROR (fname);
1236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
1237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Set the data.  This is done by copying from the old file.  */
1239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    newdata = elf_newdata (scn);
1240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (newdata == NULL)
1241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      INTERNAL_ERROR (fname);
1242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Copy the structure.  */
1244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    *newdata = *shdr_info[cnt].data;
1245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* We know the size.  */
1247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
1248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1249521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* We have to adjust symbol tables.  The st_shndx member might
1250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       have to be updated.  */
1251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
1252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		|| shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
1253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
1254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		Elf_Data *versiondata = NULL;
1255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		Elf_Data *shndxdata = NULL;
1256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1257a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
1258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (shdr_info[cnt].symtab_idx != 0)
1260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
12616d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
1262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* This section has extended section information.
1263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       We have to modify that information, too.  */
1264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
1265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					     NULL);
1266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
126758d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    elf_assert ((versiondata->d_size / sizeof (Elf32_Word))
12686d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				>= shdr_info[cnt].data->d_size / elsize);
1269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
1270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (shdr_info[cnt].version_idx != 0)
1272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
127358d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    elf_assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
1274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* This section has associated version
1275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       information.  We have to modify that
1276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       information, too.  */
1277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
1278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					       NULL);
1279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
12806d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    elf_assert (versiondata != NULL
12816d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				&& versiondata->d_buf != NULL
12826d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				&& ((versiondata->d_size / sizeof (GElf_Versym))
12836d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				    >= shdr_info[cnt].data->d_size / elsize));
1284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
1285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		shdr_info[cnt].newsymidx
1287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  = (Elf32_Word *) xcalloc (shdr_info[cnt].data->d_size
1288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					    / elsize, sizeof (Elf32_Word));
1289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		bool last_was_local = true;
1291b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		size_t destidx;
1292b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		size_t inner;
1293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		for (destidx = inner = 1;
1294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     inner < shdr_info[cnt].data->d_size / elsize;
1295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ++inner)
1296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
1297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    Elf32_Word sec;
1298b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    GElf_Sym sym_mem;
1299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    Elf32_Word xshndx;
1300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
1301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						      shndxdata, inner,
1302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						      &sym_mem, &xshndx);
1303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sym == NULL)
1304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      INTERNAL_ERROR (fname);
1305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sym->st_shndx == SHN_UNDEF
1307b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			|| (sym->st_shndx >= shnum
1308b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    && sym->st_shndx != SHN_XINDEX))
1309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      {
1310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			/* This is no section index, leave it alone
1311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   unless it is moved.  */
1312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (destidx != inner
1313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    && gelf_update_symshndx (shdr_info[cnt].data,
1314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						     shndxdata,
1315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						     destidx, sym,
1316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						     xshndx) == 0)
1317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  INTERNAL_ERROR (fname);
1318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			shdr_info[cnt].newsymidx[inner] = destidx++;
1320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (last_was_local
1322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  {
1324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    last_was_local = false;
1325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    shdr_info[cnt].shdr.sh_info = destidx - 1;
1326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  }
1327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			continue;
1329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      }
1330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* Get the full section index, if necessary from the
1332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       XINDEX table.  */
1333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sym->st_shndx != SHN_XINDEX)
1334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      sec = shdr_info[sym->st_shndx].idx;
1335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else
1336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      {
13376d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			elf_assert (shndxdata != NULL
13386d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				    && shndxdata->d_buf != NULL);
1339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			sec = shdr_info[xshndx].idx;
1341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      }
1342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sec != 0)
1344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      {
1345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			GElf_Section nshndx;
1346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			Elf32_Word nxshndx;
1347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (sec < SHN_LORESERVE)
1349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  {
1350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    nshndx = sec;
1351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    nxshndx = 0;
1352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  }
1353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			else
1354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  {
1355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    nshndx = SHN_XINDEX;
1356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    nxshndx = sec;
1357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  }
1358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
135958d3619facfb708f4998d73270ca4082b20853b9Roland McGrath			elf_assert (sec < SHN_LORESERVE || shndxdata != NULL);
1360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if ((inner != destidx || nshndx != sym->st_shndx
1362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     || (shndxdata != NULL && nxshndx != xshndx))
1363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    && (sym->st_shndx = nshndx,
1364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				gelf_update_symshndx (shdr_info[cnt].data,
1365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						      shndxdata,
1366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						      destidx, sym,
1367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						      nxshndx) == 0))
1368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  INTERNAL_ERROR (fname);
1369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			shdr_info[cnt].newsymidx[inner] = destidx++;
1371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (last_was_local
1373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  {
1375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    last_was_local = false;
1376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    shdr_info[cnt].shdr.sh_info = destidx - 1;
1377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  }
1378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      }
1379521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    else if (debug_fname == NULL
1380521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			     || shdr_info[cnt].debug_data == NULL)
13817a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		      /* This is a section or group signature symbol
13827a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard			 for a section which has been removed.  */
13837a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		      {
13847a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard			size_t sidx = (sym->st_shndx != SHN_XINDEX
13857a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard					? sym->st_shndx : xshndx);
138658d3619facfb708f4998d73270ca4082b20853b9Roland McGrath			elf_assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION
138758d3619facfb708f4998d73270ca4082b20853b9Roland McGrath				    || ((shdr_info[sidx].shdr.sh_type
138858d3619facfb708f4998d73270ca4082b20853b9Roland McGrath					 == SHT_GROUP)
138958d3619facfb708f4998d73270ca4082b20853b9Roland McGrath					&& (shdr_info[sidx].shdr.sh_info
139058d3619facfb708f4998d73270ca4082b20853b9Roland McGrath					    == inner)));
13917a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		      }
1392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
1393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (destidx != inner)
1395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
1396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* The size of the symbol table changed.  */
1397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    shdr_info[cnt].shdr.sh_size = newdata->d_size
1398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      = destidx * elsize;
1399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    any_symtab_changes = true;
1400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
1401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
1402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
1403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* The symbol table didn't really change.  */
1404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    free (shdr_info[cnt].newsymidx);
1405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    shdr_info[cnt].newsymidx = NULL;
1406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
1407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
1408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
1409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* If we have to, compute the offset of the section.  */
1411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (shdr_info[cnt].shdr.sh_offset == 0)
1412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[cnt].shdr.sh_offset
1413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
1414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
1415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Set the section header in the new file.  */
1417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
1418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* There cannot be any overflows.  */
1419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  INTERNAL_ERROR (fname);
1420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Remember the last section written so far.  */
1422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
1423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   ? shdr_info[cnt].shdr.sh_size : 0);
1424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
1425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
1426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Adjust symbol references if symbol tables changed.  */
1429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (any_symtab_changes)
1430521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath    /* Find all relocation sections which use this symbol table.  */
1431521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath    for (cnt = 1; cnt <= shdridx; ++cnt)
1432521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      {
1433521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	/* Update section headers when the data size has changed.
1434521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	   We also update the SHT_NOBITS section in the debug
1435521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	   file so that the section headers match in sh_size.  */
1436521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	inline void update_section_size (const Elf_Data *newdata)
1437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1438521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  GElf_Shdr shdr_mem;
1439521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1440521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  shdr->sh_size = newdata->d_size;
1441521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  (void) gelf_update_shdr (scn, shdr);
1442521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  if (debugelf != NULL)
14439aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	    {
1444521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      /* libelf will use d_size to set sh_size.  */
1445521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
1446521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath							     cnt), NULL);
14476d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (debugdata == NULL)
14486d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		INTERNAL_ERROR (fname);
1449521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      debugdata->d_size = newdata->d_size;
14509aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	    }
1451521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	}
14529aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath
1453521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	if (shdr_info[cnt].idx == 0 && debug_fname == NULL)
1454521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  /* Ignore sections which are discarded.  When we are saving a
1455521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	     relocation section in a separate debug file, we must fix up
1456521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	     the symbol table references.  */
1457521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  continue;
1458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1459521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	const Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
14606d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	elf_assert (symtabidx < shnum + 2);
1461521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
1462521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	switch (shdr_info[cnt].shdr.sh_type)
1463521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  {
1464521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    inline bool no_symtab_updates (void)
1465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* If the symbol table hasn't changed, do not do anything.  */
1467521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      if (shdr_info[symtabidx].newsymidx == NULL)
1468521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		return true;
1469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1470521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      /* If the symbol table is not discarded, but additionally
1471521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 duplicated in the separate debug file and this section
1472521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 is discarded, don't adjust anything.  */
1473521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      return (shdr_info[cnt].idx == 0
1474521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      && shdr_info[symtabidx].debug_data != NULL);
1475521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    }
1476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1477521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  case SHT_REL:
1478521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  case SHT_RELA:
1479521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (no_symtab_updates ())
1480521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      break;
1481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1482521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    Elf_Data *d = elf_getdata (shdr_info[cnt].idx == 0
1483521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       ? elf_getscn (debugelf, cnt)
1484521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       : elf_getscn (newelf,
1485521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath						     shdr_info[cnt].idx),
1486521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       NULL);
14876d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (d != NULL && d->d_buf != NULL
14886d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			&& shdr_info[cnt].shdr.sh_entsize != 0);
1489521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    size_t nrels = (shdr_info[cnt].shdr.sh_size
1490521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			    / shdr_info[cnt].shdr.sh_entsize);
1491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
14926d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    size_t symsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
14936d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    const Elf32_Word symidxn = (shdr_info[symtabidx].data->d_size
14946d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard					/ symsize);
1495521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (shdr_info[cnt].shdr.sh_type == SHT_REL)
1496521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      for (size_t relidx = 0; relidx < nrels; ++relidx)
1497521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		{
1498521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  GElf_Rel rel_mem;
1499521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  if (gelf_getrel (d, relidx, &rel_mem) == NULL)
1500521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    INTERNAL_ERROR (fname);
1501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1502521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  size_t symidx = GELF_R_SYM (rel_mem.r_info);
15036d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		  elf_assert (symidx < symidxn);
1504521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  if (newsymidx[symidx] != symidx)
1505521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    {
1506521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      rel_mem.r_info
1507521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			= GELF_R_INFO (newsymidx[symidx],
1508521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       GELF_R_TYPE (rel_mem.r_info));
1509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1510521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      if (gelf_update_rel (d, relidx, &rel_mem) == 0)
1511521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			INTERNAL_ERROR (fname);
1512521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    }
1513521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		}
1514521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    else
1515521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      for (size_t relidx = 0; relidx < nrels; ++relidx)
1516521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		{
1517521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  GElf_Rela rel_mem;
1518521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  if (gelf_getrela (d, relidx, &rel_mem) == NULL)
1519521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    INTERNAL_ERROR (fname);
1520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1521521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  size_t symidx = GELF_R_SYM (rel_mem.r_info);
15226d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		  elf_assert (symidx < symidxn);
1523521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  if (newsymidx[symidx] != symidx)
1524521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    {
1525521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      rel_mem.r_info
1526521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			= GELF_R_INFO (newsymidx[symidx],
1527521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       GELF_R_TYPE (rel_mem.r_info));
1528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1529521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      if (gelf_update_rela (d, relidx, &rel_mem) == 0)
1530521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			INTERNAL_ERROR (fname);
1531521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    }
1532521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		}
1533521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    break;
1534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1535521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  case SHT_HASH:
1536521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (no_symtab_updates ())
1537521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      break;
1538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1539521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* We have to recompute the hash table.  */
1540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
15416d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr_info[cnt].idx > 0);
1542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1543521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The hash section in the new file.  */
1544521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    scn = elf_getscn (newelf, shdr_info[cnt].idx);
1545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1546521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The symbol table data.  */
1547521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    Elf_Data *symd = elf_getdata (elf_getscn (newelf,
1548521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath						      shdr_info[symtabidx].idx),
1549521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath					  NULL);
15506d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (symd != NULL && symd->d_buf != NULL);
1551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1552521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The hash table data.  */
1553521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    Elf_Data *hashd = elf_getdata (scn, NULL);
15546d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (hashd != NULL && hashd->d_buf != NULL);
1555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1556521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (shdr_info[cnt].shdr.sh_entsize == sizeof (Elf32_Word))
1557521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      {
1558521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Sane arches first.  */
15596d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (hashd->d_size >= 2 * sizeof (Elf32_Word));
1560521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
1561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1562521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		size_t strshndx = shdr_info[symtabidx].old_sh_link;
1563a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
1564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
15656d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		Elf32_Word nchain = bucket[1];
15666d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		Elf32_Word nbucket = bucket[0];
15676d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		uint64_t used_buf = ((2ULL + nchain + nbucket)
15686d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				     * sizeof (Elf32_Word));
15696d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (used_buf <= hashd->d_size);
15706d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard
1571521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Adjust the nchain value.  The symbol table size
1572521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		   changed.  We keep the same size for the bucket array.  */
1573521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		bucket[1] = symd->d_size / elsize;
1574521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		bucket += 2;
1575521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		Elf32_Word *chain = bucket + nbucket;
1576521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1577521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* New size of the section.  */
15786d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		size_t n_size = ((2 + symd->d_size / elsize + nbucket)
1579521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				 * sizeof (Elf32_Word));
15806d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (n_size <= hashd->d_size);
15816d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		hashd->d_size = n_size;
1582521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		update_section_size (hashd);
1583521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1584521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Clear the arrays.  */
1585521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		memset (bucket, '\0',
1586521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			(symd->d_size / elsize + nbucket)
1587521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			* sizeof (Elf32_Word));
1588521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1589521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1590521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		     inner < symd->d_size / elsize; ++inner)
1591521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  {
1592521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    GElf_Sym sym_mem;
1593521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
159458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    elf_assert (sym != NULL);
1595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1596521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    const char *name = elf_strptr (elf, strshndx,
1597521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath						   sym->st_name);
15986d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    elf_assert (name != NULL && nbucket != 0);
1599521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    size_t hidx = elf_hash (name) % nbucket;
1600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1601521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    if (bucket[hidx] == 0)
1602521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      bucket[hidx] = inner;
1603521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    else
1604521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      {
1605521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			hidx = bucket[hidx];
1606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
16076d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			while (chain[hidx] != 0 && chain[hidx] < nchain)
1608521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			  hidx = chain[hidx];
1609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1610521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			chain[hidx] = inner;
1611521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      }
1612521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  }
1613521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      }
1614521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    else
1615521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      {
1616521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Alpha and S390 64-bit use 64-bit SHT_HASH entries.  */
161758d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		elf_assert (shdr_info[cnt].shdr.sh_entsize
161858d3619facfb708f4998d73270ca4082b20853b9Roland McGrath			    == sizeof (Elf64_Xword));
1619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1620521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
1621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1622521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		size_t strshndx = shdr_info[symtabidx].old_sh_link;
1623a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
1624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
16256d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (symd->d_size >= 2 * sizeof (Elf64_Xword));
16266d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		Elf64_Xword nbucket = bucket[0];
16276d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		Elf64_Xword nchain = bucket[1];
16286d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		uint64_t maxwords = hashd->d_size / sizeof (Elf64_Xword);
16296d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (maxwords >= 2
16306d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			    && maxwords - 2 >= nbucket
16316d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			    && maxwords - 2 - nbucket >= nchain);
16326d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard
1633521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Adjust the nchain value.  The symbol table size
1634521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		   changed.  We keep the same size for the bucket array.  */
1635521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		bucket[1] = symd->d_size / elsize;
1636521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		bucket += 2;
1637521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		Elf64_Xword *chain = bucket + nbucket;
1638521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1639521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* New size of the section.  */
16406d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		size_t n_size = ((2 + symd->d_size / elsize + nbucket)
1641521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				 * sizeof (Elf64_Xword));
16426d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (n_size <= hashd->d_size);
16436d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		hashd->d_size = n_size;
1644521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		update_section_size (hashd);
1645521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1646521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Clear the arrays.  */
1647521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		memset (bucket, '\0',
1648521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			(symd->d_size / elsize + nbucket)
1649521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			* sizeof (Elf64_Xword));
1650521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1651521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1652521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		     inner < symd->d_size / elsize; ++inner)
1653521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  {
1654521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    GElf_Sym sym_mem;
1655521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
165658d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    elf_assert (sym != NULL);
1657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1658521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    const char *name = elf_strptr (elf, strshndx,
1659521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath						   sym->st_name);
16606d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    elf_assert (name != NULL && nbucket != 0);
1661521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    size_t hidx = elf_hash (name) % nbucket;
1662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1663521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    if (bucket[hidx] == 0)
1664521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      bucket[hidx] = inner;
1665521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    else
1666521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      {
1667521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			hidx = bucket[hidx];
1668521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
16696d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			while (chain[hidx] != 0 && chain[hidx] < nchain)
1670521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			  hidx = chain[hidx];
1671521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1672521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			chain[hidx] = inner;
1673521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      }
1674521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  }
1675521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      }
1676521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    break;
1677521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1678521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  case SHT_GNU_versym:
1679521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* If the symbol table changed we have to adjust the entries.  */
1680521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (no_symtab_updates ())
1681521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      break;
1682521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
16836d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr_info[cnt].idx > 0);
1684521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1685521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The symbol version section in the new file.  */
1686521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    scn = elf_getscn (newelf, shdr_info[cnt].idx);
1687521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1688521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The symbol table data.  */
1689521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    symd = elf_getdata (elf_getscn (newelf, shdr_info[symtabidx].idx),
1690521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				NULL);
16916d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (symd != NULL && symd->d_buf != NULL);
16926d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    size_t symz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
16936d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    const Elf32_Word syms = (shdr_info[symtabidx].data->d_size / symz);
1694521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1695521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The version symbol data.  */
1696521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    Elf_Data *verd = elf_getdata (scn, NULL);
16976d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (verd != NULL && verd->d_buf != NULL);
1698521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1699521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The symbol version array.  */
1700521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    GElf_Half *verstab = (GElf_Half *) verd->d_buf;
1701521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1702521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* Walk through the list and */
1703a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard	    size_t elsize = gelf_fsize (elf, verd->d_type, 1, EV_CURRENT);
17046d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    Elf32_Word vers = verd->d_size / elsize;
17056d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    for (size_t inner = 1; inner < vers && inner < syms; ++inner)
17066d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (newsymidx[inner] != 0 && newsymidx[inner] < vers)
1707521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Overwriting the same array works since the
1708521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		   reordering can only move entries to lower indices
1709521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		   in the array.  */
1710521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		verstab[newsymidx[inner]] = verstab[inner];
1711521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1712521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* New size of the section.  */
1713521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    verd->d_size = gelf_fsize (newelf, verd->d_type,
1714521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       symd->d_size
1715521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       / gelf_fsize (elf, symd->d_type, 1,
1716a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard						     EV_CURRENT),
1717a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard				       EV_CURRENT);
1718521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    update_section_size (verd);
1719521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    break;
1720521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1721521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  case SHT_GROUP:
1722521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (no_symtab_updates ())
1723521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      break;
1724521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1725521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* Yes, the symbol table changed.
1726521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	       Update the section header of the section group.  */
1727521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    scn = elf_getscn (newelf, shdr_info[cnt].idx);
1728521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    GElf_Shdr shdr_mem;
1729521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
17306d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr != NULL);
1731521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
17326d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    size_t symsz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
17336d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    const Elf32_Word symn = (shdr_info[symtabidx].data->d_size
17346d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				     / symsz);
17356d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr->sh_info < symn);
1736521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    shdr->sh_info = newsymidx[shdr->sh_info];
1737521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1738521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    (void) gelf_update_shdr (scn, shdr);
1739521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    break;
1740521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  }
1741521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      }
1742b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
17431662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard  /* Remove any relocations between debug sections in ET_REL
17441662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard     for the debug file when requested.  These relocations are always
17451662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard     zero based between the unallocated sections.  */
17461662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard  if (debug_fname != NULL && reloc_debug && ehdr->e_type == ET_REL)
17471662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard    {
17481662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard      scn = NULL;
17491662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard      cnt = 0;
17501662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard      while ((scn = elf_nextscn (debugelf, scn)) != NULL)
17511662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	{
17521662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	  cnt++;
17531662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	  /* We need the actual section and header from the debugelf
17541662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	     not just the cached original in shdr_info because we
17551662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	     might want to change the size.  */
17561662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	  GElf_Shdr shdr_mem;
17571662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
17581662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	  if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
17591662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	    {
17601662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      /* Make sure that this relocation section points to a
17611662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 section to relocate with contents, that isn't
17621662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 allocated and that is a debug section.  */
17631662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      Elf_Scn *tscn = elf_getscn (debugelf, shdr->sh_info);
17641662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      GElf_Shdr tshdr_mem;
17651662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
17661662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      if (tshdr->sh_type == SHT_NOBITS
17671662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  || tshdr->sh_size == 0
17681662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  || (tshdr->sh_flags & SHF_ALLOC) != 0)
17691662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		continue;
17701662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
17711662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      const char *tname =  elf_strptr (debugelf, shstrndx,
17721662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard					       tshdr->sh_name);
17731662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      if (! tname || ! ebl_debugscn_p (ebl, tname))
17741662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		continue;
17751662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
17761662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      /* OK, lets relocate all trivial cross debug section
17771662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 relocations. */
17781662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      Elf_Data *reldata = elf_getdata (scn, NULL);
17796d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (reldata == NULL || reldata->d_buf == NULL)
17806d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		INTERNAL_ERROR (fname);
17811662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      /* We actually wanted the rawdata, but since we already
17821662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 accessed it earlier as elf_getdata () that won't
17831662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 work. But debug sections are all ELF_T_BYTE, so it
17841662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 doesn't really matter.  */
17851662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      Elf_Data *tdata = elf_getdata (tscn, NULL);
17866d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (tdata == NULL || tdata->d_buf == NULL
17876d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		  || tdata->d_type != ELF_T_BYTE)
17881662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		INTERNAL_ERROR (fname);
17891662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
17901662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      /* Pick up the symbol table and shndx table to
17911662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 resolve relocation symbol indexes.  */
17921662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      Elf64_Word symt = shdr->sh_link;
17931662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      Elf_Data *symdata, *xndxdata;
17946d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      elf_assert (symt < shnum + 2);
17956d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      elf_assert (shdr_info[symt].symtab_idx < shnum + 2);
17961662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      symdata = (shdr_info[symt].debug_data
17971662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			 ?: shdr_info[symt].data);
17981662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      xndxdata = (shdr_info[shdr_info[symt].symtab_idx].debug_data
17991662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			  ?: shdr_info[shdr_info[symt].symtab_idx].data);
18001662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
18011662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      /* Apply one relocation.  Returns true when trivial
18021662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 relocation actually done.  */
18031662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      bool relocate (GElf_Addr offset, const GElf_Sxword addend,
180463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			     bool is_rela, int rtype, int symndx)
18051662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      {
18061662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		/* R_*_NONE relocs can always just be removed.  */
18071662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		if (rtype == 0)
18081662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  return true;
18091662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
18101662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		/* We only do simple absolute relocations.  */
18111662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		Elf_Type type = ebl_reloc_simple_type (ebl, rtype);
18121662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		if (type == ELF_T_NUM)
18131662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  return false;
18141662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
18151662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		/* These are the types we can relocate.  */
18161662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard#define TYPES   DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half);		\
18171662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword);		\
18181662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
18191662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
18201662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		/* And only for relocations against other debug sections.  */
18211662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		GElf_Sym sym_mem;
18221662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		Elf32_Word xndx;
18231662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
18241662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard						  symndx, &sym_mem,
18251662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard						  &xndx);
182663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		Elf32_Word sec = (sym->st_shndx == SHN_XINDEX
182763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard				  ? xndx : sym->st_shndx);
18286d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		if (sec >= shnum + 2)
18296d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		  INTERNAL_ERROR (fname);
18306d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard
183163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		if (ebl_debugscn_p (ebl, shdr_info[sec].name))
18321662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  {
183363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    size_t size;
18341662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
18351662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard#define DO_TYPE(NAME, Name) GElf_##Name Name;
183663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    union { TYPES; } tmpbuf;
18371662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard#undef DO_TYPE
18381662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
183963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    switch (type)
184063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
18411662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard#define DO_TYPE(NAME, Name)				\
184263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			case ELF_T_##NAME:		\
184363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			  size = sizeof (GElf_##Name);	\
184463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			  tmpbuf.Name = 0;		\
184563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			  break;
184663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			TYPES;
18471662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard#undef DO_TYPE
184863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      default:
184963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			return false;
185063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      }
185163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard
185202a958bc2662c1c9c2d6b663742b9c8e720e25b2Mark Wielaard		    if (offset > tdata->d_size
185302a958bc2662c1c9c2d6b663742b9c8e720e25b2Mark Wielaard			|| tdata->d_size - offset < size)
18546d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		      {
18556d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			cleanup_debug ();
18566d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			error (EXIT_FAILURE, 0, gettext ("bad relocation"));
18576d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		      }
18581662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
185963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    /* When the symbol value is zero then for SHT_REL
186063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       sections this is all that needs to be checked.
186163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       The addend is contained in the original data at
186263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       the offset already.  So if the (section) symbol
186363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       address is zero and the given addend is zero
186463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       just remove the relocation, it isn't needed
186563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       anymore.  */
186663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    if (addend == 0 && sym->st_value == 0)
186763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      return true;
186863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard
186963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    Elf_Data tmpdata =
187063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
187163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_type = type,
187263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_buf = &tmpbuf,
187363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_size = size,
187463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_version = EV_CURRENT,
187563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      };
187663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    Elf_Data rdata =
187763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
187863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_type = type,
187963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_buf = tdata->d_buf + offset,
188063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_size = size,
188163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_version = EV_CURRENT,
188263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      };
188363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard
188463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    GElf_Addr value = sym->st_value;
188563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    if (is_rela)
188663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
188763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			/* For SHT_RELA sections we just take the
188863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			   given addend and add it to the value.  */
188963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			value += addend;
189063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      }
189163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    else
189263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
189363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			/* For SHT_REL sections we have to peek at
189463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			   what is already in the section at the given
189563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			   offset to get the addend.  */
189663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			Elf_Data *d = gelf_xlatetom (debugelf, &tmpdata,
189763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard						     &rdata,
18981662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard						     ehdr->e_ident[EI_DATA]);
189963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			if (d == NULL)
19001662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			  INTERNAL_ERROR (fname);
190163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			assert (d == &tmpdata);
190263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      }
19031662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
190463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    switch (type)
190563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
190663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard#define DO_TYPE(NAME, Name)					\
190763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			case ELF_T_##NAME:			\
190863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			  tmpbuf.Name += (GElf_##Name) value;	\
190963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			  break;
191063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			TYPES;
191163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard#undef DO_TYPE
191263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      default:
191363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			abort ();
19141662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		      }
191563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard
191663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    /* Now finally put in the new value.  */
191763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    Elf_Data *s = gelf_xlatetof (debugelf, &rdata,
191863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard						 &tmpdata,
191963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard						 ehdr->e_ident[EI_DATA]);
192063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    if (s == NULL)
192163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      INTERNAL_ERROR (fname);
192263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    assert (s == &rdata);
192363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard
192463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    return true;
19251662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  }
19261662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		return false;
19271662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      }
19281662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
19296d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (shdr->sh_entsize == 0)
19306d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		INTERNAL_ERROR (fname);
19316d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard
19321662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      size_t nrels = shdr->sh_size / shdr->sh_entsize;
19331662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      size_t next = 0;
19341662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      if (shdr->sh_type == SHT_REL)
19351662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		for (size_t relidx = 0; relidx < nrels; ++relidx)
19361662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  {
19371662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		    GElf_Rel rel_mem;
19381662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		    GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
193963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    if (! relocate (r->r_offset, 0, false,
19401662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard				    GELF_R_TYPE (r->r_info),
19411662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard				    GELF_R_SYM (r->r_info)))
19421662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		      {
19431662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			if (relidx != next)
19441662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			  gelf_update_rel (reldata, next, r);
19451662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			++next;
19461662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		      }
19471662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  }
19481662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      else
19491662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		for (size_t relidx = 0; relidx < nrels; ++relidx)
19501662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  {
19511662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		    GElf_Rela rela_mem;
19521662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		    GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
195363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    if (! relocate (r->r_offset, r->r_addend, true,
19541662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard				    GELF_R_TYPE (r->r_info),
19551662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard				    GELF_R_SYM (r->r_info)))
19561662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		      {
19571662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			if (relidx != next)
19581662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			  gelf_update_rela (reldata, next, r);
19591662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			++next;
19601662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		      }
19611662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  }
19621662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
19631662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      nrels = next;
19641662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
19651662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      gelf_update_shdr (scn, shdr);
19661662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	    }
19671662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	}
19681662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard    }
19691662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
1970b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now that we have done all adjustments to the data,
1971b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     we can actually write out the debug file.  */
1972b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (debug_fname != NULL)
1973b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1974b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Finally write the file.  */
19753cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper      if (unlikely (elf_update (debugelf, ELF_C_WRITE) == -1))
1976b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1977b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, 0, gettext ("while writing '%s': %s"),
19786d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		 tmp_debug_fname, elf_errmsg (-1));
1979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
1980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto fail_close;
1981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1983b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Create the real output file.  First rename, then change the
1984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 mode.  */
1985b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rename (tmp_debug_fname, debug_fname) != 0
1986b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || fchmod (debug_fd, mode) != 0)
1987b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1988b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("while creating '%s'"), debug_fname);
1989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
1990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto fail_close;
1991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1992b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1993b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* The temporary file does not exist anymore.  */
19946d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      free (tmp_debug_fname);
1995b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      tmp_debug_fname = NULL;
1996b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1997f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath      if (!remove_shdrs)
1998b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1999f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  uint32_t debug_crc;
2000f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  Elf_Data debug_crc_data =
2001f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	    {
2002f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      .d_type = ELF_T_WORD,
2003f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      .d_buf = &debug_crc,
2004f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      .d_size = sizeof (debug_crc),
2005f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      .d_version = EV_CURRENT
2006f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	    };
2007f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath
2008f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  /* Compute the checksum which we will add to the executable.  */
2009f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  if (crc32_file (debug_fd, &debug_crc) != 0)
2010f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	    {
2011f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      error (0, errno, gettext ("\
2012f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrathwhile computing checksum for debug information"));
2013f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      unlink (debug_fname);
2014f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      result = 1;
2015f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      goto fail_close;
2016f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	    }
2017b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2018f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  /* Store it in the debuglink section data.  */
2019f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  if (unlikely (gelf_xlatetof (newelf, &debuglink_crc_data,
2020f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath				       &debug_crc_data, ehdr->e_ident[EI_DATA])
2021f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath			!= &debuglink_crc_data))
2022f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	    INTERNAL_ERROR (fname);
2023f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	}
2024b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2025b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2026b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Finally finish the ELF header.  Fill in the fields not handled by
2027b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     libelf from the old file.  */
2028b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr = gelf_getehdr (newelf, &newehdr_mem);
2029b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (newehdr == NULL)
2030b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    INTERNAL_ERROR (fname);
2031b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2032b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
2033b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_type = ehdr->e_type;
2034b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_machine = ehdr->e_machine;
2035b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_version = ehdr->e_version;
2036b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_entry = ehdr->e_entry;
2037b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_flags = ehdr->e_flags;
2038b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_phoff = ehdr->e_phoff;
20390b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath
2040b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We need to position the section header table.  */
2041b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
2042b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_shoff = ((shdr_info[shdridx].shdr.sh_offset
2043b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       + shdr_info[shdridx].shdr.sh_size + offsize - 1)
2044b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      & ~((GElf_Off) (offsize - 1)));
2045b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
2046b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2047b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* The new section header string table index.  */
2048b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (likely (idx < SHN_HIRESERVE) && likely (idx != SHN_XINDEX))
2049b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    newehdr->e_shstrndx = idx;
2050b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2052b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* The index does not fit in the ELF header field.  */
2053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[0].scn = elf_getscn (elf, 0);
2054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (gelf_getshdr (shdr_info[0].scn, &shdr_info[0].shdr) == NULL)
2056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	INTERNAL_ERROR (fname);
2057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[0].shdr.sh_link = idx;
2059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      (void) gelf_update_shdr (shdr_info[0].scn, &shdr_info[0].shdr);
2060b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      newehdr->e_shstrndx = SHN_XINDEX;
2062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2064b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (gelf_update_ehdr (newelf, newehdr) == 0)
2065b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2066b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("%s: error while creating ELF header: %s"),
20676d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     output_fname ?: fname, elf_errmsg (-1));
20686d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
2069b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 1;
2070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2071b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2072b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We have everything from the old file.  */
2073b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf_cntl (elf, ELF_C_FDDONE) != 0)
2074b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("%s: error while reading the file: %s"),
2076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     fname, elf_errmsg (-1));
20776d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
2078b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 1;
2079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2080b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2081b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* The ELF library better follows our layout when this is not a
2082b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     relocatable object file.  */
2083b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_flagelf (newelf, ELF_C_SET,
2084b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0)
2085b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       | (permissive ? ELF_F_PERMISSIVE : 0));
2086b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2087b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Finally write the file.  */
2088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf_update (newelf, ELF_C_WRITE) == -1)
2089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("while writing '%s': %s"),
20916d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     output_fname ?: fname, elf_errmsg (-1));
2092b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = 1;
2093b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
20940b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath
20950b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath  if (remove_shdrs)
20960b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath    {
20970b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath      /* libelf can't cope without the section headers being properly intact.
20980b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	 So we just let it write them normally, and then we nuke them later.  */
20990b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath
21000b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath      if (newehdr->e_ident[EI_CLASS] == ELFCLASS32)
21010b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	{
21020b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  assert (offsetof (Elf32_Ehdr, e_shentsize) + sizeof (Elf32_Half)
21030b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  == offsetof (Elf32_Ehdr, e_shnum));
21040b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  assert (offsetof (Elf32_Ehdr, e_shnum) + sizeof (Elf32_Half)
21050b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  == offsetof (Elf32_Ehdr, e_shstrndx));
21060b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  const Elf32_Off zero_off = 0;
21070b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  const Elf32_Half zero[3] = { 0, 0, SHN_UNDEF };
21080b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  if (pwrite_retry (fd, &zero_off, sizeof zero_off,
21090b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath			    offsetof (Elf32_Ehdr, e_shoff)) != sizeof zero_off
21100b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      || (pwrite_retry (fd, zero, sizeof zero,
21110b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath				offsetof (Elf32_Ehdr, e_shentsize))
21120b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  != sizeof zero)
21130b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      || ftruncate64 (fd, shdr_info[shdridx].shdr.sh_offset) < 0)
21140b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	    {
21150b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      error (0, errno, gettext ("while writing '%s'"),
21166d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		     output_fname ?: fname);
21170b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      result = 1;
21180b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	    }
21190b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	}
21200b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath      else
21210b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	{
21220b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  assert (offsetof (Elf64_Ehdr, e_shentsize) + sizeof (Elf64_Half)
21230b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  == offsetof (Elf64_Ehdr, e_shnum));
21240b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  assert (offsetof (Elf64_Ehdr, e_shnum) + sizeof (Elf64_Half)
21250b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  == offsetof (Elf64_Ehdr, e_shstrndx));
21260b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  const Elf64_Off zero_off = 0;
21270b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  const Elf64_Half zero[3] = { 0, 0, SHN_UNDEF };
21280b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  if (pwrite_retry (fd, &zero_off, sizeof zero_off,
21290b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath			    offsetof (Elf64_Ehdr, e_shoff)) != sizeof zero_off
21300b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      || (pwrite_retry (fd, zero, sizeof zero,
21310b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath				offsetof (Elf64_Ehdr, e_shentsize))
21320b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  != sizeof zero)
21330b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      || ftruncate64 (fd, shdr_info[shdridx].shdr.sh_offset) < 0)
21340b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	    {
21350b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      error (0, errno, gettext ("while writing '%s'"),
21366d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		     output_fname ?: fname);
21370b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      result = 1;
21380b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	    }
21390b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	}
21400b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath    }
2141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper fail_close:
2143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr_info != NULL)
2144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* For some sections we might have created an table to map symbol
2146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 table indices.  */
2147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (any_symtab_changes)
2148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	for (cnt = 1; cnt <= shdridx; ++cnt)
2149521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  {
2150521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    free (shdr_info[cnt].newsymidx);
2151521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (shdr_info[cnt].debug_data != NULL)
2152521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      free (shdr_info[cnt].debug_data->d_buf);
2153521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  }
2154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2155a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard      /* Free data we allocated for the .gnu_debuglink section. */
2156a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard      free (debuglink_buf);
2157a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard
2158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Free the memory.  */
2159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
2160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	free (shdr_info);
2161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Free other resources.  */
2164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shstrtab_data != NULL)
2165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    free (shstrtab_data->d_buf);
2166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shst != NULL)
2167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ebl_strtabfree (shst);
2168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* That was it.  Close the descriptors.  */
2170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf_end (newelf) != 0)
2171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
21726d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      error (0, 0, gettext ("error while finishing '%s': %s"),
21736d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     output_fname ?: fname, elf_errmsg (-1));
2174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = 1;
2175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (debugelf != NULL && elf_end (debugelf) != 0)
2178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("error while finishing '%s': %s"), debug_fname,
2180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     elf_errmsg (-1));
2181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = 1;
2182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper fail:
2185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Close the EBL backend.  */
2186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ebl != NULL)
2187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ebl_closebackend (ebl);
2188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
21896d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard  cleanup_debug ();
2190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If requested, preserve the timestamp.  */
2192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (tvp != NULL)
2193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
21948c4aa0ef998191ed828a37190dc179b91649938aMax Filippov      if (futimens (fd, tvp) != 0)
2195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("\
2197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot set access and modification date of '%s'"),
2198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 output_fname ?: fname);
2199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
2200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Close the file descriptor if we created a new file.  */
2204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (output_fname != NULL)
2205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    close (fd);
2206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
2208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
22106d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaardstatic void
22111ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaardcleanup_debug (void)
22126d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard{
22136d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard  if (debug_fd >= 0)
22146d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    {
22156d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      if (tmp_debug_fname != NULL)
22166d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	{
22176d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  unlink (tmp_debug_fname);
22186d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  free (tmp_debug_fname);
22196d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  tmp_debug_fname = NULL;
22206d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	}
22216d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      close (debug_fd);
22226d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      debug_fd = -1;
22236d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    }
22246d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard}
2225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
2227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperhandle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
22288c4aa0ef998191ed828a37190dc179b91649938aMax Filippov	   struct timespec tvp[2])
2229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
2231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t fname_len = strlen (fname) + 1;
2232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char new_prefix[prefix_len + 1 + fname_len];
2233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *cp = new_prefix;
2234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Create the full name of the file.  */
2236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (prefix != NULL)
2237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      cp = mempcpy (cp, prefix, prefix_len);
2239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      *cp++ = ':';
2240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  memcpy (cp, fname, fname_len);
2242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Process all the files contained in the archive.  */
2245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *subelf;
2246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Cmd cmd = ELF_C_RDWR;
2247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result = 0;
2248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
2249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* The the header for this element.  */
2251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
2252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf_kind (subelf) == ELF_K_ELF)
2254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
2255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (elf_kind (subelf) == ELF_K_AR)
2256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
2257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Get next archive element.  */
2259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      cmd = elf_next (subelf);
2260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (unlikely (elf_end (subelf) != 0))
2261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	INTERNAL_ERROR (fname);
2262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (tvp != NULL)
2265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
22668c4aa0ef998191ed828a37190dc179b91649938aMax Filippov      if (unlikely (futimens (fd, tvp) != 0))
2267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("\
2269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot set access and modification date of '%s'"), fname);
2270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
2271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (unlikely (close (fd) != 0))
2275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
2276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
2278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
22793cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
22803cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
22813cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper#include "debugpred.h"
2282