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.  */
3133425454a10d307fae891fb667cf7969e945cde79Josh Stone  struct stat pre_st;
3148c4aa0ef998191ed828a37190dc179b91649938aMax Filippov  struct timespec tv[2];
315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper again:
316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (preserve_dates)
317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3183425454a10d307fae891fb667cf7969e945cde79Josh Stone      if (stat (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.  */
3413425454a10d307fae891fb667cf7969e945cde79Josh Stone  struct stat st;
3423425454a10d307fae891fb667cf7969e945cde79Josh Stone  if (fstat (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
647df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard	 not loaded can be freely moved by us.  In theory we can also
648df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard	 freely move around allocated nobits sections.  But we don't
649df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard	 to keep the layout of all allocated sections as similar as
650df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard	 possible to the original file.  In relocatable object files
651df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard	 everything can be moved.  */
652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type == ET_REL
653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].shdr.sh_offset = 0;
655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If this is an extended section index table store an
657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 appropriate reference.  */
658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
66058d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	  elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Cross-reference the sections contained in the section
666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     group.  */
667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
6686d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  if (shdr_info[cnt].data == NULL
6696d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      || shdr_info[cnt].data->d_size < sizeof (Elf32_Word))
670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    INTERNAL_ERROR (fname);
671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* XXX Fix for unaligned access.  */
6731c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	  Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
6741c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	  size_t inner;
675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (inner = 1;
676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ++inner)
67858d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	    {
67958d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	      if (grpref[inner] < shnum)
68058d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		shdr_info[grpref[inner]].group_idx = cnt;
68158d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	      else
68258d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		goto illformed;
68358d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	    }
684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* If the section group contains only one element and this
687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       is n COMDAT section we can drop it right away.  */
688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    shdr_info[cnt].idx = 0;
689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    shdr_info[cnt].group_cnt = inner - 1;
691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
69458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	  elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If this section is part of a group make sure it is not
699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 discarded right away.  */
700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
70258d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	  elf_assert (shdr_info[cnt].group_idx != 0);
703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* The section group section will be removed.  */
707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      shdr_info[cnt].group_idx = 0;
708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      shdr_info[cnt].shdr.sh_flags &= ~SHF_GROUP;
709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Increment the counter.  */
713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ++cnt;
714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now determine which sections can go away.  The general rule is that
717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     all sections which are not used at runtime are stripped out.  But
718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     there are a few exceptions:
719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     - special sections named ".comment" and ".note" are kept
721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     - OS or architecture specific sections are kept since we might not
722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper       know how to handle them
723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     - if a section is referred to from a section which is not removed
724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper       in the sh_link or sh_info element it cannot be removed either
725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  */
726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 1; cnt < shnum; ++cnt)
727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Check whether the section can be removed.  */
728f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath    if (remove_shdrs ? !(shdr_info[cnt].shdr.sh_flags & SHF_ALLOC)
729f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	: ebl_section_strip_p (ebl, ehdr, &shdr_info[cnt].shdr,
730f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath			       shdr_info[cnt].name, remove_comment,
731f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath			       remove_debug))
732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* For now assume this section will be removed.  */
734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].idx = 0;
735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
736b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	idx = shdr_info[cnt].group_idx;
737b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	while (idx != 0)
738b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
739ce4550aefd57ab68f6f279a5b662eb1716d7b361Roland McGrath	    /* The section group data is already loaded.  */
7406d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr_info[idx].data != NULL
7416d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			&& shdr_info[idx].data->d_buf != NULL
7426d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			&& shdr_info[idx].data->d_size >= sizeof (Elf32_Word));
743ce4550aefd57ab68f6f279a5b662eb1716d7b361Roland McGrath
7441c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	    /* If the references section group is a normal section
7451c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	       group and has one element remaining, or if it is an
7461c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	       empty COMDAT section group it is removed.  */
7471c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	    bool is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
7481c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath			      & GRP_COMDAT) != 0;
749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    --shdr_info[idx].group_cnt;
751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if ((!is_comdat && shdr_info[idx].group_cnt == 1)
752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		|| (is_comdat && shdr_info[idx].group_cnt == 0))
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		shdr_info[idx].idx = 0;
755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* Continue recursively.  */
756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		idx = shdr_info[idx].group_idx;
757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    else
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      break;
760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Mark the SHT_NULL section as handled.  */
764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[0].idx = 2;
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Handle exceptions: section groups and cross-references.  We might
768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     have to repeat this a few times since the resetting of the flag
769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     might propagate.  */
770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  do
771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      changes = false;
773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = 1; cnt < shnum; ++cnt)
775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr_info[cnt].idx == 0)
777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* If a relocation section is marked as being removed make
779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 sure the section it is relocating is removed, too.  */
78058d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	      if (shdr_info[cnt].shdr.sh_type == SHT_REL
781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   || shdr_info[cnt].shdr.sh_type == SHT_RELA)
78258d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		{
78358d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		  if (shdr_info[cnt].shdr.sh_info >= shnum)
78458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    goto illformed;
78558d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		  else if (shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
78658d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    shdr_info[cnt].idx = 1;
78758d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		}
7887a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard
7897a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard	      /* If a group section is marked as being removed make
7907a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		 sure all the sections it contains are being removed, too.  */
7917a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard	      if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
7927a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		{
7937a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		  Elf32_Word *grpref;
7947a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		  grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
7957a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		  for (size_t in = 1;
7967a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		       in < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
7977a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		       ++in)
7986d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    if (grpref[in] < shnum)
7997a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		      {
8006d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			if (shdr_info[grpref[in]].idx != 0)
8016d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			  {
8026d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			    shdr_info[cnt].idx = 1;
8036d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			    break;
8046d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			  }
8057a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		      }
8066d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    else
8076d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		      goto illformed;
8087a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		}
809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr_info[cnt].idx == 1)
812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* The content of symbol tables we don't remove must not
814b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 reference any section which we do remove.  Otherwise
815b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 we cannot remove the section.  */
816521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      if (debug_fname != NULL
817521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  && shdr_info[cnt].debug_data == NULL
818521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  && (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
819521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB))
820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Make sure the data is loaded.  */
822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (shdr_info[cnt].data == NULL)
823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      shdr_info[cnt].data
825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			= elf_getdata (shdr_info[cnt].scn, NULL);
826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (shdr_info[cnt].data == NULL)
827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			INTERNAL_ERROR (fname);
828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
8291c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath		  Elf_Data *symdata = shdr_info[cnt].data;
830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* If there is an extended section index table load it
832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     as well.  */
833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (shdr_info[cnt].symtab_idx != 0
834b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
83658d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		      elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
837b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      shdr_info[shdr_info[cnt].symtab_idx].data
839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			= elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
840b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				       NULL);
841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
842b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			INTERNAL_ERROR (fname);
843b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
8441c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath		  Elf_Data *xndxdata
8451c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath		    = shdr_info[shdr_info[cnt].symtab_idx].data;
846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
847b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Go through all symbols and make sure the section they
848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     reference is not removed.  */
849a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard		  size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
851b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  for (size_t inner = 0;
852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       inner < shdr_info[cnt].data->d_size / elsize;
853b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       ++inner)
854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
855b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Sym sym_mem;
856b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      Elf32_Word xndx;
8571c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath		      GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
8581c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath							inner, &sym_mem,
8591c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath							&xndx);
860b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (sym == NULL)
861b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			INTERNAL_ERROR (fname);
862b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
8631c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath		      size_t scnidx = sym->st_shndx;
864b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (scnidx == SHN_UNDEF || scnidx >= shnum
865b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  || (scnidx >= SHN_LORESERVE
866b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      && scnidx <= SHN_HIRESERVE
867b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      && scnidx != SHN_XINDEX)
868b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  /* Don't count in the section symbols.  */
869b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
870b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			/* This is no section index, leave it alone.  */
871b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			continue;
872b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      else if (scnidx == SHN_XINDEX)
873b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			scnidx = xndx;
874b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
87558d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		      if (scnidx >= shnum)
87658d3619facfb708f4998d73270ca4082b20853b9Roland McGrath			goto illformed;
87758d3619facfb708f4998d73270ca4082b20853b9Roland McGrath
878b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (shdr_info[scnidx].idx == 0)
879521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			/* This symbol table has a real symbol in
880521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			   a discarded section.  So preserve the
881521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			   original table in the debug file.  */
882521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			shdr_info[cnt].debug_data = symdata;
883b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
884b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
885b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
886b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Cross referencing happens:
887b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 - for the cases the ELF specification says.  That are
888b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_DYNAMIC in sh_link to string table
889b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_HASH in sh_link to symbol table
890b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_REL and SHT_RELA in sh_link to symbol table
891b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
892b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_GROUP in sh_link to symbol table
893b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   + SHT_SYMTAB_SHNDX in sh_link to symbol table
894b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   Other (OS or architecture-specific) sections might as
895b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   well use this field so we process it unconditionally.
896b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 - references inside section groups
897b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 - specially marked references in sh_info if the SHF_INFO_LINK
898b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 flag is set
899b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      */
900b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
901b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
902b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
903b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
904b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  changes |= shdr_info[cnt].shdr.sh_link < cnt;
905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
906b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
907b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Handle references through sh_info.  */
90858d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	      if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
909b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
91058d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		  if (shdr_info[cnt].shdr.sh_info >= shnum)
91158d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    goto illformed;
91258d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		  else if ( shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
91358d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    {
91458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		      shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
91558d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		      changes |= shdr_info[cnt].shdr.sh_info < cnt;
91658d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    }
917b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Mark the section as investigated.  */
920b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      shdr_info[cnt].idx = 2;
921b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
922521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
923521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  if (debug_fname != NULL
924521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      && (shdr_info[cnt].idx == 0 || shdr_info[cnt].debug_data != NULL))
925521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    {
926521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      /* This section is being preserved in the debug file.
927521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 Sections it refers to must be preserved there too.
928521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
929521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 In this pass we mark sections to be preserved in both
930521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 files by setting the .debug_data pointer to the original
931521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 file's .data pointer.  Below, we'll copy the section
932521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 contents.  */
933521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
934521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      inline void check_preserved (size_t i)
935521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      {
9366d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		if (i != 0 && i < shnum + 2 && shdr_info[i].idx != 0
93704a14163323bc4d2d335909a2af7259bc53ddf8bRoland McGrath		    && shdr_info[i].debug_data == NULL)
938521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  {
939521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    if (shdr_info[i].data == NULL)
940521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
941521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    if (shdr_info[i].data == NULL)
942521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      INTERNAL_ERROR (fname);
943521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
944521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    shdr_info[i].debug_data = shdr_info[i].data;
945521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    changes |= i < cnt;
946521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  }
947521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      }
948521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
949521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      check_preserved (shdr_info[cnt].shdr.sh_link);
950521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
951521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		check_preserved (shdr_info[cnt].shdr.sh_info);
952521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    }
953b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
954b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
955b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (changes);
956b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
957b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Copy the removed sections to the debug output file.
958b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     The ones that are not removed in the stripped file are SHT_NOBITS.  */
959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (debug_fname != NULL)
960b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
961b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = 1; cnt < shnum; ++cnt)
962b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
963b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  scn = elf_newscn (debugelf);
964b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (scn == NULL)
9656d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    {
9666d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      cleanup_debug ();
9676d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      error (EXIT_FAILURE, 0,
9686d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		     gettext ("while generating output file: %s"),
9696d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		     elf_errmsg (-1));
9706d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    }
971b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
9721c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	  bool discard_section = (shdr_info[cnt].idx > 0
973521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				  && shdr_info[cnt].debug_data == NULL
9749aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath				  && shdr_info[cnt].shdr.sh_type != SHT_NOTE
9757a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard				  && shdr_info[cnt].shdr.sh_type != SHT_GROUP
9761c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath				  && cnt != ehdr->e_shstrndx);
977b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
978b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Set the section header in the new file.  */
9791c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	  GElf_Shdr debugshdr = shdr_info[cnt].shdr;
980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (discard_section)
981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    debugshdr.sh_type = SHT_NOBITS;
982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
9833cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	  if (unlikely (gelf_update_shdr (scn, &debugshdr) == 0))
984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* There cannot be any overflows.  */
985b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    INTERNAL_ERROR (fname);
986b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
987b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Get the data from the old file if necessary. */
988b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr_info[cnt].data == NULL)
989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (shdr_info[cnt].data == NULL)
992b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		INTERNAL_ERROR (fname);
993b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
994b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
995b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Set the data.  This is done by copying from the old file.  */
9961c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath	  Elf_Data *debugdata = elf_newdata (scn);
997b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (debugdata == NULL)
998b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    INTERNAL_ERROR (fname);
999b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1000b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Copy the structure.  This data may be modified in place
1001b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     before we write out the file.  */
1002b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  *debugdata = *shdr_info[cnt].data;
1003b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (discard_section)
1004b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    debugdata->d_buf = NULL;
10057a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard	  else if (shdr_info[cnt].debug_data != NULL
10067a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		   || shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1007521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    {
1008521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      /* Copy the original data before it gets modified.  */
1009521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      shdr_info[cnt].debug_data = debugdata;
10106d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (debugdata->d_buf == NULL)
10116d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		INTERNAL_ERROR (fname);
1012521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      debugdata->d_buf = memcpy (xmalloc (debugdata->d_size),
1013521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath					 debugdata->d_buf, debugdata->d_size);
1014521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    }
1015b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1016b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1017b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Finish the ELF header.  Fill in the fields not handled by
1018b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 libelf from the old file.  */
1019b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
1020b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (debugehdr == NULL)
1021b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	INTERNAL_ERROR (fname);
1022b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1023b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
1024b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_type = ehdr->e_type;
1025b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_machine = ehdr->e_machine;
1026b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_version = ehdr->e_version;
1027b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_entry = ehdr->e_entry;
1028b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_flags = ehdr->e_flags;
1029b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debugehdr->e_shstrndx = ehdr->e_shstrndx;
1030b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
10313cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper      if (unlikely (gelf_update_ehdr (debugelf, debugehdr) == 0))
1032b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1033b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, 0, gettext ("%s: error while creating ELF header: %s"),
1034b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 debug_fname, elf_errmsg (-1));
1035b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
1036b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto fail_close;
1037b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1038b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1039b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1040df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard  /* Although we always create a new section header string table we
1041df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard     don't explicitly mark the existing one as unused.  It can still
1042df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard     be used through a symbol table section we are keeping.  If not it
1043df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard     will already be marked as unused.  */
1044b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1045b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We need a string table for the section headers.  */
1046b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shst = ebl_strtabinit (true);
1047b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shst == NULL)
10486d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    {
10496d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
10506d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      error (EXIT_FAILURE, errno, gettext ("while preparing output for '%s'"),
10516d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     output_fname ?: fname);
10526d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    }
1053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Assign new section numbers.  */
1055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[0].idx = 0;
1056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = idx = 1; cnt < shnum; ++cnt)
1057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (shdr_info[cnt].idx > 0)
1058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].idx = idx++;
1060b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Create a new section.  */
1062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].newscn = elf_newscn (newelf);
1063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (shdr_info[cnt].newscn == NULL)
10646d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  {
10656d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    cleanup_debug ();
10666d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    error (EXIT_FAILURE, 0,
10676d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		   gettext ("while generating output file: %s"),
10686d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		   elf_errmsg (-1));
10696d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  }
1070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
107158d3619facfb708f4998d73270ca4082b20853b9Roland McGrath	elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
1072b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1073b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Add this name to the section header string table.  */
1074b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);
1075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1077b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Test whether we are doing anything at all.  */
1078b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (cnt == idx)
1079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Nope, all removable sections are already gone.  */
1080b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    goto fail_close;
1081b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1082b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Create the reference to the file with the debug info.  */
1083f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath  if (debug_fname != NULL && !remove_shdrs)
1084b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1085b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Add the section header string table section name.  */
1086b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].se = ebl_strtabadd (shst, ".gnu_debuglink", 15);
1087b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].idx = idx++;
1088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Create the section header.  */
1090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
1091b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_flags = 0;
1092b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_addr = 0;
1093b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1094b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_entsize = 0;
1096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_addralign = 4;
1097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We set the offset to zero here.  Before we write the ELF file the
1098b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 field must have the correct value.  This is done in the final
1099b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 loop over all section.  Then we have all the information needed.  */
1100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_offset = 0;
1101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Create the section.  */
1103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].newscn = elf_newscn (newelf);
1104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr_info[cnt].newscn == NULL)
11056d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	{
11066d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  cleanup_debug ();
11076d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  error (EXIT_FAILURE, 0,
11086d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		 gettext ("while create section header section: %s"),
11096d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		 elf_errmsg (-1));
11106d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	}
111158d3619facfb708f4998d73270ca4082b20853b9Roland McGrath      elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
1112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
1114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr_info[cnt].data == NULL)
11156d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	{
11166d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  cleanup_debug ();
11176d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  error (EXIT_FAILURE, 0, gettext ("cannot allocate section data: %s"),
11186d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		 elf_errmsg (-1));
11196d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	}
1120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
11211c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath      char *debug_basename = basename (debug_fname_embed ?: debug_fname);
11221c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath      off_t crc_offset = strlen (debug_basename) + 1;
1123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Align to 4 byte boundary */
1124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      crc_offset = ((crc_offset - 1) & ~3) + 4;
1125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].data->d_align = 4;
1127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
1128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	= crc_offset + 4;
1129a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard      debuglink_buf = xcalloc (1, shdr_info[cnt].data->d_size);
1130a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard      shdr_info[cnt].data->d_buf = debuglink_buf;
1131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      strcpy (shdr_info[cnt].data->d_buf, debug_basename);
1133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Cache this Elf_Data describing the CRC32 word in the section.
1135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 We'll fill this in when we have written the debug file.  */
1136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debuglink_crc_data = *shdr_info[cnt].data;
1137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debuglink_crc_data.d_buf = ((char *) debuglink_crc_data.d_buf
1138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				  + crc_offset);
1139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debuglink_crc_data.d_size = 4;
1140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* One more section done.  */
1142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ++cnt;
1143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Index of the section header table in the shdr_info array.  */
1146e219f1c1b2a5a2e4f248714fdc93d031cdc5ee6aUlrich Drepper  shdridx = cnt;
1147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Add the section header string table section name.  */
1149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].se = ebl_strtabadd (shst, ".shstrtab", 10);
1150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].idx = idx;
1151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Create the section header.  */
1153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
1154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_flags = 0;
1155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_addr = 0;
1156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_entsize = 0;
1159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We set the offset to zero here.  Before we write the ELF file the
1160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     field must have the correct value.  This is done in the final
1161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     loop over all section.  Then we have all the information needed.  */
1162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_offset = 0;
1163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_addralign = 1;
1164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Create the section.  */
1166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].newscn = elf_newscn (newelf);
1167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr_info[cnt].newscn == NULL)
11686d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    {
11696d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
11706d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      error (EXIT_FAILURE, 0,
11716d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     gettext ("while create section header section: %s"),
11726d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     elf_errmsg (-1));
11736d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    }
117458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath  elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
1175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Finalize the string table and fill in the correct indices in the
1177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     section headers.  */
1178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
1179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shstrtab_data == NULL)
11806d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    {
11816d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
11826d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      error (EXIT_FAILURE, 0,
11836d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     gettext ("while create section header string table: %s"),
11846d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     elf_errmsg (-1));
11856d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    }
1186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl_strtabfinalize (shst, shstrtab_data);
1187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We have to set the section size.  */
1189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
1190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Update the section information.  */
1192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Off lastoffset = 0;
1193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 1; cnt <= shdridx; ++cnt)
1194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (shdr_info[cnt].idx > 0)
1195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf_Data *newdata;
1197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	scn = elf_getscn (newelf, shdr_info[cnt].idx);
11996d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	elf_assert (scn != NULL);
1200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Update the name.  */
1202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	shdr_info[cnt].shdr.sh_name = ebl_strtaboffset (shdr_info[cnt].se);
1203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Update the section header from the input file.  Some fields
1205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   might be section indeces which now have to be adjusted.  */
1206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (shdr_info[cnt].shdr.sh_link != 0)
1207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[cnt].shdr.sh_link =
1208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    shdr_info[shdr_info[cnt].shdr.sh_link].idx;
1209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
12126d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr_info[cnt].data != NULL
12136d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			&& shdr_info[cnt].data->d_buf != NULL);
1214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    for (size_t inner = 0;
1217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 ++inner)
12196d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (grpref[inner] < shnum)
12206d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		grpref[inner] = shdr_info[grpref[inner]].idx;
12216d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      else
12226d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		goto illformed;
1223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
1224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag.  */
1226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[cnt].shdr.sh_info =
1228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    shdr_info[shdr_info[cnt].shdr.sh_info].idx;
1229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Get the data from the old file if necessary.  We already
12313a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper	   created the data for the section header string table.  */
1232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (cnt < shnum)
1233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
1234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (shdr_info[cnt].data == NULL)
1235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
1236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (shdr_info[cnt].data == NULL)
1238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  INTERNAL_ERROR (fname);
1239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
1240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Set the data.  This is done by copying from the old file.  */
1242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    newdata = elf_newdata (scn);
1243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (newdata == NULL)
1244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      INTERNAL_ERROR (fname);
1245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Copy the structure.  */
1247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    *newdata = *shdr_info[cnt].data;
1248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* We know the size.  */
1250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
1251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1252521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* We have to adjust symbol tables.  The st_shndx member might
1253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       have to be updated.  */
1254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
1255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		|| shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
1256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
1257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		Elf_Data *versiondata = NULL;
1258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		Elf_Data *shndxdata = NULL;
1259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1260a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
1261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (shdr_info[cnt].symtab_idx != 0)
1263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
12646d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
1265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* This section has extended section information.
1266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       We have to modify that information, too.  */
1267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
1268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					     NULL);
1269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
127058d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    elf_assert ((versiondata->d_size / sizeof (Elf32_Word))
12716d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				>= shdr_info[cnt].data->d_size / elsize);
1272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
1273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (shdr_info[cnt].version_idx != 0)
1275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
127658d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    elf_assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
1277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* This section has associated version
1278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       information.  We have to modify that
1279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       information, too.  */
1280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
1281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					       NULL);
1282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
12836d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    elf_assert (versiondata != NULL
12846d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				&& versiondata->d_buf != NULL
12856d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				&& ((versiondata->d_size / sizeof (GElf_Versym))
12866d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				    >= shdr_info[cnt].data->d_size / elsize));
1287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
1288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		shdr_info[cnt].newsymidx
1290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  = (Elf32_Word *) xcalloc (shdr_info[cnt].data->d_size
1291b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					    / elsize, sizeof (Elf32_Word));
1292b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		bool last_was_local = true;
1294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		size_t destidx;
1295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		size_t inner;
1296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		for (destidx = inner = 1;
1297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     inner < shdr_info[cnt].data->d_size / elsize;
1298b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ++inner)
1299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
1300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    Elf32_Word sec;
1301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    GElf_Sym sym_mem;
1302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    Elf32_Word xshndx;
1303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
1304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						      shndxdata, inner,
1305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						      &sym_mem, &xshndx);
1306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sym == NULL)
1307b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      INTERNAL_ERROR (fname);
1308b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sym->st_shndx == SHN_UNDEF
1310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			|| (sym->st_shndx >= shnum
1311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    && sym->st_shndx != SHN_XINDEX))
1312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      {
1313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			/* This is no section index, leave it alone
1314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   unless it is moved.  */
1315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (destidx != inner
1316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    && gelf_update_symshndx (shdr_info[cnt].data,
1317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						     shndxdata,
1318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						     destidx, sym,
1319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						     xshndx) == 0)
1320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  INTERNAL_ERROR (fname);
1321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			shdr_info[cnt].newsymidx[inner] = destidx++;
1323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (last_was_local
1325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  {
1327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    last_was_local = false;
1328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    shdr_info[cnt].shdr.sh_info = destidx - 1;
1329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  }
1330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			continue;
1332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      }
1333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* Get the full section index, if necessary from the
1335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       XINDEX table.  */
1336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sym->st_shndx != SHN_XINDEX)
1337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      sec = shdr_info[sym->st_shndx].idx;
1338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else
1339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      {
13406d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			elf_assert (shndxdata != NULL
13416d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				    && shndxdata->d_buf != NULL);
1342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			sec = shdr_info[xshndx].idx;
1344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      }
1345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sec != 0)
1347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      {
1348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			GElf_Section nshndx;
1349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			Elf32_Word nxshndx;
1350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (sec < SHN_LORESERVE)
1352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  {
1353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    nshndx = sec;
1354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    nxshndx = 0;
1355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  }
1356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			else
1357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  {
1358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    nshndx = SHN_XINDEX;
1359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    nxshndx = sec;
1360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  }
1361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
136258d3619facfb708f4998d73270ca4082b20853b9Roland McGrath			elf_assert (sec < SHN_LORESERVE || shndxdata != NULL);
1363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if ((inner != destidx || nshndx != sym->st_shndx
1365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     || (shndxdata != NULL && nxshndx != xshndx))
1366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    && (sym->st_shndx = nshndx,
1367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				gelf_update_symshndx (shdr_info[cnt].data,
1368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						      shndxdata,
1369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						      destidx, sym,
1370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						      nxshndx) == 0))
1371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  INTERNAL_ERROR (fname);
1372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			shdr_info[cnt].newsymidx[inner] = destidx++;
1374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (last_was_local
1376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  {
1378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    last_was_local = false;
1379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    shdr_info[cnt].shdr.sh_info = destidx - 1;
1380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  }
1381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      }
13823a45dbbe7e1862e72bc886fa7f12a5c5c09311e0Mark Wielaard		    else if (debug_fname != NULL
13833a45dbbe7e1862e72bc886fa7f12a5c5c09311e0Mark Wielaard			     && shdr_info[cnt].debug_data == NULL)
13843a45dbbe7e1862e72bc886fa7f12a5c5c09311e0Mark Wielaard		      /* The symbol points to a section that is discarded
13853a45dbbe7e1862e72bc886fa7f12a5c5c09311e0Mark Wielaard			 but isn't preserved in the debug file. Check that
13863a45dbbe7e1862e72bc886fa7f12a5c5c09311e0Mark Wielaard			 this is a section or group signature symbol
13877a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard			 for a section which has been removed.  */
13887a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		      {
13897a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard			size_t sidx = (sym->st_shndx != SHN_XINDEX
13907a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard					? sym->st_shndx : xshndx);
139158d3619facfb708f4998d73270ca4082b20853b9Roland McGrath			elf_assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION
139258d3619facfb708f4998d73270ca4082b20853b9Roland McGrath				    || ((shdr_info[sidx].shdr.sh_type
139358d3619facfb708f4998d73270ca4082b20853b9Roland McGrath					 == SHT_GROUP)
139458d3619facfb708f4998d73270ca4082b20853b9Roland McGrath					&& (shdr_info[sidx].shdr.sh_info
139558d3619facfb708f4998d73270ca4082b20853b9Roland McGrath					    == inner)));
13967a125b9306c4743eaee062bdab301f890e3c6309Mark Wielaard		      }
1397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
1398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (destidx != inner)
1400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
1401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* The size of the symbol table changed.  */
1402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    shdr_info[cnt].shdr.sh_size = newdata->d_size
1403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      = destidx * elsize;
1404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    any_symtab_changes = true;
1405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
1406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
1407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
1408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* The symbol table didn't really change.  */
1409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    free (shdr_info[cnt].newsymidx);
1410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    shdr_info[cnt].newsymidx = NULL;
1411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
1412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
1413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
1414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* If we have to, compute the offset of the section.  */
1416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (shdr_info[cnt].shdr.sh_offset == 0)
1417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr_info[cnt].shdr.sh_offset
1418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
1419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
1420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Set the section header in the new file.  */
1422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
1423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* There cannot be any overflows.  */
1424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  INTERNAL_ERROR (fname);
1425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Remember the last section written so far.  */
1427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
1428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   ? shdr_info[cnt].shdr.sh_size : 0);
1429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
1430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
1431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Adjust symbol references if symbol tables changed.  */
1434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (any_symtab_changes)
1435521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath    /* Find all relocation sections which use this symbol table.  */
1436521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath    for (cnt = 1; cnt <= shdridx; ++cnt)
1437521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      {
1438521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	/* Update section headers when the data size has changed.
1439521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	   We also update the SHT_NOBITS section in the debug
1440521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	   file so that the section headers match in sh_size.  */
1441521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	inline void update_section_size (const Elf_Data *newdata)
1442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1443521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  GElf_Shdr shdr_mem;
1444521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1445521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  shdr->sh_size = newdata->d_size;
1446521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  (void) gelf_update_shdr (scn, shdr);
1447521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  if (debugelf != NULL)
14489aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	    {
1449521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      /* libelf will use d_size to set sh_size.  */
1450521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
1451521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath							     cnt), NULL);
14526d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (debugdata == NULL)
14536d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		INTERNAL_ERROR (fname);
1454521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      debugdata->d_size = newdata->d_size;
14559aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	    }
1456521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	}
14579aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath
1458521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	if (shdr_info[cnt].idx == 0 && debug_fname == NULL)
1459521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  /* Ignore sections which are discarded.  When we are saving a
1460521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	     relocation section in a separate debug file, we must fix up
1461521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	     the symbol table references.  */
1462521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  continue;
1463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1464521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	const Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
14656d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	elf_assert (symtabidx < shnum + 2);
1466521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
1467521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	switch (shdr_info[cnt].shdr.sh_type)
1468521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  {
1469521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    inline bool no_symtab_updates (void)
1470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* If the symbol table hasn't changed, do not do anything.  */
1472521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      if (shdr_info[symtabidx].newsymidx == NULL)
1473521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		return true;
1474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1475521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      /* If the symbol table is not discarded, but additionally
1476521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 duplicated in the separate debug file and this section
1477521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		 is discarded, don't adjust anything.  */
1478521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      return (shdr_info[cnt].idx == 0
1479521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      && shdr_info[symtabidx].debug_data != NULL);
1480521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    }
1481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1482521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  case SHT_REL:
1483521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  case SHT_RELA:
1484521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (no_symtab_updates ())
1485521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      break;
1486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1487521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    Elf_Data *d = elf_getdata (shdr_info[cnt].idx == 0
1488521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       ? elf_getscn (debugelf, cnt)
1489521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       : elf_getscn (newelf,
1490521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath						     shdr_info[cnt].idx),
1491521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       NULL);
14926d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (d != NULL && d->d_buf != NULL
14936d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			&& shdr_info[cnt].shdr.sh_entsize != 0);
1494521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    size_t nrels = (shdr_info[cnt].shdr.sh_size
1495521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			    / shdr_info[cnt].shdr.sh_entsize);
1496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
14976d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    size_t symsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
14986d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    const Elf32_Word symidxn = (shdr_info[symtabidx].data->d_size
14996d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard					/ symsize);
1500521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (shdr_info[cnt].shdr.sh_type == SHT_REL)
1501521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      for (size_t relidx = 0; relidx < nrels; ++relidx)
1502521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		{
1503521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  GElf_Rel rel_mem;
1504521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  if (gelf_getrel (d, relidx, &rel_mem) == NULL)
1505521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    INTERNAL_ERROR (fname);
1506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1507521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  size_t symidx = GELF_R_SYM (rel_mem.r_info);
15086d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		  elf_assert (symidx < symidxn);
1509521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  if (newsymidx[symidx] != symidx)
1510521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    {
1511521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      rel_mem.r_info
1512521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			= GELF_R_INFO (newsymidx[symidx],
1513521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       GELF_R_TYPE (rel_mem.r_info));
1514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1515521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      if (gelf_update_rel (d, relidx, &rel_mem) == 0)
1516521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			INTERNAL_ERROR (fname);
1517521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    }
1518521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		}
1519521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    else
1520521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      for (size_t relidx = 0; relidx < nrels; ++relidx)
1521521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		{
1522521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  GElf_Rela rel_mem;
1523521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  if (gelf_getrela (d, relidx, &rel_mem) == NULL)
1524521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    INTERNAL_ERROR (fname);
1525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1526521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  size_t symidx = GELF_R_SYM (rel_mem.r_info);
15276d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		  elf_assert (symidx < symidxn);
1528521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  if (newsymidx[symidx] != symidx)
1529521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    {
1530521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      rel_mem.r_info
1531521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			= GELF_R_INFO (newsymidx[symidx],
1532521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       GELF_R_TYPE (rel_mem.r_info));
1533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1534521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      if (gelf_update_rela (d, relidx, &rel_mem) == 0)
1535521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			INTERNAL_ERROR (fname);
1536521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    }
1537521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		}
1538521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    break;
1539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1540521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  case SHT_HASH:
1541521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (no_symtab_updates ())
1542521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      break;
1543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1544521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* We have to recompute the hash table.  */
1545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
15466d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr_info[cnt].idx > 0);
1547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1548521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The hash section in the new file.  */
1549521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    scn = elf_getscn (newelf, shdr_info[cnt].idx);
1550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1551521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The symbol table data.  */
1552521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    Elf_Data *symd = elf_getdata (elf_getscn (newelf,
1553521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath						      shdr_info[symtabidx].idx),
1554521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath					  NULL);
15556d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (symd != NULL && symd->d_buf != NULL);
1556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1557521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The hash table data.  */
1558521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    Elf_Data *hashd = elf_getdata (scn, NULL);
15596d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (hashd != NULL && hashd->d_buf != NULL);
1560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1561521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (shdr_info[cnt].shdr.sh_entsize == sizeof (Elf32_Word))
1562521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      {
1563521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Sane arches first.  */
15646d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (hashd->d_size >= 2 * sizeof (Elf32_Word));
1565521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
1566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1567521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		size_t strshndx = shdr_info[symtabidx].old_sh_link;
1568a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
1569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
15706d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		Elf32_Word nchain = bucket[1];
15716d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		Elf32_Word nbucket = bucket[0];
15726d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		uint64_t used_buf = ((2ULL + nchain + nbucket)
15736d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				     * sizeof (Elf32_Word));
15746d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (used_buf <= hashd->d_size);
15756d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard
1576521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Adjust the nchain value.  The symbol table size
1577521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		   changed.  We keep the same size for the bucket array.  */
1578521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		bucket[1] = symd->d_size / elsize;
1579521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		bucket += 2;
1580521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		Elf32_Word *chain = bucket + nbucket;
1581521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1582521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* New size of the section.  */
15836d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		size_t n_size = ((2 + symd->d_size / elsize + nbucket)
1584521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				 * sizeof (Elf32_Word));
15856d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (n_size <= hashd->d_size);
15866d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		hashd->d_size = n_size;
1587521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		update_section_size (hashd);
1588521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1589521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Clear the arrays.  */
1590521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		memset (bucket, '\0',
1591521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			(symd->d_size / elsize + nbucket)
1592521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			* sizeof (Elf32_Word));
1593521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1594521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1595521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		     inner < symd->d_size / elsize; ++inner)
1596521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  {
1597521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    GElf_Sym sym_mem;
1598521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
159958d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    elf_assert (sym != NULL);
1600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1601521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    const char *name = elf_strptr (elf, strshndx,
1602521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath						   sym->st_name);
16036d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    elf_assert (name != NULL && nbucket != 0);
1604521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    size_t hidx = elf_hash (name) % nbucket;
1605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1606521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    if (bucket[hidx] == 0)
1607521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      bucket[hidx] = inner;
1608521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    else
1609521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      {
1610521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			hidx = bucket[hidx];
1611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
16126d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			while (chain[hidx] != 0 && chain[hidx] < nchain)
1613521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			  hidx = chain[hidx];
1614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1615521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			chain[hidx] = inner;
1616521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      }
1617521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  }
1618521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      }
1619521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    else
1620521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      {
1621521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Alpha and S390 64-bit use 64-bit SHT_HASH entries.  */
162258d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		elf_assert (shdr_info[cnt].shdr.sh_entsize
162358d3619facfb708f4998d73270ca4082b20853b9Roland McGrath			    == sizeof (Elf64_Xword));
1624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1625521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
1626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1627521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		size_t strshndx = shdr_info[symtabidx].old_sh_link;
1628a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
1629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
16306d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (symd->d_size >= 2 * sizeof (Elf64_Xword));
16316d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		Elf64_Xword nbucket = bucket[0];
16326d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		Elf64_Xword nchain = bucket[1];
16336d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		uint64_t maxwords = hashd->d_size / sizeof (Elf64_Xword);
16346d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (maxwords >= 2
16356d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			    && maxwords - 2 >= nbucket
16366d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			    && maxwords - 2 - nbucket >= nchain);
16376d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard
1638521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Adjust the nchain value.  The symbol table size
1639521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		   changed.  We keep the same size for the bucket array.  */
1640521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		bucket[1] = symd->d_size / elsize;
1641521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		bucket += 2;
1642521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		Elf64_Xword *chain = bucket + nbucket;
1643521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1644521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* New size of the section.  */
16456d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		size_t n_size = ((2 + symd->d_size / elsize + nbucket)
1646521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				 * sizeof (Elf64_Xword));
16476d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		elf_assert (n_size <= hashd->d_size);
16486d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		hashd->d_size = n_size;
1649521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		update_section_size (hashd);
1650521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1651521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Clear the arrays.  */
1652521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		memset (bucket, '\0',
1653521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			(symd->d_size / elsize + nbucket)
1654521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			* sizeof (Elf64_Xword));
1655521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1656521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1657521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		     inner < symd->d_size / elsize; ++inner)
1658521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  {
1659521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    GElf_Sym sym_mem;
1660521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
166158d3619facfb708f4998d73270ca4082b20853b9Roland McGrath		    elf_assert (sym != NULL);
1662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1663521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    const char *name = elf_strptr (elf, strshndx,
1664521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath						   sym->st_name);
16656d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		    elf_assert (name != NULL && nbucket != 0);
1666521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    size_t hidx = elf_hash (name) % nbucket;
1667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1668521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    if (bucket[hidx] == 0)
1669521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      bucket[hidx] = inner;
1670521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		    else
1671521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      {
1672521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			hidx = bucket[hidx];
1673521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
16746d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			while (chain[hidx] != 0 && chain[hidx] < nchain)
1675521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			  hidx = chain[hidx];
1676521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1677521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath			chain[hidx] = inner;
1678521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		      }
1679521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		  }
1680521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      }
1681521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    break;
1682521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1683521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  case SHT_GNU_versym:
1684521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* If the symbol table changed we have to adjust the entries.  */
1685521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (no_symtab_updates ())
1686521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      break;
1687521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
16886d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr_info[cnt].idx > 0);
1689521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1690521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The symbol version section in the new file.  */
1691521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    scn = elf_getscn (newelf, shdr_info[cnt].idx);
1692521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1693521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The symbol table data.  */
1694521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    symd = elf_getdata (elf_getscn (newelf, shdr_info[symtabidx].idx),
1695521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				NULL);
16966d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (symd != NULL && symd->d_buf != NULL);
16976d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    size_t symz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
16986d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    const Elf32_Word syms = (shdr_info[symtabidx].data->d_size / symz);
1699521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1700521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The version symbol data.  */
1701521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    Elf_Data *verd = elf_getdata (scn, NULL);
17026d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (verd != NULL && verd->d_buf != NULL);
1703521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1704521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* The symbol version array.  */
1705521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    GElf_Half *verstab = (GElf_Half *) verd->d_buf;
1706521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1707521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* Walk through the list and */
1708a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard	    size_t elsize = gelf_fsize (elf, verd->d_type, 1, EV_CURRENT);
17096d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    Elf32_Word vers = verd->d_size / elsize;
17106d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    for (size_t inner = 1; inner < vers && inner < syms; ++inner)
17116d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (newsymidx[inner] != 0 && newsymidx[inner] < vers)
1712521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		/* Overwriting the same array works since the
1713521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		   reordering can only move entries to lower indices
1714521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		   in the array.  */
1715521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath		verstab[newsymidx[inner]] = verstab[inner];
1716521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1717521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* New size of the section.  */
1718521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    verd->d_size = gelf_fsize (newelf, verd->d_type,
1719521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       symd->d_size
1720521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath				       / gelf_fsize (elf, symd->d_type, 1,
1721a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard						     EV_CURRENT),
1722a2b964c7dbbf54162b2c50931c172568fb4cfa70Mark Wielaard				       EV_CURRENT);
1723521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    update_section_size (verd);
1724521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    break;
1725521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1726521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  case SHT_GROUP:
1727521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (no_symtab_updates ())
1728521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      break;
1729521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1730521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    /* Yes, the symbol table changed.
1731521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	       Update the section header of the section group.  */
1732521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    scn = elf_getscn (newelf, shdr_info[cnt].idx);
1733521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    GElf_Shdr shdr_mem;
1734521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
17356d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr != NULL);
1736521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
17376d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    size_t symsz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
17386d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    const Elf32_Word symn = (shdr_info[symtabidx].data->d_size
17396d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				     / symsz);
17406d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	    elf_assert (shdr->sh_info < symn);
1741521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    shdr->sh_info = newsymidx[shdr->sh_info];
1742521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath
1743521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    (void) gelf_update_shdr (scn, shdr);
1744521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    break;
1745521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  }
1746521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      }
1747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
17481662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard  /* Remove any relocations between debug sections in ET_REL
17491662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard     for the debug file when requested.  These relocations are always
17501662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard     zero based between the unallocated sections.  */
17511662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard  if (debug_fname != NULL && reloc_debug && ehdr->e_type == ET_REL)
17521662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard    {
17531662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard      scn = NULL;
17541662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard      cnt = 0;
17551662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard      while ((scn = elf_nextscn (debugelf, scn)) != NULL)
17561662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	{
17571662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	  cnt++;
17581662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	  /* We need the actual section and header from the debugelf
17591662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	     not just the cached original in shdr_info because we
17601662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	     might want to change the size.  */
17611662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	  GElf_Shdr shdr_mem;
17621662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
17631662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	  if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
17641662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	    {
17651662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      /* Make sure that this relocation section points to a
17661662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 section to relocate with contents, that isn't
17671662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 allocated and that is a debug section.  */
17681662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      Elf_Scn *tscn = elf_getscn (debugelf, shdr->sh_info);
17691662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      GElf_Shdr tshdr_mem;
17701662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
17711662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      if (tshdr->sh_type == SHT_NOBITS
17721662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  || tshdr->sh_size == 0
17731662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  || (tshdr->sh_flags & SHF_ALLOC) != 0)
17741662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		continue;
17751662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
17761662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      const char *tname =  elf_strptr (debugelf, shstrndx,
17771662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard					       tshdr->sh_name);
17781662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      if (! tname || ! ebl_debugscn_p (ebl, tname))
17791662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		continue;
17801662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
17811662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      /* OK, lets relocate all trivial cross debug section
17821662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 relocations. */
17831662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      Elf_Data *reldata = elf_getdata (scn, NULL);
17846d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (reldata == NULL || reldata->d_buf == NULL)
17856d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		INTERNAL_ERROR (fname);
17861662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      /* We actually wanted the rawdata, but since we already
17871662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 accessed it earlier as elf_getdata () that won't
17881662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 work. But debug sections are all ELF_T_BYTE, so it
17891662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 doesn't really matter.  */
17901662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      Elf_Data *tdata = elf_getdata (tscn, NULL);
17916d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (tdata == NULL || tdata->d_buf == NULL
17926d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		  || tdata->d_type != ELF_T_BYTE)
17931662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		INTERNAL_ERROR (fname);
17941662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
17951662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      /* Pick up the symbol table and shndx table to
17961662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 resolve relocation symbol indexes.  */
17971662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      Elf64_Word symt = shdr->sh_link;
17981662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      Elf_Data *symdata, *xndxdata;
17996d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      elf_assert (symt < shnum + 2);
18006d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      elf_assert (shdr_info[symt].symtab_idx < shnum + 2);
18011662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      symdata = (shdr_info[symt].debug_data
18021662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			 ?: shdr_info[symt].data);
18031662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      xndxdata = (shdr_info[shdr_info[symt].symtab_idx].debug_data
18041662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			  ?: shdr_info[shdr_info[symt].symtab_idx].data);
18051662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
18061662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      /* Apply one relocation.  Returns true when trivial
18071662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		 relocation actually done.  */
18081662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      bool relocate (GElf_Addr offset, const GElf_Sxword addend,
180963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			     bool is_rela, int rtype, int symndx)
18101662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      {
18111662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		/* R_*_NONE relocs can always just be removed.  */
18121662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		if (rtype == 0)
18131662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  return true;
18141662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
18151662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		/* We only do simple absolute relocations.  */
18161662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		Elf_Type type = ebl_reloc_simple_type (ebl, rtype);
18171662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		if (type == ELF_T_NUM)
18181662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  return false;
18191662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
18201662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		/* These are the types we can relocate.  */
18211662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard#define TYPES   DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half);		\
18221662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword);		\
18231662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
18241662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
18251662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		/* And only for relocations against other debug sections.  */
18261662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		GElf_Sym sym_mem;
18271662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		Elf32_Word xndx;
18281662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
18291662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard						  symndx, &sym_mem,
18301662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard						  &xndx);
183163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		Elf32_Word sec = (sym->st_shndx == SHN_XINDEX
183263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard				  ? xndx : sym->st_shndx);
18336d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		if (sec >= shnum + 2)
18346d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		  INTERNAL_ERROR (fname);
18356d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard
183663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		if (ebl_debugscn_p (ebl, shdr_info[sec].name))
18371662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  {
183863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    size_t size;
18391662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
18401662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard#define DO_TYPE(NAME, Name) GElf_##Name Name;
184163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    union { TYPES; } tmpbuf;
18421662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard#undef DO_TYPE
18431662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
184463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    switch (type)
184563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
18461662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard#define DO_TYPE(NAME, Name)				\
184763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			case ELF_T_##NAME:		\
184863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			  size = sizeof (GElf_##Name);	\
184963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			  tmpbuf.Name = 0;		\
185063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			  break;
185163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			TYPES;
18521662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard#undef DO_TYPE
185363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      default:
185463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			return false;
185563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      }
185663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard
185702a958bc2662c1c9c2d6b663742b9c8e720e25b2Mark Wielaard		    if (offset > tdata->d_size
185802a958bc2662c1c9c2d6b663742b9c8e720e25b2Mark Wielaard			|| tdata->d_size - offset < size)
18596d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		      {
18606d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			cleanup_debug ();
18616d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			error (EXIT_FAILURE, 0, gettext ("bad relocation"));
18626d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		      }
18631662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
186463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    /* When the symbol value is zero then for SHT_REL
186563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       sections this is all that needs to be checked.
186663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       The addend is contained in the original data at
186763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       the offset already.  So if the (section) symbol
186863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       address is zero and the given addend is zero
186963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       just remove the relocation, it isn't needed
187063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		       anymore.  */
187163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    if (addend == 0 && sym->st_value == 0)
187263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      return true;
187363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard
187463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    Elf_Data tmpdata =
187563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
187663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_type = type,
187763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_buf = &tmpbuf,
187863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_size = size,
187963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_version = EV_CURRENT,
188063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      };
188163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    Elf_Data rdata =
188263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
188363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_type = type,
188463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_buf = tdata->d_buf + offset,
188563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_size = size,
188663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			.d_version = EV_CURRENT,
188763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      };
188863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard
188963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    GElf_Addr value = sym->st_value;
189063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    if (is_rela)
189163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
189263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			/* For SHT_RELA sections we just take the
189363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			   given addend and add it to the value.  */
189463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			value += addend;
189563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      }
189663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    else
189763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
189863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			/* For SHT_REL sections we have to peek at
189963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			   what is already in the section at the given
190063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			   offset to get the addend.  */
190163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			Elf_Data *d = gelf_xlatetom (debugelf, &tmpdata,
190263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard						     &rdata,
19031662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard						     ehdr->e_ident[EI_DATA]);
190463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			if (d == NULL)
19051662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			  INTERNAL_ERROR (fname);
190663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			assert (d == &tmpdata);
190763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      }
19081662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
190963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    switch (type)
191063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      {
191163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard#define DO_TYPE(NAME, Name)					\
191263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			case ELF_T_##NAME:			\
191363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			  tmpbuf.Name += (GElf_##Name) value;	\
191463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			  break;
191563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			TYPES;
191663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard#undef DO_TYPE
191763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      default:
191863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard			abort ();
19191662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		      }
192063868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard
192163868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    /* Now finally put in the new value.  */
192263868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    Elf_Data *s = gelf_xlatetof (debugelf, &rdata,
192363868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard						 &tmpdata,
192463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard						 ehdr->e_ident[EI_DATA]);
192563868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    if (s == NULL)
192663868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		      INTERNAL_ERROR (fname);
192763868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    assert (s == &rdata);
192863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard
192963868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    return true;
19301662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  }
19311662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		return false;
19321662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      }
19331662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
19346d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	      if (shdr->sh_entsize == 0)
19356d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		INTERNAL_ERROR (fname);
19366d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard
19371662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      size_t nrels = shdr->sh_size / shdr->sh_entsize;
19381662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      size_t next = 0;
19391662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      if (shdr->sh_type == SHT_REL)
19401662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		for (size_t relidx = 0; relidx < nrels; ++relidx)
19411662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  {
19421662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		    GElf_Rel rel_mem;
19431662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		    GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
194463868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    if (! relocate (r->r_offset, 0, false,
19451662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard				    GELF_R_TYPE (r->r_info),
19461662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard				    GELF_R_SYM (r->r_info)))
19471662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		      {
19481662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			if (relidx != next)
19491662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			  gelf_update_rel (reldata, next, r);
19501662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			++next;
19511662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		      }
19521662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  }
19531662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      else
19541662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		for (size_t relidx = 0; relidx < nrels; ++relidx)
19551662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  {
19561662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		    GElf_Rela rela_mem;
19571662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		    GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
195863868c2afb1123bf8ac2f99048e6f3f70dcf4c0eMark Wielaard		    if (! relocate (r->r_offset, r->r_addend, true,
19591662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard				    GELF_R_TYPE (r->r_info),
19601662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard				    GELF_R_SYM (r->r_info)))
19611662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		      {
19621662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			if (relidx != next)
19631662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			  gelf_update_rela (reldata, next, r);
19641662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			++next;
19651662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		      }
19661662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		  }
19671662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
19681662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      nrels = next;
19691662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
19701662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	      gelf_update_shdr (scn, shdr);
19711662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	    }
19721662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	}
19731662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard    }
19741662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
1975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now that we have done all adjustments to the data,
1976b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     we can actually write out the debug file.  */
1977b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (debug_fname != NULL)
1978b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Finally write the file.  */
19803cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper      if (unlikely (elf_update (debugelf, ELF_C_WRITE) == -1))
1981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, 0, gettext ("while writing '%s': %s"),
19836d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		 tmp_debug_fname, elf_errmsg (-1));
1984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
1985b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto fail_close;
1986b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1987b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1988b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Create the real output file.  First rename, then change the
1989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 mode.  */
1990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rename (tmp_debug_fname, debug_fname) != 0
1991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || fchmod (debug_fd, mode) != 0)
1992b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1993b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("while creating '%s'"), debug_fname);
1994b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
1995b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto fail_close;
1996b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1997b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1998b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* The temporary file does not exist anymore.  */
19996d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      free (tmp_debug_fname);
2000b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      tmp_debug_fname = NULL;
2001b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2002f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath      if (!remove_shdrs)
2003b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2004f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  uint32_t debug_crc;
2005f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  Elf_Data debug_crc_data =
2006f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	    {
2007f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      .d_type = ELF_T_WORD,
2008f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      .d_buf = &debug_crc,
2009f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      .d_size = sizeof (debug_crc),
2010f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      .d_version = EV_CURRENT
2011f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	    };
2012f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath
2013f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  /* Compute the checksum which we will add to the executable.  */
2014f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  if (crc32_file (debug_fd, &debug_crc) != 0)
2015f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	    {
2016f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      error (0, errno, gettext ("\
2017f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrathwhile computing checksum for debug information"));
2018f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      unlink (debug_fname);
2019f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      result = 1;
2020f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	      goto fail_close;
2021f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	    }
2022b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2023f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  /* Store it in the debuglink section data.  */
2024f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	  if (unlikely (gelf_xlatetof (newelf, &debuglink_crc_data,
2025f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath				       &debug_crc_data, ehdr->e_ident[EI_DATA])
2026f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath			!= &debuglink_crc_data))
2027f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	    INTERNAL_ERROR (fname);
2028f151b7d4b103b6d07ac510833cb2550de064621cRoland McGrath	}
2029b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2030b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2031b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Finally finish the ELF header.  Fill in the fields not handled by
2032b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     libelf from the old file.  */
2033b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr = gelf_getehdr (newelf, &newehdr_mem);
2034b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (newehdr == NULL)
2035b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    INTERNAL_ERROR (fname);
2036b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2037b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
2038b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_type = ehdr->e_type;
2039b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_machine = ehdr->e_machine;
2040b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_version = ehdr->e_version;
2041b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_entry = ehdr->e_entry;
2042b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_flags = ehdr->e_flags;
2043b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_phoff = ehdr->e_phoff;
20440b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath
2045b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We need to position the section header table.  */
2046b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
2047b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_shoff = ((shdr_info[shdridx].shdr.sh_offset
2048b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       + shdr_info[shdridx].shdr.sh_size + offsize - 1)
2049b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      & ~((GElf_Off) (offsize - 1)));
2050b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
2051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2052b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* The new section header string table index.  */
2053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (likely (idx < SHN_HIRESERVE) && likely (idx != SHN_XINDEX))
2054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    newehdr->e_shstrndx = idx;
2055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* The index does not fit in the ELF header field.  */
2058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[0].scn = elf_getscn (elf, 0);
2059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2060b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (gelf_getshdr (shdr_info[0].scn, &shdr_info[0].shdr) == NULL)
2061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	INTERNAL_ERROR (fname);
2062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      shdr_info[0].shdr.sh_link = idx;
2064b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      (void) gelf_update_shdr (shdr_info[0].scn, &shdr_info[0].shdr);
2065b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2066b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      newehdr->e_shstrndx = SHN_XINDEX;
2067b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2068b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2069b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (gelf_update_ehdr (newelf, newehdr) == 0)
2070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2071b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("%s: error while creating ELF header: %s"),
20726d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     output_fname ?: fname, elf_errmsg (-1));
20736d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
2074b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 1;
2075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2077b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We have everything from the old file.  */
2078b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf_cntl (elf, ELF_C_FDDONE) != 0)
2079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2080b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("%s: error while reading the file: %s"),
2081b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     fname, elf_errmsg (-1));
20826d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      cleanup_debug ();
2083b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 1;
2084b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2085b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2086b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* The ELF library better follows our layout when this is not a
2087b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     relocatable object file.  */
2088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_flagelf (newelf, ELF_C_SET,
2089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0)
2090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       | (permissive ? ELF_F_PERMISSIVE : 0));
2091b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2092b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Finally write the file.  */
2093b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf_update (newelf, ELF_C_WRITE) == -1)
2094b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("while writing '%s': %s"),
20966d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     output_fname ?: fname, elf_errmsg (-1));
2097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = 1;
2098b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
20990b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath
21000b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath  if (remove_shdrs)
21010b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath    {
21020b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath      /* libelf can't cope without the section headers being properly intact.
21030b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	 So we just let it write them normally, and then we nuke them later.  */
21040b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath
21050b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath      if (newehdr->e_ident[EI_CLASS] == ELFCLASS32)
21060b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	{
21070b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  assert (offsetof (Elf32_Ehdr, e_shentsize) + sizeof (Elf32_Half)
21080b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  == offsetof (Elf32_Ehdr, e_shnum));
21090b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  assert (offsetof (Elf32_Ehdr, e_shnum) + sizeof (Elf32_Half)
21100b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  == offsetof (Elf32_Ehdr, e_shstrndx));
21110b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  const Elf32_Off zero_off = 0;
21120b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  const Elf32_Half zero[3] = { 0, 0, SHN_UNDEF };
21130b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  if (pwrite_retry (fd, &zero_off, sizeof zero_off,
21140b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath			    offsetof (Elf32_Ehdr, e_shoff)) != sizeof zero_off
21150b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      || (pwrite_retry (fd, zero, sizeof zero,
21160b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath				offsetof (Elf32_Ehdr, e_shentsize))
21170b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  != sizeof zero)
21183425454a10d307fae891fb667cf7969e945cde79Josh Stone	      || ftruncate (fd, shdr_info[shdridx].shdr.sh_offset) < 0)
21190b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	    {
21200b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      error (0, errno, gettext ("while writing '%s'"),
21216d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		     output_fname ?: fname);
21220b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      result = 1;
21230b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	    }
21240b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	}
21250b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath      else
21260b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	{
21270b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  assert (offsetof (Elf64_Ehdr, e_shentsize) + sizeof (Elf64_Half)
21280b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  == offsetof (Elf64_Ehdr, e_shnum));
21290b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  assert (offsetof (Elf64_Ehdr, e_shnum) + sizeof (Elf64_Half)
21300b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  == offsetof (Elf64_Ehdr, e_shstrndx));
21310b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  const Elf64_Off zero_off = 0;
21320b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  const Elf64_Half zero[3] = { 0, 0, SHN_UNDEF };
21330b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	  if (pwrite_retry (fd, &zero_off, sizeof zero_off,
21340b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath			    offsetof (Elf64_Ehdr, e_shoff)) != sizeof zero_off
21350b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      || (pwrite_retry (fd, zero, sizeof zero,
21360b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath				offsetof (Elf64_Ehdr, e_shentsize))
21370b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		  != sizeof zero)
21383425454a10d307fae891fb667cf7969e945cde79Josh Stone	      || ftruncate (fd, shdr_info[shdridx].shdr.sh_offset) < 0)
21390b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	    {
21400b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      error (0, errno, gettext ("while writing '%s'"),
21416d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		     output_fname ?: fname);
21420b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	      result = 1;
21430b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	    }
21440b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	}
21450b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath    }
2146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper fail_close:
2148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr_info != NULL)
2149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* For some sections we might have created an table to map symbol
2151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 table indices.  */
2152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (any_symtab_changes)
2153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	for (cnt = 1; cnt <= shdridx; ++cnt)
2154521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  {
2155521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    free (shdr_info[cnt].newsymidx);
2156521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	    if (shdr_info[cnt].debug_data != NULL)
2157521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	      free (shdr_info[cnt].debug_data->d_buf);
2158521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	  }
2159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2160a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard      /* Free data we allocated for the .gnu_debuglink section. */
2161a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard      free (debuglink_buf);
2162a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard
2163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Free the memory.  */
2164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
2165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	free (shdr_info);
2166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Free other resources.  */
2169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shstrtab_data != NULL)
2170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    free (shstrtab_data->d_buf);
2171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shst != NULL)
2172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ebl_strtabfree (shst);
2173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* That was it.  Close the descriptors.  */
2175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf_end (newelf) != 0)
2176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
21776d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      error (0, 0, gettext ("error while finishing '%s': %s"),
21786d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	     output_fname ?: fname, elf_errmsg (-1));
2179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = 1;
2180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (debugelf != NULL && elf_end (debugelf) != 0)
2183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("error while finishing '%s': %s"), debug_fname,
2185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     elf_errmsg (-1));
2186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = 1;
2187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper fail:
2190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Close the EBL backend.  */
2191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ebl != NULL)
2192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ebl_closebackend (ebl);
2193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
21946d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard  cleanup_debug ();
2195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If requested, preserve the timestamp.  */
2197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (tvp != NULL)
2198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
21998c4aa0ef998191ed828a37190dc179b91649938aMax Filippov      if (futimens (fd, tvp) != 0)
2200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("\
2202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot set access and modification date of '%s'"),
2203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 output_fname ?: fname);
2204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
2205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Close the file descriptor if we created a new file.  */
2209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (output_fname != NULL)
2210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    close (fd);
2211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
2213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
22156d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaardstatic void
22161ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaardcleanup_debug (void)
22176d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard{
22186d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard  if (debug_fd >= 0)
22196d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    {
22206d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      if (tmp_debug_fname != NULL)
22216d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	{
22226d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  unlink (tmp_debug_fname);
22236d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  free (tmp_debug_fname);
22246d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	  tmp_debug_fname = NULL;
22256d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	}
22266d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      close (debug_fd);
22276d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard      debug_fd = -1;
22286d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard    }
22296d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard}
2230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
2232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperhandle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
22338c4aa0ef998191ed828a37190dc179b91649938aMax Filippov	   struct timespec tvp[2])
2234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
2236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t fname_len = strlen (fname) + 1;
2237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char new_prefix[prefix_len + 1 + fname_len];
2238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *cp = new_prefix;
2239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Create the full name of the file.  */
2241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (prefix != NULL)
2242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      cp = mempcpy (cp, prefix, prefix_len);
2244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      *cp++ = ':';
2245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  memcpy (cp, fname, fname_len);
2247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Process all the files contained in the archive.  */
2250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *subelf;
2251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Cmd cmd = ELF_C_RDWR;
2252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result = 0;
2253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
2254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* The the header for this element.  */
2256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
2257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf_kind (subelf) == ELF_K_ELF)
2259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
2260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (elf_kind (subelf) == ELF_K_AR)
2261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
2262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Get next archive element.  */
2264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      cmd = elf_next (subelf);
2265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (unlikely (elf_end (subelf) != 0))
2266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	INTERNAL_ERROR (fname);
2267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (tvp != NULL)
2270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
22718c4aa0ef998191ed828a37190dc179b91649938aMax Filippov      if (unlikely (futimens (fd, tvp) != 0))
2272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("\
2274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot set access and modification date of '%s'"), fname);
2275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
2276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (unlikely (close (fd) != 0))
2280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
2281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
2283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
22843cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
22853cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
22863cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper#include "debugpred.h"
2287