strip.c revision 441f72d43a9b550baa779fc82f70816da5f74f0e
1441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Discard section not used at runtime from object files.
2441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
3441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
4441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   This program is Open Source software; you can redistribute it and/or
6441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   modify it under the terms of the Open Software License version 1.0 as
7441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   published by the Open Source Initiative.
8441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
9441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   You should have received a copy of the Open Software License along
10441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   with this program; if not, you may obtain a copy of the Open Software
11441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   License version 1.0 from http://www.opensource.org/licenses/osl.php or
12441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   3001 King Ranch Road, Ukiah, CA 95482.   */
14441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
15441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifdef HAVE_CONFIG_H
16441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project# include <config.h>
17441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif
18441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
19441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <argp.h>
20441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <assert.h>
21441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <byteswap.h>
22441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <endian.h>
23441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <error.h>
24441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <fcntl.h>
25441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <gelf.h>
26441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libelf.h>
27441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libintl.h>
28441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <locale.h>
29441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <mcheck.h>
30441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdbool.h>
31441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdio.h>
32441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdio_ext.h>
33441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdlib.h>
34441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <string.h>
35441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <unistd.h>
36441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <sys/param.h>
37441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <sys/time.h>
38441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
39441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <elf-knowledge.h>
40441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libebl.h>
41441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <system.h>
42441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
43441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
44441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Name and version of program.  */
45441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void print_version (FILE *stream, struct argp_state *state);
46441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectvoid (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
47441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
48441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
49441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Values for the parameters which have no short form.  */
50441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define OPT_REMOVE_COMMENT	0x100
51441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define OPT_PERMISSIVE		0x101
52441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
53441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
54441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Definitions of arguments for argp functions.  */
55441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const struct argp_option options[] =
56441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
57441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { NULL, 0, NULL, 0, N_("Output selection:") },
58441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { NULL, 'o', "FILE", 0, N_("Place stripped output into FILE") },
59441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { NULL, 'f', "FILE", 0, N_("Extract the removed sections into FILE") },
60441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
61441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { NULL, 0, NULL, 0, N_("Output options:") },
62441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols") },
63441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "preserve-dates", 'p', NULL, 0,
64441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    N_("Copy modified/access timestamps to the output") },
65441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
66441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    N_("Remove .comment section") },
67441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "permissive", OPT_PERMISSIVE, NULL, 0,
68441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    N_("Relax a few rules to handle slightly broken ELF files") },
69441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { NULL, 0, NULL, 0, NULL }
70441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project};
71441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
72441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Short description of program.  */
73441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char doc[] = N_("Discard symbols from object files.");
74441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
75441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Strings for arguments in help texts.  */
76441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char args_doc[] = N_("[FILE...]");
77441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
78441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Prototype for option handler.  */
79441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
80441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
81441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Function to print some extra text in the help message.  */
82441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic char *more_help (int key, const char *text, void *input);
83441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
84441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Data structure to communicate with argp functions.  */
85441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic struct argp argp =
86441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
87441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  options, parse_opt, args_doc, doc, NULL, more_help
88441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project};
89441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
90441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
91441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print symbols in file named FNAME.  */
92441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int process_file (const char *fname);
93441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
94441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Handle one ELF file.  */
95441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int handle_elf (int fd, Elf *elf, const char *prefix,
96441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       const char *fname, mode_t mode, struct timeval tvp[2]);
97441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
98441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Handle all files contained in the archive.  */
99441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      struct timeval tvp[2]);
101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define INTERNAL_ERROR(fname) \
103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"),      \
104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 fname, __LINE__, VERSION, __DATE__, elf_errmsg (-1))
105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Name of the output file.  */
108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *output_fname;
109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Name of the debug output file.  */
111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *debug_fname;
112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* If true output files shall have same date as the input file.  */
114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool preserve_dates;
115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* If true .comment sections will be removed.  */
117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool remove_comment;
118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* If true remove all debug sections.  */
120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool remove_debug;
121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* If true relax some ELF rules for input files.  */
123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool permissive;
124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectint
127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmain (int argc, char *argv[])
128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int remaining;
130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int result = 0;
131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Make memory leak detection possible.  */
133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  mtrace ();
134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We use no threads here which can interfere with handling a stream.  */
136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Set locale.  */
141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  setlocale (LC_ALL, "");
142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Make sure the message catalog can be found.  */
144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bindtextdomain (PACKAGE, LOCALEDIR);
145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Initialize the message catalog.  */
147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  textdomain (PACKAGE);
148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Parse and process arguments.  */
150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Tell the library which version we are expecting.  */
153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  elf_version (EV_CURRENT);
154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (remaining == argc)
156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* The user didn't specify a name so we use a.out.  */
157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    result = process_file ("a.out");
158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* If we have seen the `-o' or '-f' option there must be exactly one
161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 input file.  */
162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if ((output_fname != NULL || debug_fname != NULL)
163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && remaining + 1 < argc)
164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	error (EXIT_FAILURE, 0, gettext ("\
165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectOnly one input file allowed together with '-o' and '-f'"));
166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Process all the remaining files.  */
168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      do
169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result |= process_file (argv[remaining]);
170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      while (++remaining < argc);
171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print the version information.  */
178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_version (FILE *stream, struct argp_state *state)
180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fprintf (stream, "strip (%s) %s\n", PACKAGE_NAME, VERSION);
182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fprintf (stream, gettext ("\
183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectCopyright (C) %s Red Hat, Inc.\n\
184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectThis is free software; see the source for copying conditions.  There is NO\n\
185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project"), "2004");
187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Handle program arguments.  */
192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic error_t
193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectparse_opt (int key, char *arg, struct argp_state *state)
194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  switch (key)
196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'f':
198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debug_fname = arg;
199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'o':
202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      output_fname = arg;
203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'p':
206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      preserve_dates = true;
207441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
209441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case OPT_REMOVE_COMMENT:
210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      remove_comment = true;
211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
212441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'g':
214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      remove_debug = true;
215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case OPT_PERMISSIVE:
218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      permissive = true;
219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    default:
222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return ARGP_ERR_UNKNOWN;
223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return 0;
225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
227441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic char *
229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmore_help (int key, const char *text, void *input)
230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *buf;
232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  switch (key)
234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case ARGP_KEY_HELP_EXTRA:
236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* We print some extra information.  */
237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    PACKAGE_BUGREPORT) < 0)
239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	buf = NULL;
240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return buf;
241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    default:
243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return (char *) text;
246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int
250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprocess_file (const char *fname)
251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If we have to preserve the modify and access timestamps get them
253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     now.  We cannot use fstat() after opening the file since the open
254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     would change the access time.  */
255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct stat64 pre_st;
256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct timeval tv[2];
257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project again:
258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (preserve_dates)
259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (stat64 (fname, &pre_st) != 0)
261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("cannot stat input file \"%s\""), fname);
263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  return 1;
264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* If we have to preserve the timestamp, we need it in the
267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 format utimes() understands.  */
268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      TIMESPEC_TO_TIMEVAL (&tv[0], &pre_st.st_atim);
269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      TIMESPEC_TO_TIMEVAL (&tv[1], &pre_st.st_mtim);
270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Open the file.  */
273441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int fd = open (fname, O_RDWR);
274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (fd == -1)
275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, errno, gettext ("while opening \"%s\""), fname);
277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return 1;
278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We always use fstat() even if we called stat() before.  This is
281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     done to make sure the information returned by stat() is for the
282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     same file.  */
283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct stat64 st;
284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (fstat64 (fd, &st) != 0)
285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, errno, gettext ("cannot stat input file \"%s\""), fname);
287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return 1;
288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Paranoid mode on.  */
290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (preserve_dates
291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      && (st.st_ino != pre_st.st_ino || st.st_dev != pre_st.st_dev))
292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* We detected a race.  Try again.  */
294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      close (fd);
295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      goto again;
296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Now get the ELF descriptor.  */
299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf *elf = elf_begin (fd, ELF_C_RDWR, NULL);
300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int result;
301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  switch (elf_kind (elf))
302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case ELF_K_ELF:
304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      result = handle_elf (fd, elf, NULL, fname, st.st_mode & ACCESSPERMS,
305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   preserve_dates ? tv : NULL);
306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case ELF_K_AR:
309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* It is not possible to strip the content of an archive direct
310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 the output to a specific file.  */
311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (output_fname != NULL))
312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, 0, gettext ("%s: cannot use -o when stripping archive"),
314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 fname);
315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = handle_ar (fd, elf, NULL, fname, preserve_dates ? tv : NULL);
319441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    default:
322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("%s: File format not recognized"), fname);
323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      result = 1;
324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (elf_end (elf) != 0))
328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    INTERNAL_ERROR (fname);
329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  close (fd);
331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Maximum size of array allocated on stack.  */
337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define MAX_STACK_ALLOC	(400 * 1024)
338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic uint32_t
341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcrc32_file (int fd, uint32_t *resp)
342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  unsigned char buffer[1024 * 8];
344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  uint32_t crc = 0;
345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  ssize_t count;
346441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
347441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We have to rewind.  */
348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (lseek (fd, 0, SEEK_SET) < 0)
349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return 1;
350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((count = TEMP_FAILURE_RETRY (read (fd, buffer, sizeof (buffer)))) > 0)
352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    crc = crc32 (crc, buffer, count);
353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  *resp = crc;
355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return count != 0;
357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int
361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projecthandle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    mode_t mode, struct timeval tvp[2])
363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
364441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
365441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t fname_len = strlen (fname) + 1;
366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *fullname = alloca (prefix_len + 1 + fname_len);
367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *cp = fullname;
368441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf *newelf;
369441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf *debugelf = NULL;
370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *tmp_debug_fname = NULL;
371441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int result = 0;
372441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr ehdr_mem;
373441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr *ehdr;
374441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t shstrndx;
375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t shnum;
376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct shdr_info
377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  {
378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf_Scn *scn;
379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    GElf_Shdr shdr;
380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf_Data *data;
381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    const char *name;
382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word idx;		/* Index in new file.  */
383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word old_sh_link;	/* Original value of shdr.sh_link.  */
384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word symtab_idx;
385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word version_idx;
386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word group_idx;
387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word group_cnt;
388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf_Scn *newscn;
389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    struct Ebl_Strent *se;
390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    Elf32_Word *newsymidx;
391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  } *shdr_info = NULL;
392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn;
393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t idx;
395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool changes;
396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr newehdr_mem;
397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr *newehdr;
398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr debugehdr_mem;
399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr *debugehdr;
400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct Ebl_Strtab *shst = NULL;
401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  uint32_t debug_crc;
402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool any_symtab_changes = false;
403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *shstrtab_data = NULL;
404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Create the full name of the file.  */
406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (prefix != NULL)
407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      cp = mempcpy (cp, prefix, prefix_len);
409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      *cp++ = ':';
410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  memcpy (cp, fname, fname_len);
412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If we are not replacing the input file open a new file here.  */
414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (output_fname != NULL)
415441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      fd = open (output_fname, O_RDWR | O_CREAT, mode);
417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (fd == -1))
418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("cannot open `%s'"), output_fname);
420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  return 1;
421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int debug_fd = -1;
425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the EBL handling.  The -g option is currently the only reason
427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     we need EBL so dont open the backend unless necessary.  */
428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Ebl *ebl = NULL;
429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (remove_debug)
430441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ebl = ebl_openbackend (elf);
432441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ebl == NULL)
433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
434441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("cannot open EBL backend"));
435441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
436441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail;
437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Open the additional file the debug information will be stored in.  */
441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debug_fname != NULL)
442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
443441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Create a temporary file name.  We do not want to overwrite
444441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 the debug file if the file would not contain any
445441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 information.  */
446441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t debug_fname_len = strlen (debug_fname);
447441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      tmp_debug_fname = (char *) alloca (debug_fname_len + sizeof (".XXXXXX"));
448441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      strcpy (mempcpy (tmp_debug_fname, debug_fname, debug_fname_len),
449441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ".XXXXXX");
450441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
451441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debug_fd = mkstemp (tmp_debug_fname);
452441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (debug_fd == -1))
453441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
454441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("cannot open `%s'"), debug_fname);
455441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
456441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail;
457441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
458441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
459441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
460441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the information from the old file.  */
461441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  ehdr = gelf_getehdr (elf, &ehdr_mem);
462441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr == NULL)
463441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    INTERNAL_ERROR (fname);
464441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
465441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
466441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (elf_getshstrndx (elf, &shstrndx) < 0))
467441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
468441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
469441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
470441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We now create a new ELF descriptor for the same file.  We
471441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     construct it almost exactly in the same way with some information
472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     dropped.  */
473441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (output_fname != NULL)
474441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
475441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
476441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    newelf = elf_clone (elf, ELF_C_EMPTY);
477441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
478441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0)
479441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      || (ehdr->e_type != ET_REL
480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && unlikely (gelf_newphdr (newelf, ehdr->e_phnum) == 0)))
481441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
482441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("cannot create new file `%s': %s"),
483441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     output_fname, elf_errmsg (-1));
484441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      goto fail;
485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
486441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
487441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Copy over the old program header if needed.  */
488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_type != ET_REL)
489441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	GElf_Phdr phdr_mem;
492441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	GElf_Phdr *phdr;
493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
494441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	phdr = gelf_getphdr (elf, cnt, &phdr_mem);
495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (phdr == NULL
496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    || unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
497441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  INTERNAL_ERROR (fname);
498441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
499441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debug_fname != NULL)
501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
502441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Also create an ELF descriptor for the debug file */
503441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugelf = elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL);
504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0)
505441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  || (ehdr->e_type != ET_REL
506441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && unlikely (gelf_newphdr (debugelf, ehdr->e_phnum) == 0)))
507441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
508441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, 0, gettext ("cannot create new file `%s': %s"),
509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 debug_fname, elf_errmsg (-1));
510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail_close;
511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
512441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
513441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Copy over the old program header if needed.  */
514441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_type != ET_REL)
515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
516441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    GElf_Phdr phdr_mem;
518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    GElf_Phdr *phdr;
519441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    phdr = gelf_getphdr (elf, cnt, &phdr_mem);
521441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (phdr == NULL
522441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		|| unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
523441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      INTERNAL_ERROR (fname);
524441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
526441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
527441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Number of sections.  */
528441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (elf_getshnum (elf, &shnum) < 0))
529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
530441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("cannot determine number of sections: %s"),
531441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     elf_errmsg (-1));
532441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      goto fail_close;
533441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
534441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
535441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Storage for section information.  We leave room for two more
536441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     entries since we unconditionally create a section header string
537441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     table.  Maybe some weird tool created an ELF file without one.
538441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     The other one is used for the debug link section.  */
539441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
540441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    shdr_info = (struct shdr_info *) xcalloc (shnum + 2,
541441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					      sizeof (struct shdr_info));
542441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
543441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info = (struct shdr_info *) alloca ((shnum + 2)
545441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					       * sizeof (struct shdr_info));
546441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
547441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
549441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Prepare section information data structure.  */
550441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  scn = NULL;
551441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  cnt = 1;
552441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((scn = elf_nextscn (elf, scn)) != NULL)
553441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
554441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* This should always be true (i.e., there should not be any
555441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 holes in the numbering).  */
556441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      assert (elf_ndxscn (scn) == cnt);
557441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
558441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].scn = scn;
559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Get the header.  */
561441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL)
562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	INTERNAL_ERROR (fname);
563441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
564441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Get the name of the section.  */
565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].name = elf_strptr (elf, shstrndx,
566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					shdr_info[cnt].shdr.sh_name);
567441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr_info[cnt].name == NULL)
568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
569441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, 0, gettext ("illformed file `%s'"), fname);
570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail_close;
571441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
572441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
573441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Mark them as present but not yet investigated.  */
574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].idx = 1;
575441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
576441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Remember the shdr.sh_link value.  */
577441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link;
578441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
579441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Sections in files other than relocatable object files which
580441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 are not loaded can be freely moved by us.  In relocatable
581441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 object files everything can be moved.  */
582441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_type == ET_REL
583441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
584441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].shdr.sh_offset = 0;
585441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
586441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* If this is an extended section index table store an
587441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 appropriate reference.  */
588441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
589441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
590441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
591441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
592441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
593441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
594441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
595441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf32_Word *grpref;
596441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  size_t inner;
597441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
598441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Cross-reference the sections contained in the section
599441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     group.  */
600441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
601441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[cnt].data == NULL)
602441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    INTERNAL_ERROR (fname);
603441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
604441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* XXX Fix for unaligned access.  */
605441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
606441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  for (inner = 1;
607441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
608441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       ++inner)
609441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[grpref[inner]].group_idx = cnt;
610441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
611441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
612441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* If the section group contains only one element and this
613441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       is n COMDAT section we can drop it right away.  */
614441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[cnt].idx = 0;
615441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
616441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[cnt].group_cnt = inner - 1;
617441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
618441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
619441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
620441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
621441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
622441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
623441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
624441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* If this section is part of a group make sure it is not
625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 discarded right away.  */
626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
627441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  assert (shdr_info[cnt].group_idx != 0);
629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
631441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
632441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The section group section will be removed.  */
633441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr_info[cnt].group_idx = 0;
634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr_info[cnt].shdr.sh_flags &= ~SHF_GROUP;
635441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
637441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
638441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Increment the counter.  */
639441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ++cnt;
640441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
641441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Now determine which sections can go away.  The general rule is that
643441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     all sections which are not used at runtime are stripped out.  But
644441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     there are a few exceptions:
645441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     - special sections named ".comment" and ".note" are kept
647441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     - OS or architecture specific sections are kept since we might not
648441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       know how to handle them
649441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     - if a section is referred to from a section which is not removed
650441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       in the sh_link or sh_info element it cannot be removed either
651441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  */
652441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 1; cnt < shnum; ++cnt)
653441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* Check whether the section can be removed.  */
654441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    if (SECTION_STRIP_P (ebl, elf, ehdr, &shdr_info[cnt].shdr,
655441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 shdr_info[cnt].name, remove_comment, remove_debug))
656441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
657441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* For now assume this section will be removed.  */
658441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].idx = 0;
659441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
660441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	idx = shdr_info[cnt].group_idx;
661441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	while (idx != 0)
662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
663441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* If the references section group is a normal section
664441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       group and has one element remaining, or if it is an
665441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       empty COMDAT section group it is removed.  */
666441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    bool is_comdat;
667441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
668441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* The section group data is already loaded.  */
669441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    assert (shdr_info[idx].data != NULL);
670441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
672441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 & GRP_COMDAT) != 0;
673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    --shdr_info[idx].group_cnt;
675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if ((!is_comdat && shdr_info[idx].group_cnt == 1)
676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		|| (is_comdat && shdr_info[idx].group_cnt == 0))
677441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      {
678441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		shdr_info[idx].idx = 0;
679441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		/* Continue recursively.  */
680441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		idx = shdr_info[idx].group_idx;
681441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      }
682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    else
683441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      break;
684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
685441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
686441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
687441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Mark the SHT_NULL section as handled.  */
688441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[0].idx = 2;
689441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
690441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
691441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Handle exceptions: section groups and cross-references.  We might
692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     have to repeat this a few times since the resetting of the flag
693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     might propagate.  */
694441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  do
695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      changes = false;
697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
698441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (cnt = 1; cnt < shnum; ++cnt)
699441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
700441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[cnt].idx == 0)
701441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
702441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* If a relocation section is marked as being removed make
703441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 sure the section it is relocating is removed, too.  */
704441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if ((shdr_info[cnt].shdr.sh_type == SHT_REL
705441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   || shdr_info[cnt].shdr.sh_type == SHT_RELA)
706441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
707441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		shdr_info[cnt].idx = 1;
708441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
709441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
710441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[cnt].idx == 1)
711441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
712441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The content of symbol tables we don't remove must not
713441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 reference any section which we do remove.  Otherwise
714441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 we cannot remove the section.  */
715441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
716441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
717441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
718441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  Elf_Data *symdata;
719441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  Elf_Data *xndxdata;
720441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  size_t elsize;
721441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
722441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Make sure the data is loaded.  */
723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (shdr_info[cnt].data == NULL)
724441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
725441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      shdr_info[cnt].data
726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			= elf_getdata (shdr_info[cnt].scn, NULL);
727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (shdr_info[cnt].data == NULL)
728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			INTERNAL_ERROR (fname);
729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  symdata = shdr_info[cnt].data;
731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* If there is an extended section index table load it
733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     as well.  */
734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (shdr_info[cnt].symtab_idx != 0
735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      shdr_info[shdr_info[cnt].symtab_idx].data
740441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			= elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				       NULL);
742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			INTERNAL_ERROR (fname);
744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  xndxdata = shdr_info[shdr_info[cnt].symtab_idx].data;
746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Go through all symbols and make sure the section they
748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     reference is not removed.  */
749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
750441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
751441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  for (size_t inner = 0;
752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       inner < shdr_info[cnt].data->d_size / elsize;
753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       ++inner)
754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
755441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      GElf_Sym sym_mem;
756441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      Elf32_Word xndx;
757441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      GElf_Sym *sym;
758441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      size_t scnidx;
759441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      sym = gelf_getsymshndx (symdata, xndxdata, inner,
761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					      &sym_mem, &xndx);
762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (sym == NULL)
763441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			INTERNAL_ERROR (fname);
764441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
765441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      scnidx = sym->st_shndx;
766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (scnidx == SHN_UNDEF || scnidx >= shnum
767441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  || (scnidx >= SHN_LORESERVE
768441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      && scnidx <= SHN_HIRESERVE
769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      && scnidx != SHN_XINDEX)
770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  /* Don't count in the section symbols.  */
771441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
772441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			/* This is no section index, leave it alone.  */
773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			continue;
774441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      else if (scnidx == SHN_XINDEX)
775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			scnidx = xndx;
776441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
777441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (shdr_info[scnidx].idx == 0)
778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			{
779441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  /* Mark this section as used.  */
780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  shdr_info[scnidx].idx = 1;
781441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  changes |= scnidx < cnt;
782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			}
783441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
785441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
786441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Cross referencing happens:
787441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 - for the cases the ELF specification says.  That are
788441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 + SHT_DYNAMIC in sh_link to string table
789441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 + SHT_HASH in sh_link to symbol table
790441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 + SHT_REL and SHT_RELA in sh_link to symbol table
791441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
792441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 + SHT_GROUP in sh_link to symbol table
793441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 + SHT_SYMTAB_SHNDX in sh_link to symbol table
794441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 Other (OS or architecture-specific) sections might as
795441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 well use this field so we process it unconditionally.
796441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 - references inside section groups
797441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 - specially marked references in sh_info if the SHF_INFO_LINK
798441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 flag is set
799441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      */
800441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
801441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
802441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
803441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
804441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  changes |= shdr_info[cnt].shdr.sh_link < cnt;
805441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
806441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
807441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Handle references through sh_info.  */
808441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)
809441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  && shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
810441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
811441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
812441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  changes |= shdr_info[cnt].shdr.sh_info < cnt;
813441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
814441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
815441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Mark the section as investigated.  */
816441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr_info[cnt].idx = 2;
817441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
818441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
819441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
820441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (changes);
821441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
822441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Write out a copy of all the sections to the debug output file.
823441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     The ones that are not removed in the stripped file are SHT_NOBITS */
824441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debug_fname != NULL)
825441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
826441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (cnt = 1; cnt < shnum; ++cnt)
827441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
828441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf_Data *debugdata;
829441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr debugshdr;
830441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  int discard_section;
831441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
832441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  scn = elf_newscn (debugelf);
833441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (scn == NULL)
834441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    error (EXIT_FAILURE, 0,
835441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   gettext ("while generating output file: %s"),
836441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   elf_errmsg (-1));
837441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
838441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  discard_section = shdr_info[cnt].idx > 0 && cnt != ehdr->e_shstrndx;
839441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
840441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Set the section header in the new file.  */
841441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  debugshdr = shdr_info[cnt].shdr;
842441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (discard_section)
843441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    debugshdr.sh_type = SHT_NOBITS;
844441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
845441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (unlikely (gelf_update_shdr (scn, &debugshdr)) == 0)
846441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* There cannot be any overflows.  */
847441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    INTERNAL_ERROR (fname);
848441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
849441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Get the data from the old file if necessary. */
850441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[cnt].data == NULL)
851441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
852441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
853441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr_info[cnt].data == NULL)
854441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		INTERNAL_ERROR (fname);
855441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
856441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
857441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Set the data.  This is done by copying from the old file.  */
858441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  debugdata = elf_newdata (scn);
859441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (debugdata == NULL)
860441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    INTERNAL_ERROR (fname);
861441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
862441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Copy the structure.  */
863441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  *debugdata = *shdr_info[cnt].data;
864441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (discard_section)
865441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    debugdata->d_buf = NULL;
866441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
867441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
868441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Finish the ELF header.  Fill in the fields not handled by
869441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 libelf from the old file.  */
870441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
871441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (debugehdr == NULL)
872441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	INTERNAL_ERROR (fname);
873441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
874441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
875441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_type = ehdr->e_type;
876441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_machine = ehdr->e_machine;
877441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_version = ehdr->e_version;
878441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_entry = ehdr->e_entry;
879441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_flags = ehdr->e_flags;
880441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debugehdr->e_shstrndx = ehdr->e_shstrndx;
881441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
882441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (gelf_update_ehdr (debugelf, debugehdr)) == 0)
883441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
884441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, 0, gettext ("%s: error while creating ELF header: %s"),
885441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 debug_fname, elf_errmsg (-1));
886441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
887441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail_close;
888441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
889441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
890441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Finally write the file.  */
891441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (elf_update (debugelf, ELF_C_WRITE)) == -1)
892441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
893441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, 0, gettext ("while writing `%s': %s"),
894441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 debug_fname, elf_errmsg (-1));
895441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
896441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail_close;
897441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
898441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
899441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Create the real output file.  First rename, then change the
900441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 mode.  */
901441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (rename (tmp_debug_fname, debug_fname) != 0
902441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  || fchmod (debug_fd, mode) != 0)
903441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
904441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("while creating '%s'"), debug_fname);
905441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
906441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail_close;
907441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
908441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
909441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* The temporary file does not exist anymore.  */
910441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      tmp_debug_fname = NULL;
911441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
912441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Compute the checksum which we will add to the executable.  */
913441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (crc32_file (debug_fd, &debug_crc) != 0)
914441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
915441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno,
916441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 gettext ("while computing checksum for debug information"));
917441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unlink (debug_fname);
918441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
919441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto fail_close;
920441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
921441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
922441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
923441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
924441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Mark the section header string table as unused, we will create
925441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     a new one.  */
926441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[shstrndx].idx = 0;
927441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
928441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We need a string table for the section headers.  */
929441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shst = ebl_strtabinit (true);
930441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shst == NULL)
931441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, errno, gettext ("while preparing output for `%s'"),
932441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   output_fname ?: fname);
933441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
934441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Assign new section numbers.  */
935441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[0].idx = 0;
936441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = idx = 1; cnt < shnum; ++cnt)
937441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    if (shdr_info[cnt].idx > 0)
938441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
939441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].idx = idx++;
940441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
941441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Create a new section.  */
942441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].newscn = elf_newscn (newelf);
943441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (shdr_info[cnt].newscn == NULL)
944441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (EXIT_FAILURE, 0, gettext ("while generating output file: %s"),
945441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 elf_errmsg (-1));
946441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
947441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
948441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
949441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Add this name to the section header string table.  */
950441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);
951441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
952441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
953441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Test whether we are doing anything at all.  */
954441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (cnt == idx)
955441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* Nope, all removable sections are already gone.  */
956441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    goto fail_close;
957441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
958441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Create the reference to the file with the debug info.  */
959441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debug_fname != NULL)
960441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
961441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      char *debug_basename;
962441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      off_t crc_offset;
963441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
964441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Add the section header string table section name.  */
965441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].se = ebl_strtabadd (shst, ".gnu_debuglink", 15);
966441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].idx = idx++;
967441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
968441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Create the section header.  */
969441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
970441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_flags = 0;
971441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_addr = 0;
972441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
973441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
974441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_entsize = 0;
975441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_addralign = 4;
976441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* We set the offset to zero here.  Before we write the ELF file the
977441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 field must have the correct value.  This is done in the final
978441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 loop over all section.  Then we have all the information needed.  */
979441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_offset = 0;
980441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
981441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Create the section.  */
982441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].newscn = elf_newscn (newelf);
983441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr_info[cnt].newscn == NULL)
984441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	error (EXIT_FAILURE, 0,
985441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       gettext ("while create section header section: %s"),
986441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       elf_errmsg (-1));
987441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
988441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
989441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
990441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr_info[cnt].data == NULL)
991441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	error (EXIT_FAILURE, 0, gettext ("cannot allocate section data: %s"),
992441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       elf_errmsg (-1));
993441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
994441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      debug_basename = basename (debug_fname);
995441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      crc_offset = strlen (debug_basename) + 1;
996441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Align to 4 byte boundary */
997441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      crc_offset = ((crc_offset - 1) & ~3) + 4;
998441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
999441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].data->d_align = 4;
1000441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
1001441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	= crc_offset + 4;
1002441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[cnt].data->d_buf = xcalloc (1, shdr_info[cnt].data->d_size);
1003441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1004441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      strcpy (shdr_info[cnt].data->d_buf, debug_basename);
1005441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Store the crc value in the correct byteorder */
1006441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if ((__BYTE_ORDER == __LITTLE_ENDIAN
1007441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
1008441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  || (__BYTE_ORDER == __BIG_ENDIAN
1009441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
1010441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	debug_crc = bswap_32 (debug_crc);
1011441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      memcpy ((char *)shdr_info[cnt].data->d_buf + crc_offset,
1012441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (char *) &debug_crc, 4);
1013441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1014441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* One more section done.  */
1015441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ++cnt;
1016441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1017441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1018441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Index of the section header table in the shdr_info array.  */
1019441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t shdridx = cnt;
1020441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1021441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Add the section header string table section name.  */
1022441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].se = ebl_strtabadd (shst, ".shstrtab", 10);
1023441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].idx = idx;
1024441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1025441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Create the section header.  */
1026441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
1027441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_flags = 0;
1028441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_addr = 0;
1029441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1030441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1031441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_entsize = 0;
1032441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We set the offset to zero here.  Before we write the ELF file the
1033441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     field must have the correct value.  This is done in the final
1034441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     loop over all section.  Then we have all the information needed.  */
1035441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_offset = 0;
1036441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_addralign = 1;
1037441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1038441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Create the section.  */
1039441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].newscn = elf_newscn (newelf);
1040441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr_info[cnt].newscn == NULL)
1041441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
1042441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("while create section header section: %s"),
1043441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   elf_errmsg (-1));
1044441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
1045441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1046441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Finalize the string table and fill in the correct indices in the
1047441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     section headers.  */
1048441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
1049441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shstrtab_data == NULL)
1050441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
1051441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("while create section header string table: %s"),
1052441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   elf_errmsg (-1));
1053441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  ebl_strtabfinalize (shst, shstrtab_data);
1054441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1055441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We have to set the section size.  */
1056441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
1057441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1058441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Update the section information.  */
1059441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Off lastoffset = 0;
1060441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 1; cnt <= shdridx; ++cnt)
1061441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    if (shdr_info[cnt].idx > 0)
1062441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
1063441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	Elf_Data *newdata;
1064441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1065441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	scn = elf_getscn (newelf, shdr_info[cnt].idx);
1066441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	assert (scn != NULL);
1067441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1068441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Update the name.  */
1069441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	shdr_info[cnt].shdr.sh_name = ebl_strtaboffset (shdr_info[cnt].se);
1070441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1071441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Update the section header from the input file.  Some fields
1072441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   might be section indeces which now have to be adjusted.  */
1073441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (shdr_info[cnt].shdr.sh_link != 0)
1074441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[cnt].shdr.sh_link =
1075441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[shdr_info[cnt].shdr.sh_link].idx;
1076441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1077441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1078441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
1079441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    assert (shdr_info[cnt].data != NULL);
1080441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1081441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1082441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    for (size_t inner = 0;
1083441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1084441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 ++inner)
1085441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      grpref[inner] = shdr_info[grpref[inner]].idx;
1086441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
1087441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1088441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag.  */
1089441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1090441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[cnt].shdr.sh_info =
1091441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[shdr_info[cnt].shdr.sh_info].idx;
1092441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1093441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Get the data from the old file if necessary.  We already
1094441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project           created the data for the section header string table.  */
1095441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (cnt < shnum)
1096441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
1097441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (shdr_info[cnt].data == NULL)
1098441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      {
1099441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (shdr_info[cnt].data == NULL)
1101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  INTERNAL_ERROR (fname);
1102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      }
1103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* Set the data.  This is done by copying from the old file.  */
1105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    newdata = elf_newdata (scn);
1106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (newdata == NULL)
1107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      INTERNAL_ERROR (fname);
1108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* Copy the structure.  */
1110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    *newdata = *shdr_info[cnt].data;
1111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* We know the size.  */
1113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
1114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* We have to adjust symtol tables.  The st_shndx member might
1116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       have to be updated.  */
1117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
1118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		|| shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
1119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      {
1120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		Elf_Data *versiondata = NULL;
1121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		Elf_Data *shndxdata = NULL;
1122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					    ehdr->e_version);
1125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (shdr_info[cnt].symtab_idx != 0)
1127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
1129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* This section has extended section information.
1130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       We have to modify that information, too.  */
1131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
1132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					     NULL);
1133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    assert ((versiondata->d_size / sizeof (Elf32_Word))
1135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    >= shdr_info[cnt].data->d_size / elsize);
1136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (shdr_info[cnt].version_idx != 0)
1139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
1141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* This section has associated version
1142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       information.  We have to modify that
1143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       information, too.  */
1144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
1145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					       NULL);
1146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    assert ((versiondata->d_size / sizeof (GElf_Versym))
1148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    >= shdr_info[cnt].data->d_size / elsize);
1149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		shdr_info[cnt].newsymidx
1152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  = (Elf32_Word *) xcalloc (shdr_info[cnt].data->d_size
1153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					    / elsize, sizeof (Elf32_Word));
1154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		bool last_was_local = true;
1156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		size_t destidx;
1157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		size_t inner;
1158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		for (destidx = inner = 1;
1159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     inner < shdr_info[cnt].data->d_size / elsize;
1160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     ++inner)
1161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    Elf32_Word sec;
1163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    GElf_Sym sym_mem;
1164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    Elf32_Word xshndx;
1165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
1166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						      shndxdata, inner,
1167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						      &sym_mem, &xshndx);
1168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (sym == NULL)
1169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      INTERNAL_ERROR (fname);
1170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (sym->st_shndx == SHN_UNDEF
1172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			|| (sym->st_shndx >= shnum
1173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    && sym->st_shndx != SHN_XINDEX))
1174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      {
1175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			/* This is no section index, leave it alone
1176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   unless it is moved.  */
1177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if (destidx != inner
1178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    && gelf_update_symshndx (shdr_info[cnt].data,
1179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						     shndxdata,
1180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						     destidx, sym,
1181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						     xshndx) == 0)
1182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  INTERNAL_ERROR (fname);
1183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			shdr_info[cnt].newsymidx[inner] = destidx++;
1185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if (last_was_local
1187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  {
1189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    last_was_local = false;
1190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    shdr_info[cnt].shdr.sh_info = destidx - 1;
1191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  }
1192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			continue;
1194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      }
1195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* Get the full section index, if necessary from the
1197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       XINDEX table.  */
1198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (sym->st_shndx != SHN_XINDEX)
1199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      sec = shdr_info[sym->st_shndx].idx;
1200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    else
1201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      {
1202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			assert (shndxdata != NULL);
1203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			sec = shdr_info[xshndx].idx;
1205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      }
1206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1207441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (sec != 0)
1208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      {
1209441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			GElf_Section nshndx;
1210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			Elf32_Word nxshndx;
1211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1212441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if (sec < SHN_LORESERVE)
1213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  {
1214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    nshndx = sec;
1215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    nxshndx = 0;
1216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  }
1217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			else
1218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  {
1219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    nshndx = SHN_XINDEX;
1220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    nxshndx = sec;
1221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  }
1222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			assert (sec < SHN_LORESERVE || shndxdata != NULL);
1224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if ((inner != destidx || nshndx != sym->st_shndx
1226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     || (shndxdata != NULL && nxshndx != xshndx))
1227441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    && (sym->st_shndx = nshndx,
1228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				gelf_update_symshndx (shdr_info[cnt].data,
1229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						      shndxdata,
1230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						      destidx, sym,
1231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						      nxshndx) == 0))
1232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  INTERNAL_ERROR (fname);
1233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			shdr_info[cnt].newsymidx[inner] = destidx++;
1235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if (last_was_local
1237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  {
1239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    last_was_local = false;
1240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    shdr_info[cnt].shdr.sh_info = destidx - 1;
1241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  }
1242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      }
1243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    else
1244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      /* This is a section symbol for a section which has
1245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 been removed.  */
1246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION);
1247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (destidx != inner)
1250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* The size of the symbol table changed.  */
1252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    shdr_info[cnt].shdr.sh_size = newdata->d_size
1253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      = destidx * elsize;
1254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    any_symtab_changes = true;
1255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		else
1257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* The symbol table didn't really change.  */
1259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    free (shdr_info[cnt].newsymidx);
1260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    shdr_info[cnt].newsymidx = NULL;
1261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      }
1263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
1264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* If we have to, compute the offset of the section.  */
1266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (shdr_info[cnt].shdr.sh_offset == 0)
1267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr_info[cnt].shdr.sh_offset
1268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
1269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
1270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Set the section header in the new file.  */
1272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
1273441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* There cannot be any overflows.  */
1274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  INTERNAL_ERROR (fname);
1275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Remember the last section written so far.  */
1277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
1278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   ? shdr_info[cnt].shdr.sh_size : 0);
1279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
1280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
1281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
1282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Adjust symbol references if symbol tables changed.  */
1284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (any_symtab_changes)
1285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Find all relocation sections which use this
1287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 symbol table.  */
1288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (cnt = 1; cnt <= shdridx; ++cnt)
1289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[cnt].idx == 0)
1291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* Ignore sections which are discarded.  */
1292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    continue;
1293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr_info[cnt].shdr.sh_type == SHT_REL
1295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      || shdr_info[cnt].shdr.sh_type == SHT_RELA)
1296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* If the symbol table hasn't changed, do not do anything.  */
1298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr_info[shdr_info[cnt].old_sh_link].newsymidx == NULL)
1299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		continue;
1300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      Elf32_Word *newsymidx
1302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		= shdr_info[shdr_info[cnt].old_sh_link].newsymidx;
1303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      Elf_Data *d = elf_getdata (elf_getscn (newelf,
1304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						     shdr_info[cnt].idx),
1305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					 NULL);
1306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      assert (d != NULL);
1307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      size_t nrels = (shdr_info[cnt].shdr.sh_size
1308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      / shdr_info[cnt].shdr.sh_entsize);
1309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr_info[cnt].shdr.sh_type == SHT_REL)
1311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		for (size_t relidx = 0; relidx < nrels; ++relidx)
1312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    GElf_Rel rel_mem;
1314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (gelf_getrel (d, relidx, &rel_mem) == NULL)
1315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      INTERNAL_ERROR (fname);
1316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    size_t symidx = GELF_R_SYM (rel_mem.r_info);
1318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (newsymidx[symidx] != symidx)
1319441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      {
1320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			rel_mem.r_info
1321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  = GELF_R_INFO (newsymidx[symidx],
1322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					 GELF_R_TYPE (rel_mem.r_info));
1323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if (gelf_update_rel (d, relidx, &rel_mem) == 0)
1325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  INTERNAL_ERROR (fname);
1326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      }
1327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else
1329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		for (size_t relidx = 0; relidx < nrels; ++relidx)
1330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
1331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    GElf_Rela rel_mem;
1332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (gelf_getrela (d, relidx, &rel_mem) == NULL)
1333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      INTERNAL_ERROR (fname);
1334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    size_t symidx = GELF_R_SYM (rel_mem.r_info);
1336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (newsymidx[symidx] != symidx)
1337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      {
1338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			rel_mem.r_info
1339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  = GELF_R_INFO (newsymidx[symidx],
1340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					 GELF_R_TYPE (rel_mem.r_info));
1341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			if (gelf_update_rela (d, relidx, &rel_mem) == 0)
1343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  INTERNAL_ERROR (fname);
1344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      }
1345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
1346441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1347441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (shdr_info[cnt].shdr.sh_type == SHT_HASH)
1348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* We have to recompute the hash table.  */
1350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
1351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* We do not have to do anything if the symbol table was
1353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 not changed.  */
1354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr_info[symtabidx].newsymidx == NULL)
1355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		continue;
1356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The symbol version section in the new file.  */
1358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      scn = elf_getscn (newelf, shdr_info[cnt].idx);
1359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The symbol table data.  */
1361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      Elf_Data *symd = elf_getdata (elf_getscn (newelf,
1362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project							shdr_info[symtabidx].idx),
1363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					    NULL);
1364441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      assert (symd != NULL);
1365441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The hash table data.  */
1367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      Elf_Data *hashd = elf_getdata (scn, NULL);
1368441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      assert (hashd != NULL);
1369441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr_info[cnt].shdr.sh_entsize == sizeof (Elf32_Word))
1371441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1372441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Sane arches first.  */
1373441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
1374441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  size_t strshndx = shdr_info[symtabidx].old_sh_link;
1376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					      ehdr->e_version);
1378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Convert to the correct byte order.  */
1380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (gelf_xlatetom (newelf, hashd, hashd,
1381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     BYTE_ORDER == LITTLE_ENDIAN
1382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
1383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    INTERNAL_ERROR (fname);
1384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Adjust the nchain value.  The symbol table size
1386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     changed.  We keep the same size for the bucket array.  */
1387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  bucket[1] = symd->d_size / elsize;
1388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  Elf32_Word nbucket = bucket[0];
1389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  bucket += 2;
1390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  Elf32_Word *chain = bucket + nbucket;
1391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* New size of the section.  */
1393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Shdr shdr_mem;
1394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  shdr->sh_size = hashd->d_size
1396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    = (2 + symd->d_size / elsize + nbucket)
1397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      * sizeof (Elf32_Word);
1398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  (void) gelf_update_shdr (scn, shdr);
1399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Clear the arrays.  */
1401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  memset (bucket, '\0',
1402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  (symd->d_size / elsize + nbucket)
1403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  * sizeof (Elf32_Word));
1404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       inner < symd->d_size / elsize; ++inner)
1407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
1408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      GElf_Sym sym_mem;
1409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
1410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      assert (sym != NULL);
1411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      const char *name = elf_strptr (elf, strshndx,
1413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						     sym->st_name);
1414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      assert (name != NULL);
1415441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      size_t hidx = elf_hash (name) % nbucket;
1416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (bucket[hidx] == 0)
1418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			bucket[hidx] = inner;
1419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      else
1420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			{
1421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  hidx = bucket[hidx];
1422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  while (chain[hidx] != 0)
1424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    hidx = chain[hidx];
1425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  chain[hidx] = inner;
1427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			}
1428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
1429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
1430441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else
1431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1432441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Alpha and S390 64-bit use 64-bit SHT_HASH entries.  */
1433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  assert (shdr_info[cnt].shdr.sh_entsize
1434441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  == sizeof (Elf64_Xword));
1435441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1436441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
1437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  size_t strshndx = shdr_info[symtabidx].old_sh_link;
1439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					      ehdr->e_version);
1441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Convert to the correct byte order.  */
1443441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (gelf_xlatetom (newelf, hashd, hashd,
1444441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     BYTE_ORDER == LITTLE_ENDIAN
1445441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
1446441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    INTERNAL_ERROR (fname);
1447441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1448441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Adjust the nchain value.  The symbol table size
1449441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     changed.  We keep the same size for the bucket array.  */
1450441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  bucket[1] = symd->d_size / elsize;
1451441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  Elf64_Xword nbucket = bucket[0];
1452441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  bucket += 2;
1453441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  Elf64_Xword *chain = bucket + nbucket;
1454441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1455441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* New size of the section.  */
1456441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Shdr shdr_mem;
1457441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1458441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  shdr->sh_size = hashd->d_size
1459441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    = (2 + symd->d_size / elsize + nbucket)
1460441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      * sizeof (Elf64_Xword);
1461441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  (void) gelf_update_shdr (scn, shdr);
1462441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1463441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Clear the arrays.  */
1464441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  memset (bucket, '\0',
1465441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  (symd->d_size / elsize + nbucket)
1466441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  * sizeof (Elf64_Xword));
1467441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1468441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1469441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       inner < symd->d_size / elsize; ++inner)
1470441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
1471441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      GElf_Sym sym_mem;
1472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
1473441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      assert (sym != NULL);
1474441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1475441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      const char *name = elf_strptr (elf, strshndx,
1476441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						     sym->st_name);
1477441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      assert (name != NULL);
1478441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      size_t hidx = elf_hash (name) % nbucket;
1479441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (bucket[hidx] == 0)
1481441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			bucket[hidx] = inner;
1482441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      else
1483441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			{
1484441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  hidx = bucket[hidx];
1485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1486441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  while (chain[hidx] != 0)
1487441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    hidx = chain[hidx];
1488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1489441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  chain[hidx] = inner;
1490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			}
1491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
1492441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	        }
1493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1494441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Convert back to the file byte order.  */
1495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (gelf_xlatetof (newelf, hashd, hashd,
1496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				 BYTE_ORDER == LITTLE_ENDIAN
1497441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				 ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
1498441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		INTERNAL_ERROR (fname);
1499441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym)
1501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1502441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* If the symbol table changed we have to adjust the
1503441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 entries.  */
1504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
1505441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1506441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* We do not have to do anything if the symbol table was
1507441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 not changed.  */
1508441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr_info[symtabidx].newsymidx == NULL)
1509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		continue;
1510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The symbol version section in the new file.  */
1512441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      scn = elf_getscn (newelf, shdr_info[cnt].idx);
1513441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1514441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The symbol table data.  */
1515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      Elf_Data *symd = elf_getdata (elf_getscn (newelf,
1516441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project							shdr_info[symtabidx].idx),
1517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					    NULL);
1518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      assert (symd != NULL);
1519441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The version symbol data.  */
1521441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      Elf_Data *verd = elf_getdata (scn, NULL);
1522441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      assert (verd != NULL);
1523441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1524441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Convert to the correct byte order.  */
1525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (gelf_xlatetom (newelf, verd, verd,
1526441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				 BYTE_ORDER == LITTLE_ENDIAN
1527441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				 ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
1528441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		INTERNAL_ERROR (fname);
1529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1530441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The symbol version array.  */
1531441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Half *verstab = (GElf_Half *) verd->d_buf;
1532441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1533441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* New indices of the symbols.  */
1534441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      Elf32_Word *newsymidx = shdr_info[symtabidx].newsymidx;
1535441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1536441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Walk through the list and */
1537441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      size_t elsize = gelf_fsize (elf, verd->d_type, 1,
1538441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					  ehdr->e_version);
1539441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      for (size_t inner = 1; inner < verd->d_size / elsize; ++inner)
1540441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (newsymidx[inner] != 0)
1541441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Overwriting the same array works since the
1542441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     reordering can only move entries to lower indices
1543441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     in the array.  */
1544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  verstab[newsymidx[inner]] = verstab[inner];
1545441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1546441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* New size of the section.  */
1547441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Shdr shdr_mem;
1548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1549441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr->sh_size = verd->d_size
1550441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		= gelf_fsize (newelf, verd->d_type,
1551441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      symd->d_size / gelf_fsize (elf, symd->d_type, 1,
1552441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project							 ehdr->e_version),
1553441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      ehdr->e_version);
1554441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (void) gelf_update_shdr (scn, shdr);
1555441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1556441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Convert back to the file byte order.  */
1557441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (gelf_xlatetof (newelf, verd, verd,
1558441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				 BYTE_ORDER == LITTLE_ENDIAN
1559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				 ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
1560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		INTERNAL_ERROR (fname);
1561441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1563441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1564441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Check whether the associated symbol table changed.  */
1565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr_info[shdr_info[cnt].old_sh_link].newsymidx != NULL)
1566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1567441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Yes the symbol table changed.  Update the section
1568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     header of the section group.  */
1569441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  scn = elf_getscn (newelf, shdr_info[cnt].idx);
1570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Shdr shdr_mem;
1571441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1572441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  assert (shdr != NULL);
1573441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  size_t stabidx = shdr_info[cnt].old_sh_link;
1575441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  shdr->sh_info = shdr_info[stabidx].newsymidx[shdr->sh_info];
1576441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1577441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  (void) gelf_update_shdr (scn, shdr);
1578441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
1579441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1580441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1581441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1582441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1583441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Finally finish the ELF header.  Fill in the fields not handled by
1584441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     libelf from the old file.  */
1585441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr = gelf_getehdr (newelf, &newehdr_mem);
1586441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (newehdr == NULL)
1587441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    INTERNAL_ERROR (fname);
1588441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1589441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
1590441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_type = ehdr->e_type;
1591441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_machine = ehdr->e_machine;
1592441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_version = ehdr->e_version;
1593441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_entry = ehdr->e_entry;
1594441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_flags = ehdr->e_flags;
1595441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_phoff = ehdr->e_phoff;
1596441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We need to position the section header table.  */
1597441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
1598441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_shoff = ((shdr_info[shdridx].shdr.sh_offset
1599441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       + shdr_info[shdridx].shdr.sh_size + offsize - 1)
1600441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      & ~((GElf_Off) (offsize - 1)));
1601441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
1602441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1603441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* The new section header string table index.  */
1604441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (likely (idx < SHN_HIRESERVE) && likely (idx != SHN_XINDEX))
1605441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    newehdr->e_shstrndx = idx;
1606441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
1607441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1608441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* The index does not fit in the ELF header field.  */
1609441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[0].scn = elf_getscn (elf, 0);
1610441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1611441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (gelf_getshdr (shdr_info[0].scn, &shdr_info[0].shdr) == NULL)
1612441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	INTERNAL_ERROR (fname);
1613441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1614441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr_info[0].shdr.sh_link = idx;
1615441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      (void) gelf_update_shdr (shdr_info[0].scn, &shdr_info[0].shdr);
1616441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1617441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      newehdr->e_shstrndx = SHN_XINDEX;
1618441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1619441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1620441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (gelf_update_ehdr (newelf, newehdr) == 0)
1621441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1622441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("%s: error while creating ELF header: %s"),
1623441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     fname, elf_errmsg (-1));
1624441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return 1;
1625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1627441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We have everything from the old file.  */
1628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (elf_cntl (elf, ELF_C_FDDONE) != 0)
1629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("%s: error while reading the file: %s"),
1631441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     fname, elf_errmsg (-1));
1632441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return 1;
1633441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1635441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* The ELF library better follows our layout when this is not a
1636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     relocatable object file.  */
1637441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  elf_flagelf (newelf, ELF_C_SET,
1638441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0)
1639441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       | (permissive ? ELF_F_PERMISSIVE : 0));
1640441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1641441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Finally write the file.  */
1642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (elf_update (newelf, ELF_C_WRITE) == -1)
1643441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1644441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("while writing `%s': %s"),
1645441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     fname, elf_errmsg (-1));
1646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      result = 1;
1647441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1648441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1649441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project fail_close:
1650441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr_info != NULL)
1651441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1652441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* For some sections we might have created an table to map symbol
1653441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 table indices.  */
1654441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (any_symtab_changes)
1655441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	for (cnt = 1; cnt <= shdridx; ++cnt)
1656441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  free (shdr_info[cnt].newsymidx);
1657441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1658441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Free the memory.  */
1659441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
1660441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	free (shdr_info);
1661441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1663441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Free other resources.  */
1664441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shstrtab_data != NULL)
1665441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    free (shstrtab_data->d_buf);
1666441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shst != NULL)
1667441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ebl_strtabfree (shst);
1668441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1669441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* That was it.  Close the descriptors.  */
1670441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (elf_end (newelf) != 0)
1671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1672441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("error while finishing `%s': %s"), fname,
1673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     elf_errmsg (-1));
1674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      result = 1;
1675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1677441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debugelf != NULL && elf_end (debugelf) != 0)
1678441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1679441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("error while finishing `%s': %s"), debug_fname,
1680441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     elf_errmsg (-1));
1681441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      result = 1;
1682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1683441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project fail:
1685441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Close the EBL backend.  */
1686441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ebl != NULL)
1687441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ebl_closebackend (ebl);
1688441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1689441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Close debug file descriptor, if opened */
1690441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (debug_fd >= 0)
1691441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (tmp_debug_fname != NULL)
1693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	unlink (tmp_debug_fname);
1694441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      close (debug_fd);
1695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If requested, preserve the timestamp.  */
1698441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (tvp != NULL)
1699441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1700441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (futimes (fd, tvp) != 0)
1701441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1702441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("\
1703441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcannot set access and modification date of \"%s\""),
1704441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 output_fname ?: fname);
1705441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
1706441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1707441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1708441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1709441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Close the file descriptor if we created a new file.  */
1710441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (output_fname != NULL)
1711441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    close (fd);
1712441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1713441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
1714441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1715441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1716441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1717441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int
1718441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projecthandle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
1719441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   struct timeval tvp[2])
1720441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1721441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
1722441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t fname_len = strlen (fname) + 1;
1723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char new_prefix[prefix_len + 1 + fname_len];
1724441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *cp = new_prefix;
1725441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Create the full name of the file.  */
1727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (prefix != NULL)
1728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      cp = mempcpy (cp, prefix, prefix_len);
1730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      *cp++ = ':';
1731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  memcpy (cp, fname, fname_len);
1733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Process all the files contained in the archive.  */
1736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf *subelf;
1737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Cmd cmd = ELF_C_RDWR;
1738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int result = 0;
1739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
1740441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* The the header for this element.  */
1742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
1743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (elf_kind (subelf) == ELF_K_ELF)
1745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
1746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (elf_kind (subelf) == ELF_K_AR)
1747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
1748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Get next archive element.  */
1750441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      cmd = elf_next (subelf);
1751441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (elf_end (subelf) != 0))
1752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	INTERNAL_ERROR (fname);
1753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1755441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (tvp != NULL)
1756441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1757441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (futimes (fd, tvp) != 0))
1758441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1759441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("\
1760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcannot set access and modification date of \"%s\""), fname);
1761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  result = 1;
1762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1763441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1764441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1765441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (close (fd) != 0))
1766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, errno, gettext ("while closing `%s'"), fname);
1767441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1768441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
1769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1770