1441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Discard section not used at runtime from object files.
2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008 Red Hat, Inc.
3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   This file is part of Red Hat elfutils.
4441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
7cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   it under the terms of the GNU General Public License as published by the
8cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Free Software Foundation; version 2 of the License.
9441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
10cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
11cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
12cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   General Public License for more details.
14cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
15cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   You should have received a copy of the GNU General Public License along
16cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
17cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
19cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is an included package of the Open Invention Network.
20cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   An included package of the Open Invention Network is a package for which
21cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Open Invention Network licensees cross-license their patents.  No patent
22cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   license is granted, either expressly or impliedly, by designation as an
23cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   included package.  Should you wish to participate in the Open Invention
24cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Network licensing program, please visit www.openinventionnetwork.com
25cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   <http://www.openinventionnetwork.com>.  */
26441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
27441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifdef HAVE_CONFIG_H
28441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project# include <config.h>
29441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif
30441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
31441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <argp.h>
32441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <assert.h>
33441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <byteswap.h>
34441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <endian.h>
35441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <error.h>
36441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <fcntl.h>
37441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <gelf.h>
38441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libelf.h>
39441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libintl.h>
40441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <locale.h>
41441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <mcheck.h>
42441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdbool.h>
43441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdio.h>
44441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdio_ext.h>
45441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdlib.h>
46441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <string.h>
47441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <unistd.h>
48441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <sys/param.h>
49441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <sys/time.h>
50441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
51441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <elf-knowledge.h>
52441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libebl.h>
53441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <system.h>
54441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
55441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
56441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Name and version of program.  */
57441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void print_version (FILE *stream, struct argp_state *state);
58441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectvoid (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
59441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
60cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Bug report address.  */
61cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengconst char *argp_program_bug_address = PACKAGE_BUGREPORT;
62cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
63441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
64441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Values for the parameters which have no short form.  */
65441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define OPT_REMOVE_COMMENT	0x100
66441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define OPT_PERMISSIVE		0x101
67441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
68441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
69441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Definitions of arguments for argp functions.  */
70441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const struct argp_option options[] =
71441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
72cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
73cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "output", 'o', "FILE", 0, N_("Place stripped output into FILE"), 0 },
74cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'f', "FILE", 0, N_("Extract the removed sections into FILE"), 0 },
75cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'F', "FILE", 0, N_("Embed name FILE instead of -f argument"), 0 },
76cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
77cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 0, NULL, 0, N_("Output options:"), 0 },
78cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "strip-all", 's', NULL, OPTION_HIDDEN, NULL, 0 },
79cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols"), 0 },
80cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'd', NULL, OPTION_ALIAS, NULL, 0 },
81cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'S', NULL, OPTION_ALIAS, NULL, 0 },
82441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "preserve-dates", 'p', NULL, 0,
83cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    N_("Copy modified/access timestamps to the output"), 0 },
84441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
85cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    N_("Remove .comment section"), 0 },
86cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "remove-section", 'R', "SECTION", OPTION_HIDDEN, NULL, 0 },
87441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "permissive", OPT_PERMISSIVE, NULL, 0,
88cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    N_("Relax a few rules to handle slightly broken ELF files"), 0 },
89cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 0, NULL, 0, NULL, 0 }
90441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project};
91441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
92441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Short description of program.  */
93441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char doc[] = N_("Discard symbols from object files.");
94441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
95441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Strings for arguments in help texts.  */
96441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char args_doc[] = N_("[FILE...]");
97441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
98441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Prototype for option handler.  */
99441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Data structure to communicate with argp functions.  */
102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic struct argp argp =
103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  options, parse_opt, args_doc, doc, NULL, NULL, NULL
105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project};
106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print symbols in file named FNAME.  */
109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int process_file (const char *fname);
110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Handle one ELF file.  */
112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int handle_elf (int fd, Elf *elf, const char *prefix,
113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       const char *fname, mode_t mode, struct timeval tvp[2]);
114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Handle all files contained in the archive.  */
116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      struct timeval tvp[2]);
118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define INTERNAL_ERROR(fname) \
120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"),      \
121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Name of the output file.  */
125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *output_fname;
126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Name of the debug output file.  */
128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *debug_fname;
129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Name to pretend the debug output file has.  */
131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char *debug_fname_embed;
132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* If true output files shall have same date as the input file.  */
134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool preserve_dates;
135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* If true .comment sections will be removed.  */
137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool remove_comment;
138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* If true remove all debug sections.  */
140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool remove_debug;
141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* If true relax some ELF rules for input files.  */
143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool permissive;
144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectint
147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmain (int argc, char *argv[])
148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int remaining;
150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int result = 0;
151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Make memory leak detection possible.  */
153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  mtrace ();
154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We use no threads here which can interfere with handling a stream.  */
156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Set locale.  */
161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  setlocale (LC_ALL, "");
162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Make sure the message catalog can be found.  */
164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Initialize the message catalog.  */
167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  textdomain (PACKAGE_TARNAME);
168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Parse and process arguments.  */
170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return EXIT_FAILURE;
172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Tell the library which version we are expecting.  */
174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  elf_version (EV_CURRENT);
175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (remaining == argc)
177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* The user didn't specify a name so we use a.out.  */
178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    result = process_file ("a.out");
179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* If we have seen the '-o' or '-f' option there must be exactly one
182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 input file.  */
183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if ((output_fname != NULL || debug_fname != NULL)
184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && remaining + 1 < argc)
185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	error (EXIT_FAILURE, 0, gettext ("\
186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectOnly one input file allowed together with '-o' and '-f'"));
187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Process all the remaining files.  */
189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      do
190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result |= process_file (argv[remaining]);
191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      while (++remaining < argc);
192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print the version information.  */
199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  fprintf (stream, "strip (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fprintf (stream, gettext ("\
204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectCopyright (C) %s Red Hat, Inc.\n\
205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectThis is free software; see the source for copying conditions.  There is NO\n\
206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng"), "2008");
208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
209441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
212441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Handle program arguments.  */
213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic error_t
214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectparse_opt (int key, char *arg, struct argp_state *state)
215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  switch (key)
217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'f':
219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (debug_fname != NULL)
220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, 0, gettext ("-f option specified twice"));
222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  return EINVAL;
223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debug_fname = arg;
225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'F':
228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (debug_fname_embed != NULL)
229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, 0, gettext ("-F option specified twice"));
231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  return EINVAL;
232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      debug_fname_embed = arg;
234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'o':
237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (output_fname != NULL)
238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, 0, gettext ("-o option specified twice"));
240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  return EINVAL;
241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      output_fname = arg;
243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'p':
246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      preserve_dates = true;
247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case OPT_REMOVE_COMMENT:
250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      remove_comment = true;
251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'R':
254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (!strcmp (arg, ".comment"))
255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	remove_comment = true;
256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  argp_error (state,
259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      gettext ("-R option supports only .comment section"));
260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  return EINVAL;
261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'g':
265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'd':
266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'S':
267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      remove_debug = true;
268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case OPT_PERMISSIVE:
271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      permissive = true;
272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
273441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 's':			/* Ignored for compatibility.  */
275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    default:
278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return ARGP_ERR_UNKNOWN;
279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return 0;
281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int
285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprocess_file (const char *fname)
286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If we have to preserve the modify and access timestamps get them
288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     now.  We cannot use fstat() after opening the file since the open
289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     would change the access time.  */
290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct stat64 pre_st;
291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct timeval tv[2];
292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project again:
293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (preserve_dates)
294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (stat64 (fname, &pre_st) != 0)
296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, errno, gettext ("cannot stat input file '%s'"), fname);
298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  return 1;
299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* If we have to preserve the timestamp, we need it in the
302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 format utimes() understands.  */
303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      TIMESPEC_TO_TIMEVAL (&tv[0], &pre_st.st_atim);
304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      TIMESPEC_TO_TIMEVAL (&tv[1], &pre_st.st_mtim);
305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Open the file.  */
308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int fd = open (fname, output_fname == NULL ? O_RDWR : O_RDONLY);
309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (fd == -1)
310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, errno, gettext ("while opening '%s'"), fname);
312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return 1;
313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We always use fstat() even if we called stat() before.  This is
316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     done to make sure the information returned by stat() is for the
317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     same file.  */
318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct stat64 st;
319441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (fstat64 (fd, &st) != 0)
320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, errno, gettext ("cannot stat input file '%s'"), fname);
322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return 1;
323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Paranoid mode on.  */
325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (preserve_dates
326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      && (st.st_ino != pre_st.st_ino || st.st_dev != pre_st.st_dev))
327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* We detected a race.  Try again.  */
329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      close (fd);
330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      goto again;
331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Now get the ELF descriptor.  */
334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *elf = elf_begin (fd, output_fname == NULL ? ELF_C_RDWR : ELF_C_READ,
335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			NULL);
336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int result;
337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  switch (elf_kind (elf))
338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case ELF_K_ELF:
340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      result = handle_elf (fd, elf, NULL, fname, st.st_mode & ACCESSPERMS,
341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   preserve_dates ? tv : NULL);
342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case ELF_K_AR:
345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* It is not possible to strip the content of an archive direct
346441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 the output to a specific file.  */
347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (output_fname != NULL || debug_fname != NULL))
348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, 0, gettext ("%s: cannot use -o or -f when stripping archive"),
350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 fname);
351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = handle_ar (fd, elf, NULL, fname, preserve_dates ? tv : NULL);
355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    default:
358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("%s: File format not recognized"), fname);
359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      result = 1;
360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (elf_end (elf) != 0))
364441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    INTERNAL_ERROR (fname);
365441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  close (fd);
367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
368441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
369441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
371441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
372441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Maximum size of array allocated on stack.  */
373441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define MAX_STACK_ALLOC	(400 * 1024)
374441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int
376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projecthandle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    mode_t mode, struct timeval tvp[2])
378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t fname_len = strlen (fname) + 1;
381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *fullname = alloca (prefix_len + 1 + fname_len);
382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *cp = fullname;
383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf *debugelf = NULL;
384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *tmp_debug_fname = NULL;
385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int result = 0;
386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shdridx = 0;
387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t shstrndx;
388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct shdr_info
389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  {
390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf_Scn *scn;
391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    GElf_Shdr shdr;
392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf_Data *data;
393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    Elf_Data *debug_data;
394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    const char *name;
395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word idx;		/* Index in new file.  */
396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word old_sh_link;	/* Original value of shdr.sh_link.  */
397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word symtab_idx;
398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word version_idx;
399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word group_idx;
400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word group_cnt;
401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf_Scn *newscn;
402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    struct Ebl_Strent *se;
403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word *newsymidx;
404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  } *shdr_info = NULL;
405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn;
406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t idx;
408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool changes;
409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr newehdr_mem;
410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr *newehdr;
411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr debugehdr_mem;
412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr *debugehdr;
413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct Ebl_Strtab *shst = NULL;
414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data debuglink_crc_data;
415441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool any_symtab_changes = false;
416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *shstrtab_data = NULL;
417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Create the full name of the file.  */
419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (prefix != NULL)
420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      cp = mempcpy (cp, prefix, prefix_len);
422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      *cp++ = ':';
423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  memcpy (cp, fname, fname_len);
425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If we are not replacing the input file open a new file here.  */
427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (output_fname != NULL)
428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      fd = open (output_fname, O_RDWR | O_CREAT, mode);
430441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (fd == -1))
431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, errno, gettext ("cannot open '%s'"), output_fname);
433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  return 1;
434441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
435441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
436441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int debug_fd = -1;
438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the EBL handling.  The -g option is currently the only reason
440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     we need EBL so dont open the backend unless necessary.  */
441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Ebl *ebl = NULL;
442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (remove_debug)
443441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
444441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ebl = ebl_openbackend (elf);
445441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ebl == NULL)
446441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
447441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("cannot open EBL backend"));
448441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
449441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail;
450441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
451441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
452441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
453441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Open the additional file the debug information will be stored in.  */
454441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debug_fname != NULL)
455441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
456441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Create a temporary file name.  We do not want to overwrite
457441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 the debug file if the file would not contain any
458441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 information.  */
459441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t debug_fname_len = strlen (debug_fname);
460441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      tmp_debug_fname = (char *) alloca (debug_fname_len + sizeof (".XXXXXX"));
461441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      strcpy (mempcpy (tmp_debug_fname, debug_fname, debug_fname_len),
462441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ".XXXXXX");
463441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
464441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debug_fd = mkstemp (tmp_debug_fname);
465441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (debug_fd == -1))
466441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, errno, gettext ("cannot open '%s'"), debug_fname);
468441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
469441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail;
470441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
471441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
473441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the information from the old file.  */
474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Ehdr ehdr_mem;
475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
476441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr == NULL)
477441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    INTERNAL_ERROR (fname);
478441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
479441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (elf_getshstrndx (elf, &shstrndx) < 0))
481441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
482441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
483441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
484441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We now create a new ELF descriptor for the same file.  We
485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     construct it almost exactly in the same way with some information
486441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     dropped.  */
487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *newelf;
488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (output_fname != NULL)
489441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    newelf = elf_clone (elf, ELF_C_EMPTY);
492441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0)
494441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      || (ehdr->e_type != ET_REL
495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && unlikely (gelf_newphdr (newelf, ehdr->e_phnum) == 0)))
496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, 0, gettext ("cannot create new file '%s': %s"),
498441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     output_fname, elf_errmsg (-1));
499441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      goto fail;
500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
502441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Copy over the old program header if needed.  */
503441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_type != ET_REL)
504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
505441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
506441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	GElf_Phdr phdr_mem;
507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
508441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (phdr == NULL
509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    || unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  INTERNAL_ERROR (fname);
511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
512441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
513441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debug_fname != NULL)
514441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Also create an ELF descriptor for the debug file */
516441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugelf = elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL);
517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0)
518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  || (ehdr->e_type != ET_REL
519441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && unlikely (gelf_newphdr (debugelf, ehdr->e_phnum) == 0)))
520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, 0, gettext ("cannot create new file '%s': %s"),
522441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 debug_fname, elf_errmsg (-1));
523441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail_close;
524441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
526441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Copy over the old program header if needed.  */
527441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_type != ET_REL)
528441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
530441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    GElf_Phdr phdr_mem;
531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
532441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (phdr == NULL
533441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		|| unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
534441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      INTERNAL_ERROR (fname);
535441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
536441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
537441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
538441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Number of sections.  */
539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shnum;
540441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (elf_getshnum (elf, &shnum) < 0))
541441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
542441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("cannot determine number of sections: %s"),
543441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     elf_errmsg (-1));
544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      goto fail_close;
545441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
546441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
547441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Storage for section information.  We leave room for two more
548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     entries since we unconditionally create a section header string
549441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     table.  Maybe some weird tool created an ELF file without one.
550441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     The other one is used for the debug link section.  */
551441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
552441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    shdr_info = (struct shdr_info *) xcalloc (shnum + 2,
553441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					      sizeof (struct shdr_info));
554441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
555441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
556441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info = (struct shdr_info *) alloca ((shnum + 2)
557441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					       * sizeof (struct shdr_info));
558441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
561441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Prepare section information data structure.  */
562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  scn = NULL;
563441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  cnt = 1;
564441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((scn = elf_nextscn (elf, scn)) != NULL)
565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* This should always be true (i.e., there should not be any
567441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 holes in the numbering).  */
568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      assert (elf_ndxscn (scn) == cnt);
569441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].scn = scn;
571441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
572441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Get the header.  */
573441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL)
574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	INTERNAL_ERROR (fname);
575441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
576441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Get the name of the section.  */
577441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].name = elf_strptr (elf, shstrndx,
578441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					shdr_info[cnt].shdr.sh_name);
579441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr_info[cnt].name == NULL)
580441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, 0, gettext ("illformed file '%s'"), fname);
582441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail_close;
583441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
584441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
585441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Mark them as present but not yet investigated.  */
586441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].idx = 1;
587441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
588441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Remember the shdr.sh_link value.  */
589441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link;
590441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
591441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Sections in files other than relocatable object files which
592441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 are not loaded can be freely moved by us.  In relocatable
593441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 object files everything can be moved.  */
594441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_type == ET_REL
595441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
596441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].shdr.sh_offset = 0;
597441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
598441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* If this is an extended section index table store an
599441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 appropriate reference.  */
600441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
601441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
602441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
603441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
604441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
605441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
606441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
607441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Cross-reference the sections contained in the section
608441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     group.  */
609441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
610441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[cnt].data == NULL)
611441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    INTERNAL_ERROR (fname);
612441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
613441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* XXX Fix for unaligned access.  */
614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  size_t inner;
616441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  for (inner = 1;
617441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
618441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       ++inner)
619441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[grpref[inner]].group_idx = cnt;
620441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
621441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
622441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* If the section group contains only one element and this
623441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       is n COMDAT section we can drop it right away.  */
624441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[cnt].idx = 0;
625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[cnt].group_cnt = inner - 1;
627441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
631441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
632441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
633441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* If this section is part of a group make sure it is not
635441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 discarded right away.  */
636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
637441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
638441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  assert (shdr_info[cnt].group_idx != 0);
639441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
640441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
641441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The section group section will be removed.  */
643441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr_info[cnt].group_idx = 0;
644441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr_info[cnt].shdr.sh_flags &= ~SHF_GROUP;
645441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
647441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
648441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Increment the counter.  */
649441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ++cnt;
650441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
651441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
652441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Now determine which sections can go away.  The general rule is that
653441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     all sections which are not used at runtime are stripped out.  But
654441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     there are a few exceptions:
655441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
656441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     - special sections named ".comment" and ".note" are kept
657441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     - OS or architecture specific sections are kept since we might not
658441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       know how to handle them
659441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     - if a section is referred to from a section which is not removed
660441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       in the sh_link or sh_info element it cannot be removed either
661441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  */
662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 1; cnt < shnum; ++cnt)
663441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* Check whether the section can be removed.  */
664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    if (ebl_section_strip_p (ebl, ehdr, &shdr_info[cnt].shdr,
665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     shdr_info[cnt].name, remove_comment,
666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     remove_debug))
667441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
668441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* For now assume this section will be removed.  */
669441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].idx = 0;
670441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	idx = shdr_info[cnt].group_idx;
672441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	while (idx != 0)
673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* The section group data is already loaded.  */
675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    assert (shdr_info[idx].data != NULL);
676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* If the references section group is a normal section
678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       group and has one element remaining, or if it is an
679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       empty COMDAT section group it is removed.  */
680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    bool is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      & GRP_COMDAT) != 0;
682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
683441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    --shdr_info[idx].group_cnt;
684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if ((!is_comdat && shdr_info[idx].group_cnt == 1)
685441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		|| (is_comdat && shdr_info[idx].group_cnt == 0))
686441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      {
687441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		shdr_info[idx].idx = 0;
688441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		/* Continue recursively.  */
689441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		idx = shdr_info[idx].group_idx;
690441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      }
691441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    else
692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      break;
693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
694441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Mark the SHT_NULL section as handled.  */
697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[0].idx = 2;
698441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
699441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
700441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Handle exceptions: section groups and cross-references.  We might
701441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     have to repeat this a few times since the resetting of the flag
702441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     might propagate.  */
703441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  do
704441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
705441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      changes = false;
706441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
707441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (cnt = 1; cnt < shnum; ++cnt)
708441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
709441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[cnt].idx == 0)
710441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
711441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* If a relocation section is marked as being removed make
712441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 sure the section it is relocating is removed, too.  */
713441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if ((shdr_info[cnt].shdr.sh_type == SHT_REL
714441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   || shdr_info[cnt].shdr.sh_type == SHT_RELA)
715441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
716441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		shdr_info[cnt].idx = 1;
717441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
718441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
719441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[cnt].idx == 1)
720441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
721441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The content of symbol tables we don't remove must not
722441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 reference any section which we do remove.  Otherwise
723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 we cannot remove the section.  */
724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (debug_fname != NULL
725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  && shdr_info[cnt].debug_data == NULL
726cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  && (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
727cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB))
728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Make sure the data is loaded.  */
730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (shdr_info[cnt].data == NULL)
731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      shdr_info[cnt].data
733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			= elf_getdata (shdr_info[cnt].scn, NULL);
734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (shdr_info[cnt].data == NULL)
735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			INTERNAL_ERROR (fname);
736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
737cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  Elf_Data *symdata = shdr_info[cnt].data;
738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* If there is an extended section index table load it
740441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     as well.  */
741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (shdr_info[cnt].symtab_idx != 0
742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      shdr_info[shdr_info[cnt].symtab_idx].data
747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			= elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				       NULL);
749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
750441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			INTERNAL_ERROR (fname);
751441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
752cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  Elf_Data *xndxdata
753cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    = shdr_info[shdr_info[cnt].symtab_idx].data;
754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
755441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Go through all symbols and make sure the section they
756441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     reference is not removed.  */
757cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
758cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					      ehdr->e_version);
759441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  for (size_t inner = 0;
761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       inner < shdr_info[cnt].data->d_size / elsize;
762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       ++inner)
763441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
764441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      GElf_Sym sym_mem;
765441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      Elf32_Word xndx;
766cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng							inner, &sym_mem,
768cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng							&xndx);
769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (sym == NULL)
770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			INTERNAL_ERROR (fname);
771441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
772cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      size_t scnidx = sym->st_shndx;
773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (scnidx == SHN_UNDEF || scnidx >= shnum
774441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  || (scnidx >= SHN_LORESERVE
775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      && scnidx <= SHN_HIRESERVE
776441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      && scnidx != SHN_XINDEX)
777441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  /* Don't count in the section symbols.  */
778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
779441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			/* This is no section index, leave it alone.  */
780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			continue;
781441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      else if (scnidx == SHN_XINDEX)
782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			scnidx = xndx;
783441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (shdr_info[scnidx].idx == 0)
785cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			/* This symbol table has a real symbol in
786cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   a discarded section.  So preserve the
787cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   original table in the debug file.  */
788cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			shdr_info[cnt].debug_data = symdata;
789441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
790441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
791441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
792441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Cross referencing happens:
793441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 - for the cases the ELF specification says.  That are
794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   + SHT_DYNAMIC in sh_link to string table
795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   + SHT_HASH in sh_link to symbol table
796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   + SHT_REL and SHT_RELA in sh_link to symbol table
797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   + SHT_GROUP in sh_link to symbol table
799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   + SHT_SYMTAB_SHNDX in sh_link to symbol table
800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   Other (OS or architecture-specific) sections might as
801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   well use this field so we process it unconditionally.
802441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 - references inside section groups
803441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 - specially marked references in sh_info if the SHF_INFO_LINK
804441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 flag is set
805441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      */
806441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
807441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
808441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
809441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
810441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  changes |= shdr_info[cnt].shdr.sh_link < cnt;
811441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
812441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
813441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Handle references through sh_info.  */
814441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)
815441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  && shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
816441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
817441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
818441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  changes |= shdr_info[cnt].shdr.sh_info < cnt;
819441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
820441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
821441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Mark the section as investigated.  */
822441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr_info[cnt].idx = 2;
823441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (debug_fname != NULL
826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      && (shdr_info[cnt].idx == 0 || shdr_info[cnt].debug_data != NULL))
827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* This section is being preserved in the debug file.
829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 Sections it refers to must be preserved there too.
830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 In this pass we mark sections to be preserved in both
832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 files by setting the .debug_data pointer to the original
833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 file's .data pointer.  Below, we'll copy the section
834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 contents.  */
835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      inline void check_preserved (size_t i)
837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      {
838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		if (i != 0 && shdr_info[i].idx != 0)
839cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  {
840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    if (shdr_info[i].data == NULL)
841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
842cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    if (shdr_info[i].data == NULL)
843cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      INTERNAL_ERROR (fname);
844cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    shdr_info[i].debug_data = shdr_info[i].data;
846cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    changes |= i < cnt;
847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  }
848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      }
849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
850cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      check_preserved (shdr_info[cnt].shdr.sh_link);
851cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
852cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		check_preserved (shdr_info[cnt].shdr.sh_info);
853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
854441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
855441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
856441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (changes);
857441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
858cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Copy the removed sections to the debug output file.
859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     The ones that are not removed in the stripped file are SHT_NOBITS.  */
860441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debug_fname != NULL)
861441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
862441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (cnt = 1; cnt < shnum; ++cnt)
863441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
864441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  scn = elf_newscn (debugelf);
865441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (scn == NULL)
866441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    error (EXIT_FAILURE, 0,
867441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   gettext ("while generating output file: %s"),
868441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   elf_errmsg (-1));
869441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  bool discard_section = (shdr_info[cnt].idx > 0
871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				  && shdr_info[cnt].debug_data == NULL
872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				  && shdr_info[cnt].shdr.sh_type != SHT_NOTE
873cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				  && cnt != ehdr->e_shstrndx);
874441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
875441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Set the section header in the new file.  */
876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Shdr debugshdr = shdr_info[cnt].shdr;
877441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (discard_section)
878441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    debugshdr.sh_type = SHT_NOBITS;
879441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
880cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (gelf_update_shdr (scn, &debugshdr) == 0))
881441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* There cannot be any overflows.  */
882441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    INTERNAL_ERROR (fname);
883441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
884441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Get the data from the old file if necessary. */
885441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[cnt].data == NULL)
886441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
887441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
888441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr_info[cnt].data == NULL)
889441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		INTERNAL_ERROR (fname);
890441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
891441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
892441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Set the data.  This is done by copying from the old file.  */
893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  Elf_Data *debugdata = elf_newdata (scn);
894441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (debugdata == NULL)
895441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    INTERNAL_ERROR (fname);
896441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Copy the structure.  This data may be modified in place
898cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     before we write out the file.  */
899441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  *debugdata = *shdr_info[cnt].data;
900441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (discard_section)
901441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    debugdata->d_buf = NULL;
902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else if (shdr_info[cnt].debug_data != NULL)
903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* Copy the original data before it gets modified.  */
905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      shdr_info[cnt].debug_data = debugdata;
906cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      debugdata->d_buf = memcpy (xmalloc (debugdata->d_size),
907cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					 debugdata->d_buf, debugdata->d_size);
908cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
909441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
910441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
911441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Finish the ELF header.  Fill in the fields not handled by
912441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 libelf from the old file.  */
913441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
914441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (debugehdr == NULL)
915441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	INTERNAL_ERROR (fname);
916441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
917441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
918441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_type = ehdr->e_type;
919441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_machine = ehdr->e_machine;
920441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_version = ehdr->e_version;
921441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_entry = ehdr->e_entry;
922441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_flags = ehdr->e_flags;
923441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_shstrndx = ehdr->e_shstrndx;
924441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (gelf_update_ehdr (debugelf, debugehdr) == 0))
926441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
927441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, 0, gettext ("%s: error while creating ELF header: %s"),
928441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 debug_fname, elf_errmsg (-1));
929441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
930441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail_close;
931441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
932441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
933441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
934441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Mark the section header string table as unused, we will create
935441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     a new one.  */
936441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[shstrndx].idx = 0;
937441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
938441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We need a string table for the section headers.  */
939441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shst = ebl_strtabinit (true);
940441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shst == NULL)
941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, errno, gettext ("while preparing output for '%s'"),
942441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   output_fname ?: fname);
943441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
944441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Assign new section numbers.  */
945441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[0].idx = 0;
946441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = idx = 1; cnt < shnum; ++cnt)
947441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    if (shdr_info[cnt].idx > 0)
948441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
949441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].idx = idx++;
950441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
951441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Create a new section.  */
952441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].newscn = elf_newscn (newelf);
953441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (shdr_info[cnt].newscn == NULL)
954441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (EXIT_FAILURE, 0, gettext ("while generating output file: %s"),
955441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 elf_errmsg (-1));
956441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
957441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
958441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
959441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Add this name to the section header string table.  */
960441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);
961441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
962441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
963441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Test whether we are doing anything at all.  */
964441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (cnt == idx)
965441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* Nope, all removable sections are already gone.  */
966441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    goto fail_close;
967441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
968441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Create the reference to the file with the debug info.  */
969441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debug_fname != NULL)
970441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
971441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Add the section header string table section name.  */
972441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].se = ebl_strtabadd (shst, ".gnu_debuglink", 15);
973441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].idx = idx++;
974441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
975441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Create the section header.  */
976441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
977441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_flags = 0;
978441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_addr = 0;
979441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
980441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
981441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_entsize = 0;
982441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_addralign = 4;
983441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* We set the offset to zero here.  Before we write the ELF file the
984441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 field must have the correct value.  This is done in the final
985441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 loop over all section.  Then we have all the information needed.  */
986441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_offset = 0;
987441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
988441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Create the section.  */
989441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].newscn = elf_newscn (newelf);
990441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr_info[cnt].newscn == NULL)
991441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	error (EXIT_FAILURE, 0,
992441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       gettext ("while create section header section: %s"),
993441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       elf_errmsg (-1));
994441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
995441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
996441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
997441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr_info[cnt].data == NULL)
998441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	error (EXIT_FAILURE, 0, gettext ("cannot allocate section data: %s"),
999441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       elf_errmsg (-1));
1000441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char *debug_basename = basename (debug_fname_embed ?: debug_fname);
1002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      off_t crc_offset = strlen (debug_basename) + 1;
1003441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Align to 4 byte boundary */
1004441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      crc_offset = ((crc_offset - 1) & ~3) + 4;
1005441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1006441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].data->d_align = 4;
1007441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
1008441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	= crc_offset + 4;
1009441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].data->d_buf = xcalloc (1, shdr_info[cnt].data->d_size);
1010441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1011441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      strcpy (shdr_info[cnt].data->d_buf, debug_basename);
1012cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Cache this Elf_Data describing the CRC32 word in the section.
1014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 We'll fill this in when we have written the debug file.  */
1015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      debuglink_crc_data = *shdr_info[cnt].data;
1016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      debuglink_crc_data.d_buf = ((char *) debuglink_crc_data.d_buf
1017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				  + crc_offset);
1018cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      debuglink_crc_data.d_size = 4;
1019441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1020441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* One more section done.  */
1021441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ++cnt;
1022441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1023441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1024441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Index of the section header table in the shdr_info array.  */
1025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  shdridx = cnt;
1026441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1027441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Add the section header string table section name.  */
1028441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].se = ebl_strtabadd (shst, ".shstrtab", 10);
1029441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].idx = idx;
1030441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1031441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Create the section header.  */
1032441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
1033441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_flags = 0;
1034441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_addr = 0;
1035441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1036441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1037441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_entsize = 0;
1038441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We set the offset to zero here.  Before we write the ELF file the
1039441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     field must have the correct value.  This is done in the final
1040441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     loop over all section.  Then we have all the information needed.  */
1041441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_offset = 0;
1042441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_addralign = 1;
1043441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1044441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Create the section.  */
1045441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].newscn = elf_newscn (newelf);
1046441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr_info[cnt].newscn == NULL)
1047441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
1048441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("while create section header section: %s"),
1049441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   elf_errmsg (-1));
1050441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
1051441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1052441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Finalize the string table and fill in the correct indices in the
1053441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     section headers.  */
1054441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
1055441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shstrtab_data == NULL)
1056441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
1057441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("while create section header string table: %s"),
1058441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   elf_errmsg (-1));
1059441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  ebl_strtabfinalize (shst, shstrtab_data);
1060441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1061441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We have to set the section size.  */
1062441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
1063441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1064441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Update the section information.  */
1065441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Off lastoffset = 0;
1066441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 1; cnt <= shdridx; ++cnt)
1067441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    if (shdr_info[cnt].idx > 0)
1068441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
1069441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	Elf_Data *newdata;
1070441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1071441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	scn = elf_getscn (newelf, shdr_info[cnt].idx);
1072441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	assert (scn != NULL);
1073441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1074441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Update the name.  */
1075441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].shdr.sh_name = ebl_strtaboffset (shdr_info[cnt].se);
1076441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1077441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Update the section header from the input file.  Some fields
1078441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   might be section indeces which now have to be adjusted.  */
1079441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (shdr_info[cnt].shdr.sh_link != 0)
1080441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[cnt].shdr.sh_link =
1081441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[shdr_info[cnt].shdr.sh_link].idx;
1082441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1083441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1084441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
1085441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    assert (shdr_info[cnt].data != NULL);
1086441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1087441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1088441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    for (size_t inner = 0;
1089441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1090441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 ++inner)
1091441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      grpref[inner] = shdr_info[grpref[inner]].idx;
1092441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
1093441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1094441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag.  */
1095441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1096441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[cnt].shdr.sh_info =
1097441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[shdr_info[cnt].shdr.sh_info].idx;
1098441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1099441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Get the data from the old file if necessary.  We already
1100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project           created the data for the section header string table.  */
1101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (cnt < shnum)
1102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
1103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (shdr_info[cnt].data == NULL)
1104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      {
1105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (shdr_info[cnt].data == NULL)
1107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  INTERNAL_ERROR (fname);
1108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      }
1109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* Set the data.  This is done by copying from the old file.  */
1111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    newdata = elf_newdata (scn);
1112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (newdata == NULL)
1113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      INTERNAL_ERROR (fname);
1114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* Copy the structure.  */
1116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    *newdata = *shdr_info[cnt].data;
1117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* We know the size.  */
1119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
1120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* We have to adjust symbol tables.  The st_shndx member might
1122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       have to be updated.  */
1123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
1124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		|| shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
1125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      {
1126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		Elf_Data *versiondata = NULL;
1127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		Elf_Data *shndxdata = NULL;
1128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					    ehdr->e_version);
1131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (shdr_info[cnt].symtab_idx != 0)
1133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
1135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* This section has extended section information.
1136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       We have to modify that information, too.  */
1137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
1138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					     NULL);
1139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    assert ((versiondata->d_size / sizeof (Elf32_Word))
1141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    >= shdr_info[cnt].data->d_size / elsize);
1142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (shdr_info[cnt].version_idx != 0)
1145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
1147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* This section has associated version
1148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       information.  We have to modify that
1149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       information, too.  */
1150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
1151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					       NULL);
1152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    assert ((versiondata->d_size / sizeof (GElf_Versym))
1154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    >= shdr_info[cnt].data->d_size / elsize);
1155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		shdr_info[cnt].newsymidx
1158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  = (Elf32_Word *) xcalloc (shdr_info[cnt].data->d_size
1159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					    / elsize, sizeof (Elf32_Word));
1160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		bool last_was_local = true;
1162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		size_t destidx;
1163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		size_t inner;
1164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		for (destidx = inner = 1;
1165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     inner < shdr_info[cnt].data->d_size / elsize;
1166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     ++inner)
1167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    Elf32_Word sec;
1169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    GElf_Sym sym_mem;
1170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    Elf32_Word xshndx;
1171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
1172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						      shndxdata, inner,
1173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						      &sym_mem, &xshndx);
1174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (sym == NULL)
1175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      INTERNAL_ERROR (fname);
1176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (sym->st_shndx == SHN_UNDEF
1178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			|| (sym->st_shndx >= shnum
1179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    && sym->st_shndx != SHN_XINDEX))
1180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      {
1181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			/* This is no section index, leave it alone
1182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   unless it is moved.  */
1183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if (destidx != inner
1184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    && gelf_update_symshndx (shdr_info[cnt].data,
1185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						     shndxdata,
1186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						     destidx, sym,
1187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						     xshndx) == 0)
1188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  INTERNAL_ERROR (fname);
1189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			shdr_info[cnt].newsymidx[inner] = destidx++;
1191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if (last_was_local
1193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  {
1195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    last_was_local = false;
1196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    shdr_info[cnt].shdr.sh_info = destidx - 1;
1197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  }
1198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			continue;
1200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      }
1201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* Get the full section index, if necessary from the
1203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       XINDEX table.  */
1204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (sym->st_shndx != SHN_XINDEX)
1205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      sec = shdr_info[sym->st_shndx].idx;
1206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    else
1207441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      {
1208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			assert (shndxdata != NULL);
1209441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			sec = shdr_info[xshndx].idx;
1211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      }
1212441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (sec != 0)
1214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      {
1215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			GElf_Section nshndx;
1216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			Elf32_Word nxshndx;
1217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if (sec < SHN_LORESERVE)
1219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  {
1220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    nshndx = sec;
1221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    nxshndx = 0;
1222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  }
1223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			else
1224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  {
1225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    nshndx = SHN_XINDEX;
1226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    nxshndx = sec;
1227441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  }
1228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			assert (sec < SHN_LORESERVE || shndxdata != NULL);
1230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if ((inner != destidx || nshndx != sym->st_shndx
1232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     || (shndxdata != NULL && nxshndx != xshndx))
1233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    && (sym->st_shndx = nshndx,
1234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				gelf_update_symshndx (shdr_info[cnt].data,
1235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						      shndxdata,
1236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						      destidx, sym,
1237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						      nxshndx) == 0))
1238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  INTERNAL_ERROR (fname);
1239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			shdr_info[cnt].newsymidx[inner] = destidx++;
1241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if (last_was_local
1243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  {
1245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    last_was_local = false;
1246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    shdr_info[cnt].shdr.sh_info = destidx - 1;
1247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  }
1248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      }
1249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    else if (debug_fname == NULL
1250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     || shdr_info[cnt].debug_data == NULL)
1251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      /* This is a section symbol for a section which has
1252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 been removed.  */
1253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION);
1254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (destidx != inner)
1257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* The size of the symbol table changed.  */
1259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    shdr_info[cnt].shdr.sh_size = newdata->d_size
1260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      = destidx * elsize;
1261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    any_symtab_changes = true;
1262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		else
1264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* The symbol table didn't really change.  */
1266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    free (shdr_info[cnt].newsymidx);
1267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    shdr_info[cnt].newsymidx = NULL;
1268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      }
1270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
1271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* If we have to, compute the offset of the section.  */
1273441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (shdr_info[cnt].shdr.sh_offset == 0)
1274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[cnt].shdr.sh_offset
1275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
1276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
1277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Set the section header in the new file.  */
1279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
1280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* There cannot be any overflows.  */
1281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  INTERNAL_ERROR (fname);
1282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Remember the last section written so far.  */
1284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
1285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   ? shdr_info[cnt].shdr.sh_size : 0);
1286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
1287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
1288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
1289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Adjust symbol references if symbol tables changed.  */
1291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (any_symtab_changes)
1292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    /* Find all relocation sections which use this symbol table.  */
1293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    for (cnt = 1; cnt <= shdridx; ++cnt)
1294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      {
1295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	/* Update section headers when the data size has changed.
1296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   We also update the SHT_NOBITS section in the debug
1297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   file so that the section headers match in sh_size.  */
1298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	inline void update_section_size (const Elf_Data *newdata)
1299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Shdr shdr_mem;
1301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  shdr->sh_size = newdata->d_size;
1303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  (void) gelf_update_shdr (scn, shdr);
1304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (debugelf != NULL)
1305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* libelf will use d_size to set sh_size.  */
1307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
1308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng							     cnt), NULL);
1309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      debugdata->d_size = newdata->d_size;
1310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	if (shdr_info[cnt].idx == 0 && debug_fname == NULL)
1314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Ignore sections which are discarded.  When we are saving a
1315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     relocation section in a separate debug file, we must fix up
1316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     the symbol table references.  */
1317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  continue;
1318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	const Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
1320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
1321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	switch (shdr_info[cnt].shdr.sh_type)
1322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  {
1323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    inline bool no_symtab_updates (void)
1324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* If the symbol table hasn't changed, do not do anything.  */
1326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (shdr_info[symtabidx].newsymidx == NULL)
1327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		return true;
1328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* If the symbol table is not discarded, but additionally
1330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 duplicated in the separate debug file and this section
1331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 is discarded, don't adjust anything.  */
1332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      return (shdr_info[cnt].idx == 0
1333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      && shdr_info[symtabidx].debug_data != NULL);
1334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case SHT_REL:
1337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case SHT_RELA:
1338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    if (no_symtab_updates ())
1339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      break;
1340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    Elf_Data *d = elf_getdata (shdr_info[cnt].idx == 0
1342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       ? elf_getscn (debugelf, cnt)
1343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       : elf_getscn (newelf,
1344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						     shdr_info[cnt].idx),
1345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       NULL);
1346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    assert (d != NULL);
1347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    size_t nrels = (shdr_info[cnt].shdr.sh_size
1348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    / shdr_info[cnt].shdr.sh_entsize);
1349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    if (shdr_info[cnt].shdr.sh_type == SHT_REL)
1351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      for (size_t relidx = 0; relidx < nrels; ++relidx)
1352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
1353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  GElf_Rel rel_mem;
1354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (gelf_getrel (d, relidx, &rel_mem) == NULL)
1355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    INTERNAL_ERROR (fname);
1356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  size_t symidx = GELF_R_SYM (rel_mem.r_info);
1358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (newsymidx[symidx] != symidx)
1359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    {
1360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      rel_mem.r_info
1361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			= GELF_R_INFO (newsymidx[symidx],
1362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       GELF_R_TYPE (rel_mem.r_info));
1363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (gelf_update_rel (d, relidx, &rel_mem) == 0)
1365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			INTERNAL_ERROR (fname);
1366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    }
1367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
1368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    else
1369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      for (size_t relidx = 0; relidx < nrels; ++relidx)
1370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
1371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  GElf_Rela rel_mem;
1372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (gelf_getrela (d, relidx, &rel_mem) == NULL)
1373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    INTERNAL_ERROR (fname);
1374441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  size_t symidx = GELF_R_SYM (rel_mem.r_info);
1376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (newsymidx[symidx] != symidx)
1377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    {
1378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      rel_mem.r_info
1379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			= GELF_R_INFO (newsymidx[symidx],
1380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       GELF_R_TYPE (rel_mem.r_info));
1381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (gelf_update_rela (d, relidx, &rel_mem) == 0)
1383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			INTERNAL_ERROR (fname);
1384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    }
1385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
1386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break;
1387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case SHT_HASH:
1389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    if (no_symtab_updates ())
1390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      break;
1391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* We have to recompute the hash table.  */
1393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    assert (shdr_info[cnt].idx > 0);
1395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* The hash section in the new file.  */
1397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    scn = elf_getscn (newelf, shdr_info[cnt].idx);
1398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* The symbol table data.  */
1400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    Elf_Data *symd = elf_getdata (elf_getscn (newelf,
1401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						      shdr_info[symtabidx].idx),
1402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					  NULL);
1403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    assert (symd != NULL);
1404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* The hash table data.  */
1406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    Elf_Data *hashd = elf_getdata (scn, NULL);
1407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    assert (hashd != NULL);
1408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    if (shdr_info[cnt].shdr.sh_entsize == sizeof (Elf32_Word))
1410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      {
1411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* Sane arches first.  */
1412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
1413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		size_t strshndx = shdr_info[symtabidx].old_sh_link;
1415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					    ehdr->e_version);
1417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* Adjust the nchain value.  The symbol table size
1419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   changed.  We keep the same size for the bucket array.  */
1420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		bucket[1] = symd->d_size / elsize;
1421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		Elf32_Word nbucket = bucket[0];
1422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		bucket += 2;
1423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		Elf32_Word *chain = bucket + nbucket;
1424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* New size of the section.  */
1426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		hashd->d_size = ((2 + symd->d_size / elsize + nbucket)
1427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				 * sizeof (Elf32_Word));
1428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		update_section_size (hashd);
1429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* Clear the arrays.  */
1431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		memset (bucket, '\0',
1432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			(symd->d_size / elsize + nbucket)
1433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			* sizeof (Elf32_Word));
1434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     inner < symd->d_size / elsize; ++inner)
1437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  {
1438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    GElf_Sym sym_mem;
1439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
1440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    assert (sym != NULL);
1441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    const char *name = elf_strptr (elf, strshndx,
1443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						   sym->st_name);
1444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    assert (name != NULL);
1445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    size_t hidx = elf_hash (name) % nbucket;
1446441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    if (bucket[hidx] == 0)
1448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      bucket[hidx] = inner;
1449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    else
1450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      {
1451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			hidx = bucket[hidx];
1452441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			while (chain[hidx] != 0)
1454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  hidx = chain[hidx];
1455441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			chain[hidx] = inner;
1457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      }
1458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  }
1459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      }
1460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    else
1461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      {
1462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* Alpha and S390 64-bit use 64-bit SHT_HASH entries.  */
1463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		assert (shdr_info[cnt].shdr.sh_entsize
1464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			== sizeof (Elf64_Xword));
1465441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
1467441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		size_t strshndx = shdr_info[symtabidx].old_sh_link;
1469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					    ehdr->e_version);
1471441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* Adjust the nchain value.  The symbol table size
1473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   changed.  We keep the same size for the bucket array.  */
1474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		bucket[1] = symd->d_size / elsize;
1475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		Elf64_Xword nbucket = bucket[0];
1476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		bucket += 2;
1477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		Elf64_Xword *chain = bucket + nbucket;
1478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* New size of the section.  */
1480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		hashd->d_size = ((2 + symd->d_size / elsize + nbucket)
1481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				 * sizeof (Elf64_Xword));
1482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		update_section_size (hashd);
1483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* Clear the arrays.  */
1485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		memset (bucket, '\0',
1486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			(symd->d_size / elsize + nbucket)
1487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			* sizeof (Elf64_Xword));
1488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     inner < symd->d_size / elsize; ++inner)
1491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  {
1492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    GElf_Sym sym_mem;
1493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
1494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    assert (sym != NULL);
1495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    const char *name = elf_strptr (elf, strshndx,
1497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						   sym->st_name);
1498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    assert (name != NULL);
1499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    size_t hidx = elf_hash (name) % nbucket;
1500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    if (bucket[hidx] == 0)
1502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      bucket[hidx] = inner;
1503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    else
1504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      {
1505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			hidx = bucket[hidx];
1506441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			while (chain[hidx] != 0)
1508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  hidx = chain[hidx];
1509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			chain[hidx] = inner;
1511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      }
1512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  }
1513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      }
1514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break;
1515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case SHT_GNU_versym:
1517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* If the symbol table changed we have to adjust the entries.  */
1518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    if (no_symtab_updates ())
1519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      break;
1520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    assert (shdr_info[cnt].idx > 0);
1522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* The symbol version section in the new file.  */
1524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    scn = elf_getscn (newelf, shdr_info[cnt].idx);
1525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* The symbol table data.  */
1527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    symd = elf_getdata (elf_getscn (newelf, shdr_info[symtabidx].idx),
1528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				NULL);
1529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    assert (symd != NULL);
1530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* The version symbol data.  */
1532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    Elf_Data *verd = elf_getdata (scn, NULL);
1533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    assert (verd != NULL);
1534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* The symbol version array.  */
1536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    GElf_Half *verstab = (GElf_Half *) verd->d_buf;
1537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* Walk through the list and */
1539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    size_t elsize = gelf_fsize (elf, verd->d_type, 1,
1540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					ehdr->e_version);
1541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    for (size_t inner = 1; inner < verd->d_size / elsize; ++inner)
1542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (newsymidx[inner] != 0)
1543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* Overwriting the same array works since the
1544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   reordering can only move entries to lower indices
1545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   in the array.  */
1546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		verstab[newsymidx[inner]] = verstab[inner];
1547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* New size of the section.  */
1549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    verd->d_size = gelf_fsize (newelf, verd->d_type,
1550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       symd->d_size
1551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       / gelf_fsize (elf, symd->d_type, 1,
1552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						     ehdr->e_version),
1553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       ehdr->e_version);
1554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    update_section_size (verd);
1555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break;
1556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case SHT_GROUP:
1558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    if (no_symtab_updates ())
1559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      break;
1560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* Yes, the symbol table changed.
1562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       Update the section header of the section group.  */
1563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    scn = elf_getscn (newelf, shdr_info[cnt].idx);
1564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    GElf_Shdr shdr_mem;
1565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    assert (shdr != NULL);
1567441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    shdr->sh_info = newsymidx[shdr->sh_info];
1569441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    (void) gelf_update_shdr (scn, shdr);
1571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break;
1572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  }
1573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      }
1574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Now that we have done all adjustments to the data,
1576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     we can actually write out the debug file.  */
1577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (debug_fname != NULL)
1578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint32_t debug_crc;
1580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf_Data debug_crc_data =
1581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  .d_type = ELF_T_WORD,
1583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  .d_buf = &debug_crc,
1584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  .d_size = sizeof (debug_crc),
1585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  .d_version = EV_CURRENT
1586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	};
1587441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Finally write the file.  */
1589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (elf_update (debugelf, ELF_C_WRITE) == -1))
1590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, 0, gettext ("while writing '%s': %s"),
1592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 debug_fname, elf_errmsg (-1));
1593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  result = 1;
1594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  goto fail_close;
1595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1596441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Create the real output file.  First rename, then change the
1598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 mode.  */
1599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (rename (tmp_debug_fname, debug_fname) != 0
1600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  || fchmod (debug_fd, mode) != 0)
1601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, errno, gettext ("while creating '%s'"), debug_fname);
1603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  result = 1;
1604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  goto fail_close;
1605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1606441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* The temporary file does not exist anymore.  */
1608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      tmp_debug_fname = NULL;
1609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Compute the checksum which we will add to the executable.  */
1611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (crc32_file (debug_fd, &debug_crc) != 0)
1612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, errno,
1614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 gettext ("while computing checksum for debug information"));
1615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  unlink (debug_fname);
1616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  result = 1;
1617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  goto fail_close;
1618441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Store it in the debuglink section data.  */
1621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (gelf_xlatetof (newelf, &debuglink_crc_data,
1622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				   &debug_crc_data, ehdr->e_ident[EI_DATA])
1623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    != &debuglink_crc_data))
1624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	INTERNAL_ERROR (fname);
1625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1627441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Finally finish the ELF header.  Fill in the fields not handled by
1628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     libelf from the old file.  */
1629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr = gelf_getehdr (newelf, &newehdr_mem);
1630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (newehdr == NULL)
1631441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    INTERNAL_ERROR (fname);
1632441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1633441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
1634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_type = ehdr->e_type;
1635441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_machine = ehdr->e_machine;
1636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_version = ehdr->e_version;
1637441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_entry = ehdr->e_entry;
1638441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_flags = ehdr->e_flags;
1639441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_phoff = ehdr->e_phoff;
1640441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We need to position the section header table.  */
1641441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
1642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_shoff = ((shdr_info[shdridx].shdr.sh_offset
1643441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       + shdr_info[shdridx].shdr.sh_size + offsize - 1)
1644441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      & ~((GElf_Off) (offsize - 1)));
1645441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
1646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1647441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* The new section header string table index.  */
1648441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (likely (idx < SHN_HIRESERVE) && likely (idx != SHN_XINDEX))
1649441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    newehdr->e_shstrndx = idx;
1650441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
1651441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1652441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* The index does not fit in the ELF header field.  */
1653441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[0].scn = elf_getscn (elf, 0);
1654441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1655441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (gelf_getshdr (shdr_info[0].scn, &shdr_info[0].shdr) == NULL)
1656441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	INTERNAL_ERROR (fname);
1657441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1658441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[0].shdr.sh_link = idx;
1659441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      (void) gelf_update_shdr (shdr_info[0].scn, &shdr_info[0].shdr);
1660441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1661441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      newehdr->e_shstrndx = SHN_XINDEX;
1662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1663441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1664441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (gelf_update_ehdr (newelf, newehdr) == 0)
1665441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1666441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("%s: error while creating ELF header: %s"),
1667441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     fname, elf_errmsg (-1));
1668441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return 1;
1669441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1670441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We have everything from the old file.  */
1672441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (elf_cntl (elf, ELF_C_FDDONE) != 0)
1673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("%s: error while reading the file: %s"),
1675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     fname, elf_errmsg (-1));
1676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return 1;
1677441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1678441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1679441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* The ELF library better follows our layout when this is not a
1680441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     relocatable object file.  */
1681441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  elf_flagelf (newelf, ELF_C_SET,
1682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0)
1683441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       | (permissive ? ELF_F_PERMISSIVE : 0));
1684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1685441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Finally write the file.  */
1686441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (elf_update (newelf, ELF_C_WRITE) == -1)
1687441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, 0, gettext ("while writing '%s': %s"),
1689441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     fname, elf_errmsg (-1));
1690441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      result = 1;
1691441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project fail_close:
1694441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr_info != NULL)
1695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* For some sections we might have created an table to map symbol
1697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 table indices.  */
1698441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (any_symtab_changes)
1699441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	for (cnt = 1; cnt <= shdridx; ++cnt)
1700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  {
1701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    free (shdr_info[cnt].newsymidx);
1702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    if (shdr_info[cnt].debug_data != NULL)
1703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      free (shdr_info[cnt].debug_data->d_buf);
1704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  }
1705441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1706441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Free the memory.  */
1707441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
1708441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	free (shdr_info);
1709441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1710441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1711441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Free other resources.  */
1712441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shstrtab_data != NULL)
1713441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    free (shstrtab_data->d_buf);
1714441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shst != NULL)
1715441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ebl_strtabfree (shst);
1716441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1717441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* That was it.  Close the descriptors.  */
1718441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (elf_end (newelf) != 0)
1719441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, 0, gettext ("error while finishing '%s': %s"), fname,
1721441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     elf_errmsg (-1));
1722441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      result = 1;
1723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1724441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1725441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debugelf != NULL && elf_end (debugelf) != 0)
1726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1727cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, 0, gettext ("error while finishing '%s': %s"), debug_fname,
1728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     elf_errmsg (-1));
1729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      result = 1;
1730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project fail:
1733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Close the EBL backend.  */
1734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ebl != NULL)
1735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ebl_closebackend (ebl);
1736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Close debug file descriptor, if opened */
1738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debug_fd >= 0)
1739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1740441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (tmp_debug_fname != NULL)
1741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	unlink (tmp_debug_fname);
1742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      close (debug_fd);
1743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If requested, preserve the timestamp.  */
1746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (tvp != NULL)
1747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (futimes (fd, tvp) != 0)
1749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1750441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("\
1751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcannot set access and modification date of '%s'"),
1752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 output_fname ?: fname);
1753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
1754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1755441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1756441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1757441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Close the file descriptor if we created a new file.  */
1758441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (output_fname != NULL)
1759441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    close (fd);
1760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
1762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1763441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1764441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1765441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int
1766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projecthandle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
1767441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   struct timeval tvp[2])
1768441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
1770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t fname_len = strlen (fname) + 1;
1771441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char new_prefix[prefix_len + 1 + fname_len];
1772441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *cp = new_prefix;
1773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1774441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Create the full name of the file.  */
1775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (prefix != NULL)
1776441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1777441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      cp = mempcpy (cp, prefix, prefix_len);
1778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      *cp++ = ':';
1779441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  memcpy (cp, fname, fname_len);
1781441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1783441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Process all the files contained in the archive.  */
1784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf *subelf;
1785441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Cmd cmd = ELF_C_RDWR;
1786441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int result = 0;
1787441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
1788441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1789441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* The the header for this element.  */
1790441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
1791441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1792441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (elf_kind (subelf) == ELF_K_ELF)
1793441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
1794441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (elf_kind (subelf) == ELF_K_AR)
1795441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
1796441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1797441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Get next archive element.  */
1798441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      cmd = elf_next (subelf);
1799441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (elf_end (subelf) != 0))
1800441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	INTERNAL_ERROR (fname);
1801441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1802441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1803441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (tvp != NULL)
1804441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1805441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (futimes (fd, tvp) != 0))
1806441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1807441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("\
1808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcannot set access and modification date of '%s'"), fname);
1809441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
1810441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1811441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1812441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1813441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (close (fd) != 0))
1814cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
1815441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1816441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
1817441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1820cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "debugpred.h"
1821