xref: /aosp_15_r20/external/elfutils/src/unstrip.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Combine stripped files with separate symbols and debug information.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2007-2012, 2014, 2015 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker    Written by Roland McGrath <[email protected]>, 2007.
5*7304104dSAndroid Build Coastguard Worker 
6*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker    it under the terms of the GNU General Public License as published by
8*7304104dSAndroid Build Coastguard Worker    the Free Software Foundation; either version 3 of the License, or
9*7304104dSAndroid Build Coastguard Worker    (at your option) any later version.
10*7304104dSAndroid Build Coastguard Worker 
11*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
12*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
13*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*7304104dSAndroid Build Coastguard Worker    GNU General Public License for more details.
15*7304104dSAndroid Build Coastguard Worker 
16*7304104dSAndroid Build Coastguard Worker    You should have received a copy of the GNU General Public License
17*7304104dSAndroid Build Coastguard Worker    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18*7304104dSAndroid Build Coastguard Worker 
19*7304104dSAndroid Build Coastguard Worker /* TODO:
20*7304104dSAndroid Build Coastguard Worker 
21*7304104dSAndroid Build Coastguard Worker   * SHX_XINDEX
22*7304104dSAndroid Build Coastguard Worker 
23*7304104dSAndroid Build Coastguard Worker   * prelink vs .debug_* linked addresses
24*7304104dSAndroid Build Coastguard Worker 
25*7304104dSAndroid Build Coastguard Worker  */
26*7304104dSAndroid Build Coastguard Worker 
27*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
28*7304104dSAndroid Build Coastguard Worker # include <config.h>
29*7304104dSAndroid Build Coastguard Worker #endif
30*7304104dSAndroid Build Coastguard Worker 
31*7304104dSAndroid Build Coastguard Worker #include <argp.h>
32*7304104dSAndroid Build Coastguard Worker #include <assert.h>
33*7304104dSAndroid Build Coastguard Worker #include <errno.h>
34*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
35*7304104dSAndroid Build Coastguard Worker #include <fnmatch.h>
36*7304104dSAndroid Build Coastguard Worker #include <locale.h>
37*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
38*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
39*7304104dSAndroid Build Coastguard Worker #include <stdio_ext.h>
40*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
41*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
42*7304104dSAndroid Build Coastguard Worker #include <string.h>
43*7304104dSAndroid Build Coastguard Worker #include <unistd.h>
44*7304104dSAndroid Build Coastguard Worker #include <sys/stat.h>
45*7304104dSAndroid Build Coastguard Worker 
46*7304104dSAndroid Build Coastguard Worker #include <gelf.h>
47*7304104dSAndroid Build Coastguard Worker #include <libebl.h>
48*7304104dSAndroid Build Coastguard Worker #include <libdwfl.h>
49*7304104dSAndroid Build Coastguard Worker #include "system.h"
50*7304104dSAndroid Build Coastguard Worker #include "libdwelf.h"
51*7304104dSAndroid Build Coastguard Worker #include "libeu.h"
52*7304104dSAndroid Build Coastguard Worker #include "printversion.h"
53*7304104dSAndroid Build Coastguard Worker 
54*7304104dSAndroid Build Coastguard Worker /* Name and version of program.  */
55*7304104dSAndroid Build Coastguard Worker ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
56*7304104dSAndroid Build Coastguard Worker 
57*7304104dSAndroid Build Coastguard Worker /* Bug report address.  */
58*7304104dSAndroid Build Coastguard Worker ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
59*7304104dSAndroid Build Coastguard Worker 
60*7304104dSAndroid Build Coastguard Worker /* Definitions of arguments for argp functions.  */
61*7304104dSAndroid Build Coastguard Worker static const struct argp_option options[] =
62*7304104dSAndroid Build Coastguard Worker {
63*7304104dSAndroid Build Coastguard Worker   /* Group 2 will follow group 1 from dwfl_standard_argp.  */
64*7304104dSAndroid Build Coastguard Worker   { "match-file-names", 'f', NULL, 0,
65*7304104dSAndroid Build Coastguard Worker     N_("Match MODULE against file names, not module names"), 2 },
66*7304104dSAndroid Build Coastguard Worker   { "ignore-missing", 'i', NULL, 0, N_("Silently skip unfindable files"), 0 },
67*7304104dSAndroid Build Coastguard Worker 
68*7304104dSAndroid Build Coastguard Worker   { NULL, 0, NULL, 0, N_("Output options:"), 0 },
69*7304104dSAndroid Build Coastguard Worker   { "output", 'o', "FILE", 0, N_("Place output into FILE"), 0 },
70*7304104dSAndroid Build Coastguard Worker   { "output-directory", 'd', "DIRECTORY",
71*7304104dSAndroid Build Coastguard Worker     0, N_("Create multiple output files under DIRECTORY"), 0 },
72*7304104dSAndroid Build Coastguard Worker   { "module-names", 'm', NULL, 0, N_("Use module rather than file names"), 0 },
73*7304104dSAndroid Build Coastguard Worker   { "all", 'a', NULL, 0,
74*7304104dSAndroid Build Coastguard Worker     N_("Create output for modules that have no separate debug information"),
75*7304104dSAndroid Build Coastguard Worker     0 },
76*7304104dSAndroid Build Coastguard Worker   { "relocate", 'R', NULL, 0,
77*7304104dSAndroid Build Coastguard Worker     N_("Apply relocations to section contents in ET_REL files"), 0 },
78*7304104dSAndroid Build Coastguard Worker   { "list-only", 'n', NULL, 0,
79*7304104dSAndroid Build Coastguard Worker     N_("Only list module and file names, build IDs"), 0 },
80*7304104dSAndroid Build Coastguard Worker  { "force", 'F', NULL, 0,
81*7304104dSAndroid Build Coastguard Worker     N_("Force combining files even if some ELF headers don't seem to match"),
82*7304104dSAndroid Build Coastguard Worker    0 },
83*7304104dSAndroid Build Coastguard Worker   { NULL, 0, NULL, 0, NULL, 0 }
84*7304104dSAndroid Build Coastguard Worker };
85*7304104dSAndroid Build Coastguard Worker 
86*7304104dSAndroid Build Coastguard Worker struct arg_info
87*7304104dSAndroid Build Coastguard Worker {
88*7304104dSAndroid Build Coastguard Worker   const char *output_file;
89*7304104dSAndroid Build Coastguard Worker   const char *output_dir;
90*7304104dSAndroid Build Coastguard Worker   Dwfl *dwfl;
91*7304104dSAndroid Build Coastguard Worker   char **args;
92*7304104dSAndroid Build Coastguard Worker   bool list;
93*7304104dSAndroid Build Coastguard Worker   bool all;
94*7304104dSAndroid Build Coastguard Worker   bool ignore;
95*7304104dSAndroid Build Coastguard Worker   bool modnames;
96*7304104dSAndroid Build Coastguard Worker   bool match_files;
97*7304104dSAndroid Build Coastguard Worker   bool relocate;
98*7304104dSAndroid Build Coastguard Worker   bool force;
99*7304104dSAndroid Build Coastguard Worker };
100*7304104dSAndroid Build Coastguard Worker 
101*7304104dSAndroid Build Coastguard Worker /* Handle program arguments.  */
102*7304104dSAndroid Build Coastguard Worker static error_t
parse_opt(int key,char * arg,struct argp_state * state)103*7304104dSAndroid Build Coastguard Worker parse_opt (int key, char *arg, struct argp_state *state)
104*7304104dSAndroid Build Coastguard Worker {
105*7304104dSAndroid Build Coastguard Worker   struct arg_info *info = state->input;
106*7304104dSAndroid Build Coastguard Worker 
107*7304104dSAndroid Build Coastguard Worker   switch (key)
108*7304104dSAndroid Build Coastguard Worker     {
109*7304104dSAndroid Build Coastguard Worker     case ARGP_KEY_INIT:
110*7304104dSAndroid Build Coastguard Worker       state->child_inputs[0] = &info->dwfl;
111*7304104dSAndroid Build Coastguard Worker       break;
112*7304104dSAndroid Build Coastguard Worker 
113*7304104dSAndroid Build Coastguard Worker     case 'o':
114*7304104dSAndroid Build Coastguard Worker       if (info->output_file != NULL)
115*7304104dSAndroid Build Coastguard Worker 	{
116*7304104dSAndroid Build Coastguard Worker 	  argp_error (state, _("-o option specified twice"));
117*7304104dSAndroid Build Coastguard Worker 	  return EINVAL;
118*7304104dSAndroid Build Coastguard Worker 	}
119*7304104dSAndroid Build Coastguard Worker       info->output_file = arg;
120*7304104dSAndroid Build Coastguard Worker       break;
121*7304104dSAndroid Build Coastguard Worker 
122*7304104dSAndroid Build Coastguard Worker     case 'd':
123*7304104dSAndroid Build Coastguard Worker       if (info->output_dir != NULL)
124*7304104dSAndroid Build Coastguard Worker 	{
125*7304104dSAndroid Build Coastguard Worker 	  argp_error (state, _("-d option specified twice"));
126*7304104dSAndroid Build Coastguard Worker 	  return EINVAL;
127*7304104dSAndroid Build Coastguard Worker 	}
128*7304104dSAndroid Build Coastguard Worker       info->output_dir = arg;
129*7304104dSAndroid Build Coastguard Worker       break;
130*7304104dSAndroid Build Coastguard Worker 
131*7304104dSAndroid Build Coastguard Worker     case 'm':
132*7304104dSAndroid Build Coastguard Worker       info->modnames = true;
133*7304104dSAndroid Build Coastguard Worker       break;
134*7304104dSAndroid Build Coastguard Worker     case 'f':
135*7304104dSAndroid Build Coastguard Worker       info->match_files = true;
136*7304104dSAndroid Build Coastguard Worker       break;
137*7304104dSAndroid Build Coastguard Worker     case 'a':
138*7304104dSAndroid Build Coastguard Worker       info->all = true;
139*7304104dSAndroid Build Coastguard Worker       break;
140*7304104dSAndroid Build Coastguard Worker     case 'i':
141*7304104dSAndroid Build Coastguard Worker       info->ignore = true;
142*7304104dSAndroid Build Coastguard Worker       break;
143*7304104dSAndroid Build Coastguard Worker     case 'n':
144*7304104dSAndroid Build Coastguard Worker       info->list = true;
145*7304104dSAndroid Build Coastguard Worker       break;
146*7304104dSAndroid Build Coastguard Worker     case 'R':
147*7304104dSAndroid Build Coastguard Worker       info->relocate = true;
148*7304104dSAndroid Build Coastguard Worker       break;
149*7304104dSAndroid Build Coastguard Worker     case 'F':
150*7304104dSAndroid Build Coastguard Worker       info->force = true;
151*7304104dSAndroid Build Coastguard Worker       break;
152*7304104dSAndroid Build Coastguard Worker 
153*7304104dSAndroid Build Coastguard Worker     case ARGP_KEY_ARGS:
154*7304104dSAndroid Build Coastguard Worker     case ARGP_KEY_NO_ARGS:
155*7304104dSAndroid Build Coastguard Worker       /* We "consume" all the arguments here.  */
156*7304104dSAndroid Build Coastguard Worker       info->args = &state->argv[state->next];
157*7304104dSAndroid Build Coastguard Worker 
158*7304104dSAndroid Build Coastguard Worker       if (info->output_file != NULL && info->output_dir != NULL)
159*7304104dSAndroid Build Coastguard Worker 	{
160*7304104dSAndroid Build Coastguard Worker 	  argp_error (state, _("only one of -o or -d allowed"));
161*7304104dSAndroid Build Coastguard Worker 	  return EINVAL;
162*7304104dSAndroid Build Coastguard Worker 	}
163*7304104dSAndroid Build Coastguard Worker 
164*7304104dSAndroid Build Coastguard Worker       if (info->list && (info->dwfl == NULL
165*7304104dSAndroid Build Coastguard Worker 			 || info->output_dir != NULL
166*7304104dSAndroid Build Coastguard Worker 			 || info->output_file != NULL))
167*7304104dSAndroid Build Coastguard Worker 	{
168*7304104dSAndroid Build Coastguard Worker 	  argp_error (state,
169*7304104dSAndroid Build Coastguard Worker 		      _("-n cannot be used with explicit files or -o or -d"));
170*7304104dSAndroid Build Coastguard Worker 	  return EINVAL;
171*7304104dSAndroid Build Coastguard Worker 	}
172*7304104dSAndroid Build Coastguard Worker 
173*7304104dSAndroid Build Coastguard Worker       if (info->output_dir != NULL)
174*7304104dSAndroid Build Coastguard Worker 	{
175*7304104dSAndroid Build Coastguard Worker 	  struct stat st;
176*7304104dSAndroid Build Coastguard Worker 	  error_t fail = 0;
177*7304104dSAndroid Build Coastguard Worker 	  if (stat (info->output_dir, &st) < 0)
178*7304104dSAndroid Build Coastguard Worker 	    fail = errno;
179*7304104dSAndroid Build Coastguard Worker 	  else if (!S_ISDIR (st.st_mode))
180*7304104dSAndroid Build Coastguard Worker 	    fail = ENOTDIR;
181*7304104dSAndroid Build Coastguard Worker 	  if (fail)
182*7304104dSAndroid Build Coastguard Worker 	    {
183*7304104dSAndroid Build Coastguard Worker 	      argp_failure (state, EXIT_FAILURE, fail,
184*7304104dSAndroid Build Coastguard Worker 			    _("output directory '%s'"), info->output_dir);
185*7304104dSAndroid Build Coastguard Worker 	      return fail;
186*7304104dSAndroid Build Coastguard Worker 	    }
187*7304104dSAndroid Build Coastguard Worker 	}
188*7304104dSAndroid Build Coastguard Worker 
189*7304104dSAndroid Build Coastguard Worker       if (info->dwfl == NULL)
190*7304104dSAndroid Build Coastguard Worker 	{
191*7304104dSAndroid Build Coastguard Worker 	  if (state->next + 2 != state->argc)
192*7304104dSAndroid Build Coastguard Worker 	    {
193*7304104dSAndroid Build Coastguard Worker 	      argp_error (state, _("exactly two file arguments are required"));
194*7304104dSAndroid Build Coastguard Worker 	      return EINVAL;
195*7304104dSAndroid Build Coastguard Worker 	    }
196*7304104dSAndroid Build Coastguard Worker 
197*7304104dSAndroid Build Coastguard Worker 	  if (info->ignore || info->all || info->modnames || info->relocate)
198*7304104dSAndroid Build Coastguard Worker 	    {
199*7304104dSAndroid Build Coastguard Worker 	      argp_error (state, _("\
200*7304104dSAndroid Build Coastguard Worker -m, -a, -R, and -i options not allowed with explicit files"));
201*7304104dSAndroid Build Coastguard Worker 	      return EINVAL;
202*7304104dSAndroid Build Coastguard Worker 	    }
203*7304104dSAndroid Build Coastguard Worker 
204*7304104dSAndroid Build Coastguard Worker 	  /* Bail out immediately to prevent dwfl_standard_argp's parser
205*7304104dSAndroid Build Coastguard Worker 	     from defaulting to "-e a.out".  */
206*7304104dSAndroid Build Coastguard Worker 	  return ENOSYS;
207*7304104dSAndroid Build Coastguard Worker 	}
208*7304104dSAndroid Build Coastguard Worker       else if (info->output_file == NULL && info->output_dir == NULL
209*7304104dSAndroid Build Coastguard Worker 	       && !info->list)
210*7304104dSAndroid Build Coastguard Worker 	{
211*7304104dSAndroid Build Coastguard Worker 	  argp_error (state,
212*7304104dSAndroid Build Coastguard Worker 		      _("-o or -d is required when using implicit files"));
213*7304104dSAndroid Build Coastguard Worker 	  return EINVAL;
214*7304104dSAndroid Build Coastguard Worker 	}
215*7304104dSAndroid Build Coastguard Worker       break;
216*7304104dSAndroid Build Coastguard Worker 
217*7304104dSAndroid Build Coastguard Worker     default:
218*7304104dSAndroid Build Coastguard Worker       return ARGP_ERR_UNKNOWN;
219*7304104dSAndroid Build Coastguard Worker     }
220*7304104dSAndroid Build Coastguard Worker   return 0;
221*7304104dSAndroid Build Coastguard Worker }
222*7304104dSAndroid Build Coastguard Worker 
223*7304104dSAndroid Build Coastguard Worker #define ELF_CHECK(call, msg)						      \
224*7304104dSAndroid Build Coastguard Worker   do									      \
225*7304104dSAndroid Build Coastguard Worker     {									      \
226*7304104dSAndroid Build Coastguard Worker       if (unlikely (!(call)))						      \
227*7304104dSAndroid Build Coastguard Worker 	error_exit (0, msg, elf_errmsg (-1));				      \
228*7304104dSAndroid Build Coastguard Worker     } while (0)
229*7304104dSAndroid Build Coastguard Worker 
230*7304104dSAndroid Build Coastguard Worker /* Copy INELF to newly-created OUTELF, exit via error for any problems.  */
231*7304104dSAndroid Build Coastguard Worker static void
copy_elf(Elf * outelf,Elf * inelf)232*7304104dSAndroid Build Coastguard Worker copy_elf (Elf *outelf, Elf *inelf)
233*7304104dSAndroid Build Coastguard Worker {
234*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (gelf_newehdr (outelf, gelf_getclass (inelf)),
235*7304104dSAndroid Build Coastguard Worker 	     _("cannot create ELF header: %s"));
236*7304104dSAndroid Build Coastguard Worker 
237*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
238*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (elf_getshdrstrndx (inelf, &shstrndx) == 0,
239*7304104dSAndroid Build Coastguard Worker 	     _("cannot get shdrstrndx:%s"));
240*7304104dSAndroid Build Coastguard Worker 
241*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr ehdr_mem;
242*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr *ehdr = gelf_getehdr (inelf, &ehdr_mem);
243*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (ehdr != NULL, _("cannot get ELF header: %s"));
244*7304104dSAndroid Build Coastguard Worker   if (shstrndx < SHN_LORESERVE)
245*7304104dSAndroid Build Coastguard Worker     ehdr->e_shstrndx = shstrndx;
246*7304104dSAndroid Build Coastguard Worker   else
247*7304104dSAndroid Build Coastguard Worker     {
248*7304104dSAndroid Build Coastguard Worker       ehdr->e_shstrndx = SHN_XINDEX;
249*7304104dSAndroid Build Coastguard Worker       Elf_Scn *scn0 = elf_getscn (outelf, 0);
250*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr0_mem;
251*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr0 = gelf_getshdr (scn0, &shdr0_mem);
252*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (shdr0 != NULL,
253*7304104dSAndroid Build Coastguard Worker 		 _("cannot get new zero section: %s"));
254*7304104dSAndroid Build Coastguard Worker       shdr0->sh_link = shstrndx;
255*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_update_shdr (scn0, shdr0),
256*7304104dSAndroid Build Coastguard Worker 		 _("cannot update new zero section: %s"));
257*7304104dSAndroid Build Coastguard Worker     }
258*7304104dSAndroid Build Coastguard Worker 
259*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (gelf_update_ehdr (outelf, ehdr),
260*7304104dSAndroid Build Coastguard Worker 	     _("cannot copy ELF header: %s"));
261*7304104dSAndroid Build Coastguard Worker 
262*7304104dSAndroid Build Coastguard Worker   size_t phnum;
263*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (elf_getphdrnum (inelf, &phnum) == 0,
264*7304104dSAndroid Build Coastguard Worker 	     _("cannot get number of program headers: %s"));
265*7304104dSAndroid Build Coastguard Worker 
266*7304104dSAndroid Build Coastguard Worker   if (phnum > 0)
267*7304104dSAndroid Build Coastguard Worker     {
268*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_newphdr (outelf, phnum),
269*7304104dSAndroid Build Coastguard Worker 		 _("cannot create program headers: %s"));
270*7304104dSAndroid Build Coastguard Worker 
271*7304104dSAndroid Build Coastguard Worker       GElf_Phdr phdr_mem;
272*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < phnum; ++i)
273*7304104dSAndroid Build Coastguard Worker 	ELF_CHECK (gelf_update_phdr (outelf, i,
274*7304104dSAndroid Build Coastguard Worker 				     gelf_getphdr (inelf, i, &phdr_mem)),
275*7304104dSAndroid Build Coastguard Worker 		   _("cannot copy program header: %s"));
276*7304104dSAndroid Build Coastguard Worker     }
277*7304104dSAndroid Build Coastguard Worker 
278*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
279*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (inelf, scn)) != NULL)
280*7304104dSAndroid Build Coastguard Worker     {
281*7304104dSAndroid Build Coastguard Worker       Elf_Scn *newscn = elf_newscn (outelf);
282*7304104dSAndroid Build Coastguard Worker 
283*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
284*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_update_shdr (newscn, gelf_getshdr (scn, &shdr_mem)),
285*7304104dSAndroid Build Coastguard Worker 		 _("cannot copy section header: %s"));
286*7304104dSAndroid Build Coastguard Worker 
287*7304104dSAndroid Build Coastguard Worker       Elf_Data *data = elf_getdata (scn, NULL);
288*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (data != NULL, _("cannot get section data: %s"));
289*7304104dSAndroid Build Coastguard Worker       Elf_Data *newdata = elf_newdata (newscn);
290*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (newdata != NULL, _("cannot copy section data: %s"));
291*7304104dSAndroid Build Coastguard Worker       *newdata = *data;
292*7304104dSAndroid Build Coastguard Worker       elf_flagdata (newdata, ELF_C_SET, ELF_F_DIRTY);
293*7304104dSAndroid Build Coastguard Worker     }
294*7304104dSAndroid Build Coastguard Worker }
295*7304104dSAndroid Build Coastguard Worker 
296*7304104dSAndroid Build Coastguard Worker /* Create directories containing PATH.  */
297*7304104dSAndroid Build Coastguard Worker static void
make_directories(const char * path)298*7304104dSAndroid Build Coastguard Worker make_directories (const char *path)
299*7304104dSAndroid Build Coastguard Worker {
300*7304104dSAndroid Build Coastguard Worker   const char *lastslash = strrchr (path, '/');
301*7304104dSAndroid Build Coastguard Worker   if (lastslash == NULL)
302*7304104dSAndroid Build Coastguard Worker     return;
303*7304104dSAndroid Build Coastguard Worker 
304*7304104dSAndroid Build Coastguard Worker   while (lastslash > path && lastslash[-1] == '/')
305*7304104dSAndroid Build Coastguard Worker     --lastslash;
306*7304104dSAndroid Build Coastguard Worker   if (lastslash == path)
307*7304104dSAndroid Build Coastguard Worker     return;
308*7304104dSAndroid Build Coastguard Worker 
309*7304104dSAndroid Build Coastguard Worker   char *dir = strndup (path, lastslash - path);
310*7304104dSAndroid Build Coastguard Worker   if (dir == NULL)
311*7304104dSAndroid Build Coastguard Worker     error(EXIT_FAILURE, errno, _("memory exhausted"));
312*7304104dSAndroid Build Coastguard Worker 
313*7304104dSAndroid Build Coastguard Worker   while (mkdir (dir, ACCESSPERMS) < 0 && errno != EEXIST)
314*7304104dSAndroid Build Coastguard Worker     {
315*7304104dSAndroid Build Coastguard Worker       if (errno == ENOENT)
316*7304104dSAndroid Build Coastguard Worker         make_directories (dir);
317*7304104dSAndroid Build Coastguard Worker       else
318*7304104dSAndroid Build Coastguard Worker         error_exit (errno, _("cannot create directory '%s'"), dir);
319*7304104dSAndroid Build Coastguard Worker     }
320*7304104dSAndroid Build Coastguard Worker   free (dir);
321*7304104dSAndroid Build Coastguard Worker }
322*7304104dSAndroid Build Coastguard Worker 
323*7304104dSAndroid Build Coastguard Worker /* Keep track of new section data we are creating, so we can free it
324*7304104dSAndroid Build Coastguard Worker    when done.  */
325*7304104dSAndroid Build Coastguard Worker struct data_list
326*7304104dSAndroid Build Coastguard Worker {
327*7304104dSAndroid Build Coastguard Worker   void *data;
328*7304104dSAndroid Build Coastguard Worker   struct data_list *next;
329*7304104dSAndroid Build Coastguard Worker };
330*7304104dSAndroid Build Coastguard Worker 
331*7304104dSAndroid Build Coastguard Worker struct data_list *new_data_list;
332*7304104dSAndroid Build Coastguard Worker 
333*7304104dSAndroid Build Coastguard Worker static void
record_new_data(void * data)334*7304104dSAndroid Build Coastguard Worker record_new_data (void *data)
335*7304104dSAndroid Build Coastguard Worker {
336*7304104dSAndroid Build Coastguard Worker   struct data_list *next = new_data_list;
337*7304104dSAndroid Build Coastguard Worker   new_data_list = xmalloc (sizeof (struct data_list));
338*7304104dSAndroid Build Coastguard Worker   new_data_list->data = data;
339*7304104dSAndroid Build Coastguard Worker   new_data_list->next = next;
340*7304104dSAndroid Build Coastguard Worker }
341*7304104dSAndroid Build Coastguard Worker 
342*7304104dSAndroid Build Coastguard Worker static void
free_new_data(void)343*7304104dSAndroid Build Coastguard Worker free_new_data (void)
344*7304104dSAndroid Build Coastguard Worker {
345*7304104dSAndroid Build Coastguard Worker   struct data_list *list = new_data_list;
346*7304104dSAndroid Build Coastguard Worker   while (list != NULL)
347*7304104dSAndroid Build Coastguard Worker     {
348*7304104dSAndroid Build Coastguard Worker       struct data_list *next = list->next;
349*7304104dSAndroid Build Coastguard Worker       free (list->data);
350*7304104dSAndroid Build Coastguard Worker       free (list);
351*7304104dSAndroid Build Coastguard Worker       list = next;
352*7304104dSAndroid Build Coastguard Worker     }
353*7304104dSAndroid Build Coastguard Worker   new_data_list = NULL;
354*7304104dSAndroid Build Coastguard Worker }
355*7304104dSAndroid Build Coastguard Worker 
356*7304104dSAndroid Build Coastguard Worker /* The binutils linker leaves gratuitous section symbols in .symtab
357*7304104dSAndroid Build Coastguard Worker    that strip has to remove.  Older linkers likewise include a
358*7304104dSAndroid Build Coastguard Worker    symbol for every section, even unallocated ones, in .dynsym.
359*7304104dSAndroid Build Coastguard Worker    Because of this, the related sections can shrink in the stripped
360*7304104dSAndroid Build Coastguard Worker    file from their original size.  Older versions of strip do not
361*7304104dSAndroid Build Coastguard Worker    adjust the sh_size field in the debuginfo file's SHT_NOBITS
362*7304104dSAndroid Build Coastguard Worker    version of the section header, so it can appear larger.  */
363*7304104dSAndroid Build Coastguard Worker static bool
section_can_shrink(const GElf_Shdr * shdr)364*7304104dSAndroid Build Coastguard Worker section_can_shrink (const GElf_Shdr *shdr)
365*7304104dSAndroid Build Coastguard Worker {
366*7304104dSAndroid Build Coastguard Worker   switch (shdr->sh_type)
367*7304104dSAndroid Build Coastguard Worker     {
368*7304104dSAndroid Build Coastguard Worker     case SHT_SYMTAB:
369*7304104dSAndroid Build Coastguard Worker     case SHT_DYNSYM:
370*7304104dSAndroid Build Coastguard Worker     case SHT_HASH:
371*7304104dSAndroid Build Coastguard Worker     case SHT_GNU_versym:
372*7304104dSAndroid Build Coastguard Worker       return true;
373*7304104dSAndroid Build Coastguard Worker     }
374*7304104dSAndroid Build Coastguard Worker   return false;
375*7304104dSAndroid Build Coastguard Worker }
376*7304104dSAndroid Build Coastguard Worker 
377*7304104dSAndroid Build Coastguard Worker /* See if this symbol table has a leading section symbol for every single
378*7304104dSAndroid Build Coastguard Worker    section, in order.  The binutils linker produces this.  While we're here,
379*7304104dSAndroid Build Coastguard Worker    update each section symbol's st_value.  */
380*7304104dSAndroid Build Coastguard Worker static size_t
symtab_count_leading_section_symbols(Elf * elf,Elf_Scn * scn,size_t shnum,Elf_Data * newsymdata)381*7304104dSAndroid Build Coastguard Worker symtab_count_leading_section_symbols (Elf *elf, Elf_Scn *scn, size_t shnum,
382*7304104dSAndroid Build Coastguard Worker 				      Elf_Data *newsymdata)
383*7304104dSAndroid Build Coastguard Worker {
384*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
385*7304104dSAndroid Build Coastguard Worker   Elf_Data *shndxdata = NULL;	/* XXX */
386*7304104dSAndroid Build Coastguard Worker 
387*7304104dSAndroid Build Coastguard Worker   for (size_t i = 1; i < shnum; ++i)
388*7304104dSAndroid Build Coastguard Worker     {
389*7304104dSAndroid Build Coastguard Worker       GElf_Sym sym_mem;
390*7304104dSAndroid Build Coastguard Worker       GElf_Word shndx = SHN_UNDEF;
391*7304104dSAndroid Build Coastguard Worker       GElf_Sym *sym = gelf_getsymshndx (data, shndxdata, i, &sym_mem, &shndx);
392*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
393*7304104dSAndroid Build Coastguard Worker 
394*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
395*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, i), &shdr_mem);
396*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
397*7304104dSAndroid Build Coastguard Worker 
398*7304104dSAndroid Build Coastguard Worker       if (sym->st_shndx != SHN_XINDEX)
399*7304104dSAndroid Build Coastguard Worker 	shndx = sym->st_shndx;
400*7304104dSAndroid Build Coastguard Worker 
401*7304104dSAndroid Build Coastguard Worker       if (shndx != i || GELF_ST_TYPE (sym->st_info) != STT_SECTION)
402*7304104dSAndroid Build Coastguard Worker 	return i;
403*7304104dSAndroid Build Coastguard Worker 
404*7304104dSAndroid Build Coastguard Worker       sym->st_value = shdr->sh_addr;
405*7304104dSAndroid Build Coastguard Worker       if (sym->st_shndx != SHN_XINDEX)
406*7304104dSAndroid Build Coastguard Worker 	shndx = SHN_UNDEF;
407*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_update_symshndx (newsymdata, shndxdata, i, sym, shndx),
408*7304104dSAndroid Build Coastguard Worker 		 _("cannot update symbol table: %s"));
409*7304104dSAndroid Build Coastguard Worker     }
410*7304104dSAndroid Build Coastguard Worker 
411*7304104dSAndroid Build Coastguard Worker   return shnum;
412*7304104dSAndroid Build Coastguard Worker }
413*7304104dSAndroid Build Coastguard Worker 
414*7304104dSAndroid Build Coastguard Worker static void
update_shdr(Elf_Scn * outscn,GElf_Shdr * newshdr)415*7304104dSAndroid Build Coastguard Worker update_shdr (Elf_Scn *outscn, GElf_Shdr *newshdr)
416*7304104dSAndroid Build Coastguard Worker {
417*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (gelf_update_shdr (outscn, newshdr),
418*7304104dSAndroid Build Coastguard Worker 	     _("cannot update section header: %s"));
419*7304104dSAndroid Build Coastguard Worker }
420*7304104dSAndroid Build Coastguard Worker 
421*7304104dSAndroid Build Coastguard Worker /* We expanded the output section, so update its header.  */
422*7304104dSAndroid Build Coastguard Worker static void
update_sh_size(Elf_Scn * outscn,const Elf_Data * data)423*7304104dSAndroid Build Coastguard Worker update_sh_size (Elf_Scn *outscn, const Elf_Data *data)
424*7304104dSAndroid Build Coastguard Worker {
425*7304104dSAndroid Build Coastguard Worker   GElf_Shdr shdr_mem;
426*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *newshdr = gelf_getshdr (outscn, &shdr_mem);
427*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (newshdr != NULL, _("cannot get section header: %s"));
428*7304104dSAndroid Build Coastguard Worker 
429*7304104dSAndroid Build Coastguard Worker   newshdr->sh_size = data->d_size;
430*7304104dSAndroid Build Coastguard Worker 
431*7304104dSAndroid Build Coastguard Worker   update_shdr (outscn, newshdr);
432*7304104dSAndroid Build Coastguard Worker }
433*7304104dSAndroid Build Coastguard Worker 
434*7304104dSAndroid Build Coastguard Worker static inline void
adjust_reloc(GElf_Xword * info,size_t map[],size_t map_size)435*7304104dSAndroid Build Coastguard Worker adjust_reloc (GElf_Xword *info,
436*7304104dSAndroid Build Coastguard Worker 	      size_t map[], size_t map_size)
437*7304104dSAndroid Build Coastguard Worker {
438*7304104dSAndroid Build Coastguard Worker   size_t ndx = GELF_R_SYM (*info);
439*7304104dSAndroid Build Coastguard Worker   if (ndx != STN_UNDEF)
440*7304104dSAndroid Build Coastguard Worker     {
441*7304104dSAndroid Build Coastguard Worker       if (ndx > map_size)
442*7304104dSAndroid Build Coastguard Worker 	error_exit (0, "bad symbol ndx section");
443*7304104dSAndroid Build Coastguard Worker       *info = GELF_R_INFO (map[ndx - 1], GELF_R_TYPE (*info));
444*7304104dSAndroid Build Coastguard Worker     }
445*7304104dSAndroid Build Coastguard Worker }
446*7304104dSAndroid Build Coastguard Worker 
447*7304104dSAndroid Build Coastguard Worker /* Update relocation sections using the symbol table.  */
448*7304104dSAndroid Build Coastguard Worker static void
adjust_relocs(Elf_Scn * outscn,Elf_Scn * inscn,const GElf_Shdr * shdr,size_t map[],size_t map_size,const GElf_Shdr * symshdr)449*7304104dSAndroid Build Coastguard Worker adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
450*7304104dSAndroid Build Coastguard Worker 	       size_t map[], size_t map_size, const GElf_Shdr *symshdr)
451*7304104dSAndroid Build Coastguard Worker {
452*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (outscn, NULL);
453*7304104dSAndroid Build Coastguard Worker 
454*7304104dSAndroid Build Coastguard Worker   switch (shdr->sh_type)
455*7304104dSAndroid Build Coastguard Worker     {
456*7304104dSAndroid Build Coastguard Worker     case SHT_REL:
457*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_entsize == 0)
458*7304104dSAndroid Build Coastguard Worker 	error_exit (0, "REL section cannot have zero sh_entsize");
459*7304104dSAndroid Build Coastguard Worker 
460*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i)
461*7304104dSAndroid Build Coastguard Worker 	{
462*7304104dSAndroid Build Coastguard Worker 	  GElf_Rel rel_mem;
463*7304104dSAndroid Build Coastguard Worker 	  GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
464*7304104dSAndroid Build Coastguard Worker 	  ELF_CHECK (rel != NULL, _("gelf_getrel failed: %s"));
465*7304104dSAndroid Build Coastguard Worker 	  adjust_reloc (&rel->r_info, map, map_size);
466*7304104dSAndroid Build Coastguard Worker 	  ELF_CHECK (gelf_update_rel (data, i, rel),
467*7304104dSAndroid Build Coastguard Worker 		     _("cannot update relocation: %s"));
468*7304104dSAndroid Build Coastguard Worker 	}
469*7304104dSAndroid Build Coastguard Worker       break;
470*7304104dSAndroid Build Coastguard Worker 
471*7304104dSAndroid Build Coastguard Worker     case SHT_RELA:
472*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_entsize == 0)
473*7304104dSAndroid Build Coastguard Worker 	error_exit (0, "RELA section cannot have zero sh_entsize");
474*7304104dSAndroid Build Coastguard Worker 
475*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i)
476*7304104dSAndroid Build Coastguard Worker 	{
477*7304104dSAndroid Build Coastguard Worker 	  GElf_Rela rela_mem;
478*7304104dSAndroid Build Coastguard Worker 	  GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
479*7304104dSAndroid Build Coastguard Worker 	  ELF_CHECK (rela != NULL, _("gelf_getrela failed: %s"));
480*7304104dSAndroid Build Coastguard Worker 	  adjust_reloc (&rela->r_info, map, map_size);
481*7304104dSAndroid Build Coastguard Worker 	  ELF_CHECK (gelf_update_rela (data, i, rela),
482*7304104dSAndroid Build Coastguard Worker 		     _("cannot update relocation: %s"));
483*7304104dSAndroid Build Coastguard Worker 	}
484*7304104dSAndroid Build Coastguard Worker       break;
485*7304104dSAndroid Build Coastguard Worker 
486*7304104dSAndroid Build Coastguard Worker     case SHT_GROUP:
487*7304104dSAndroid Build Coastguard Worker       {
488*7304104dSAndroid Build Coastguard Worker 	GElf_Shdr shdr_mem;
489*7304104dSAndroid Build Coastguard Worker 	GElf_Shdr *newshdr = gelf_getshdr (outscn, &shdr_mem);
490*7304104dSAndroid Build Coastguard Worker 	ELF_CHECK (newshdr != NULL, _("cannot get section header: %s"));
491*7304104dSAndroid Build Coastguard Worker 	if (newshdr->sh_info != STN_UNDEF)
492*7304104dSAndroid Build Coastguard Worker 	  {
493*7304104dSAndroid Build Coastguard Worker 	    newshdr->sh_info = map[newshdr->sh_info - 1];
494*7304104dSAndroid Build Coastguard Worker 	    update_shdr (outscn, newshdr);
495*7304104dSAndroid Build Coastguard Worker 	  }
496*7304104dSAndroid Build Coastguard Worker 	break;
497*7304104dSAndroid Build Coastguard Worker       }
498*7304104dSAndroid Build Coastguard Worker 
499*7304104dSAndroid Build Coastguard Worker     case SHT_HASH:
500*7304104dSAndroid Build Coastguard Worker       /* We must expand the table and rejigger its contents.  */
501*7304104dSAndroid Build Coastguard Worker       {
502*7304104dSAndroid Build Coastguard Worker 	if (shdr->sh_entsize == 0)
503*7304104dSAndroid Build Coastguard Worker 	  error_exit (0, "HASH section cannot have zero sh_entsize");
504*7304104dSAndroid Build Coastguard Worker 	if (symshdr->sh_entsize == 0)
505*7304104dSAndroid Build Coastguard Worker 	  error_exit (0, "Symbol table cannot have zero sh_entsize");
506*7304104dSAndroid Build Coastguard Worker 	const size_t nsym = symshdr->sh_size / symshdr->sh_entsize;
507*7304104dSAndroid Build Coastguard Worker 	const size_t onent = shdr->sh_size / shdr->sh_entsize;
508*7304104dSAndroid Build Coastguard Worker 	if (data->d_size != shdr->sh_size)
509*7304104dSAndroid Build Coastguard Worker 	  error_exit (0, "HASH section has inconsistent size");
510*7304104dSAndroid Build Coastguard Worker 
511*7304104dSAndroid Build Coastguard Worker #define CONVERT_HASH(Hash_Word)						      \
512*7304104dSAndroid Build Coastguard Worker 	{								      \
513*7304104dSAndroid Build Coastguard Worker 	  const Hash_Word *const old_hash = data->d_buf;		      \
514*7304104dSAndroid Build Coastguard Worker 	  const size_t nbucket = old_hash[0];				      \
515*7304104dSAndroid Build Coastguard Worker 	  const size_t nchain = old_hash[1];				      \
516*7304104dSAndroid Build Coastguard Worker 	  const Hash_Word *const old_bucket = &old_hash[2];		      \
517*7304104dSAndroid Build Coastguard Worker 	  const Hash_Word *const old_chain = &old_bucket[nbucket];	      \
518*7304104dSAndroid Build Coastguard Worker 	  if (onent != 2 + nbucket + nchain)				      \
519*7304104dSAndroid Build Coastguard Worker 	    error_exit (0, "HASH section has inconsistent entsize");	      \
520*7304104dSAndroid Build Coastguard Worker 									      \
521*7304104dSAndroid Build Coastguard Worker 	  const size_t nent = 2 + nbucket + nsym;			      \
522*7304104dSAndroid Build Coastguard Worker 	  Hash_Word *const new_hash = xcalloc (nent, sizeof new_hash[0]);     \
523*7304104dSAndroid Build Coastguard Worker 	  Hash_Word *const new_bucket = &new_hash[2];			      \
524*7304104dSAndroid Build Coastguard Worker 	  Hash_Word *const new_chain = &new_bucket[nbucket];		      \
525*7304104dSAndroid Build Coastguard Worker 									      \
526*7304104dSAndroid Build Coastguard Worker 	  new_hash[0] = nbucket;					      \
527*7304104dSAndroid Build Coastguard Worker 	  new_hash[1] = nsym;						      \
528*7304104dSAndroid Build Coastguard Worker 	  for (size_t i = 0; i < nbucket; ++i)				      \
529*7304104dSAndroid Build Coastguard Worker 	    if (old_bucket[i] != STN_UNDEF)				      \
530*7304104dSAndroid Build Coastguard Worker 	      new_bucket[i] = map[old_bucket[i] - 1];			      \
531*7304104dSAndroid Build Coastguard Worker 									      \
532*7304104dSAndroid Build Coastguard Worker 	  for (size_t i = 1; i < nchain; ++i)				      \
533*7304104dSAndroid Build Coastguard Worker 	    if (old_chain[i] != STN_UNDEF)				      \
534*7304104dSAndroid Build Coastguard Worker 	      new_chain[map[i - 1]] = map[old_chain[i] - 1];		      \
535*7304104dSAndroid Build Coastguard Worker 									      \
536*7304104dSAndroid Build Coastguard Worker 	  record_new_data (new_hash);					\
537*7304104dSAndroid Build Coastguard Worker 	  data->d_buf = new_hash;					      \
538*7304104dSAndroid Build Coastguard Worker 	  data->d_size = nent * sizeof new_hash[0];			      \
539*7304104dSAndroid Build Coastguard Worker 	}
540*7304104dSAndroid Build Coastguard Worker 
541*7304104dSAndroid Build Coastguard Worker 	switch (shdr->sh_entsize)
542*7304104dSAndroid Build Coastguard Worker 	  {
543*7304104dSAndroid Build Coastguard Worker 	  case 4:
544*7304104dSAndroid Build Coastguard Worker 	    CONVERT_HASH (Elf32_Word);
545*7304104dSAndroid Build Coastguard Worker 	    break;
546*7304104dSAndroid Build Coastguard Worker 	  case 8:
547*7304104dSAndroid Build Coastguard Worker 	    CONVERT_HASH (Elf64_Xword);
548*7304104dSAndroid Build Coastguard Worker 	    break;
549*7304104dSAndroid Build Coastguard Worker 	  default:
550*7304104dSAndroid Build Coastguard Worker 	    abort ();
551*7304104dSAndroid Build Coastguard Worker 	  }
552*7304104dSAndroid Build Coastguard Worker 
553*7304104dSAndroid Build Coastguard Worker 	elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
554*7304104dSAndroid Build Coastguard Worker 	update_sh_size (outscn, data);
555*7304104dSAndroid Build Coastguard Worker 
556*7304104dSAndroid Build Coastguard Worker #undef	CONVERT_HASH
557*7304104dSAndroid Build Coastguard Worker       }
558*7304104dSAndroid Build Coastguard Worker       break;
559*7304104dSAndroid Build Coastguard Worker 
560*7304104dSAndroid Build Coastguard Worker     case SHT_GNU_versym:
561*7304104dSAndroid Build Coastguard Worker       /* We must expand the table and move its elements around.  */
562*7304104dSAndroid Build Coastguard Worker       {
563*7304104dSAndroid Build Coastguard Worker 	if (shdr->sh_entsize == 0)
564*7304104dSAndroid Build Coastguard Worker 	  error_exit (0, "GNU_versym section cannot have zero sh_entsize");
565*7304104dSAndroid Build Coastguard Worker 	if (symshdr->sh_entsize == 0)
566*7304104dSAndroid Build Coastguard Worker 	  error_exit (0, "Symbol table cannot have zero sh_entsize");
567*7304104dSAndroid Build Coastguard Worker 	const size_t nent = symshdr->sh_size / symshdr->sh_entsize;
568*7304104dSAndroid Build Coastguard Worker 	const size_t onent = shdr->sh_size / shdr->sh_entsize;
569*7304104dSAndroid Build Coastguard Worker 	assert (nent >= onent);
570*7304104dSAndroid Build Coastguard Worker 
571*7304104dSAndroid Build Coastguard Worker 	/* We don't bother using gelf_update_versym because there is
572*7304104dSAndroid Build Coastguard Worker 	   really no conversion to be done.  */
573*7304104dSAndroid Build Coastguard Worker 	assert (sizeof (Elf32_Versym) == sizeof (GElf_Versym));
574*7304104dSAndroid Build Coastguard Worker 	assert (sizeof (Elf64_Versym) == sizeof (GElf_Versym));
575*7304104dSAndroid Build Coastguard Worker 	GElf_Versym *versym = xcalloc (nent, sizeof versym[0]);
576*7304104dSAndroid Build Coastguard Worker 
577*7304104dSAndroid Build Coastguard Worker 	for (size_t i = 1; i < onent; ++i)
578*7304104dSAndroid Build Coastguard Worker 	  {
579*7304104dSAndroid Build Coastguard Worker 	    GElf_Versym *v = gelf_getversym (data, i, &versym[map[i - 1]]);
580*7304104dSAndroid Build Coastguard Worker 	    ELF_CHECK (v != NULL, _("cannot get symbol version: %s"));
581*7304104dSAndroid Build Coastguard Worker 	  }
582*7304104dSAndroid Build Coastguard Worker 
583*7304104dSAndroid Build Coastguard Worker 	record_new_data (versym);
584*7304104dSAndroid Build Coastguard Worker 	data->d_buf = versym;
585*7304104dSAndroid Build Coastguard Worker 	data->d_size = nent * sizeof versym[0];
586*7304104dSAndroid Build Coastguard Worker 	elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
587*7304104dSAndroid Build Coastguard Worker 	update_sh_size (outscn, data);
588*7304104dSAndroid Build Coastguard Worker       }
589*7304104dSAndroid Build Coastguard Worker       break;
590*7304104dSAndroid Build Coastguard Worker 
591*7304104dSAndroid Build Coastguard Worker     default:
592*7304104dSAndroid Build Coastguard Worker       error_exit (0,
593*7304104dSAndroid Build Coastguard Worker 		  _("unexpected section type in [%zu] with sh_link to symtab"),
594*7304104dSAndroid Build Coastguard Worker 		  elf_ndxscn (inscn));
595*7304104dSAndroid Build Coastguard Worker     }
596*7304104dSAndroid Build Coastguard Worker }
597*7304104dSAndroid Build Coastguard Worker 
598*7304104dSAndroid Build Coastguard Worker /* Adjust all the relocation sections in the file.  */
599*7304104dSAndroid Build Coastguard Worker static void
adjust_all_relocs(Elf * elf,Elf_Scn * symtab,const GElf_Shdr * symshdr,size_t map[],size_t map_size,bool scn_filter[])600*7304104dSAndroid Build Coastguard Worker adjust_all_relocs (Elf *elf, Elf_Scn *symtab, const GElf_Shdr *symshdr,
601*7304104dSAndroid Build Coastguard Worker 		   size_t map[], size_t map_size, bool scn_filter[])
602*7304104dSAndroid Build Coastguard Worker {
603*7304104dSAndroid Build Coastguard Worker   size_t new_sh_link = elf_ndxscn (symtab);
604*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
605*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (elf, scn)) != NULL)
606*7304104dSAndroid Build Coastguard Worker     if (scn != symtab)
607*7304104dSAndroid Build Coastguard Worker       {
608*7304104dSAndroid Build Coastguard Worker 	if (scn_filter != NULL)
609*7304104dSAndroid Build Coastguard Worker 	  {
610*7304104dSAndroid Build Coastguard Worker 	    size_t ndx = elf_ndxscn (scn);
611*7304104dSAndroid Build Coastguard Worker 
612*7304104dSAndroid Build Coastguard Worker 	    /* Skip relocations that were already mapped during adjust_relocs
613*7304104dSAndroid Build Coastguard Worker 	       for the stripped symtab.  This is to avoid mapping a relocation's
614*7304104dSAndroid Build Coastguard Worker 	       symbol index from X to Y during the first adjust_relocs and then
615*7304104dSAndroid Build Coastguard Worker 	       wrongly remapping it from Y to Z during the second call.  */
616*7304104dSAndroid Build Coastguard Worker 	    if (scn_filter[ndx])
617*7304104dSAndroid Build Coastguard Worker 	      continue;
618*7304104dSAndroid Build Coastguard Worker 	  }
619*7304104dSAndroid Build Coastguard Worker 
620*7304104dSAndroid Build Coastguard Worker 	GElf_Shdr shdr_mem;
621*7304104dSAndroid Build Coastguard Worker 	GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
622*7304104dSAndroid Build Coastguard Worker 	ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
623*7304104dSAndroid Build Coastguard Worker 
624*7304104dSAndroid Build Coastguard Worker 	if (shdr->sh_type != SHT_NOBITS && shdr->sh_link == new_sh_link)
625*7304104dSAndroid Build Coastguard Worker 	  adjust_relocs (scn, scn, shdr, map, map_size, symshdr);
626*7304104dSAndroid Build Coastguard Worker       }
627*7304104dSAndroid Build Coastguard Worker }
628*7304104dSAndroid Build Coastguard Worker 
629*7304104dSAndroid Build Coastguard Worker /* The original file probably had section symbols for all of its
630*7304104dSAndroid Build Coastguard Worker    sections, even the unallocated ones.  To match it as closely as
631*7304104dSAndroid Build Coastguard Worker    possible, add in section symbols for the added sections.  */
632*7304104dSAndroid Build Coastguard Worker static Elf_Data *
add_new_section_symbols(Elf_Scn * old_symscn,size_t old_shnum,Elf * elf,bool rel,Elf_Scn * symscn,size_t shnum)633*7304104dSAndroid Build Coastguard Worker add_new_section_symbols (Elf_Scn *old_symscn, size_t old_shnum,
634*7304104dSAndroid Build Coastguard Worker 			 Elf *elf, bool rel, Elf_Scn *symscn, size_t shnum)
635*7304104dSAndroid Build Coastguard Worker {
636*7304104dSAndroid Build Coastguard Worker   const size_t added = shnum - old_shnum;
637*7304104dSAndroid Build Coastguard Worker 
638*7304104dSAndroid Build Coastguard Worker   GElf_Shdr shdr_mem;
639*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
640*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
641*7304104dSAndroid Build Coastguard Worker   if (shdr->sh_entsize == 0)
642*7304104dSAndroid Build Coastguard Worker     error_exit (0, "Symbol table section cannot have zero sh_entsize");
643*7304104dSAndroid Build Coastguard Worker 
644*7304104dSAndroid Build Coastguard Worker   const size_t nsym = shdr->sh_size / shdr->sh_entsize;
645*7304104dSAndroid Build Coastguard Worker   size_t symndx_map[nsym - 1];
646*7304104dSAndroid Build Coastguard Worker 
647*7304104dSAndroid Build Coastguard Worker   shdr->sh_info += added;
648*7304104dSAndroid Build Coastguard Worker   shdr->sh_size += added * shdr->sh_entsize;
649*7304104dSAndroid Build Coastguard Worker   update_shdr (symscn, shdr);
650*7304104dSAndroid Build Coastguard Worker 
651*7304104dSAndroid Build Coastguard Worker   Elf_Data *symdata = elf_getdata (symscn, NULL);
652*7304104dSAndroid Build Coastguard Worker   Elf_Data *shndxdata = NULL;	/* XXX */
653*7304104dSAndroid Build Coastguard Worker 
654*7304104dSAndroid Build Coastguard Worker   symdata->d_size = shdr->sh_size;
655*7304104dSAndroid Build Coastguard Worker   symdata->d_buf = xmalloc (symdata->d_size);
656*7304104dSAndroid Build Coastguard Worker   record_new_data (symdata->d_buf);
657*7304104dSAndroid Build Coastguard Worker 
658*7304104dSAndroid Build Coastguard Worker   /* Copy the existing section symbols.  */
659*7304104dSAndroid Build Coastguard Worker   Elf_Data *old_symdata = elf_getdata (old_symscn, NULL);
660*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < old_shnum; ++i)
661*7304104dSAndroid Build Coastguard Worker     {
662*7304104dSAndroid Build Coastguard Worker       GElf_Sym sym_mem;
663*7304104dSAndroid Build Coastguard Worker       GElf_Word shndx = SHN_UNDEF;
664*7304104dSAndroid Build Coastguard Worker       GElf_Sym *sym = gelf_getsymshndx (old_symdata, shndxdata,
665*7304104dSAndroid Build Coastguard Worker 					i, &sym_mem, &shndx);
666*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
667*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, i,
668*7304104dSAndroid Build Coastguard Worker 				       sym, shndx),
669*7304104dSAndroid Build Coastguard Worker 		 _("cannot update symbol table: %s"));
670*7304104dSAndroid Build Coastguard Worker 
671*7304104dSAndroid Build Coastguard Worker       if (i > 0)
672*7304104dSAndroid Build Coastguard Worker 	symndx_map[i - 1] = i;
673*7304104dSAndroid Build Coastguard Worker     }
674*7304104dSAndroid Build Coastguard Worker 
675*7304104dSAndroid Build Coastguard Worker   /* Add in the new section symbols.  */
676*7304104dSAndroid Build Coastguard Worker   for (size_t i = old_shnum; i < shnum; ++i)
677*7304104dSAndroid Build Coastguard Worker     {
678*7304104dSAndroid Build Coastguard Worker       GElf_Shdr i_shdr_mem;
679*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *i_shdr = gelf_getshdr (elf_getscn (elf, i), &i_shdr_mem);
680*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (i_shdr != NULL, _("cannot get section header: %s"));
681*7304104dSAndroid Build Coastguard Worker       GElf_Sym sym =
682*7304104dSAndroid Build Coastguard Worker 	{
683*7304104dSAndroid Build Coastguard Worker 	  .st_value = rel ? 0 : i_shdr->sh_addr,
684*7304104dSAndroid Build Coastguard Worker 	  .st_info = GELF_ST_INFO (STB_LOCAL, STT_SECTION),
685*7304104dSAndroid Build Coastguard Worker 	  .st_shndx = i < SHN_LORESERVE ? i : SHN_XINDEX
686*7304104dSAndroid Build Coastguard Worker 	};
687*7304104dSAndroid Build Coastguard Worker       GElf_Word shndx = i < SHN_LORESERVE ? SHN_UNDEF : i;
688*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, i,
689*7304104dSAndroid Build Coastguard Worker 				       &sym, shndx),
690*7304104dSAndroid Build Coastguard Worker 		 _("cannot update symbol table: %s"));
691*7304104dSAndroid Build Coastguard Worker     }
692*7304104dSAndroid Build Coastguard Worker 
693*7304104dSAndroid Build Coastguard Worker   /* Now copy the rest of the existing symbols.  */
694*7304104dSAndroid Build Coastguard Worker   for (size_t i = old_shnum; i < nsym; ++i)
695*7304104dSAndroid Build Coastguard Worker     {
696*7304104dSAndroid Build Coastguard Worker       GElf_Sym sym_mem;
697*7304104dSAndroid Build Coastguard Worker       GElf_Word shndx = SHN_UNDEF;
698*7304104dSAndroid Build Coastguard Worker       GElf_Sym *sym = gelf_getsymshndx (old_symdata, shndxdata,
699*7304104dSAndroid Build Coastguard Worker 					i, &sym_mem, &shndx);
700*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
701*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_update_symshndx (symdata, shndxdata,
702*7304104dSAndroid Build Coastguard Worker 				       i + added, sym, shndx),
703*7304104dSAndroid Build Coastguard Worker 		 _("cannot update symbol table: %s"));
704*7304104dSAndroid Build Coastguard Worker 
705*7304104dSAndroid Build Coastguard Worker       symndx_map[i - 1] = i + added;
706*7304104dSAndroid Build Coastguard Worker     }
707*7304104dSAndroid Build Coastguard Worker 
708*7304104dSAndroid Build Coastguard Worker   /* Adjust any relocations referring to the old symbol table.  */
709*7304104dSAndroid Build Coastguard Worker   adjust_all_relocs (elf, symscn, shdr, symndx_map, nsym - 1, NULL);
710*7304104dSAndroid Build Coastguard Worker 
711*7304104dSAndroid Build Coastguard Worker   return symdata;
712*7304104dSAndroid Build Coastguard Worker }
713*7304104dSAndroid Build Coastguard Worker 
714*7304104dSAndroid Build Coastguard Worker /* This has the side effect of updating STT_SECTION symbols' values,
715*7304104dSAndroid Build Coastguard Worker    in case of prelink adjustments.  */
716*7304104dSAndroid Build Coastguard Worker static Elf_Data *
check_symtab_section_symbols(Elf * elf,bool rel,Elf_Scn * scn,size_t shnum,size_t shstrndx,Elf_Scn * oscn,size_t oshnum,size_t oshstrndx,size_t debuglink)717*7304104dSAndroid Build Coastguard Worker check_symtab_section_symbols (Elf *elf, bool rel, Elf_Scn *scn,
718*7304104dSAndroid Build Coastguard Worker 			      size_t shnum, size_t shstrndx,
719*7304104dSAndroid Build Coastguard Worker 			      Elf_Scn *oscn, size_t oshnum, size_t oshstrndx,
720*7304104dSAndroid Build Coastguard Worker 			      size_t debuglink)
721*7304104dSAndroid Build Coastguard Worker {
722*7304104dSAndroid Build Coastguard Worker   size_t n = symtab_count_leading_section_symbols (elf, oscn, oshnum,
723*7304104dSAndroid Build Coastguard Worker 						   elf_getdata (scn, NULL));
724*7304104dSAndroid Build Coastguard Worker 
725*7304104dSAndroid Build Coastguard Worker   if (n == oshnum)
726*7304104dSAndroid Build Coastguard Worker     return add_new_section_symbols (oscn, n, elf, rel, scn, shnum);
727*7304104dSAndroid Build Coastguard Worker 
728*7304104dSAndroid Build Coastguard Worker   if (n == oshstrndx || (n == debuglink && n == oshstrndx - 1))
729*7304104dSAndroid Build Coastguard Worker     return add_new_section_symbols (oscn, n, elf, rel, scn, shstrndx);
730*7304104dSAndroid Build Coastguard Worker 
731*7304104dSAndroid Build Coastguard Worker   return NULL;
732*7304104dSAndroid Build Coastguard Worker }
733*7304104dSAndroid Build Coastguard Worker 
734*7304104dSAndroid Build Coastguard Worker struct section
735*7304104dSAndroid Build Coastguard Worker {
736*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn;
737*7304104dSAndroid Build Coastguard Worker   const char *name;
738*7304104dSAndroid Build Coastguard Worker   const char *sig;
739*7304104dSAndroid Build Coastguard Worker   Elf_Scn *outscn;
740*7304104dSAndroid Build Coastguard Worker   Dwelf_Strent *strent;
741*7304104dSAndroid Build Coastguard Worker   GElf_Shdr shdr;
742*7304104dSAndroid Build Coastguard Worker };
743*7304104dSAndroid Build Coastguard Worker 
744*7304104dSAndroid Build Coastguard Worker static int
compare_alloc_sections(const struct section * s1,const struct section * s2,bool rel)745*7304104dSAndroid Build Coastguard Worker compare_alloc_sections (const struct section *s1, const struct section *s2,
746*7304104dSAndroid Build Coastguard Worker 			bool rel)
747*7304104dSAndroid Build Coastguard Worker {
748*7304104dSAndroid Build Coastguard Worker   if (!rel)
749*7304104dSAndroid Build Coastguard Worker     {
750*7304104dSAndroid Build Coastguard Worker       /* Sort by address.  */
751*7304104dSAndroid Build Coastguard Worker       if (s1->shdr.sh_addr < s2->shdr.sh_addr)
752*7304104dSAndroid Build Coastguard Worker 	return -1;
753*7304104dSAndroid Build Coastguard Worker       if (s1->shdr.sh_addr > s2->shdr.sh_addr)
754*7304104dSAndroid Build Coastguard Worker 	return 1;
755*7304104dSAndroid Build Coastguard Worker     }
756*7304104dSAndroid Build Coastguard Worker 
757*7304104dSAndroid Build Coastguard Worker   /* At the same address, preserve original section order.  */
758*7304104dSAndroid Build Coastguard Worker   return (ssize_t) elf_ndxscn (s1->scn) - (ssize_t) elf_ndxscn (s2->scn);
759*7304104dSAndroid Build Coastguard Worker }
760*7304104dSAndroid Build Coastguard Worker 
761*7304104dSAndroid Build Coastguard Worker static int
compare_unalloc_sections(const GElf_Shdr * shdr1,const GElf_Shdr * shdr2,const char * name1,const char * name2,const char * sig1,const char * sig2)762*7304104dSAndroid Build Coastguard Worker compare_unalloc_sections (const GElf_Shdr *shdr1, const GElf_Shdr *shdr2,
763*7304104dSAndroid Build Coastguard Worker 			  const char *name1, const char *name2,
764*7304104dSAndroid Build Coastguard Worker 			  const char *sig1, const char *sig2)
765*7304104dSAndroid Build Coastguard Worker {
766*7304104dSAndroid Build Coastguard Worker   /* Sort by sh_flags as an arbitrary ordering.  */
767*7304104dSAndroid Build Coastguard Worker   if (shdr1->sh_flags < shdr2->sh_flags)
768*7304104dSAndroid Build Coastguard Worker     return -1;
769*7304104dSAndroid Build Coastguard Worker   if (shdr1->sh_flags > shdr2->sh_flags)
770*7304104dSAndroid Build Coastguard Worker     return 1;
771*7304104dSAndroid Build Coastguard Worker 
772*7304104dSAndroid Build Coastguard Worker   /* Sizes should be the same.  */
773*7304104dSAndroid Build Coastguard Worker   if (shdr1->sh_size < shdr2->sh_size)
774*7304104dSAndroid Build Coastguard Worker     return -1;
775*7304104dSAndroid Build Coastguard Worker   if (shdr1->sh_size > shdr2->sh_size)
776*7304104dSAndroid Build Coastguard Worker     return 1;
777*7304104dSAndroid Build Coastguard Worker 
778*7304104dSAndroid Build Coastguard Worker   /* Are they both SHT_GROUP sections? Then compare signatures.  */
779*7304104dSAndroid Build Coastguard Worker   if (sig1 != NULL && sig2 != NULL)
780*7304104dSAndroid Build Coastguard Worker     return strcmp (sig1, sig2);
781*7304104dSAndroid Build Coastguard Worker 
782*7304104dSAndroid Build Coastguard Worker   /* Sort by name as last resort.  */
783*7304104dSAndroid Build Coastguard Worker   return strcmp (name1, name2);
784*7304104dSAndroid Build Coastguard Worker }
785*7304104dSAndroid Build Coastguard Worker 
786*7304104dSAndroid Build Coastguard Worker static int
compare_sections(const void * a,const void * b,bool rel)787*7304104dSAndroid Build Coastguard Worker compare_sections (const void *a, const void *b, bool rel)
788*7304104dSAndroid Build Coastguard Worker {
789*7304104dSAndroid Build Coastguard Worker   const struct section *s1 = a;
790*7304104dSAndroid Build Coastguard Worker   const struct section *s2 = b;
791*7304104dSAndroid Build Coastguard Worker 
792*7304104dSAndroid Build Coastguard Worker   /* Sort all non-allocated sections last.  */
793*7304104dSAndroid Build Coastguard Worker   if ((s1->shdr.sh_flags ^ s2->shdr.sh_flags) & SHF_ALLOC)
794*7304104dSAndroid Build Coastguard Worker     return (s1->shdr.sh_flags & SHF_ALLOC) ? -1 : 1;
795*7304104dSAndroid Build Coastguard Worker 
796*7304104dSAndroid Build Coastguard Worker   return ((s1->shdr.sh_flags & SHF_ALLOC)
797*7304104dSAndroid Build Coastguard Worker 	  ? compare_alloc_sections (s1, s2, rel)
798*7304104dSAndroid Build Coastguard Worker 	  : compare_unalloc_sections (&s1->shdr, &s2->shdr,
799*7304104dSAndroid Build Coastguard Worker 				      s1->name, s2->name,
800*7304104dSAndroid Build Coastguard Worker 				      s1->sig, s2->sig));
801*7304104dSAndroid Build Coastguard Worker }
802*7304104dSAndroid Build Coastguard Worker 
803*7304104dSAndroid Build Coastguard Worker static int
compare_sections_rel(const void * a,const void * b)804*7304104dSAndroid Build Coastguard Worker compare_sections_rel (const void *a, const void *b)
805*7304104dSAndroid Build Coastguard Worker {
806*7304104dSAndroid Build Coastguard Worker   return compare_sections (a, b, true);
807*7304104dSAndroid Build Coastguard Worker }
808*7304104dSAndroid Build Coastguard Worker 
809*7304104dSAndroid Build Coastguard Worker static int
compare_sections_nonrel(const void * a,const void * b)810*7304104dSAndroid Build Coastguard Worker compare_sections_nonrel (const void *a, const void *b)
811*7304104dSAndroid Build Coastguard Worker {
812*7304104dSAndroid Build Coastguard Worker   return compare_sections (a, b, false);
813*7304104dSAndroid Build Coastguard Worker }
814*7304104dSAndroid Build Coastguard Worker 
815*7304104dSAndroid Build Coastguard Worker 
816*7304104dSAndroid Build Coastguard Worker struct symbol
817*7304104dSAndroid Build Coastguard Worker {
818*7304104dSAndroid Build Coastguard Worker   size_t *map;
819*7304104dSAndroid Build Coastguard Worker 
820*7304104dSAndroid Build Coastguard Worker   union
821*7304104dSAndroid Build Coastguard Worker   {
822*7304104dSAndroid Build Coastguard Worker     const char *name;
823*7304104dSAndroid Build Coastguard Worker     Dwelf_Strent *strent;
824*7304104dSAndroid Build Coastguard Worker   };
825*7304104dSAndroid Build Coastguard Worker   union
826*7304104dSAndroid Build Coastguard Worker   {
827*7304104dSAndroid Build Coastguard Worker     struct
828*7304104dSAndroid Build Coastguard Worker     {
829*7304104dSAndroid Build Coastguard Worker       GElf_Addr value;
830*7304104dSAndroid Build Coastguard Worker       GElf_Xword size;
831*7304104dSAndroid Build Coastguard Worker       GElf_Word shndx;
832*7304104dSAndroid Build Coastguard Worker       union
833*7304104dSAndroid Build Coastguard Worker       {
834*7304104dSAndroid Build Coastguard Worker 	struct
835*7304104dSAndroid Build Coastguard Worker 	{
836*7304104dSAndroid Build Coastguard Worker 	  uint8_t info;
837*7304104dSAndroid Build Coastguard Worker 	  uint8_t other;
838*7304104dSAndroid Build Coastguard Worker 	} info;
839*7304104dSAndroid Build Coastguard Worker 	int16_t compare;
840*7304104dSAndroid Build Coastguard Worker       };
841*7304104dSAndroid Build Coastguard Worker     };
842*7304104dSAndroid Build Coastguard Worker 
843*7304104dSAndroid Build Coastguard Worker     /* For a symbol discarded after first sort, this matches its better's
844*7304104dSAndroid Build Coastguard Worker        map pointer.  */
845*7304104dSAndroid Build Coastguard Worker     size_t *duplicate;
846*7304104dSAndroid Build Coastguard Worker   };
847*7304104dSAndroid Build Coastguard Worker };
848*7304104dSAndroid Build Coastguard Worker 
849*7304104dSAndroid Build Coastguard Worker /* Collect input symbols into our internal form.  */
850*7304104dSAndroid Build Coastguard Worker static void
collect_symbols(Elf * outelf,bool rel,Elf_Scn * symscn,Elf_Scn * strscn,const size_t nent,const GElf_Addr bias,const size_t scnmap[],struct symbol * table,size_t * map,struct section * split_bss)851*7304104dSAndroid Build Coastguard Worker collect_symbols (Elf *outelf, bool rel, Elf_Scn *symscn, Elf_Scn *strscn,
852*7304104dSAndroid Build Coastguard Worker 		 const size_t nent, const GElf_Addr bias,
853*7304104dSAndroid Build Coastguard Worker 		 const size_t scnmap[], struct symbol *table, size_t *map,
854*7304104dSAndroid Build Coastguard Worker 		 struct section *split_bss)
855*7304104dSAndroid Build Coastguard Worker {
856*7304104dSAndroid Build Coastguard Worker   Elf_Data *symdata = elf_getdata (symscn, NULL);
857*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (symdata != NULL, _("cannot get symbol section data: %s"));
858*7304104dSAndroid Build Coastguard Worker   Elf_Data *strdata = elf_getdata (strscn, NULL);
859*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (strdata != NULL, _("cannot get string section data: %s"));
860*7304104dSAndroid Build Coastguard Worker   Elf_Data *shndxdata = NULL;	/* XXX */
861*7304104dSAndroid Build Coastguard Worker 
862*7304104dSAndroid Build Coastguard Worker   for (size_t i = 1; i < nent; ++i)
863*7304104dSAndroid Build Coastguard Worker     {
864*7304104dSAndroid Build Coastguard Worker       GElf_Sym sym_mem;
865*7304104dSAndroid Build Coastguard Worker       GElf_Word shndx = SHN_UNDEF;
866*7304104dSAndroid Build Coastguard Worker       GElf_Sym *sym = gelf_getsymshndx (symdata, shndxdata, i,
867*7304104dSAndroid Build Coastguard Worker 					&sym_mem, &shndx);
868*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
869*7304104dSAndroid Build Coastguard Worker       if (sym->st_shndx != SHN_XINDEX)
870*7304104dSAndroid Build Coastguard Worker 	shndx = sym->st_shndx;
871*7304104dSAndroid Build Coastguard Worker 
872*7304104dSAndroid Build Coastguard Worker       if (sym->st_name >= strdata->d_size
873*7304104dSAndroid Build Coastguard Worker 	  || memrchr (strdata->d_buf + sym->st_name, '\0',
874*7304104dSAndroid Build Coastguard Worker 		      strdata->d_size - sym->st_name) == NULL)
875*7304104dSAndroid Build Coastguard Worker 	error_exit (0,
876*7304104dSAndroid Build Coastguard Worker 		    _("invalid string offset in symbol [%zu]"), i);
877*7304104dSAndroid Build Coastguard Worker 
878*7304104dSAndroid Build Coastguard Worker       struct symbol *s = &table[i - 1];
879*7304104dSAndroid Build Coastguard Worker       s->map = &map[i - 1];
880*7304104dSAndroid Build Coastguard Worker       s->name = strdata->d_buf + sym->st_name;
881*7304104dSAndroid Build Coastguard Worker       s->value = sym->st_value + bias;
882*7304104dSAndroid Build Coastguard Worker       s->size = sym->st_size;
883*7304104dSAndroid Build Coastguard Worker       s->shndx = shndx;
884*7304104dSAndroid Build Coastguard Worker       s->info.info = sym->st_info;
885*7304104dSAndroid Build Coastguard Worker       s->info.other = sym->st_other;
886*7304104dSAndroid Build Coastguard Worker       s->duplicate = NULL;
887*7304104dSAndroid Build Coastguard Worker 
888*7304104dSAndroid Build Coastguard Worker       if (scnmap != NULL && shndx != SHN_UNDEF && shndx < SHN_LORESERVE)
889*7304104dSAndroid Build Coastguard Worker 	s->shndx = scnmap[shndx - 1];
890*7304104dSAndroid Build Coastguard Worker 
891*7304104dSAndroid Build Coastguard Worker       if (GELF_ST_TYPE (s->info.info) == STT_SECTION && !rel)
892*7304104dSAndroid Build Coastguard Worker 	{
893*7304104dSAndroid Build Coastguard Worker 	  /* Update the value to match the output section.  */
894*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr shdr_mem;
895*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (outelf, s->shndx),
896*7304104dSAndroid Build Coastguard Worker 					  &shdr_mem);
897*7304104dSAndroid Build Coastguard Worker 	  ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
898*7304104dSAndroid Build Coastguard Worker 	  s->value = shdr->sh_addr;
899*7304104dSAndroid Build Coastguard Worker 	}
900*7304104dSAndroid Build Coastguard Worker       else if (split_bss != NULL
901*7304104dSAndroid Build Coastguard Worker 	       && s->value < split_bss->shdr.sh_addr
902*7304104dSAndroid Build Coastguard Worker 	       && s->value >= split_bss[-1].shdr.sh_addr
903*7304104dSAndroid Build Coastguard Worker 	       && shndx == elf_ndxscn (split_bss->outscn))
904*7304104dSAndroid Build Coastguard Worker 	/* This symbol was in .bss and was split into .dynbss.  */
905*7304104dSAndroid Build Coastguard Worker 	s->shndx = elf_ndxscn (split_bss[-1].outscn);
906*7304104dSAndroid Build Coastguard Worker     }
907*7304104dSAndroid Build Coastguard Worker }
908*7304104dSAndroid Build Coastguard Worker 
909*7304104dSAndroid Build Coastguard Worker 
910*7304104dSAndroid Build Coastguard Worker #define CMP(value)							      \
911*7304104dSAndroid Build Coastguard Worker   if (s1->value < s2->value)						      \
912*7304104dSAndroid Build Coastguard Worker     return -1;								      \
913*7304104dSAndroid Build Coastguard Worker   if (s1->value > s2->value)						      \
914*7304104dSAndroid Build Coastguard Worker     return 1
915*7304104dSAndroid Build Coastguard Worker 
916*7304104dSAndroid Build Coastguard Worker /* Symbol comparison used to sort symbols in preparation for deduplication.  */
917*7304104dSAndroid Build Coastguard Worker static int
compare_symbols(const void * a,const void * b)918*7304104dSAndroid Build Coastguard Worker compare_symbols (const void *a, const void *b)
919*7304104dSAndroid Build Coastguard Worker {
920*7304104dSAndroid Build Coastguard Worker   const struct symbol *s1 = a;
921*7304104dSAndroid Build Coastguard Worker   const struct symbol *s2 = b;
922*7304104dSAndroid Build Coastguard Worker 
923*7304104dSAndroid Build Coastguard Worker   CMP (value);
924*7304104dSAndroid Build Coastguard Worker   CMP (size);
925*7304104dSAndroid Build Coastguard Worker   CMP (shndx);
926*7304104dSAndroid Build Coastguard Worker 
927*7304104dSAndroid Build Coastguard Worker   int res = s1->compare - s2->compare;
928*7304104dSAndroid Build Coastguard Worker   if (res != 0)
929*7304104dSAndroid Build Coastguard Worker     return res;
930*7304104dSAndroid Build Coastguard Worker 
931*7304104dSAndroid Build Coastguard Worker   res = strcmp (s1->name, s2->name);
932*7304104dSAndroid Build Coastguard Worker   if (res != 0)
933*7304104dSAndroid Build Coastguard Worker     return res;
934*7304104dSAndroid Build Coastguard Worker 
935*7304104dSAndroid Build Coastguard Worker   /* Duplicates still have distinct positions in the symbol index map.
936*7304104dSAndroid Build Coastguard Worker      Compare map positions to ensure that duplicate symbols are ordered
937*7304104dSAndroid Build Coastguard Worker      consistently even if the sort function is unstable.  */
938*7304104dSAndroid Build Coastguard Worker   CMP (map);
939*7304104dSAndroid Build Coastguard Worker   error_exit (0, _("found two identical index map positions."));
940*7304104dSAndroid Build Coastguard Worker }
941*7304104dSAndroid Build Coastguard Worker 
942*7304104dSAndroid Build Coastguard Worker /* Symbol comparison used to deduplicate symbols found in both the stripped
943*7304104dSAndroid Build Coastguard Worker    and unstripped input files.
944*7304104dSAndroid Build Coastguard Worker 
945*7304104dSAndroid Build Coastguard Worker    Similar to compare_symbols, but does not differentiate symbols based
946*7304104dSAndroid Build Coastguard Worker    on their position in the symbol index map.  Duplicates can't be found
947*7304104dSAndroid Build Coastguard Worker    by comparing index map postions because they always have distinct
948*7304104dSAndroid Build Coastguard Worker    positions in the map.  */
949*7304104dSAndroid Build Coastguard Worker static int
compare_symbols_duplicate(const void * a,const void * b)950*7304104dSAndroid Build Coastguard Worker compare_symbols_duplicate (const void *a, const void *b)
951*7304104dSAndroid Build Coastguard Worker {
952*7304104dSAndroid Build Coastguard Worker   const struct symbol *s1 = a;
953*7304104dSAndroid Build Coastguard Worker   const struct symbol *s2 = b;
954*7304104dSAndroid Build Coastguard Worker 
955*7304104dSAndroid Build Coastguard Worker   CMP (value);
956*7304104dSAndroid Build Coastguard Worker   CMP (size);
957*7304104dSAndroid Build Coastguard Worker   CMP (shndx);
958*7304104dSAndroid Build Coastguard Worker 
959*7304104dSAndroid Build Coastguard Worker   return (s1->compare - s2->compare) ?: strcmp (s1->name, s2->name);
960*7304104dSAndroid Build Coastguard Worker }
961*7304104dSAndroid Build Coastguard Worker 
962*7304104dSAndroid Build Coastguard Worker /* Compare symbols for output order after slots have been assigned.  */
963*7304104dSAndroid Build Coastguard Worker static int
compare_symbols_output(const void * a,const void * b)964*7304104dSAndroid Build Coastguard Worker compare_symbols_output (const void *a, const void *b)
965*7304104dSAndroid Build Coastguard Worker {
966*7304104dSAndroid Build Coastguard Worker   const struct symbol *s1 = a;
967*7304104dSAndroid Build Coastguard Worker   const struct symbol *s2 = b;
968*7304104dSAndroid Build Coastguard Worker   int cmp;
969*7304104dSAndroid Build Coastguard Worker 
970*7304104dSAndroid Build Coastguard Worker   /* Sort discarded symbols last.  */
971*7304104dSAndroid Build Coastguard Worker   cmp = (s1->name == NULL) - (s2->name == NULL);
972*7304104dSAndroid Build Coastguard Worker 
973*7304104dSAndroid Build Coastguard Worker   if (cmp == 0)
974*7304104dSAndroid Build Coastguard Worker     /* Local symbols must come first.  */
975*7304104dSAndroid Build Coastguard Worker     cmp = ((GELF_ST_BIND (s2->info.info) == STB_LOCAL)
976*7304104dSAndroid Build Coastguard Worker 	   - (GELF_ST_BIND (s1->info.info) == STB_LOCAL));
977*7304104dSAndroid Build Coastguard Worker 
978*7304104dSAndroid Build Coastguard Worker   if (cmp == 0)
979*7304104dSAndroid Build Coastguard Worker     /* binutils always puts section symbols first.  */
980*7304104dSAndroid Build Coastguard Worker     cmp = ((GELF_ST_TYPE (s2->info.info) == STT_SECTION)
981*7304104dSAndroid Build Coastguard Worker 	   - (GELF_ST_TYPE (s1->info.info) == STT_SECTION));
982*7304104dSAndroid Build Coastguard Worker 
983*7304104dSAndroid Build Coastguard Worker   if (cmp == 0)
984*7304104dSAndroid Build Coastguard Worker     {
985*7304104dSAndroid Build Coastguard Worker       if (GELF_ST_TYPE (s1->info.info) == STT_SECTION)
986*7304104dSAndroid Build Coastguard Worker 	{
987*7304104dSAndroid Build Coastguard Worker 	  /* binutils always puts section symbols in section index order.  */
988*7304104dSAndroid Build Coastguard Worker 	  CMP (shndx);
989*7304104dSAndroid Build Coastguard Worker 	  else if (s1 != s2)
990*7304104dSAndroid Build Coastguard Worker 	    error_exit (0, _("section symbols in unexpected order"));
991*7304104dSAndroid Build Coastguard Worker 	}
992*7304104dSAndroid Build Coastguard Worker 
993*7304104dSAndroid Build Coastguard Worker       /* Nothing really matters, so preserve the original order.  */
994*7304104dSAndroid Build Coastguard Worker       CMP (map);
995*7304104dSAndroid Build Coastguard Worker       else if (s1 != s2)
996*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("found two identical symbols"));
997*7304104dSAndroid Build Coastguard Worker     }
998*7304104dSAndroid Build Coastguard Worker 
999*7304104dSAndroid Build Coastguard Worker   return cmp;
1000*7304104dSAndroid Build Coastguard Worker }
1001*7304104dSAndroid Build Coastguard Worker 
1002*7304104dSAndroid Build Coastguard Worker #undef CMP
1003*7304104dSAndroid Build Coastguard Worker 
1004*7304104dSAndroid Build Coastguard Worker /* Return true if the flags of the sections match, ignoring the SHF_INFO_LINK
1005*7304104dSAndroid Build Coastguard Worker    flag if the section contains relocation information.  */
1006*7304104dSAndroid Build Coastguard Worker static bool
sections_flags_match(Elf64_Xword sh_flags1,Elf64_Xword sh_flags2,Elf64_Word sh_type)1007*7304104dSAndroid Build Coastguard Worker sections_flags_match (Elf64_Xword sh_flags1, Elf64_Xword sh_flags2,
1008*7304104dSAndroid Build Coastguard Worker 		      Elf64_Word sh_type)
1009*7304104dSAndroid Build Coastguard Worker {
1010*7304104dSAndroid Build Coastguard Worker   if (sh_type == SHT_REL || sh_type == SHT_RELA)
1011*7304104dSAndroid Build Coastguard Worker     {
1012*7304104dSAndroid Build Coastguard Worker       sh_flags1 &= ~SHF_INFO_LINK;
1013*7304104dSAndroid Build Coastguard Worker       sh_flags2 &= ~SHF_INFO_LINK;
1014*7304104dSAndroid Build Coastguard Worker     }
1015*7304104dSAndroid Build Coastguard Worker 
1016*7304104dSAndroid Build Coastguard Worker   return sh_flags1 == sh_flags2;
1017*7304104dSAndroid Build Coastguard Worker }
1018*7304104dSAndroid Build Coastguard Worker 
1019*7304104dSAndroid Build Coastguard Worker /* Return true iff the flags, size, and name match.  */
1020*7304104dSAndroid Build Coastguard Worker static bool
sections_match(const struct section * sections,size_t i,const GElf_Shdr * shdr,const char * name)1021*7304104dSAndroid Build Coastguard Worker sections_match (const struct section *sections, size_t i,
1022*7304104dSAndroid Build Coastguard Worker 		const GElf_Shdr *shdr, const char *name)
1023*7304104dSAndroid Build Coastguard Worker {
1024*7304104dSAndroid Build Coastguard Worker   return (sections_flags_match (sections[i].shdr.sh_flags, shdr->sh_flags,
1025*7304104dSAndroid Build Coastguard Worker 				sections[i].shdr.sh_type)
1026*7304104dSAndroid Build Coastguard Worker 	  && (sections[i].shdr.sh_size == shdr->sh_size
1027*7304104dSAndroid Build Coastguard Worker 	      || (sections[i].shdr.sh_size < shdr->sh_size
1028*7304104dSAndroid Build Coastguard Worker 		  && section_can_shrink (&sections[i].shdr)))
1029*7304104dSAndroid Build Coastguard Worker 	  && !strcmp (sections[i].name, name));
1030*7304104dSAndroid Build Coastguard Worker }
1031*7304104dSAndroid Build Coastguard Worker 
1032*7304104dSAndroid Build Coastguard Worker /* Locate a matching allocated section in SECTIONS.  */
1033*7304104dSAndroid Build Coastguard Worker static struct section *
find_alloc_section(const GElf_Shdr * shdr,GElf_Addr bias,const char * name,struct section sections[],size_t nalloc)1034*7304104dSAndroid Build Coastguard Worker find_alloc_section (const GElf_Shdr *shdr, GElf_Addr bias, const char *name,
1035*7304104dSAndroid Build Coastguard Worker 		    struct section sections[], size_t nalloc)
1036*7304104dSAndroid Build Coastguard Worker {
1037*7304104dSAndroid Build Coastguard Worker   const GElf_Addr addr = shdr->sh_addr + bias;
1038*7304104dSAndroid Build Coastguard Worker   size_t l = 0, u = nalloc;
1039*7304104dSAndroid Build Coastguard Worker   while (l < u)
1040*7304104dSAndroid Build Coastguard Worker     {
1041*7304104dSAndroid Build Coastguard Worker       size_t i = (l + u) / 2;
1042*7304104dSAndroid Build Coastguard Worker       if (addr < sections[i].shdr.sh_addr)
1043*7304104dSAndroid Build Coastguard Worker 	u = i;
1044*7304104dSAndroid Build Coastguard Worker       else if (addr > sections[i].shdr.sh_addr)
1045*7304104dSAndroid Build Coastguard Worker 	l = i + 1;
1046*7304104dSAndroid Build Coastguard Worker       else
1047*7304104dSAndroid Build Coastguard Worker 	{
1048*7304104dSAndroid Build Coastguard Worker 	  /* We've found allocated sections with this address.
1049*7304104dSAndroid Build Coastguard Worker 	     Find one with matching size, flags, and name.  */
1050*7304104dSAndroid Build Coastguard Worker 	  while (i > 0 && sections[i - 1].shdr.sh_addr == addr)
1051*7304104dSAndroid Build Coastguard Worker 	    --i;
1052*7304104dSAndroid Build Coastguard Worker 	  for (; i < nalloc && sections[i].shdr.sh_addr == addr;
1053*7304104dSAndroid Build Coastguard Worker 	       ++i)
1054*7304104dSAndroid Build Coastguard Worker 	    if (sections_match (sections, i, shdr, name))
1055*7304104dSAndroid Build Coastguard Worker 	      return &sections[i];
1056*7304104dSAndroid Build Coastguard Worker 	  break;
1057*7304104dSAndroid Build Coastguard Worker 	}
1058*7304104dSAndroid Build Coastguard Worker     }
1059*7304104dSAndroid Build Coastguard Worker   return NULL;
1060*7304104dSAndroid Build Coastguard Worker }
1061*7304104dSAndroid Build Coastguard Worker 
1062*7304104dSAndroid Build Coastguard Worker static inline const char *
get_section_name(size_t ndx,const GElf_Shdr * shdr,const Elf_Data * shstrtab)1063*7304104dSAndroid Build Coastguard Worker get_section_name (size_t ndx, const GElf_Shdr *shdr, const Elf_Data *shstrtab)
1064*7304104dSAndroid Build Coastguard Worker {
1065*7304104dSAndroid Build Coastguard Worker   if (shdr->sh_name >= shstrtab->d_size)
1066*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot read section [%zu] name: %s"),
1067*7304104dSAndroid Build Coastguard Worker 		ndx, elf_errmsg (-1));
1068*7304104dSAndroid Build Coastguard Worker   return shstrtab->d_buf + shdr->sh_name;
1069*7304104dSAndroid Build Coastguard Worker }
1070*7304104dSAndroid Build Coastguard Worker 
1071*7304104dSAndroid Build Coastguard Worker /* Returns the signature of a group section, or NULL if the given
1072*7304104dSAndroid Build Coastguard Worker    section isn't a group.  */
1073*7304104dSAndroid Build Coastguard Worker static const char *
get_group_sig(Elf * elf,GElf_Shdr * shdr)1074*7304104dSAndroid Build Coastguard Worker get_group_sig (Elf *elf, GElf_Shdr *shdr)
1075*7304104dSAndroid Build Coastguard Worker {
1076*7304104dSAndroid Build Coastguard Worker   if (shdr->sh_type != SHT_GROUP)
1077*7304104dSAndroid Build Coastguard Worker     return NULL;
1078*7304104dSAndroid Build Coastguard Worker 
1079*7304104dSAndroid Build Coastguard Worker   Elf_Scn *symscn = elf_getscn (elf, shdr->sh_link);
1080*7304104dSAndroid Build Coastguard Worker   if (symscn == NULL)
1081*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("bad sh_link for group section: %s"),
1082*7304104dSAndroid Build Coastguard Worker 		elf_errmsg (-1));
1083*7304104dSAndroid Build Coastguard Worker 
1084*7304104dSAndroid Build Coastguard Worker   GElf_Shdr symshdr_mem;
1085*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1086*7304104dSAndroid Build Coastguard Worker   if (symshdr == NULL)
1087*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("couldn't get shdr for group section: %s"),
1088*7304104dSAndroid Build Coastguard Worker 		elf_errmsg (-1));
1089*7304104dSAndroid Build Coastguard Worker 
1090*7304104dSAndroid Build Coastguard Worker   Elf_Data *symdata = elf_getdata (symscn, NULL);
1091*7304104dSAndroid Build Coastguard Worker   if (symdata == NULL)
1092*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("bad data for group symbol section: %s"),
1093*7304104dSAndroid Build Coastguard Worker 		elf_errmsg (-1));
1094*7304104dSAndroid Build Coastguard Worker 
1095*7304104dSAndroid Build Coastguard Worker   GElf_Sym sym_mem;
1096*7304104dSAndroid Build Coastguard Worker   GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
1097*7304104dSAndroid Build Coastguard Worker   if (sym == NULL)
1098*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("couldn't get symbol for group section: %s"),
1099*7304104dSAndroid Build Coastguard Worker 		elf_errmsg (-1));
1100*7304104dSAndroid Build Coastguard Worker 
1101*7304104dSAndroid Build Coastguard Worker   const char *sig = elf_strptr (elf, symshdr->sh_link, sym->st_name);
1102*7304104dSAndroid Build Coastguard Worker   if (sig == NULL)
1103*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("bad symbol name for group section: %s"),
1104*7304104dSAndroid Build Coastguard Worker 		elf_errmsg (-1));
1105*7304104dSAndroid Build Coastguard Worker 
1106*7304104dSAndroid Build Coastguard Worker   return sig;
1107*7304104dSAndroid Build Coastguard Worker }
1108*7304104dSAndroid Build Coastguard Worker 
1109*7304104dSAndroid Build Coastguard Worker static inline bool
check_match(bool match,Elf_Scn * scn,const char * name)1110*7304104dSAndroid Build Coastguard Worker check_match (bool match, Elf_Scn *scn, const char *name)
1111*7304104dSAndroid Build Coastguard Worker {
1112*7304104dSAndroid Build Coastguard Worker   if (!match)
1113*7304104dSAndroid Build Coastguard Worker     {
1114*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot find matching section for [%zu] '%s'"),
1115*7304104dSAndroid Build Coastguard Worker 	     elf_ndxscn (scn), name);
1116*7304104dSAndroid Build Coastguard Worker       return true;
1117*7304104dSAndroid Build Coastguard Worker     }
1118*7304104dSAndroid Build Coastguard Worker 
1119*7304104dSAndroid Build Coastguard Worker   return false;
1120*7304104dSAndroid Build Coastguard Worker }
1121*7304104dSAndroid Build Coastguard Worker 
1122*7304104dSAndroid Build Coastguard Worker 
1123*7304104dSAndroid Build Coastguard Worker /* Fix things up when prelink has moved some allocated sections around
1124*7304104dSAndroid Build Coastguard Worker    and the debuginfo file's section headers no longer match up.
1125*7304104dSAndroid Build Coastguard Worker    This fills in SECTIONS[0..NALLOC-1].outscn or exits.
1126*7304104dSAndroid Build Coastguard Worker    If there was a .bss section that was split into two sections
1127*7304104dSAndroid Build Coastguard Worker    with the new one preceding it in sh_addr, we return that pointer.  */
1128*7304104dSAndroid Build Coastguard Worker static struct section *
find_alloc_sections_prelink(Elf * debug,Elf_Data * debug_shstrtab,Elf * main,const GElf_Ehdr * main_ehdr,Elf_Data * main_shstrtab,GElf_Addr bias,struct section * sections,size_t nalloc,size_t nsections)1129*7304104dSAndroid Build Coastguard Worker find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
1130*7304104dSAndroid Build Coastguard Worker 			     Elf *main, const GElf_Ehdr *main_ehdr,
1131*7304104dSAndroid Build Coastguard Worker 			     Elf_Data *main_shstrtab, GElf_Addr bias,
1132*7304104dSAndroid Build Coastguard Worker 			     struct section *sections,
1133*7304104dSAndroid Build Coastguard Worker 			     size_t nalloc, size_t nsections)
1134*7304104dSAndroid Build Coastguard Worker {
1135*7304104dSAndroid Build Coastguard Worker   Elf_Scn *undo = NULL;
1136*7304104dSAndroid Build Coastguard Worker   for (size_t i = nalloc; i < nsections; ++i)
1137*7304104dSAndroid Build Coastguard Worker     {
1138*7304104dSAndroid Build Coastguard Worker       const struct section *sec = &sections[i];
1139*7304104dSAndroid Build Coastguard Worker       if (sec->shdr.sh_type == SHT_PROGBITS
1140*7304104dSAndroid Build Coastguard Worker 	  && !(sec->shdr.sh_flags & SHF_ALLOC)
1141*7304104dSAndroid Build Coastguard Worker 	  && !strcmp (sec->name, ".gnu.prelink_undo"))
1142*7304104dSAndroid Build Coastguard Worker 	{
1143*7304104dSAndroid Build Coastguard Worker 	  undo = sec->scn;
1144*7304104dSAndroid Build Coastguard Worker 	  break;
1145*7304104dSAndroid Build Coastguard Worker 	}
1146*7304104dSAndroid Build Coastguard Worker     }
1147*7304104dSAndroid Build Coastguard Worker 
1148*7304104dSAndroid Build Coastguard Worker   /* Find the original allocated sections before prelinking.  */
1149*7304104dSAndroid Build Coastguard Worker   struct section *undo_sections = NULL;
1150*7304104dSAndroid Build Coastguard Worker   size_t undo_nalloc = 0;
1151*7304104dSAndroid Build Coastguard Worker   if (undo != NULL)
1152*7304104dSAndroid Build Coastguard Worker     {
1153*7304104dSAndroid Build Coastguard Worker       /* Clear assignments that might have been bogus.  */
1154*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < nalloc; ++i)
1155*7304104dSAndroid Build Coastguard Worker 	sections[i].outscn = NULL;
1156*7304104dSAndroid Build Coastguard Worker 
1157*7304104dSAndroid Build Coastguard Worker       Elf_Data *undodata = elf_rawdata (undo, NULL);
1158*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (undodata != NULL,
1159*7304104dSAndroid Build Coastguard Worker 		 _("cannot read '.gnu.prelink_undo' section: %s"));
1160*7304104dSAndroid Build Coastguard Worker 
1161*7304104dSAndroid Build Coastguard Worker       union
1162*7304104dSAndroid Build Coastguard Worker       {
1163*7304104dSAndroid Build Coastguard Worker 	Elf32_Ehdr e32;
1164*7304104dSAndroid Build Coastguard Worker 	Elf64_Ehdr e64;
1165*7304104dSAndroid Build Coastguard Worker       } ehdr;
1166*7304104dSAndroid Build Coastguard Worker       Elf_Data dst =
1167*7304104dSAndroid Build Coastguard Worker 	{
1168*7304104dSAndroid Build Coastguard Worker 	  .d_buf = &ehdr,
1169*7304104dSAndroid Build Coastguard Worker 	  .d_size = sizeof ehdr,
1170*7304104dSAndroid Build Coastguard Worker 	  .d_type = ELF_T_EHDR,
1171*7304104dSAndroid Build Coastguard Worker 	  .d_version = EV_CURRENT
1172*7304104dSAndroid Build Coastguard Worker 	};
1173*7304104dSAndroid Build Coastguard Worker       Elf_Data src = *undodata;
1174*7304104dSAndroid Build Coastguard Worker       src.d_size = gelf_fsize (main, ELF_T_EHDR, 1, EV_CURRENT);
1175*7304104dSAndroid Build Coastguard Worker       src.d_type = ELF_T_EHDR;
1176*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_xlatetom (main, &dst, &src,
1177*7304104dSAndroid Build Coastguard Worker 				main_ehdr->e_ident[EI_DATA]) != NULL,
1178*7304104dSAndroid Build Coastguard Worker 		 _("cannot read '.gnu.prelink_undo' section: %s"));
1179*7304104dSAndroid Build Coastguard Worker 
1180*7304104dSAndroid Build Coastguard Worker       uint_fast16_t phnum;
1181*7304104dSAndroid Build Coastguard Worker       uint_fast16_t shnum;  /* prelink doesn't handle > SHN_LORESERVE.  */
1182*7304104dSAndroid Build Coastguard Worker       if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
1183*7304104dSAndroid Build Coastguard Worker 	{
1184*7304104dSAndroid Build Coastguard Worker 	  phnum = ehdr.e32.e_phnum;
1185*7304104dSAndroid Build Coastguard Worker 	  shnum = ehdr.e32.e_shnum;
1186*7304104dSAndroid Build Coastguard Worker 	}
1187*7304104dSAndroid Build Coastguard Worker       else
1188*7304104dSAndroid Build Coastguard Worker 	{
1189*7304104dSAndroid Build Coastguard Worker 	  phnum = ehdr.e64.e_phnum;
1190*7304104dSAndroid Build Coastguard Worker 	  shnum = ehdr.e64.e_shnum;
1191*7304104dSAndroid Build Coastguard Worker 	}
1192*7304104dSAndroid Build Coastguard Worker 
1193*7304104dSAndroid Build Coastguard Worker       bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
1194*7304104dSAndroid Build Coastguard Worker       size_t shsize = class32 ? sizeof (Elf32_Shdr) : sizeof (Elf64_Shdr);
1195*7304104dSAndroid Build Coastguard Worker       if (unlikely (shnum == 0 || shnum > SIZE_MAX / shsize + 1))
1196*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("overflow with shnum = %zu in '%s' section"),
1197*7304104dSAndroid Build Coastguard Worker 		    (size_t) shnum, ".gnu.prelink_undo");
1198*7304104dSAndroid Build Coastguard Worker 
1199*7304104dSAndroid Build Coastguard Worker       --shnum;
1200*7304104dSAndroid Build Coastguard Worker 
1201*7304104dSAndroid Build Coastguard Worker       size_t phsize = gelf_fsize (main, ELF_T_PHDR, phnum, EV_CURRENT);
1202*7304104dSAndroid Build Coastguard Worker       src.d_buf += src.d_size + phsize;
1203*7304104dSAndroid Build Coastguard Worker       src.d_size = gelf_fsize (main, ELF_T_SHDR, shnum, EV_CURRENT);
1204*7304104dSAndroid Build Coastguard Worker       src.d_type = ELF_T_SHDR;
1205*7304104dSAndroid Build Coastguard Worker       if ((size_t) (src.d_buf - undodata->d_buf) > undodata->d_size
1206*7304104dSAndroid Build Coastguard Worker 	  || undodata->d_size - (src.d_buf - undodata->d_buf) != src.d_size)
1207*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("invalid contents in '%s' section"),
1208*7304104dSAndroid Build Coastguard Worker 		    ".gnu.prelink_undo");
1209*7304104dSAndroid Build Coastguard Worker 
1210*7304104dSAndroid Build Coastguard Worker       const size_t shdr_bytes = shnum * shsize;
1211*7304104dSAndroid Build Coastguard Worker       void *shdr = xmalloc (shdr_bytes);
1212*7304104dSAndroid Build Coastguard Worker       dst.d_buf = shdr;
1213*7304104dSAndroid Build Coastguard Worker       dst.d_size = shdr_bytes;
1214*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_xlatetom (main, &dst, &src,
1215*7304104dSAndroid Build Coastguard Worker 				main_ehdr->e_ident[EI_DATA]) != NULL,
1216*7304104dSAndroid Build Coastguard Worker 		 _("cannot read '.gnu.prelink_undo' section: %s"));
1217*7304104dSAndroid Build Coastguard Worker 
1218*7304104dSAndroid Build Coastguard Worker       undo_sections = xmalloc (shnum * sizeof undo_sections[0]);
1219*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < shnum; ++i)
1220*7304104dSAndroid Build Coastguard Worker 	{
1221*7304104dSAndroid Build Coastguard Worker 	  struct section *sec = &undo_sections[undo_nalloc];
1222*7304104dSAndroid Build Coastguard Worker 	  Elf32_Shdr (*s32)[shnum] = shdr;
1223*7304104dSAndroid Build Coastguard Worker 	  Elf64_Shdr (*s64)[shnum] = shdr;
1224*7304104dSAndroid Build Coastguard Worker 	  if (class32)
1225*7304104dSAndroid Build Coastguard Worker 	    {
1226*7304104dSAndroid Build Coastguard Worker #define COPY(field) sec->shdr.field = (*s32)[i].field
1227*7304104dSAndroid Build Coastguard Worker 	      COPY (sh_name);
1228*7304104dSAndroid Build Coastguard Worker 	      COPY (sh_type);
1229*7304104dSAndroid Build Coastguard Worker 	      COPY (sh_flags);
1230*7304104dSAndroid Build Coastguard Worker 	      COPY (sh_addr);
1231*7304104dSAndroid Build Coastguard Worker 	      COPY (sh_offset);
1232*7304104dSAndroid Build Coastguard Worker 	      COPY (sh_size);
1233*7304104dSAndroid Build Coastguard Worker 	      COPY (sh_link);
1234*7304104dSAndroid Build Coastguard Worker 	      COPY (sh_info);
1235*7304104dSAndroid Build Coastguard Worker 	      COPY (sh_addralign);
1236*7304104dSAndroid Build Coastguard Worker 	      COPY (sh_entsize);
1237*7304104dSAndroid Build Coastguard Worker #undef	COPY
1238*7304104dSAndroid Build Coastguard Worker 	    }
1239*7304104dSAndroid Build Coastguard Worker 	  else
1240*7304104dSAndroid Build Coastguard Worker 	    sec->shdr = (*s64)[i];
1241*7304104dSAndroid Build Coastguard Worker 	  if (sec->shdr.sh_flags & SHF_ALLOC)
1242*7304104dSAndroid Build Coastguard Worker 	    {
1243*7304104dSAndroid Build Coastguard Worker 	      sec->shdr.sh_addr += bias;
1244*7304104dSAndroid Build Coastguard Worker 	      sec->name = get_section_name (i + 1, &sec->shdr, main_shstrtab);
1245*7304104dSAndroid Build Coastguard Worker 	      sec->scn = elf_getscn (main, i + 1); /* Really just for ndx.  */
1246*7304104dSAndroid Build Coastguard Worker 	      sec->outscn = NULL;
1247*7304104dSAndroid Build Coastguard Worker 	      sec->strent = NULL;
1248*7304104dSAndroid Build Coastguard Worker 	      sec->sig = get_group_sig (main, &sec->shdr);
1249*7304104dSAndroid Build Coastguard Worker 	      ++undo_nalloc;
1250*7304104dSAndroid Build Coastguard Worker 	    }
1251*7304104dSAndroid Build Coastguard Worker 	}
1252*7304104dSAndroid Build Coastguard Worker       qsort (undo_sections, undo_nalloc,
1253*7304104dSAndroid Build Coastguard Worker 	     sizeof undo_sections[0], compare_sections_nonrel);
1254*7304104dSAndroid Build Coastguard Worker       free (shdr);
1255*7304104dSAndroid Build Coastguard Worker     }
1256*7304104dSAndroid Build Coastguard Worker 
1257*7304104dSAndroid Build Coastguard Worker   bool fail = false;
1258*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
1259*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (debug, scn)) != NULL)
1260*7304104dSAndroid Build Coastguard Worker     {
1261*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
1262*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1263*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1264*7304104dSAndroid Build Coastguard Worker 
1265*7304104dSAndroid Build Coastguard Worker       if (!(shdr->sh_flags & SHF_ALLOC))
1266*7304104dSAndroid Build Coastguard Worker 	continue;
1267*7304104dSAndroid Build Coastguard Worker 
1268*7304104dSAndroid Build Coastguard Worker       const char *name = get_section_name (elf_ndxscn (scn), shdr,
1269*7304104dSAndroid Build Coastguard Worker 					   debug_shstrtab);
1270*7304104dSAndroid Build Coastguard Worker 
1271*7304104dSAndroid Build Coastguard Worker       if (undo_sections != NULL)
1272*7304104dSAndroid Build Coastguard Worker 	{
1273*7304104dSAndroid Build Coastguard Worker 	  struct section *sec = find_alloc_section (shdr, 0, name,
1274*7304104dSAndroid Build Coastguard Worker 						    undo_sections,
1275*7304104dSAndroid Build Coastguard Worker 						    undo_nalloc);
1276*7304104dSAndroid Build Coastguard Worker 	  if (sec != NULL)
1277*7304104dSAndroid Build Coastguard Worker 	    {
1278*7304104dSAndroid Build Coastguard Worker 	      sec->outscn = scn;
1279*7304104dSAndroid Build Coastguard Worker 	      continue;
1280*7304104dSAndroid Build Coastguard Worker 	    }
1281*7304104dSAndroid Build Coastguard Worker 	}
1282*7304104dSAndroid Build Coastguard Worker 
1283*7304104dSAndroid Build Coastguard Worker       /* If there is no prelink info, we are just here to find
1284*7304104dSAndroid Build Coastguard Worker 	 the sections to give error messages about.  */
1285*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; shdr != NULL && i < nalloc; ++i)
1286*7304104dSAndroid Build Coastguard Worker 	if (sections[i].outscn == scn)
1287*7304104dSAndroid Build Coastguard Worker 	  shdr = NULL;
1288*7304104dSAndroid Build Coastguard Worker       fail |= check_match (shdr == NULL, scn, name);
1289*7304104dSAndroid Build Coastguard Worker     }
1290*7304104dSAndroid Build Coastguard Worker 
1291*7304104dSAndroid Build Coastguard Worker   if (fail)
1292*7304104dSAndroid Build Coastguard Worker     exit (EXIT_FAILURE);
1293*7304104dSAndroid Build Coastguard Worker 
1294*7304104dSAndroid Build Coastguard Worker   /* Now we have lined up output sections for each of the original sections
1295*7304104dSAndroid Build Coastguard Worker      before prelinking.  Translate those to the prelinked sections.
1296*7304104dSAndroid Build Coastguard Worker      This matches what prelink's undo_sections does.  */
1297*7304104dSAndroid Build Coastguard Worker   struct section *split_bss = NULL;
1298*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < undo_nalloc; ++i)
1299*7304104dSAndroid Build Coastguard Worker     {
1300*7304104dSAndroid Build Coastguard Worker       const struct section *undo_sec = &undo_sections[i];
1301*7304104dSAndroid Build Coastguard Worker 
1302*7304104dSAndroid Build Coastguard Worker       const char *name = undo_sec->name;
1303*7304104dSAndroid Build Coastguard Worker       scn = undo_sec->scn; /* This is just for elf_ndxscn.  */
1304*7304104dSAndroid Build Coastguard Worker 
1305*7304104dSAndroid Build Coastguard Worker       for (size_t j = 0; j < nalloc; ++j)
1306*7304104dSAndroid Build Coastguard Worker 	{
1307*7304104dSAndroid Build Coastguard Worker 	  struct section *sec = &sections[j];
1308*7304104dSAndroid Build Coastguard Worker #define RELA_SCALED(field) \
1309*7304104dSAndroid Build Coastguard Worker 	  (2 * sec->shdr.field == 3 * undo_sec->shdr.field)
1310*7304104dSAndroid Build Coastguard Worker 	  if (sec->outscn == NULL
1311*7304104dSAndroid Build Coastguard Worker 	      && sec->shdr.sh_name == undo_sec->shdr.sh_name
1312*7304104dSAndroid Build Coastguard Worker 	      && sec->shdr.sh_flags == undo_sec->shdr.sh_flags
1313*7304104dSAndroid Build Coastguard Worker 	      && sec->shdr.sh_addralign == undo_sec->shdr.sh_addralign
1314*7304104dSAndroid Build Coastguard Worker 	      && (((sec->shdr.sh_type == undo_sec->shdr.sh_type
1315*7304104dSAndroid Build Coastguard Worker 		    && sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
1316*7304104dSAndroid Build Coastguard Worker 		    && (sec->shdr.sh_size == undo_sec->shdr.sh_size
1317*7304104dSAndroid Build Coastguard Worker 			|| (sec->shdr.sh_size > undo_sec->shdr.sh_size
1318*7304104dSAndroid Build Coastguard Worker 			    && main_ehdr->e_type == ET_EXEC
1319*7304104dSAndroid Build Coastguard Worker 			    && !strcmp (sec->name, ".dynstr"))))
1320*7304104dSAndroid Build Coastguard Worker 		   || (sec->shdr.sh_size == undo_sec->shdr.sh_size
1321*7304104dSAndroid Build Coastguard Worker 		       && ((sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
1322*7304104dSAndroid Build Coastguard Worker 			    && undo_sec->shdr.sh_type == SHT_NOBITS)
1323*7304104dSAndroid Build Coastguard Worker 			   || undo_sec->shdr.sh_type == SHT_PROGBITS)
1324*7304104dSAndroid Build Coastguard Worker 		       && !strcmp (sec->name, ".plt")))
1325*7304104dSAndroid Build Coastguard Worker 		  || (sec->shdr.sh_type == SHT_RELA
1326*7304104dSAndroid Build Coastguard Worker 		      && undo_sec->shdr.sh_type == SHT_REL
1327*7304104dSAndroid Build Coastguard Worker 		      && RELA_SCALED (sh_entsize) && RELA_SCALED (sh_size))
1328*7304104dSAndroid Build Coastguard Worker 		  || (sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
1329*7304104dSAndroid Build Coastguard Worker 		      && (sec->shdr.sh_type == undo_sec->shdr.sh_type
1330*7304104dSAndroid Build Coastguard Worker 			  || (sec->shdr.sh_type == SHT_PROGBITS
1331*7304104dSAndroid Build Coastguard Worker 			      && undo_sec->shdr.sh_type == SHT_NOBITS))
1332*7304104dSAndroid Build Coastguard Worker 		      && sec->shdr.sh_size <= undo_sec->shdr.sh_size
1333*7304104dSAndroid Build Coastguard Worker 		      && (!strcmp (sec->name, ".bss")
1334*7304104dSAndroid Build Coastguard Worker 			  || !strcmp (sec->name, ".sbss"))
1335*7304104dSAndroid Build Coastguard Worker 		      && (sec->shdr.sh_size == undo_sec->shdr.sh_size
1336*7304104dSAndroid Build Coastguard Worker 			  || (split_bss = sec) > sections))))
1337*7304104dSAndroid Build Coastguard Worker 	    {
1338*7304104dSAndroid Build Coastguard Worker 	      sec->outscn = undo_sec->outscn;
1339*7304104dSAndroid Build Coastguard Worker 	      undo_sec = NULL;
1340*7304104dSAndroid Build Coastguard Worker 	      break;
1341*7304104dSAndroid Build Coastguard Worker 	    }
1342*7304104dSAndroid Build Coastguard Worker 	}
1343*7304104dSAndroid Build Coastguard Worker 
1344*7304104dSAndroid Build Coastguard Worker       fail |= check_match (undo_sec == NULL, scn, name);
1345*7304104dSAndroid Build Coastguard Worker     }
1346*7304104dSAndroid Build Coastguard Worker 
1347*7304104dSAndroid Build Coastguard Worker   free (undo_sections);
1348*7304104dSAndroid Build Coastguard Worker 
1349*7304104dSAndroid Build Coastguard Worker   if (fail)
1350*7304104dSAndroid Build Coastguard Worker     exit (EXIT_FAILURE);
1351*7304104dSAndroid Build Coastguard Worker 
1352*7304104dSAndroid Build Coastguard Worker   return split_bss;
1353*7304104dSAndroid Build Coastguard Worker }
1354*7304104dSAndroid Build Coastguard Worker 
1355*7304104dSAndroid Build Coastguard Worker /* Create new .shstrtab contents, subroutine of copy_elided_sections.
1356*7304104dSAndroid Build Coastguard Worker    This can't be open coded there and still use variable-length auto arrays,
1357*7304104dSAndroid Build Coastguard Worker    since the end of our block would free other VLAs too.  */
1358*7304104dSAndroid Build Coastguard Worker static Elf_Data *
new_shstrtab(Elf * unstripped,size_t unstripped_shnum,Elf_Data * shstrtab,size_t unstripped_shstrndx,struct section * sections,size_t stripped_shnum,Dwelf_Strtab * strtab)1359*7304104dSAndroid Build Coastguard Worker new_shstrtab (Elf *unstripped, size_t unstripped_shnum,
1360*7304104dSAndroid Build Coastguard Worker 	      Elf_Data *shstrtab, size_t unstripped_shstrndx,
1361*7304104dSAndroid Build Coastguard Worker 	      struct section *sections, size_t stripped_shnum,
1362*7304104dSAndroid Build Coastguard Worker 	      Dwelf_Strtab *strtab)
1363*7304104dSAndroid Build Coastguard Worker {
1364*7304104dSAndroid Build Coastguard Worker   if (strtab == NULL)
1365*7304104dSAndroid Build Coastguard Worker     return NULL;
1366*7304104dSAndroid Build Coastguard Worker 
1367*7304104dSAndroid Build Coastguard Worker   Dwelf_Strent *unstripped_strent[unstripped_shnum];
1368*7304104dSAndroid Build Coastguard Worker   memset (unstripped_strent, 0, sizeof unstripped_strent);
1369*7304104dSAndroid Build Coastguard Worker   for (struct section *sec = sections;
1370*7304104dSAndroid Build Coastguard Worker        sec < &sections[stripped_shnum - 1];
1371*7304104dSAndroid Build Coastguard Worker        ++sec)
1372*7304104dSAndroid Build Coastguard Worker     if (sec->outscn != NULL)
1373*7304104dSAndroid Build Coastguard Worker       {
1374*7304104dSAndroid Build Coastguard Worker 	if (sec->strent == NULL)
1375*7304104dSAndroid Build Coastguard Worker 	  {
1376*7304104dSAndroid Build Coastguard Worker 	    sec->strent = dwelf_strtab_add (strtab, sec->name);
1377*7304104dSAndroid Build Coastguard Worker 	    ELF_CHECK (sec->strent != NULL,
1378*7304104dSAndroid Build Coastguard Worker 		       _("cannot add section name to string table: %s"));
1379*7304104dSAndroid Build Coastguard Worker 	  }
1380*7304104dSAndroid Build Coastguard Worker 	unstripped_strent[elf_ndxscn (sec->outscn) - 1] = sec->strent;
1381*7304104dSAndroid Build Coastguard Worker       }
1382*7304104dSAndroid Build Coastguard Worker 
1383*7304104dSAndroid Build Coastguard Worker   /* Add names of sections we aren't touching.  */
1384*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < unstripped_shnum - 1; ++i)
1385*7304104dSAndroid Build Coastguard Worker     if (unstripped_strent[i] == NULL)
1386*7304104dSAndroid Build Coastguard Worker       {
1387*7304104dSAndroid Build Coastguard Worker 	Elf_Scn *scn = elf_getscn (unstripped, i + 1);
1388*7304104dSAndroid Build Coastguard Worker 	GElf_Shdr shdr_mem;
1389*7304104dSAndroid Build Coastguard Worker 	GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1390*7304104dSAndroid Build Coastguard Worker 	ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1391*7304104dSAndroid Build Coastguard Worker 	const char *name = get_section_name (i + 1, shdr, shstrtab);
1392*7304104dSAndroid Build Coastguard Worker 	unstripped_strent[i] = dwelf_strtab_add (strtab, name);
1393*7304104dSAndroid Build Coastguard Worker 	ELF_CHECK (unstripped_strent[i] != NULL,
1394*7304104dSAndroid Build Coastguard Worker 		   _("cannot add section name to string table: %s"));
1395*7304104dSAndroid Build Coastguard Worker       }
1396*7304104dSAndroid Build Coastguard Worker     else
1397*7304104dSAndroid Build Coastguard Worker       unstripped_strent[i] = NULL;
1398*7304104dSAndroid Build Coastguard Worker 
1399*7304104dSAndroid Build Coastguard Worker   /* Now finalize the string table so we can get offsets.  */
1400*7304104dSAndroid Build Coastguard Worker   Elf_Data *strtab_data = elf_getdata (elf_getscn (unstripped,
1401*7304104dSAndroid Build Coastguard Worker 						   unstripped_shstrndx), NULL);
1402*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (elf_flagdata (strtab_data, ELF_C_SET, ELF_F_DIRTY),
1403*7304104dSAndroid Build Coastguard Worker 	     _("cannot update section header string table data: %s"));
1404*7304104dSAndroid Build Coastguard Worker   if (dwelf_strtab_finalize (strtab, strtab_data) == NULL)
1405*7304104dSAndroid Build Coastguard Worker     error_exit (0, "Not enough memory to create string table");
1406*7304104dSAndroid Build Coastguard Worker 
1407*7304104dSAndroid Build Coastguard Worker   /* Update the sh_name fields of sections we aren't modifying later.  */
1408*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < unstripped_shnum - 1; ++i)
1409*7304104dSAndroid Build Coastguard Worker     if (unstripped_strent[i] != NULL)
1410*7304104dSAndroid Build Coastguard Worker       {
1411*7304104dSAndroid Build Coastguard Worker 	Elf_Scn *scn = elf_getscn (unstripped, i + 1);
1412*7304104dSAndroid Build Coastguard Worker 	GElf_Shdr shdr_mem;
1413*7304104dSAndroid Build Coastguard Worker 	GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1414*7304104dSAndroid Build Coastguard Worker 	ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1415*7304104dSAndroid Build Coastguard Worker 	shdr->sh_name = dwelf_strent_off (unstripped_strent[i]);
1416*7304104dSAndroid Build Coastguard Worker 	if (i + 1 == unstripped_shstrndx)
1417*7304104dSAndroid Build Coastguard Worker 	  shdr->sh_size = strtab_data->d_size;
1418*7304104dSAndroid Build Coastguard Worker 	update_shdr (scn, shdr);
1419*7304104dSAndroid Build Coastguard Worker       }
1420*7304104dSAndroid Build Coastguard Worker 
1421*7304104dSAndroid Build Coastguard Worker   return strtab_data;
1422*7304104dSAndroid Build Coastguard Worker }
1423*7304104dSAndroid Build Coastguard Worker 
1424*7304104dSAndroid Build Coastguard Worker /* Fill in any SHT_NOBITS sections in UNSTRIPPED by
1425*7304104dSAndroid Build Coastguard Worker    copying their contents and sh_type from STRIPPED.  */
1426*7304104dSAndroid Build Coastguard Worker static void
copy_elided_sections(Elf * unstripped,Elf * stripped,const GElf_Ehdr * stripped_ehdr,GElf_Addr bias)1427*7304104dSAndroid Build Coastguard Worker copy_elided_sections (Elf *unstripped, Elf *stripped,
1428*7304104dSAndroid Build Coastguard Worker 		      const GElf_Ehdr *stripped_ehdr, GElf_Addr bias)
1429*7304104dSAndroid Build Coastguard Worker {
1430*7304104dSAndroid Build Coastguard Worker   size_t unstripped_shstrndx;
1431*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (elf_getshdrstrndx (unstripped, &unstripped_shstrndx) == 0,
1432*7304104dSAndroid Build Coastguard Worker 	     _("cannot get section header string table section index: %s"));
1433*7304104dSAndroid Build Coastguard Worker 
1434*7304104dSAndroid Build Coastguard Worker   size_t stripped_shstrndx;
1435*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (elf_getshdrstrndx (stripped, &stripped_shstrndx) == 0,
1436*7304104dSAndroid Build Coastguard Worker 	     _("cannot get section header string table section index: %s"));
1437*7304104dSAndroid Build Coastguard Worker 
1438*7304104dSAndroid Build Coastguard Worker   size_t unstripped_shnum;
1439*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (elf_getshdrnum (unstripped, &unstripped_shnum) == 0,
1440*7304104dSAndroid Build Coastguard Worker 	     _("cannot get section count: %s"));
1441*7304104dSAndroid Build Coastguard Worker 
1442*7304104dSAndroid Build Coastguard Worker   size_t stripped_shnum;
1443*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (elf_getshdrnum (stripped, &stripped_shnum) == 0,
1444*7304104dSAndroid Build Coastguard Worker 	     _("cannot get section count: %s"));
1445*7304104dSAndroid Build Coastguard Worker 
1446*7304104dSAndroid Build Coastguard Worker   if (unlikely (stripped_shnum > unstripped_shnum))
1447*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("\
1448*7304104dSAndroid Build Coastguard Worker more sections in stripped file than debug file -- arguments reversed?"));
1449*7304104dSAndroid Build Coastguard Worker 
1450*7304104dSAndroid Build Coastguard Worker   if (unlikely (stripped_shnum == 0))
1451*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("no sections in stripped file"));
1452*7304104dSAndroid Build Coastguard Worker 
1453*7304104dSAndroid Build Coastguard Worker   /* Used as sanity check for allocated section offset, if the section
1454*7304104dSAndroid Build Coastguard Worker      offset needs to be preserved.  We want to know the max size of the
1455*7304104dSAndroid Build Coastguard Worker      ELF file, to check if any existing section offsets are OK.  */
1456*7304104dSAndroid Build Coastguard Worker   int64_t max_off = -1;
1457*7304104dSAndroid Build Coastguard Worker   if (stripped_ehdr->e_type != ET_REL)
1458*7304104dSAndroid Build Coastguard Worker     {
1459*7304104dSAndroid Build Coastguard Worker       elf_flagelf (stripped, ELF_C_SET, ELF_F_LAYOUT);
1460*7304104dSAndroid Build Coastguard Worker       max_off = elf_update (stripped, ELF_C_NULL);
1461*7304104dSAndroid Build Coastguard Worker     }
1462*7304104dSAndroid Build Coastguard Worker 
1463*7304104dSAndroid Build Coastguard Worker   /* Cache the stripped file's section details.  */
1464*7304104dSAndroid Build Coastguard Worker   struct section sections[stripped_shnum - 1];
1465*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
1466*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (stripped, scn)) != NULL)
1467*7304104dSAndroid Build Coastguard Worker     {
1468*7304104dSAndroid Build Coastguard Worker       size_t i = elf_ndxscn (scn) - 1;
1469*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &sections[i].shdr);
1470*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1471*7304104dSAndroid Build Coastguard Worker       sections[i].name = elf_strptr (stripped, stripped_shstrndx,
1472*7304104dSAndroid Build Coastguard Worker 				     shdr->sh_name);
1473*7304104dSAndroid Build Coastguard Worker       if (sections[i].name == NULL)
1474*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("cannot read section [%zu] name: %s"),
1475*7304104dSAndroid Build Coastguard Worker 		    elf_ndxscn (scn), elf_errmsg (-1));
1476*7304104dSAndroid Build Coastguard Worker       sections[i].scn = scn;
1477*7304104dSAndroid Build Coastguard Worker       sections[i].outscn = NULL;
1478*7304104dSAndroid Build Coastguard Worker       sections[i].strent = NULL;
1479*7304104dSAndroid Build Coastguard Worker       sections[i].sig = get_group_sig (stripped, shdr);
1480*7304104dSAndroid Build Coastguard Worker     }
1481*7304104dSAndroid Build Coastguard Worker 
1482*7304104dSAndroid Build Coastguard Worker   const struct section *stripped_symtab = NULL;
1483*7304104dSAndroid Build Coastguard Worker 
1484*7304104dSAndroid Build Coastguard Worker   /* Sort the sections, allocated by address and others after.  */
1485*7304104dSAndroid Build Coastguard Worker   qsort (sections, stripped_shnum - 1, sizeof sections[0],
1486*7304104dSAndroid Build Coastguard Worker 	 stripped_ehdr->e_type == ET_REL
1487*7304104dSAndroid Build Coastguard Worker 	 ? compare_sections_rel : compare_sections_nonrel);
1488*7304104dSAndroid Build Coastguard Worker   size_t nalloc = stripped_shnum - 1;
1489*7304104dSAndroid Build Coastguard Worker   while (nalloc > 0 && !(sections[nalloc - 1].shdr.sh_flags & SHF_ALLOC))
1490*7304104dSAndroid Build Coastguard Worker     {
1491*7304104dSAndroid Build Coastguard Worker       --nalloc;
1492*7304104dSAndroid Build Coastguard Worker       if (sections[nalloc].shdr.sh_type == SHT_SYMTAB)
1493*7304104dSAndroid Build Coastguard Worker 	stripped_symtab = &sections[nalloc];
1494*7304104dSAndroid Build Coastguard Worker     }
1495*7304104dSAndroid Build Coastguard Worker 
1496*7304104dSAndroid Build Coastguard Worker   Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped,
1497*7304104dSAndroid Build Coastguard Worker 						unstripped_shstrndx), NULL);
1498*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (shstrtab != NULL,
1499*7304104dSAndroid Build Coastguard Worker 	     _("cannot read section header string table: %s"));
1500*7304104dSAndroid Build Coastguard Worker 
1501*7304104dSAndroid Build Coastguard Worker   /* Match each debuginfo section with its corresponding stripped section.  */
1502*7304104dSAndroid Build Coastguard Worker   bool check_prelink = false;
1503*7304104dSAndroid Build Coastguard Worker   Elf_Scn *unstripped_symtab = NULL;
1504*7304104dSAndroid Build Coastguard Worker   size_t unstripped_strndx = 0;
1505*7304104dSAndroid Build Coastguard Worker   size_t alloc_avail = 0;
1506*7304104dSAndroid Build Coastguard Worker   scn = NULL;
1507*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (unstripped, scn)) != NULL)
1508*7304104dSAndroid Build Coastguard Worker     {
1509*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
1510*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1511*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1512*7304104dSAndroid Build Coastguard Worker 
1513*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_type == SHT_SYMTAB)
1514*7304104dSAndroid Build Coastguard Worker 	{
1515*7304104dSAndroid Build Coastguard Worker 	  unstripped_symtab = scn;
1516*7304104dSAndroid Build Coastguard Worker 	  unstripped_strndx = shdr->sh_link;
1517*7304104dSAndroid Build Coastguard Worker 	  continue;
1518*7304104dSAndroid Build Coastguard Worker 	}
1519*7304104dSAndroid Build Coastguard Worker 
1520*7304104dSAndroid Build Coastguard Worker       const size_t ndx = elf_ndxscn (scn);
1521*7304104dSAndroid Build Coastguard Worker       if (ndx == unstripped_shstrndx || ndx == unstripped_strndx)
1522*7304104dSAndroid Build Coastguard Worker 	continue;
1523*7304104dSAndroid Build Coastguard Worker 
1524*7304104dSAndroid Build Coastguard Worker       const char *name = get_section_name (ndx, shdr, shstrtab);
1525*7304104dSAndroid Build Coastguard Worker 
1526*7304104dSAndroid Build Coastguard Worker       struct section *sec = NULL;
1527*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_ALLOC)
1528*7304104dSAndroid Build Coastguard Worker 	{
1529*7304104dSAndroid Build Coastguard Worker 	  if (stripped_ehdr->e_type != ET_REL)
1530*7304104dSAndroid Build Coastguard Worker 	    {
1531*7304104dSAndroid Build Coastguard Worker 	      /* Look for the section that matches.  */
1532*7304104dSAndroid Build Coastguard Worker 	      sec = find_alloc_section (shdr, bias, name, sections, nalloc);
1533*7304104dSAndroid Build Coastguard Worker 	      if (sec == NULL)
1534*7304104dSAndroid Build Coastguard Worker 		{
1535*7304104dSAndroid Build Coastguard Worker 		  /* We couldn't figure it out.  It may be a prelink issue.  */
1536*7304104dSAndroid Build Coastguard Worker 		  check_prelink = true;
1537*7304104dSAndroid Build Coastguard Worker 		  continue;
1538*7304104dSAndroid Build Coastguard Worker 		}
1539*7304104dSAndroid Build Coastguard Worker 	    }
1540*7304104dSAndroid Build Coastguard Worker 	  else
1541*7304104dSAndroid Build Coastguard Worker 	    {
1542*7304104dSAndroid Build Coastguard Worker 	      /* The sh_addr of allocated sections does not help us,
1543*7304104dSAndroid Build Coastguard Worker 		 but the order usually matches.  */
1544*7304104dSAndroid Build Coastguard Worker 	      if (likely (sections_match (sections, alloc_avail, shdr, name)))
1545*7304104dSAndroid Build Coastguard Worker 		sec = &sections[alloc_avail++];
1546*7304104dSAndroid Build Coastguard Worker 	      else
1547*7304104dSAndroid Build Coastguard Worker 		for (size_t i = alloc_avail + 1; i < nalloc; ++i)
1548*7304104dSAndroid Build Coastguard Worker 		  if (sections_match (sections, i, shdr, name))
1549*7304104dSAndroid Build Coastguard Worker 		    {
1550*7304104dSAndroid Build Coastguard Worker 		      sec = &sections[i];
1551*7304104dSAndroid Build Coastguard Worker 		      break;
1552*7304104dSAndroid Build Coastguard Worker 		    }
1553*7304104dSAndroid Build Coastguard Worker 	    }
1554*7304104dSAndroid Build Coastguard Worker 	}
1555*7304104dSAndroid Build Coastguard Worker       else
1556*7304104dSAndroid Build Coastguard Worker 	{
1557*7304104dSAndroid Build Coastguard Worker 	  /* Locate a matching unallocated section in SECTIONS.  */
1558*7304104dSAndroid Build Coastguard Worker 	  const char *sig = get_group_sig (unstripped, shdr);
1559*7304104dSAndroid Build Coastguard Worker 	  size_t l = nalloc, u = stripped_shnum - 1;
1560*7304104dSAndroid Build Coastguard Worker 	  while (l < u)
1561*7304104dSAndroid Build Coastguard Worker 	    {
1562*7304104dSAndroid Build Coastguard Worker 	      size_t i = (l + u) / 2;
1563*7304104dSAndroid Build Coastguard Worker 	      struct section *section = &sections[i];
1564*7304104dSAndroid Build Coastguard Worker 	      int cmp = compare_unalloc_sections (shdr, &section->shdr,
1565*7304104dSAndroid Build Coastguard Worker 						  name, section->name,
1566*7304104dSAndroid Build Coastguard Worker 						  sig, section->sig);
1567*7304104dSAndroid Build Coastguard Worker 	      if (cmp < 0)
1568*7304104dSAndroid Build Coastguard Worker 		u = i;
1569*7304104dSAndroid Build Coastguard Worker 	      else if (cmp > 0)
1570*7304104dSAndroid Build Coastguard Worker 		l = i + 1;
1571*7304104dSAndroid Build Coastguard Worker 	      else
1572*7304104dSAndroid Build Coastguard Worker 		{
1573*7304104dSAndroid Build Coastguard Worker 		  sec = section;
1574*7304104dSAndroid Build Coastguard Worker 		  break;
1575*7304104dSAndroid Build Coastguard Worker 		}
1576*7304104dSAndroid Build Coastguard Worker 	    }
1577*7304104dSAndroid Build Coastguard Worker 
1578*7304104dSAndroid Build Coastguard Worker 	  if (sec == NULL)
1579*7304104dSAndroid Build Coastguard Worker 	    {
1580*7304104dSAndroid Build Coastguard Worker 	      /* An additional unallocated section is fine if not SHT_NOBITS.
1581*7304104dSAndroid Build Coastguard Worker 		 We looked it up anyway in case it's an unallocated section
1582*7304104dSAndroid Build Coastguard Worker 		 copied in both files (e.g. SHT_NOTE), and don't keep both.  */
1583*7304104dSAndroid Build Coastguard Worker 	      if (shdr->sh_type != SHT_NOBITS)
1584*7304104dSAndroid Build Coastguard Worker 		continue;
1585*7304104dSAndroid Build Coastguard Worker 
1586*7304104dSAndroid Build Coastguard Worker 	      /* Somehow some old .debug files wound up with SHT_NOBITS
1587*7304104dSAndroid Build Coastguard Worker 		 .comment sections, so let those pass.  */
1588*7304104dSAndroid Build Coastguard Worker 	      if (!strcmp (name, ".comment"))
1589*7304104dSAndroid Build Coastguard Worker 		continue;
1590*7304104dSAndroid Build Coastguard Worker 	    }
1591*7304104dSAndroid Build Coastguard Worker 	}
1592*7304104dSAndroid Build Coastguard Worker 
1593*7304104dSAndroid Build Coastguard Worker       if (sec == NULL)
1594*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("cannot find matching section for [%zu] '%s'"),
1595*7304104dSAndroid Build Coastguard Worker 		    elf_ndxscn (scn), name);
1596*7304104dSAndroid Build Coastguard Worker 
1597*7304104dSAndroid Build Coastguard Worker       sec->outscn = scn;
1598*7304104dSAndroid Build Coastguard Worker     }
1599*7304104dSAndroid Build Coastguard Worker 
1600*7304104dSAndroid Build Coastguard Worker   /* If that failed due to changes made by prelink, we take another tack.
1601*7304104dSAndroid Build Coastguard Worker      We keep track of a .bss section that was partly split into .dynbss
1602*7304104dSAndroid Build Coastguard Worker      so that collect_symbols can update symbols' st_shndx fields.  */
1603*7304104dSAndroid Build Coastguard Worker   struct section *split_bss = NULL;
1604*7304104dSAndroid Build Coastguard Worker   if (check_prelink)
1605*7304104dSAndroid Build Coastguard Worker     {
1606*7304104dSAndroid Build Coastguard Worker       Elf_Data *data = elf_getdata (elf_getscn (stripped, stripped_shstrndx),
1607*7304104dSAndroid Build Coastguard Worker 				    NULL);
1608*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (data != NULL,
1609*7304104dSAndroid Build Coastguard Worker 		 _("cannot read section header string table: %s"));
1610*7304104dSAndroid Build Coastguard Worker       split_bss = find_alloc_sections_prelink (unstripped, shstrtab,
1611*7304104dSAndroid Build Coastguard Worker 					       stripped, stripped_ehdr,
1612*7304104dSAndroid Build Coastguard Worker 					       data, bias, sections,
1613*7304104dSAndroid Build Coastguard Worker 					       nalloc, stripped_shnum - 1);
1614*7304104dSAndroid Build Coastguard Worker     }
1615*7304104dSAndroid Build Coastguard Worker 
1616*7304104dSAndroid Build Coastguard Worker   /* Make sure each main file section has a place to go.  */
1617*7304104dSAndroid Build Coastguard Worker   const struct section *stripped_dynsym = NULL;
1618*7304104dSAndroid Build Coastguard Worker   size_t debuglink = SHN_UNDEF;
1619*7304104dSAndroid Build Coastguard Worker   size_t ndx_sec_num = stripped_shnum - 1;
1620*7304104dSAndroid Build Coastguard Worker   size_t ndx_section[ndx_sec_num];
1621*7304104dSAndroid Build Coastguard Worker   Dwelf_Strtab *strtab = NULL;
1622*7304104dSAndroid Build Coastguard Worker   for (struct section *sec = sections;
1623*7304104dSAndroid Build Coastguard Worker        sec < &sections[ndx_sec_num];
1624*7304104dSAndroid Build Coastguard Worker        ++sec)
1625*7304104dSAndroid Build Coastguard Worker     {
1626*7304104dSAndroid Build Coastguard Worker       size_t secndx = elf_ndxscn (sec->scn);
1627*7304104dSAndroid Build Coastguard Worker 
1628*7304104dSAndroid Build Coastguard Worker       if (sec->outscn == NULL)
1629*7304104dSAndroid Build Coastguard Worker 	{
1630*7304104dSAndroid Build Coastguard Worker 	  /* We didn't find any corresponding section for this.  */
1631*7304104dSAndroid Build Coastguard Worker 
1632*7304104dSAndroid Build Coastguard Worker 	  if (secndx == stripped_shstrndx)
1633*7304104dSAndroid Build Coastguard Worker 	    {
1634*7304104dSAndroid Build Coastguard Worker 	      /* We only need one .shstrtab.  */
1635*7304104dSAndroid Build Coastguard Worker 	      ndx_section[secndx - 1] = unstripped_shstrndx;
1636*7304104dSAndroid Build Coastguard Worker 	      continue;
1637*7304104dSAndroid Build Coastguard Worker 	    }
1638*7304104dSAndroid Build Coastguard Worker 
1639*7304104dSAndroid Build Coastguard Worker 	  if (unstripped_symtab != NULL && sec == stripped_symtab)
1640*7304104dSAndroid Build Coastguard Worker 	    {
1641*7304104dSAndroid Build Coastguard Worker 	      /* We don't need a second symbol table.  */
1642*7304104dSAndroid Build Coastguard Worker 	      ndx_section[secndx - 1] = elf_ndxscn (unstripped_symtab);
1643*7304104dSAndroid Build Coastguard Worker 	      continue;
1644*7304104dSAndroid Build Coastguard Worker 	    }
1645*7304104dSAndroid Build Coastguard Worker 
1646*7304104dSAndroid Build Coastguard Worker 	  if (unstripped_symtab != NULL && stripped_symtab != NULL
1647*7304104dSAndroid Build Coastguard Worker 	      && secndx == stripped_symtab->shdr.sh_link
1648*7304104dSAndroid Build Coastguard Worker 	      && unstripped_strndx != 0)
1649*7304104dSAndroid Build Coastguard Worker 	    {
1650*7304104dSAndroid Build Coastguard Worker 	      /* ... nor its string table.  */
1651*7304104dSAndroid Build Coastguard Worker 	      ndx_section[secndx - 1] = unstripped_strndx;
1652*7304104dSAndroid Build Coastguard Worker 	      continue;
1653*7304104dSAndroid Build Coastguard Worker 	    }
1654*7304104dSAndroid Build Coastguard Worker 
1655*7304104dSAndroid Build Coastguard Worker 	  if (!(sec->shdr.sh_flags & SHF_ALLOC)
1656*7304104dSAndroid Build Coastguard Worker 	      && !strcmp (sec->name, ".gnu_debuglink"))
1657*7304104dSAndroid Build Coastguard Worker 	    {
1658*7304104dSAndroid Build Coastguard Worker 	      /* This was created by stripping.  We don't want it.  */
1659*7304104dSAndroid Build Coastguard Worker 	      debuglink = secndx;
1660*7304104dSAndroid Build Coastguard Worker 	      ndx_section[secndx - 1] = SHN_UNDEF;
1661*7304104dSAndroid Build Coastguard Worker 	      continue;
1662*7304104dSAndroid Build Coastguard Worker 	    }
1663*7304104dSAndroid Build Coastguard Worker 
1664*7304104dSAndroid Build Coastguard Worker 	  sec->outscn = elf_newscn (unstripped);
1665*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *newdata = elf_newdata (sec->outscn);
1666*7304104dSAndroid Build Coastguard Worker 	  ELF_CHECK (newdata != NULL && gelf_update_shdr (sec->outscn,
1667*7304104dSAndroid Build Coastguard Worker 							  &sec->shdr),
1668*7304104dSAndroid Build Coastguard Worker 		     _("cannot add new section: %s"));
1669*7304104dSAndroid Build Coastguard Worker 
1670*7304104dSAndroid Build Coastguard Worker 	  if (strtab == NULL)
1671*7304104dSAndroid Build Coastguard Worker 	    strtab = dwelf_strtab_init (true);
1672*7304104dSAndroid Build Coastguard Worker 	  sec->strent = dwelf_strtab_add (strtab, sec->name);
1673*7304104dSAndroid Build Coastguard Worker 	  ELF_CHECK (sec->strent != NULL,
1674*7304104dSAndroid Build Coastguard Worker 		     _("cannot add section name to string table: %s"));
1675*7304104dSAndroid Build Coastguard Worker 	}
1676*7304104dSAndroid Build Coastguard Worker 
1677*7304104dSAndroid Build Coastguard Worker       /* Cache the mapping of original section indices to output sections.  */
1678*7304104dSAndroid Build Coastguard Worker       ndx_section[secndx - 1] = elf_ndxscn (sec->outscn);
1679*7304104dSAndroid Build Coastguard Worker     }
1680*7304104dSAndroid Build Coastguard Worker 
1681*7304104dSAndroid Build Coastguard Worker   /* We added some sections, so we need a new shstrtab.  */
1682*7304104dSAndroid Build Coastguard Worker   Elf_Data *strtab_data = new_shstrtab (unstripped, unstripped_shnum,
1683*7304104dSAndroid Build Coastguard Worker 					shstrtab, unstripped_shstrndx,
1684*7304104dSAndroid Build Coastguard Worker 					sections, stripped_shnum,
1685*7304104dSAndroid Build Coastguard Worker 					strtab);
1686*7304104dSAndroid Build Coastguard Worker 
1687*7304104dSAndroid Build Coastguard Worker   /* Get the updated section count.  */
1688*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (elf_getshdrnum (unstripped, &unstripped_shnum) == 0,
1689*7304104dSAndroid Build Coastguard Worker 	     _("cannot get section count: %s"));
1690*7304104dSAndroid Build Coastguard Worker 
1691*7304104dSAndroid Build Coastguard Worker   bool placed[unstripped_shnum - 1];
1692*7304104dSAndroid Build Coastguard Worker   memset (placed, 0, sizeof placed);
1693*7304104dSAndroid Build Coastguard Worker 
1694*7304104dSAndroid Build Coastguard Worker   /* Now update the output sections and copy in their data.  */
1695*7304104dSAndroid Build Coastguard Worker   GElf_Off offset = 0;
1696*7304104dSAndroid Build Coastguard Worker   for (const struct section *sec = sections;
1697*7304104dSAndroid Build Coastguard Worker        sec < &sections[stripped_shnum - 1];
1698*7304104dSAndroid Build Coastguard Worker        ++sec)
1699*7304104dSAndroid Build Coastguard Worker     if (sec->outscn != NULL)
1700*7304104dSAndroid Build Coastguard Worker       {
1701*7304104dSAndroid Build Coastguard Worker 	GElf_Shdr shdr_mem;
1702*7304104dSAndroid Build Coastguard Worker 	GElf_Shdr *shdr = gelf_getshdr (sec->outscn, &shdr_mem);
1703*7304104dSAndroid Build Coastguard Worker 	ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1704*7304104dSAndroid Build Coastguard Worker 
1705*7304104dSAndroid Build Coastguard Worker 	/* In an ET_REL file under --relocate, the sh_addr of SHF_ALLOC
1706*7304104dSAndroid Build Coastguard Worker 	   sections will have been set nonzero by relocation.  This
1707*7304104dSAndroid Build Coastguard Worker 	   touched the shdrs of whichever file had the symtab.  sh_addr
1708*7304104dSAndroid Build Coastguard Worker 	   is still zero in the corresponding shdr.  The relocated
1709*7304104dSAndroid Build Coastguard Worker 	   address is what we want to use.  */
1710*7304104dSAndroid Build Coastguard Worker 	if (stripped_ehdr->e_type != ET_REL
1711*7304104dSAndroid Build Coastguard Worker 	    || !(shdr_mem.sh_flags & SHF_ALLOC)
1712*7304104dSAndroid Build Coastguard Worker 	    || shdr_mem.sh_addr == 0)
1713*7304104dSAndroid Build Coastguard Worker 	  shdr_mem.sh_addr = sec->shdr.sh_addr;
1714*7304104dSAndroid Build Coastguard Worker 
1715*7304104dSAndroid Build Coastguard Worker 	shdr_mem.sh_type = sec->shdr.sh_type;
1716*7304104dSAndroid Build Coastguard Worker 	shdr_mem.sh_size = sec->shdr.sh_size;
1717*7304104dSAndroid Build Coastguard Worker 	shdr_mem.sh_info = sec->shdr.sh_info;
1718*7304104dSAndroid Build Coastguard Worker 	shdr_mem.sh_link = sec->shdr.sh_link;
1719*7304104dSAndroid Build Coastguard Worker 
1720*7304104dSAndroid Build Coastguard Worker 	/* Buggy binutils objdump might have stripped the SHF_INFO_LINK
1721*7304104dSAndroid Build Coastguard Worker 	   put it back if necessary.  */
1722*7304104dSAndroid Build Coastguard Worker 	if ((sec->shdr.sh_type == SHT_REL || sec->shdr.sh_type == SHT_RELA)
1723*7304104dSAndroid Build Coastguard Worker 	    && sec->shdr.sh_flags != shdr_mem.sh_flags
1724*7304104dSAndroid Build Coastguard Worker 	    && (sec->shdr.sh_flags & SHF_INFO_LINK) != 0)
1725*7304104dSAndroid Build Coastguard Worker 	  shdr_mem.sh_flags |= SHF_INFO_LINK;
1726*7304104dSAndroid Build Coastguard Worker 
1727*7304104dSAndroid Build Coastguard Worker 	if (sec->shdr.sh_link != SHN_UNDEF)
1728*7304104dSAndroid Build Coastguard Worker 	  {
1729*7304104dSAndroid Build Coastguard Worker 	    if (sec->shdr.sh_link > ndx_sec_num)
1730*7304104dSAndroid Build Coastguard Worker 	      error_exit (0,
1731*7304104dSAndroid Build Coastguard Worker 			  "section [%zd] has invalid sh_link %" PRId32,
1732*7304104dSAndroid Build Coastguard Worker 			  elf_ndxscn (sec->scn), sec->shdr.sh_link);
1733*7304104dSAndroid Build Coastguard Worker 	    shdr_mem.sh_link = ndx_section[sec->shdr.sh_link - 1];
1734*7304104dSAndroid Build Coastguard Worker 	  }
1735*7304104dSAndroid Build Coastguard Worker 	if (SH_INFO_LINK_P (&sec->shdr) && sec->shdr.sh_info != 0)
1736*7304104dSAndroid Build Coastguard Worker 	  {
1737*7304104dSAndroid Build Coastguard Worker 	    if (sec->shdr.sh_info > ndx_sec_num)
1738*7304104dSAndroid Build Coastguard Worker 	      error_exit (0,
1739*7304104dSAndroid Build Coastguard Worker 			  "section [%zd] has invalid sh_info %" PRId32,
1740*7304104dSAndroid Build Coastguard Worker 			  elf_ndxscn (sec->scn), sec->shdr.sh_info);
1741*7304104dSAndroid Build Coastguard Worker 	    shdr_mem.sh_info = ndx_section[sec->shdr.sh_info - 1];
1742*7304104dSAndroid Build Coastguard Worker 	  }
1743*7304104dSAndroid Build Coastguard Worker 
1744*7304104dSAndroid Build Coastguard Worker 	if (strtab != NULL)
1745*7304104dSAndroid Build Coastguard Worker 	  shdr_mem.sh_name = dwelf_strent_off (sec->strent);
1746*7304104dSAndroid Build Coastguard Worker 
1747*7304104dSAndroid Build Coastguard Worker 	Elf_Data *indata = elf_getdata (sec->scn, NULL);
1748*7304104dSAndroid Build Coastguard Worker 	ELF_CHECK (indata != NULL, _("cannot get section data: %s"));
1749*7304104dSAndroid Build Coastguard Worker 	Elf_Data *outdata = elf_getdata (sec->outscn, NULL);
1750*7304104dSAndroid Build Coastguard Worker 	ELF_CHECK (outdata != NULL, _("cannot copy section data: %s"));
1751*7304104dSAndroid Build Coastguard Worker 	*outdata = *indata;
1752*7304104dSAndroid Build Coastguard Worker 	elf_flagdata (outdata, ELF_C_SET, ELF_F_DIRTY);
1753*7304104dSAndroid Build Coastguard Worker 
1754*7304104dSAndroid Build Coastguard Worker 	/* Preserve the file layout of the allocated sections.  */
1755*7304104dSAndroid Build Coastguard Worker 	if (stripped_ehdr->e_type != ET_REL && (shdr_mem.sh_flags & SHF_ALLOC))
1756*7304104dSAndroid Build Coastguard Worker 	  {
1757*7304104dSAndroid Build Coastguard Worker 	    if (max_off > 0 && sec->shdr.sh_offset > (Elf64_Off) max_off)
1758*7304104dSAndroid Build Coastguard Worker 		error_exit (0,
1759*7304104dSAndroid Build Coastguard Worker 			    "allocated section offset too large [%zd] %" PRIx64,
1760*7304104dSAndroid Build Coastguard Worker 			    elf_ndxscn (sec->scn), sec->shdr.sh_offset);
1761*7304104dSAndroid Build Coastguard Worker 
1762*7304104dSAndroid Build Coastguard Worker 	    shdr_mem.sh_offset = sec->shdr.sh_offset;
1763*7304104dSAndroid Build Coastguard Worker 	    placed[elf_ndxscn (sec->outscn) - 1] = true;
1764*7304104dSAndroid Build Coastguard Worker 
1765*7304104dSAndroid Build Coastguard Worker 	    const GElf_Off end_offset = (shdr_mem.sh_offset
1766*7304104dSAndroid Build Coastguard Worker 					 + (shdr_mem.sh_type == SHT_NOBITS
1767*7304104dSAndroid Build Coastguard Worker 					    ? 0 : shdr_mem.sh_size));
1768*7304104dSAndroid Build Coastguard Worker 	    if (end_offset > offset)
1769*7304104dSAndroid Build Coastguard Worker 	      offset = end_offset;
1770*7304104dSAndroid Build Coastguard Worker 	  }
1771*7304104dSAndroid Build Coastguard Worker 
1772*7304104dSAndroid Build Coastguard Worker 	update_shdr (sec->outscn, &shdr_mem);
1773*7304104dSAndroid Build Coastguard Worker 
1774*7304104dSAndroid Build Coastguard Worker 	if (shdr_mem.sh_type == SHT_SYMTAB || shdr_mem.sh_type == SHT_DYNSYM)
1775*7304104dSAndroid Build Coastguard Worker 	  {
1776*7304104dSAndroid Build Coastguard Worker 	    /* We must adjust all the section indices in the symbol table.  */
1777*7304104dSAndroid Build Coastguard Worker 
1778*7304104dSAndroid Build Coastguard Worker 	    Elf_Data *shndxdata = NULL;	/* XXX */
1779*7304104dSAndroid Build Coastguard Worker 
1780*7304104dSAndroid Build Coastguard Worker 	    if (shdr_mem.sh_entsize == 0)
1781*7304104dSAndroid Build Coastguard Worker 	      error_exit (0,
1782*7304104dSAndroid Build Coastguard Worker 			  "SYMTAB section cannot have zero sh_entsize");
1783*7304104dSAndroid Build Coastguard Worker 	    for (size_t i = 1; i < shdr_mem.sh_size / shdr_mem.sh_entsize; ++i)
1784*7304104dSAndroid Build Coastguard Worker 	      {
1785*7304104dSAndroid Build Coastguard Worker 		GElf_Sym sym_mem;
1786*7304104dSAndroid Build Coastguard Worker 		GElf_Word shndx = SHN_UNDEF;
1787*7304104dSAndroid Build Coastguard Worker 		GElf_Sym *sym = gelf_getsymshndx (outdata, shndxdata,
1788*7304104dSAndroid Build Coastguard Worker 						  i, &sym_mem, &shndx);
1789*7304104dSAndroid Build Coastguard Worker 		ELF_CHECK (sym != NULL,
1790*7304104dSAndroid Build Coastguard Worker 			   _("cannot get symbol table entry: %s"));
1791*7304104dSAndroid Build Coastguard Worker 		if (sym->st_shndx != SHN_XINDEX)
1792*7304104dSAndroid Build Coastguard Worker 		  shndx = sym->st_shndx;
1793*7304104dSAndroid Build Coastguard Worker 
1794*7304104dSAndroid Build Coastguard Worker 		if (shndx != SHN_UNDEF && shndx < SHN_LORESERVE)
1795*7304104dSAndroid Build Coastguard Worker 		  {
1796*7304104dSAndroid Build Coastguard Worker 		    if (shndx >= stripped_shnum)
1797*7304104dSAndroid Build Coastguard Worker 		      error_exit (0,
1798*7304104dSAndroid Build Coastguard Worker 				  _("symbol [%zu] has invalid section index"), i);
1799*7304104dSAndroid Build Coastguard Worker 
1800*7304104dSAndroid Build Coastguard Worker 		    shndx = ndx_section[shndx - 1];
1801*7304104dSAndroid Build Coastguard Worker 		    if (shndx < SHN_LORESERVE)
1802*7304104dSAndroid Build Coastguard Worker 		      {
1803*7304104dSAndroid Build Coastguard Worker 			sym->st_shndx = shndx;
1804*7304104dSAndroid Build Coastguard Worker 			shndx = SHN_UNDEF;
1805*7304104dSAndroid Build Coastguard Worker 		      }
1806*7304104dSAndroid Build Coastguard Worker 		    else
1807*7304104dSAndroid Build Coastguard Worker 		      sym->st_shndx = SHN_XINDEX;
1808*7304104dSAndroid Build Coastguard Worker 
1809*7304104dSAndroid Build Coastguard Worker 		    ELF_CHECK (gelf_update_symshndx (outdata, shndxdata,
1810*7304104dSAndroid Build Coastguard Worker 						     i, sym, shndx),
1811*7304104dSAndroid Build Coastguard Worker 			       _("cannot update symbol table: %s"));
1812*7304104dSAndroid Build Coastguard Worker 		  }
1813*7304104dSAndroid Build Coastguard Worker 	      }
1814*7304104dSAndroid Build Coastguard Worker 
1815*7304104dSAndroid Build Coastguard Worker 	    if (shdr_mem.sh_type == SHT_SYMTAB)
1816*7304104dSAndroid Build Coastguard Worker 	      stripped_symtab = sec;
1817*7304104dSAndroid Build Coastguard Worker 	    if (shdr_mem.sh_type == SHT_DYNSYM)
1818*7304104dSAndroid Build Coastguard Worker 	      stripped_dynsym = sec;
1819*7304104dSAndroid Build Coastguard Worker 	  }
1820*7304104dSAndroid Build Coastguard Worker 
1821*7304104dSAndroid Build Coastguard Worker 	if (shdr_mem.sh_type == SHT_GROUP)
1822*7304104dSAndroid Build Coastguard Worker 	  {
1823*7304104dSAndroid Build Coastguard Worker 	    /* We must adjust all the section indices in the group.
1824*7304104dSAndroid Build Coastguard Worker 	       Skip the first word, which is the section group flag.
1825*7304104dSAndroid Build Coastguard Worker 	       Everything else is a section index.  */
1826*7304104dSAndroid Build Coastguard Worker 	    Elf32_Word *shndx = (Elf32_Word *) outdata->d_buf;
1827*7304104dSAndroid Build Coastguard Worker 	    for (size_t i = 1; i < shdr_mem.sh_size / sizeof (Elf32_Word); ++i)
1828*7304104dSAndroid Build Coastguard Worker 	      if (shndx[i]  == SHN_UNDEF || shndx[i] >= stripped_shnum)
1829*7304104dSAndroid Build Coastguard Worker 		error_exit (0,
1830*7304104dSAndroid Build Coastguard Worker 			    _("group has invalid section index [%zd]"), i);
1831*7304104dSAndroid Build Coastguard Worker 	      else
1832*7304104dSAndroid Build Coastguard Worker 		shndx[i] = ndx_section[shndx[i] - 1];
1833*7304104dSAndroid Build Coastguard Worker 	  }
1834*7304104dSAndroid Build Coastguard Worker       }
1835*7304104dSAndroid Build Coastguard Worker 
1836*7304104dSAndroid Build Coastguard Worker   /* We may need to update the symbol table.  */
1837*7304104dSAndroid Build Coastguard Worker   Elf_Data *symdata = NULL;
1838*7304104dSAndroid Build Coastguard Worker   Dwelf_Strtab *symstrtab = NULL;
1839*7304104dSAndroid Build Coastguard Worker   Elf_Data *symstrdata = NULL;
1840*7304104dSAndroid Build Coastguard Worker   if (unstripped_symtab != NULL && (stripped_symtab != NULL
1841*7304104dSAndroid Build Coastguard Worker 				    || check_prelink /* Section adjustments. */
1842*7304104dSAndroid Build Coastguard Worker 				    || (stripped_ehdr->e_type != ET_REL
1843*7304104dSAndroid Build Coastguard Worker 					&& bias != 0)))
1844*7304104dSAndroid Build Coastguard Worker     {
1845*7304104dSAndroid Build Coastguard Worker       /* Merge the stripped file's symbol table into the unstripped one.  */
1846*7304104dSAndroid Build Coastguard Worker       const size_t stripped_nsym = (stripped_symtab == NULL ? 1
1847*7304104dSAndroid Build Coastguard Worker 				    : (stripped_symtab->shdr.sh_size
1848*7304104dSAndroid Build Coastguard Worker 				       / (stripped_symtab->shdr.sh_entsize == 0
1849*7304104dSAndroid Build Coastguard Worker 					  ? 1
1850*7304104dSAndroid Build Coastguard Worker 					  : stripped_symtab->shdr.sh_entsize)));
1851*7304104dSAndroid Build Coastguard Worker 
1852*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
1853*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (unstripped_symtab, &shdr_mem);
1854*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1855*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_entsize == 0)
1856*7304104dSAndroid Build Coastguard Worker 	error_exit (0,
1857*7304104dSAndroid Build Coastguard Worker 		    "unstripped SYMTAB section cannot have zero sh_entsize");
1858*7304104dSAndroid Build Coastguard Worker       const size_t unstripped_nsym = shdr->sh_size / shdr->sh_entsize;
1859*7304104dSAndroid Build Coastguard Worker 
1860*7304104dSAndroid Build Coastguard Worker       /* First collect all the symbols from both tables.  */
1861*7304104dSAndroid Build Coastguard Worker 
1862*7304104dSAndroid Build Coastguard Worker       const size_t total_syms = stripped_nsym - 1 + unstripped_nsym - 1;
1863*7304104dSAndroid Build Coastguard Worker       struct symbol *symbols = xmalloc (total_syms * sizeof (struct symbol));
1864*7304104dSAndroid Build Coastguard Worker       size_t *symndx_map = xmalloc (total_syms * sizeof (size_t));
1865*7304104dSAndroid Build Coastguard Worker 
1866*7304104dSAndroid Build Coastguard Worker       if (stripped_symtab != NULL)
1867*7304104dSAndroid Build Coastguard Worker 	collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL,
1868*7304104dSAndroid Build Coastguard Worker 			 stripped_symtab->scn,
1869*7304104dSAndroid Build Coastguard Worker 			 elf_getscn (stripped, stripped_symtab->shdr.sh_link),
1870*7304104dSAndroid Build Coastguard Worker 			 stripped_nsym, 0, ndx_section,
1871*7304104dSAndroid Build Coastguard Worker 			 symbols, symndx_map, NULL);
1872*7304104dSAndroid Build Coastguard Worker 
1873*7304104dSAndroid Build Coastguard Worker       Elf_Scn *unstripped_strtab = elf_getscn (unstripped, shdr->sh_link);
1874*7304104dSAndroid Build Coastguard Worker       collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL,
1875*7304104dSAndroid Build Coastguard Worker 		       unstripped_symtab, unstripped_strtab, unstripped_nsym,
1876*7304104dSAndroid Build Coastguard Worker 		       stripped_ehdr->e_type == ET_REL ? 0 : bias, NULL,
1877*7304104dSAndroid Build Coastguard Worker 		       &symbols[stripped_nsym - 1],
1878*7304104dSAndroid Build Coastguard Worker 		       &symndx_map[stripped_nsym - 1], split_bss);
1879*7304104dSAndroid Build Coastguard Worker 
1880*7304104dSAndroid Build Coastguard Worker       /* Next, sort our array of all symbols.  */
1881*7304104dSAndroid Build Coastguard Worker       qsort (symbols, total_syms, sizeof symbols[0], compare_symbols);
1882*7304104dSAndroid Build Coastguard Worker 
1883*7304104dSAndroid Build Coastguard Worker       /* Now we can weed out the duplicates.  Assign remaining symbols
1884*7304104dSAndroid Build Coastguard Worker 	 new slots, collecting a map from old indices to new.  */
1885*7304104dSAndroid Build Coastguard Worker       size_t nsym = 0;
1886*7304104dSAndroid Build Coastguard Worker       for (struct symbol *s = symbols; s < &symbols[total_syms]; ++s)
1887*7304104dSAndroid Build Coastguard Worker 	{
1888*7304104dSAndroid Build Coastguard Worker 	  /* Skip a section symbol for a removed section.  */
1889*7304104dSAndroid Build Coastguard Worker 	  if (s->shndx == SHN_UNDEF
1890*7304104dSAndroid Build Coastguard Worker 	      && GELF_ST_TYPE (s->info.info) == STT_SECTION)
1891*7304104dSAndroid Build Coastguard Worker 	    {
1892*7304104dSAndroid Build Coastguard Worker 	      s->name = NULL;	/* Mark as discarded. */
1893*7304104dSAndroid Build Coastguard Worker 	      *s->map = STN_UNDEF;
1894*7304104dSAndroid Build Coastguard Worker 	      s->duplicate = NULL;
1895*7304104dSAndroid Build Coastguard Worker 	      continue;
1896*7304104dSAndroid Build Coastguard Worker 	    }
1897*7304104dSAndroid Build Coastguard Worker 
1898*7304104dSAndroid Build Coastguard Worker 	  struct symbol *n = s;
1899*7304104dSAndroid Build Coastguard Worker 	  while (n + 1 < &symbols[total_syms]
1900*7304104dSAndroid Build Coastguard Worker 		 && !compare_symbols_duplicate (s, n + 1))
1901*7304104dSAndroid Build Coastguard Worker 	    ++n;
1902*7304104dSAndroid Build Coastguard Worker 
1903*7304104dSAndroid Build Coastguard Worker 	  while (s < n)
1904*7304104dSAndroid Build Coastguard Worker 	    {
1905*7304104dSAndroid Build Coastguard Worker 	      /* This is a duplicate.  Its twin will get the next slot.  */
1906*7304104dSAndroid Build Coastguard Worker 	      s->name = NULL;	/* Mark as discarded. */
1907*7304104dSAndroid Build Coastguard Worker 	      s->duplicate = n->map;
1908*7304104dSAndroid Build Coastguard Worker 	      ++s;
1909*7304104dSAndroid Build Coastguard Worker 	    }
1910*7304104dSAndroid Build Coastguard Worker 
1911*7304104dSAndroid Build Coastguard Worker 	  /* Allocate the next slot.  */
1912*7304104dSAndroid Build Coastguard Worker 	  *s->map = ++nsym;
1913*7304104dSAndroid Build Coastguard Worker 	}
1914*7304104dSAndroid Build Coastguard Worker 
1915*7304104dSAndroid Build Coastguard Worker       /* Now we sort again, to determine the order in the output.  */
1916*7304104dSAndroid Build Coastguard Worker       qsort (symbols, total_syms, sizeof symbols[0], compare_symbols_output);
1917*7304104dSAndroid Build Coastguard Worker 
1918*7304104dSAndroid Build Coastguard Worker       if (nsym < total_syms)
1919*7304104dSAndroid Build Coastguard Worker 	/* The discarded symbols are now at the end of the table.  */
1920*7304104dSAndroid Build Coastguard Worker 	assert (symbols[nsym].name == NULL);
1921*7304104dSAndroid Build Coastguard Worker 
1922*7304104dSAndroid Build Coastguard Worker       /* Now a final pass updates the map with the final order,
1923*7304104dSAndroid Build Coastguard Worker 	 and builds up the new string table.  */
1924*7304104dSAndroid Build Coastguard Worker       symstrtab = dwelf_strtab_init (true);
1925*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < nsym; ++i)
1926*7304104dSAndroid Build Coastguard Worker 	{
1927*7304104dSAndroid Build Coastguard Worker 	  assert (symbols[i].name != NULL);
1928*7304104dSAndroid Build Coastguard Worker 	  assert (*symbols[i].map != 0);
1929*7304104dSAndroid Build Coastguard Worker 	  *symbols[i].map = 1 + i;
1930*7304104dSAndroid Build Coastguard Worker 	  symbols[i].strent = dwelf_strtab_add (symstrtab, symbols[i].name);
1931*7304104dSAndroid Build Coastguard Worker 	}
1932*7304104dSAndroid Build Coastguard Worker 
1933*7304104dSAndroid Build Coastguard Worker       /* Scan the discarded symbols too, just to update their slots
1934*7304104dSAndroid Build Coastguard Worker 	 in SYMNDX_MAP to refer to their live duplicates.  */
1935*7304104dSAndroid Build Coastguard Worker       for (size_t i = nsym; i < total_syms; ++i)
1936*7304104dSAndroid Build Coastguard Worker 	{
1937*7304104dSAndroid Build Coastguard Worker 	  assert (symbols[i].name == NULL);
1938*7304104dSAndroid Build Coastguard Worker 	  if (symbols[i].duplicate == NULL)
1939*7304104dSAndroid Build Coastguard Worker 	    assert (*symbols[i].map == STN_UNDEF);
1940*7304104dSAndroid Build Coastguard Worker 	  else
1941*7304104dSAndroid Build Coastguard Worker 	    {
1942*7304104dSAndroid Build Coastguard Worker 	      assert (*symbols[i].duplicate != STN_UNDEF);
1943*7304104dSAndroid Build Coastguard Worker 	      *symbols[i].map = *symbols[i].duplicate;
1944*7304104dSAndroid Build Coastguard Worker 	    }
1945*7304104dSAndroid Build Coastguard Worker 	}
1946*7304104dSAndroid Build Coastguard Worker 
1947*7304104dSAndroid Build Coastguard Worker       /* Now we are ready to write the new symbol table.  */
1948*7304104dSAndroid Build Coastguard Worker       symdata = elf_getdata (unstripped_symtab, NULL);
1949*7304104dSAndroid Build Coastguard Worker       symstrdata = elf_getdata (unstripped_strtab, NULL);
1950*7304104dSAndroid Build Coastguard Worker       Elf_Data *shndxdata = NULL;	/* XXX */
1951*7304104dSAndroid Build Coastguard Worker 
1952*7304104dSAndroid Build Coastguard Worker       /* If symtab and the section header table share the string table
1953*7304104dSAndroid Build Coastguard Worker 	 add the section names to the strtab and then (after finalizing)
1954*7304104dSAndroid Build Coastguard Worker 	 fixup the section header sh_names.  Also dispose of the old data.  */
1955*7304104dSAndroid Build Coastguard Worker       Dwelf_Strent *unstripped_strent[unstripped_shnum - 1];
1956*7304104dSAndroid Build Coastguard Worker       if (unstripped_shstrndx == elf_ndxscn (unstripped_strtab))
1957*7304104dSAndroid Build Coastguard Worker 	{
1958*7304104dSAndroid Build Coastguard Worker 	  for (size_t i = 0; i < unstripped_shnum - 1; ++i)
1959*7304104dSAndroid Build Coastguard Worker 	    {
1960*7304104dSAndroid Build Coastguard Worker 	      Elf_Scn *sec = elf_getscn (unstripped, i + 1);
1961*7304104dSAndroid Build Coastguard Worker 	      GElf_Shdr mem;
1962*7304104dSAndroid Build Coastguard Worker 	      GElf_Shdr *hdr = gelf_getshdr (sec, &mem);
1963*7304104dSAndroid Build Coastguard Worker 	      const char *name = get_section_name (i + 1, hdr, shstrtab);
1964*7304104dSAndroid Build Coastguard Worker 	      unstripped_strent[i] = dwelf_strtab_add (symstrtab, name);
1965*7304104dSAndroid Build Coastguard Worker 	      ELF_CHECK (unstripped_strent[i] != NULL,
1966*7304104dSAndroid Build Coastguard Worker 			 _("cannot add section name to string table: %s"));
1967*7304104dSAndroid Build Coastguard Worker 	    }
1968*7304104dSAndroid Build Coastguard Worker 
1969*7304104dSAndroid Build Coastguard Worker 	  if (strtab != NULL)
1970*7304104dSAndroid Build Coastguard Worker 	    {
1971*7304104dSAndroid Build Coastguard Worker 	      dwelf_strtab_free (strtab);
1972*7304104dSAndroid Build Coastguard Worker 	      free (strtab_data->d_buf);
1973*7304104dSAndroid Build Coastguard Worker 	      strtab = NULL;
1974*7304104dSAndroid Build Coastguard Worker 	    }
1975*7304104dSAndroid Build Coastguard Worker 	}
1976*7304104dSAndroid Build Coastguard Worker 
1977*7304104dSAndroid Build Coastguard Worker       if (dwelf_strtab_finalize (symstrtab, symstrdata) == NULL)
1978*7304104dSAndroid Build Coastguard Worker 	error_exit (0, "Not enough memory to create symbol table");
1979*7304104dSAndroid Build Coastguard Worker 
1980*7304104dSAndroid Build Coastguard Worker       elf_flagdata (symstrdata, ELF_C_SET, ELF_F_DIRTY);
1981*7304104dSAndroid Build Coastguard Worker 
1982*7304104dSAndroid Build Coastguard Worker       /* And update the section header names if necessary.  */
1983*7304104dSAndroid Build Coastguard Worker       if (unstripped_shstrndx == elf_ndxscn (unstripped_strtab))
1984*7304104dSAndroid Build Coastguard Worker 	{
1985*7304104dSAndroid Build Coastguard Worker 	  for (size_t i = 0; i < unstripped_shnum - 1; ++i)
1986*7304104dSAndroid Build Coastguard Worker 	    {
1987*7304104dSAndroid Build Coastguard Worker 	      Elf_Scn *sec = elf_getscn (unstripped, i + 1);
1988*7304104dSAndroid Build Coastguard Worker 	      GElf_Shdr mem;
1989*7304104dSAndroid Build Coastguard Worker 	      GElf_Shdr *hdr = gelf_getshdr (sec, &mem);
1990*7304104dSAndroid Build Coastguard Worker 	      shdr->sh_name = dwelf_strent_off (unstripped_strent[i]);
1991*7304104dSAndroid Build Coastguard Worker 	      update_shdr (sec, hdr);
1992*7304104dSAndroid Build Coastguard Worker 	    }
1993*7304104dSAndroid Build Coastguard Worker 	}
1994*7304104dSAndroid Build Coastguard Worker 
1995*7304104dSAndroid Build Coastguard Worker       /* Now update the symtab shdr.  Reload symtab shdr because sh_name
1996*7304104dSAndroid Build Coastguard Worker 	 might have changed above. */
1997*7304104dSAndroid Build Coastguard Worker       shdr = gelf_getshdr (unstripped_symtab, &shdr_mem);
1998*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1999*7304104dSAndroid Build Coastguard Worker 
2000*7304104dSAndroid Build Coastguard Worker       shdr->sh_size = symdata->d_size = (1 + nsym) * shdr->sh_entsize;
2001*7304104dSAndroid Build Coastguard Worker       symdata->d_buf = xmalloc (symdata->d_size);
2002*7304104dSAndroid Build Coastguard Worker       record_new_data (symdata->d_buf);
2003*7304104dSAndroid Build Coastguard Worker 
2004*7304104dSAndroid Build Coastguard Worker       GElf_Sym sym;
2005*7304104dSAndroid Build Coastguard Worker       memset (&sym, 0, sizeof sym);
2006*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, 0, &sym, SHN_UNDEF),
2007*7304104dSAndroid Build Coastguard Worker 		 _("cannot update symbol table: %s"));
2008*7304104dSAndroid Build Coastguard Worker 
2009*7304104dSAndroid Build Coastguard Worker       shdr->sh_info = 1;
2010*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < nsym; ++i)
2011*7304104dSAndroid Build Coastguard Worker 	{
2012*7304104dSAndroid Build Coastguard Worker 	  struct symbol *s = &symbols[i];
2013*7304104dSAndroid Build Coastguard Worker 
2014*7304104dSAndroid Build Coastguard Worker 	  /* Fill in the symbol details.  */
2015*7304104dSAndroid Build Coastguard Worker 	  sym.st_name = dwelf_strent_off (s->strent);
2016*7304104dSAndroid Build Coastguard Worker 	  sym.st_value = s->value; /* Already biased to output address.  */
2017*7304104dSAndroid Build Coastguard Worker 	  sym.st_size = s->size;
2018*7304104dSAndroid Build Coastguard Worker 	  sym.st_shndx = s->shndx; /* Already mapped to output index.  */
2019*7304104dSAndroid Build Coastguard Worker 	  sym.st_info = s->info.info;
2020*7304104dSAndroid Build Coastguard Worker 	  sym.st_other = s->info.other;
2021*7304104dSAndroid Build Coastguard Worker 
2022*7304104dSAndroid Build Coastguard Worker 	  /* Keep track of the number of leading local symbols.  */
2023*7304104dSAndroid Build Coastguard Worker 	  if (GELF_ST_BIND (sym.st_info) == STB_LOCAL)
2024*7304104dSAndroid Build Coastguard Worker 	    {
2025*7304104dSAndroid Build Coastguard Worker 	      assert (shdr->sh_info == 1 + i);
2026*7304104dSAndroid Build Coastguard Worker 	      shdr->sh_info = 1 + i + 1;
2027*7304104dSAndroid Build Coastguard Worker 	    }
2028*7304104dSAndroid Build Coastguard Worker 
2029*7304104dSAndroid Build Coastguard Worker 	  ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, 1 + i,
2030*7304104dSAndroid Build Coastguard Worker 					   &sym, SHN_UNDEF),
2031*7304104dSAndroid Build Coastguard Worker 		     _("cannot update symbol table: %s"));
2032*7304104dSAndroid Build Coastguard Worker 
2033*7304104dSAndroid Build Coastguard Worker 	}
2034*7304104dSAndroid Build Coastguard Worker       elf_flagdata (symdata, ELF_C_SET, ELF_F_DIRTY);
2035*7304104dSAndroid Build Coastguard Worker       update_shdr (unstripped_symtab, shdr);
2036*7304104dSAndroid Build Coastguard Worker 
2037*7304104dSAndroid Build Coastguard Worker       /* Track which sections are adjusted during the first round
2038*7304104dSAndroid Build Coastguard Worker 	 of calls to adjust_relocs.  */
2039*7304104dSAndroid Build Coastguard Worker       bool scn_adjusted[unstripped_shnum];
2040*7304104dSAndroid Build Coastguard Worker       memset (scn_adjusted, 0, sizeof scn_adjusted);
2041*7304104dSAndroid Build Coastguard Worker 
2042*7304104dSAndroid Build Coastguard Worker       if (stripped_symtab != NULL)
2043*7304104dSAndroid Build Coastguard Worker 	{
2044*7304104dSAndroid Build Coastguard Worker 	  /* Adjust any relocations referring to the old symbol table.  */
2045*7304104dSAndroid Build Coastguard Worker 	  const size_t old_sh_link = elf_ndxscn (stripped_symtab->scn);
2046*7304104dSAndroid Build Coastguard Worker 	  for (const struct section *sec = sections;
2047*7304104dSAndroid Build Coastguard Worker 	       sec < &sections[stripped_shnum - 1];
2048*7304104dSAndroid Build Coastguard Worker 	       ++sec)
2049*7304104dSAndroid Build Coastguard Worker 	    if (sec->outscn != NULL && sec->shdr.sh_link == old_sh_link)
2050*7304104dSAndroid Build Coastguard Worker 	      {
2051*7304104dSAndroid Build Coastguard Worker 		adjust_relocs (sec->outscn, sec->scn, &sec->shdr,
2052*7304104dSAndroid Build Coastguard Worker 			       symndx_map, total_syms, shdr);
2053*7304104dSAndroid Build Coastguard Worker 		scn_adjusted[elf_ndxscn (sec->outscn)] = true;
2054*7304104dSAndroid Build Coastguard Worker 	      }
2055*7304104dSAndroid Build Coastguard Worker 	}
2056*7304104dSAndroid Build Coastguard Worker 
2057*7304104dSAndroid Build Coastguard Worker       /* Also adjust references to the other old symbol table.  */
2058*7304104dSAndroid Build Coastguard Worker       adjust_all_relocs (unstripped, unstripped_symtab, shdr,
2059*7304104dSAndroid Build Coastguard Worker 			 &symndx_map[stripped_nsym - 1],
2060*7304104dSAndroid Build Coastguard Worker 			 total_syms - (stripped_nsym - 1),
2061*7304104dSAndroid Build Coastguard Worker 			 scn_adjusted);
2062*7304104dSAndroid Build Coastguard Worker 
2063*7304104dSAndroid Build Coastguard Worker       free (symbols);
2064*7304104dSAndroid Build Coastguard Worker       free (symndx_map);
2065*7304104dSAndroid Build Coastguard Worker     }
2066*7304104dSAndroid Build Coastguard Worker   else if (stripped_symtab != NULL && stripped_shnum != unstripped_shnum)
2067*7304104dSAndroid Build Coastguard Worker     check_symtab_section_symbols (unstripped,
2068*7304104dSAndroid Build Coastguard Worker 				  stripped_ehdr->e_type == ET_REL,
2069*7304104dSAndroid Build Coastguard Worker 				  stripped_symtab->scn,
2070*7304104dSAndroid Build Coastguard Worker 				  unstripped_shnum, unstripped_shstrndx,
2071*7304104dSAndroid Build Coastguard Worker 				  stripped_symtab->outscn,
2072*7304104dSAndroid Build Coastguard Worker 				  stripped_shnum, stripped_shstrndx,
2073*7304104dSAndroid Build Coastguard Worker 				  debuglink);
2074*7304104dSAndroid Build Coastguard Worker 
2075*7304104dSAndroid Build Coastguard Worker   if (stripped_dynsym != NULL)
2076*7304104dSAndroid Build Coastguard Worker     (void) check_symtab_section_symbols (unstripped,
2077*7304104dSAndroid Build Coastguard Worker 					 stripped_ehdr->e_type == ET_REL,
2078*7304104dSAndroid Build Coastguard Worker 					 stripped_dynsym->outscn,
2079*7304104dSAndroid Build Coastguard Worker 					 unstripped_shnum,
2080*7304104dSAndroid Build Coastguard Worker 					 unstripped_shstrndx,
2081*7304104dSAndroid Build Coastguard Worker 					 stripped_dynsym->scn, stripped_shnum,
2082*7304104dSAndroid Build Coastguard Worker 					 stripped_shstrndx, debuglink);
2083*7304104dSAndroid Build Coastguard Worker 
2084*7304104dSAndroid Build Coastguard Worker   /* We need to preserve the layout of the stripped file so the
2085*7304104dSAndroid Build Coastguard Worker      phdrs will match up.  This requires us to do our own layout of
2086*7304104dSAndroid Build Coastguard Worker      the added sections.  We do manual layout even for ET_REL just
2087*7304104dSAndroid Build Coastguard Worker      so we can try to match what the original probably had.  */
2088*7304104dSAndroid Build Coastguard Worker 
2089*7304104dSAndroid Build Coastguard Worker   elf_flagelf (unstripped, ELF_C_SET, ELF_F_LAYOUT);
2090*7304104dSAndroid Build Coastguard Worker 
2091*7304104dSAndroid Build Coastguard Worker   if (offset == 0)
2092*7304104dSAndroid Build Coastguard Worker     /* For ET_REL we are starting the layout from scratch.  */
2093*7304104dSAndroid Build Coastguard Worker     offset = gelf_fsize (unstripped, ELF_T_EHDR, 1, EV_CURRENT);
2094*7304104dSAndroid Build Coastguard Worker 
2095*7304104dSAndroid Build Coastguard Worker   bool skip_reloc = false;
2096*7304104dSAndroid Build Coastguard Worker   do
2097*7304104dSAndroid Build Coastguard Worker     {
2098*7304104dSAndroid Build Coastguard Worker       skip_reloc = !skip_reloc;
2099*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < unstripped_shnum - 1; ++i)
2100*7304104dSAndroid Build Coastguard Worker 	if (!placed[i])
2101*7304104dSAndroid Build Coastguard Worker 	  {
2102*7304104dSAndroid Build Coastguard Worker 	    scn = elf_getscn (unstripped, 1 + i);
2103*7304104dSAndroid Build Coastguard Worker 
2104*7304104dSAndroid Build Coastguard Worker 	    GElf_Shdr shdr_mem;
2105*7304104dSAndroid Build Coastguard Worker 	    GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2106*7304104dSAndroid Build Coastguard Worker 	    ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
2107*7304104dSAndroid Build Coastguard Worker 
2108*7304104dSAndroid Build Coastguard Worker 	    /* We must make sure we have read in the data of all sections
2109*7304104dSAndroid Build Coastguard Worker 	       beforehand and marked them to be written out.  When we're
2110*7304104dSAndroid Build Coastguard Worker 	       modifying the existing file in place, we might overwrite
2111*7304104dSAndroid Build Coastguard Worker 	       this part of the file before we get to handling the section.  */
2112*7304104dSAndroid Build Coastguard Worker 
2113*7304104dSAndroid Build Coastguard Worker 	    ELF_CHECK (elf_flagdata (elf_getdata (scn, NULL),
2114*7304104dSAndroid Build Coastguard Worker 				     ELF_C_SET, ELF_F_DIRTY),
2115*7304104dSAndroid Build Coastguard Worker 		       _("cannot read section data: %s"));
2116*7304104dSAndroid Build Coastguard Worker 
2117*7304104dSAndroid Build Coastguard Worker 	    if (skip_reloc
2118*7304104dSAndroid Build Coastguard Worker 		&& (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA))
2119*7304104dSAndroid Build Coastguard Worker 	      continue;
2120*7304104dSAndroid Build Coastguard Worker 
2121*7304104dSAndroid Build Coastguard Worker 	    GElf_Off align = shdr->sh_addralign ?: 1;
2122*7304104dSAndroid Build Coastguard Worker 	    offset = (offset + align - 1) & -align;
2123*7304104dSAndroid Build Coastguard Worker 	    shdr->sh_offset = offset;
2124*7304104dSAndroid Build Coastguard Worker 	    if (shdr->sh_type != SHT_NOBITS)
2125*7304104dSAndroid Build Coastguard Worker 	      offset += shdr->sh_size;
2126*7304104dSAndroid Build Coastguard Worker 
2127*7304104dSAndroid Build Coastguard Worker 	    update_shdr (scn, shdr);
2128*7304104dSAndroid Build Coastguard Worker 
2129*7304104dSAndroid Build Coastguard Worker 	    if (unstripped_shstrndx == 1 + i)
2130*7304104dSAndroid Build Coastguard Worker 	      {
2131*7304104dSAndroid Build Coastguard Worker 		/* Place the section headers immediately after
2132*7304104dSAndroid Build Coastguard Worker 		   .shstrtab, and update the ELF header.  */
2133*7304104dSAndroid Build Coastguard Worker 
2134*7304104dSAndroid Build Coastguard Worker 		GElf_Ehdr ehdr_mem;
2135*7304104dSAndroid Build Coastguard Worker 		GElf_Ehdr *ehdr = gelf_getehdr (unstripped, &ehdr_mem);
2136*7304104dSAndroid Build Coastguard Worker 		ELF_CHECK (ehdr != NULL, _("cannot get ELF header: %s"));
2137*7304104dSAndroid Build Coastguard Worker 
2138*7304104dSAndroid Build Coastguard Worker 		GElf_Off sh_align = gelf_getclass (unstripped) * 4;
2139*7304104dSAndroid Build Coastguard Worker 		offset = (offset + sh_align - 1) & -sh_align;
2140*7304104dSAndroid Build Coastguard Worker 		ehdr->e_shnum = unstripped_shnum;
2141*7304104dSAndroid Build Coastguard Worker 		ehdr->e_shoff = offset;
2142*7304104dSAndroid Build Coastguard Worker 		offset += unstripped_shnum * ehdr->e_shentsize;
2143*7304104dSAndroid Build Coastguard Worker 		ELF_CHECK (gelf_update_ehdr (unstripped, ehdr),
2144*7304104dSAndroid Build Coastguard Worker 			   _("cannot update ELF header: %s"));
2145*7304104dSAndroid Build Coastguard Worker 	      }
2146*7304104dSAndroid Build Coastguard Worker 
2147*7304104dSAndroid Build Coastguard Worker 	    placed[i] = true;
2148*7304104dSAndroid Build Coastguard Worker 	  }
2149*7304104dSAndroid Build Coastguard Worker     }
2150*7304104dSAndroid Build Coastguard Worker   while (skip_reloc);
2151*7304104dSAndroid Build Coastguard Worker 
2152*7304104dSAndroid Build Coastguard Worker   size_t phnum;
2153*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (elf_getphdrnum (stripped, &phnum) == 0,
2154*7304104dSAndroid Build Coastguard Worker 	     _("cannot get number of program headers: %s"));
2155*7304104dSAndroid Build Coastguard Worker 
2156*7304104dSAndroid Build Coastguard Worker   if (phnum > 0)
2157*7304104dSAndroid Build Coastguard Worker     ELF_CHECK (gelf_newphdr (unstripped, phnum),
2158*7304104dSAndroid Build Coastguard Worker 	       _("cannot create program headers: %s"));
2159*7304104dSAndroid Build Coastguard Worker 
2160*7304104dSAndroid Build Coastguard Worker   /* Copy each program header from the stripped file.  */
2161*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < phnum; ++i)
2162*7304104dSAndroid Build Coastguard Worker     {
2163*7304104dSAndroid Build Coastguard Worker       GElf_Phdr phdr_mem;
2164*7304104dSAndroid Build Coastguard Worker       GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem);
2165*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (phdr != NULL, _("cannot get program header: %s"));
2166*7304104dSAndroid Build Coastguard Worker 
2167*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_update_phdr (unstripped, i, phdr),
2168*7304104dSAndroid Build Coastguard Worker 		 _("cannot update program header: %s"));
2169*7304104dSAndroid Build Coastguard Worker     }
2170*7304104dSAndroid Build Coastguard Worker 
2171*7304104dSAndroid Build Coastguard Worker   /* Finally, write out the file.  */
2172*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (elf_update (unstripped, ELF_C_WRITE) > 0,
2173*7304104dSAndroid Build Coastguard Worker 	     _("cannot write output file: %s"));
2174*7304104dSAndroid Build Coastguard Worker 
2175*7304104dSAndroid Build Coastguard Worker   if (strtab != NULL)
2176*7304104dSAndroid Build Coastguard Worker     {
2177*7304104dSAndroid Build Coastguard Worker       dwelf_strtab_free (strtab);
2178*7304104dSAndroid Build Coastguard Worker       free (strtab_data->d_buf);
2179*7304104dSAndroid Build Coastguard Worker     }
2180*7304104dSAndroid Build Coastguard Worker 
2181*7304104dSAndroid Build Coastguard Worker   if (symstrtab != NULL)
2182*7304104dSAndroid Build Coastguard Worker     {
2183*7304104dSAndroid Build Coastguard Worker       dwelf_strtab_free (symstrtab);
2184*7304104dSAndroid Build Coastguard Worker       free (symstrdata->d_buf);
2185*7304104dSAndroid Build Coastguard Worker     }
2186*7304104dSAndroid Build Coastguard Worker   free_new_data ();
2187*7304104dSAndroid Build Coastguard Worker }
2188*7304104dSAndroid Build Coastguard Worker 
2189*7304104dSAndroid Build Coastguard Worker /* Process one pair of files, already opened.  */
2190*7304104dSAndroid Build Coastguard Worker static void
handle_file(const char * output_file,bool create_dirs,Elf * stripped,const GElf_Ehdr * stripped_ehdr,Elf * unstripped)2191*7304104dSAndroid Build Coastguard Worker handle_file (const char *output_file, bool create_dirs,
2192*7304104dSAndroid Build Coastguard Worker 	     Elf *stripped, const GElf_Ehdr *stripped_ehdr,
2193*7304104dSAndroid Build Coastguard Worker 	     Elf *unstripped)
2194*7304104dSAndroid Build Coastguard Worker {
2195*7304104dSAndroid Build Coastguard Worker   size_t phnum;
2196*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (elf_getphdrnum (stripped, &phnum) == 0,
2197*7304104dSAndroid Build Coastguard Worker 	     _("cannot get number of program headers: %s"));
2198*7304104dSAndroid Build Coastguard Worker 
2199*7304104dSAndroid Build Coastguard Worker   /* Determine the address bias between the debuginfo file and the main
2200*7304104dSAndroid Build Coastguard Worker      file, which may have been modified by prelinking.  */
2201*7304104dSAndroid Build Coastguard Worker   GElf_Addr bias = 0;
2202*7304104dSAndroid Build Coastguard Worker   if (unstripped != NULL)
2203*7304104dSAndroid Build Coastguard Worker     for (size_t i = 0; i < phnum; ++i)
2204*7304104dSAndroid Build Coastguard Worker       {
2205*7304104dSAndroid Build Coastguard Worker 	GElf_Phdr phdr_mem;
2206*7304104dSAndroid Build Coastguard Worker 	GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem);
2207*7304104dSAndroid Build Coastguard Worker 	ELF_CHECK (phdr != NULL, _("cannot get program header: %s"));
2208*7304104dSAndroid Build Coastguard Worker 	if (phdr->p_type == PT_LOAD)
2209*7304104dSAndroid Build Coastguard Worker 	  {
2210*7304104dSAndroid Build Coastguard Worker 	    GElf_Phdr unstripped_phdr_mem;
2211*7304104dSAndroid Build Coastguard Worker 	    GElf_Phdr *unstripped_phdr = gelf_getphdr (unstripped, i,
2212*7304104dSAndroid Build Coastguard Worker 						       &unstripped_phdr_mem);
2213*7304104dSAndroid Build Coastguard Worker 	    ELF_CHECK (unstripped_phdr != NULL,
2214*7304104dSAndroid Build Coastguard Worker 		       _("cannot get program header: %s"));
2215*7304104dSAndroid Build Coastguard Worker 	    bias = phdr->p_vaddr - unstripped_phdr->p_vaddr;
2216*7304104dSAndroid Build Coastguard Worker 	    break;
2217*7304104dSAndroid Build Coastguard Worker 	  }
2218*7304104dSAndroid Build Coastguard Worker       }
2219*7304104dSAndroid Build Coastguard Worker 
2220*7304104dSAndroid Build Coastguard Worker   /* One day we could adjust all the DWARF data (like prelink itself does).  */
2221*7304104dSAndroid Build Coastguard Worker   if (bias != 0)
2222*7304104dSAndroid Build Coastguard Worker     {
2223*7304104dSAndroid Build Coastguard Worker       if (output_file == NULL)
2224*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("\
2225*7304104dSAndroid Build Coastguard Worker DWARF data not adjusted for prelinking bias; consider prelink -u"));
2226*7304104dSAndroid Build Coastguard Worker       else
2227*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("\
2228*7304104dSAndroid Build Coastguard Worker DWARF data in '%s' not adjusted for prelinking bias; consider prelink -u"),
2229*7304104dSAndroid Build Coastguard Worker 	       output_file);
2230*7304104dSAndroid Build Coastguard Worker     }
2231*7304104dSAndroid Build Coastguard Worker 
2232*7304104dSAndroid Build Coastguard Worker   if (output_file == NULL)
2233*7304104dSAndroid Build Coastguard Worker     /* Modify the unstripped file in place.  */
2234*7304104dSAndroid Build Coastguard Worker     copy_elided_sections (unstripped, stripped, stripped_ehdr, bias);
2235*7304104dSAndroid Build Coastguard Worker   else
2236*7304104dSAndroid Build Coastguard Worker     {
2237*7304104dSAndroid Build Coastguard Worker       if (create_dirs)
2238*7304104dSAndroid Build Coastguard Worker 	make_directories (output_file);
2239*7304104dSAndroid Build Coastguard Worker 
2240*7304104dSAndroid Build Coastguard Worker       /* Copy the unstripped file and then modify it.  */
2241*7304104dSAndroid Build Coastguard Worker       int outfd = open (output_file, O_RDWR | O_CREAT,
2242*7304104dSAndroid Build Coastguard Worker 			(stripped_ehdr->e_type == ET_REL
2243*7304104dSAndroid Build Coastguard Worker 			 ? DEFFILEMODE : ACCESSPERMS));
2244*7304104dSAndroid Build Coastguard Worker       if (outfd < 0)
2245*7304104dSAndroid Build Coastguard Worker 	error_exit (errno, _("cannot open '%s'"), output_file);
2246*7304104dSAndroid Build Coastguard Worker       Elf *outelf = elf_begin (outfd, ELF_C_WRITE, NULL);
2247*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (outelf != NULL, _("cannot create ELF descriptor: %s"));
2248*7304104dSAndroid Build Coastguard Worker 
2249*7304104dSAndroid Build Coastguard Worker       if (unstripped == NULL)
2250*7304104dSAndroid Build Coastguard Worker 	{
2251*7304104dSAndroid Build Coastguard Worker 	  /* Actually, we are just copying out the main file as it is.  */
2252*7304104dSAndroid Build Coastguard Worker 	  copy_elf (outelf, stripped);
2253*7304104dSAndroid Build Coastguard Worker 	  if (stripped_ehdr->e_type != ET_REL)
2254*7304104dSAndroid Build Coastguard Worker 	    elf_flagelf (outelf, ELF_C_SET, ELF_F_LAYOUT);
2255*7304104dSAndroid Build Coastguard Worker 	  ELF_CHECK (elf_update (outelf, ELF_C_WRITE) > 0,
2256*7304104dSAndroid Build Coastguard Worker 		     _("cannot write output file: %s"));
2257*7304104dSAndroid Build Coastguard Worker 	}
2258*7304104dSAndroid Build Coastguard Worker       else
2259*7304104dSAndroid Build Coastguard Worker 	{
2260*7304104dSAndroid Build Coastguard Worker 	  copy_elf (outelf, unstripped);
2261*7304104dSAndroid Build Coastguard Worker 	  copy_elided_sections (outelf, stripped, stripped_ehdr, bias);
2262*7304104dSAndroid Build Coastguard Worker 	}
2263*7304104dSAndroid Build Coastguard Worker 
2264*7304104dSAndroid Build Coastguard Worker       elf_end (outelf);
2265*7304104dSAndroid Build Coastguard Worker       close (outfd);
2266*7304104dSAndroid Build Coastguard Worker     }
2267*7304104dSAndroid Build Coastguard Worker }
2268*7304104dSAndroid Build Coastguard Worker 
2269*7304104dSAndroid Build Coastguard Worker static int
open_file(const char * file,bool writable)2270*7304104dSAndroid Build Coastguard Worker open_file (const char *file, bool writable)
2271*7304104dSAndroid Build Coastguard Worker {
2272*7304104dSAndroid Build Coastguard Worker   int fd = open (file, writable ? O_RDWR : O_RDONLY);
2273*7304104dSAndroid Build Coastguard Worker   if (fd < 0)
2274*7304104dSAndroid Build Coastguard Worker     error_exit (errno, _("cannot open '%s'"), file);
2275*7304104dSAndroid Build Coastguard Worker   return fd;
2276*7304104dSAndroid Build Coastguard Worker }
2277*7304104dSAndroid Build Coastguard Worker 
2278*7304104dSAndroid Build Coastguard Worker /* Warn, and exit if not forced to continue, if some ELF header
2279*7304104dSAndroid Build Coastguard Worker    sanity check for the stripped and unstripped files failed.  */
2280*7304104dSAndroid Build Coastguard Worker static void
warn(const char * msg,bool force,const char * stripped_file,const char * unstripped_file)2281*7304104dSAndroid Build Coastguard Worker warn (const char *msg, bool force,
2282*7304104dSAndroid Build Coastguard Worker       const char *stripped_file, const char *unstripped_file)
2283*7304104dSAndroid Build Coastguard Worker {
2284*7304104dSAndroid Build Coastguard Worker   error (force ? 0 : EXIT_FAILURE, 0, "%s'%s' and '%s' %s%s.",
2285*7304104dSAndroid Build Coastguard Worker 	 force ? _("WARNING: ") : "",
2286*7304104dSAndroid Build Coastguard Worker 	 stripped_file, unstripped_file, msg,
2287*7304104dSAndroid Build Coastguard Worker 	 force ? "" : _(", use --force"));
2288*7304104dSAndroid Build Coastguard Worker }
2289*7304104dSAndroid Build Coastguard Worker 
2290*7304104dSAndroid Build Coastguard Worker /* Handle a pair of files we need to open by name.  */
2291*7304104dSAndroid Build Coastguard Worker static void
handle_explicit_files(const char * output_file,bool create_dirs,bool force,const char * stripped_file,const char * unstripped_file)2292*7304104dSAndroid Build Coastguard Worker handle_explicit_files (const char *output_file, bool create_dirs, bool force,
2293*7304104dSAndroid Build Coastguard Worker 		       const char *stripped_file, const char *unstripped_file)
2294*7304104dSAndroid Build Coastguard Worker {
2295*7304104dSAndroid Build Coastguard Worker   int stripped_fd = open_file (stripped_file, false);
2296*7304104dSAndroid Build Coastguard Worker   Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL);
2297*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr stripped_ehdr;
2298*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr),
2299*7304104dSAndroid Build Coastguard Worker 	     _("cannot create ELF descriptor: %s"));
2300*7304104dSAndroid Build Coastguard Worker 
2301*7304104dSAndroid Build Coastguard Worker   int unstripped_fd = -1;
2302*7304104dSAndroid Build Coastguard Worker   Elf *unstripped = NULL;
2303*7304104dSAndroid Build Coastguard Worker   if (unstripped_file != NULL)
2304*7304104dSAndroid Build Coastguard Worker     {
2305*7304104dSAndroid Build Coastguard Worker       unstripped_fd = open_file (unstripped_file, output_file == NULL);
2306*7304104dSAndroid Build Coastguard Worker       unstripped = elf_begin (unstripped_fd,
2307*7304104dSAndroid Build Coastguard Worker 			      (output_file == NULL ? ELF_C_RDWR : ELF_C_READ),
2308*7304104dSAndroid Build Coastguard Worker 			      NULL);
2309*7304104dSAndroid Build Coastguard Worker       GElf_Ehdr unstripped_ehdr;
2310*7304104dSAndroid Build Coastguard Worker       ELF_CHECK (gelf_getehdr (unstripped, &unstripped_ehdr),
2311*7304104dSAndroid Build Coastguard Worker 		 _("cannot create ELF descriptor: %s"));
2312*7304104dSAndroid Build Coastguard Worker 
2313*7304104dSAndroid Build Coastguard Worker       if (memcmp (stripped_ehdr.e_ident,
2314*7304104dSAndroid Build Coastguard Worker 		  unstripped_ehdr.e_ident, EI_NIDENT) != 0)
2315*7304104dSAndroid Build Coastguard Worker 	warn (_("ELF header identification (e_ident) different"), force,
2316*7304104dSAndroid Build Coastguard Worker 	      stripped_file, unstripped_file);
2317*7304104dSAndroid Build Coastguard Worker 
2318*7304104dSAndroid Build Coastguard Worker       if (stripped_ehdr.e_type != unstripped_ehdr.e_type)
2319*7304104dSAndroid Build Coastguard Worker 	warn (_("ELF header type (e_type) different"), force,
2320*7304104dSAndroid Build Coastguard Worker 	      stripped_file, unstripped_file);
2321*7304104dSAndroid Build Coastguard Worker 
2322*7304104dSAndroid Build Coastguard Worker       if (stripped_ehdr.e_machine != unstripped_ehdr.e_machine)
2323*7304104dSAndroid Build Coastguard Worker 	warn (_("ELF header machine type (e_machine) different"), force,
2324*7304104dSAndroid Build Coastguard Worker 	      stripped_file, unstripped_file);
2325*7304104dSAndroid Build Coastguard Worker 
2326*7304104dSAndroid Build Coastguard Worker       if (stripped_ehdr.e_phnum < unstripped_ehdr.e_phnum)
2327*7304104dSAndroid Build Coastguard Worker 	warn (_("stripped program header (e_phnum) smaller than unstripped"),
2328*7304104dSAndroid Build Coastguard Worker 	      force, stripped_file, unstripped_file);
2329*7304104dSAndroid Build Coastguard Worker     }
2330*7304104dSAndroid Build Coastguard Worker 
2331*7304104dSAndroid Build Coastguard Worker   handle_file (output_file, create_dirs, stripped, &stripped_ehdr, unstripped);
2332*7304104dSAndroid Build Coastguard Worker 
2333*7304104dSAndroid Build Coastguard Worker   elf_end (stripped);
2334*7304104dSAndroid Build Coastguard Worker   close (stripped_fd);
2335*7304104dSAndroid Build Coastguard Worker 
2336*7304104dSAndroid Build Coastguard Worker   elf_end (unstripped);
2337*7304104dSAndroid Build Coastguard Worker   close (unstripped_fd);
2338*7304104dSAndroid Build Coastguard Worker }
2339*7304104dSAndroid Build Coastguard Worker 
2340*7304104dSAndroid Build Coastguard Worker 
2341*7304104dSAndroid Build Coastguard Worker /* Handle a pair of files opened implicitly by libdwfl for one module.  */
2342*7304104dSAndroid Build Coastguard Worker static void
handle_dwfl_module(const char * output_file,bool create_dirs,bool force,Dwfl_Module * mod,bool all,bool ignore,bool relocate)2343*7304104dSAndroid Build Coastguard Worker handle_dwfl_module (const char *output_file, bool create_dirs, bool force,
2344*7304104dSAndroid Build Coastguard Worker 		    Dwfl_Module *mod, bool all, bool ignore, bool relocate)
2345*7304104dSAndroid Build Coastguard Worker {
2346*7304104dSAndroid Build Coastguard Worker   GElf_Addr bias;
2347*7304104dSAndroid Build Coastguard Worker   Elf *stripped = dwfl_module_getelf (mod, &bias);
2348*7304104dSAndroid Build Coastguard Worker   if (stripped == NULL)
2349*7304104dSAndroid Build Coastguard Worker     {
2350*7304104dSAndroid Build Coastguard Worker       if (ignore)
2351*7304104dSAndroid Build Coastguard Worker 	return;
2352*7304104dSAndroid Build Coastguard Worker 
2353*7304104dSAndroid Build Coastguard Worker       const char *file;
2354*7304104dSAndroid Build Coastguard Worker       const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
2355*7304104dSAndroid Build Coastguard Worker 					      NULL, NULL, &file, NULL);
2356*7304104dSAndroid Build Coastguard Worker       if (file == NULL)
2357*7304104dSAndroid Build Coastguard Worker 	error_exit (0,
2358*7304104dSAndroid Build Coastguard Worker 		    _("cannot find stripped file for module '%s': %s"),
2359*7304104dSAndroid Build Coastguard Worker 		    modname, dwfl_errmsg (-1));
2360*7304104dSAndroid Build Coastguard Worker       else
2361*7304104dSAndroid Build Coastguard Worker 	error_exit (0,
2362*7304104dSAndroid Build Coastguard Worker 		    _("cannot open stripped file '%s' for module '%s': %s"),
2363*7304104dSAndroid Build Coastguard Worker 		    modname, file, dwfl_errmsg (-1));
2364*7304104dSAndroid Build Coastguard Worker     }
2365*7304104dSAndroid Build Coastguard Worker 
2366*7304104dSAndroid Build Coastguard Worker   Elf *debug = dwarf_getelf (dwfl_module_getdwarf (mod, &bias));
2367*7304104dSAndroid Build Coastguard Worker   if (debug == NULL && !all)
2368*7304104dSAndroid Build Coastguard Worker     {
2369*7304104dSAndroid Build Coastguard Worker       if (ignore)
2370*7304104dSAndroid Build Coastguard Worker 	return;
2371*7304104dSAndroid Build Coastguard Worker 
2372*7304104dSAndroid Build Coastguard Worker       const char *file;
2373*7304104dSAndroid Build Coastguard Worker       const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
2374*7304104dSAndroid Build Coastguard Worker 					      NULL, NULL, NULL, &file);
2375*7304104dSAndroid Build Coastguard Worker       if (file == NULL)
2376*7304104dSAndroid Build Coastguard Worker 	error_exit (0,
2377*7304104dSAndroid Build Coastguard Worker 		    _("cannot find debug file for module '%s': %s"),
2378*7304104dSAndroid Build Coastguard Worker 		    modname, dwfl_errmsg (-1));
2379*7304104dSAndroid Build Coastguard Worker       else
2380*7304104dSAndroid Build Coastguard Worker 	error_exit (0,
2381*7304104dSAndroid Build Coastguard Worker 		    _("cannot open debug file '%s' for module '%s': %s"),
2382*7304104dSAndroid Build Coastguard Worker 		    modname, file, dwfl_errmsg (-1));
2383*7304104dSAndroid Build Coastguard Worker     }
2384*7304104dSAndroid Build Coastguard Worker 
2385*7304104dSAndroid Build Coastguard Worker   if (debug == stripped)
2386*7304104dSAndroid Build Coastguard Worker     {
2387*7304104dSAndroid Build Coastguard Worker       if (all)
2388*7304104dSAndroid Build Coastguard Worker 	debug = NULL;
2389*7304104dSAndroid Build Coastguard Worker       else
2390*7304104dSAndroid Build Coastguard Worker 	{
2391*7304104dSAndroid Build Coastguard Worker 	  const char *file;
2392*7304104dSAndroid Build Coastguard Worker 	  const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
2393*7304104dSAndroid Build Coastguard Worker 						  NULL, NULL, &file, NULL);
2394*7304104dSAndroid Build Coastguard Worker 	  error_exit (0, _("module '%s' file '%s' is not stripped"),
2395*7304104dSAndroid Build Coastguard Worker 		      modname, file);
2396*7304104dSAndroid Build Coastguard Worker 	}
2397*7304104dSAndroid Build Coastguard Worker     }
2398*7304104dSAndroid Build Coastguard Worker 
2399*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr stripped_ehdr;
2400*7304104dSAndroid Build Coastguard Worker   ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr),
2401*7304104dSAndroid Build Coastguard Worker 	     _("cannot create ELF descriptor: %s"));
2402*7304104dSAndroid Build Coastguard Worker 
2403*7304104dSAndroid Build Coastguard Worker   if (stripped_ehdr.e_type == ET_REL)
2404*7304104dSAndroid Build Coastguard Worker     {
2405*7304104dSAndroid Build Coastguard Worker       if (!relocate)
2406*7304104dSAndroid Build Coastguard Worker 	{
2407*7304104dSAndroid Build Coastguard Worker 	  /* We can't use the Elf handles already open,
2408*7304104dSAndroid Build Coastguard Worker 	     because the DWARF sections have been relocated.  */
2409*7304104dSAndroid Build Coastguard Worker 
2410*7304104dSAndroid Build Coastguard Worker 	  const char *stripped_file = NULL;
2411*7304104dSAndroid Build Coastguard Worker 	  const char *unstripped_file = NULL;
2412*7304104dSAndroid Build Coastguard Worker 	  (void) dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL,
2413*7304104dSAndroid Build Coastguard Worker 				   &stripped_file, &unstripped_file);
2414*7304104dSAndroid Build Coastguard Worker 
2415*7304104dSAndroid Build Coastguard Worker 	  handle_explicit_files (output_file, create_dirs, force,
2416*7304104dSAndroid Build Coastguard Worker 				 stripped_file, unstripped_file);
2417*7304104dSAndroid Build Coastguard Worker 	  return;
2418*7304104dSAndroid Build Coastguard Worker 	}
2419*7304104dSAndroid Build Coastguard Worker 
2420*7304104dSAndroid Build Coastguard Worker       /* Relocation is what we want!  This ensures that all sections that can
2421*7304104dSAndroid Build Coastguard Worker 	 get sh_addr values assigned have them, even ones not used in DWARF.
2422*7304104dSAndroid Build Coastguard Worker 	 They might still be used in the symbol table.  */
2423*7304104dSAndroid Build Coastguard Worker       if (dwfl_module_relocations (mod) < 0)
2424*7304104dSAndroid Build Coastguard Worker 	error_exit (0,
2425*7304104dSAndroid Build Coastguard Worker 		    _("cannot cache section addresses for module '%s': %s"),
2426*7304104dSAndroid Build Coastguard Worker 		    dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
2427*7304104dSAndroid Build Coastguard Worker 		    dwfl_errmsg (-1));
2428*7304104dSAndroid Build Coastguard Worker     }
2429*7304104dSAndroid Build Coastguard Worker 
2430*7304104dSAndroid Build Coastguard Worker   handle_file (output_file, create_dirs, stripped, &stripped_ehdr, debug);
2431*7304104dSAndroid Build Coastguard Worker }
2432*7304104dSAndroid Build Coastguard Worker 
2433*7304104dSAndroid Build Coastguard Worker /* Handle one module being written to the output directory.  */
2434*7304104dSAndroid Build Coastguard Worker static void
handle_output_dir_module(const char * output_dir,Dwfl_Module * mod,bool force,bool all,bool ignore,bool modnames,bool relocate)2435*7304104dSAndroid Build Coastguard Worker handle_output_dir_module (const char *output_dir, Dwfl_Module *mod, bool force,
2436*7304104dSAndroid Build Coastguard Worker 			  bool all, bool ignore, bool modnames, bool relocate)
2437*7304104dSAndroid Build Coastguard Worker {
2438*7304104dSAndroid Build Coastguard Worker   if (! modnames)
2439*7304104dSAndroid Build Coastguard Worker     {
2440*7304104dSAndroid Build Coastguard Worker       /* Make sure we've searched for the ELF file.  */
2441*7304104dSAndroid Build Coastguard Worker       GElf_Addr bias;
2442*7304104dSAndroid Build Coastguard Worker       (void) dwfl_module_getelf (mod, &bias);
2443*7304104dSAndroid Build Coastguard Worker     }
2444*7304104dSAndroid Build Coastguard Worker 
2445*7304104dSAndroid Build Coastguard Worker   const char *file;
2446*7304104dSAndroid Build Coastguard Worker   const char *name = dwfl_module_info (mod, NULL, NULL, NULL,
2447*7304104dSAndroid Build Coastguard Worker 				       NULL, NULL, &file, NULL);
2448*7304104dSAndroid Build Coastguard Worker 
2449*7304104dSAndroid Build Coastguard Worker   if (file == NULL && ignore)
2450*7304104dSAndroid Build Coastguard Worker     return;
2451*7304104dSAndroid Build Coastguard Worker 
2452*7304104dSAndroid Build Coastguard Worker   char *output_file = xasprintf ("%s/%s", output_dir, modnames ? name : file);
2453*7304104dSAndroid Build Coastguard Worker 
2454*7304104dSAndroid Build Coastguard Worker   handle_dwfl_module (output_file, true, force, mod, all, ignore, relocate);
2455*7304104dSAndroid Build Coastguard Worker 
2456*7304104dSAndroid Build Coastguard Worker   free (output_file);
2457*7304104dSAndroid Build Coastguard Worker }
2458*7304104dSAndroid Build Coastguard Worker 
2459*7304104dSAndroid Build Coastguard Worker 
2460*7304104dSAndroid Build Coastguard Worker static void
list_module(Dwfl_Module * mod)2461*7304104dSAndroid Build Coastguard Worker list_module (Dwfl_Module *mod)
2462*7304104dSAndroid Build Coastguard Worker {
2463*7304104dSAndroid Build Coastguard Worker   /* Make sure we have searched for the files.  */
2464*7304104dSAndroid Build Coastguard Worker   GElf_Addr bias;
2465*7304104dSAndroid Build Coastguard Worker   bool have_elf = dwfl_module_getelf (mod, &bias) != NULL;
2466*7304104dSAndroid Build Coastguard Worker   bool have_dwarf = dwfl_module_getdwarf (mod, &bias) != NULL;
2467*7304104dSAndroid Build Coastguard Worker 
2468*7304104dSAndroid Build Coastguard Worker   const char *file;
2469*7304104dSAndroid Build Coastguard Worker   const char *debug;
2470*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr start;
2471*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr end;
2472*7304104dSAndroid Build Coastguard Worker   const char *name = dwfl_module_info (mod, NULL, &start, &end,
2473*7304104dSAndroid Build Coastguard Worker 				       NULL, NULL, &file, &debug);
2474*7304104dSAndroid Build Coastguard Worker   if (file != NULL && debug != NULL && (debug == file || !strcmp (debug, file)))
2475*7304104dSAndroid Build Coastguard Worker     debug = ".";
2476*7304104dSAndroid Build Coastguard Worker 
2477*7304104dSAndroid Build Coastguard Worker   const unsigned char *id;
2478*7304104dSAndroid Build Coastguard Worker   GElf_Addr id_vaddr;
2479*7304104dSAndroid Build Coastguard Worker   int id_len = dwfl_module_build_id (mod, &id, &id_vaddr);
2480*7304104dSAndroid Build Coastguard Worker 
2481*7304104dSAndroid Build Coastguard Worker   printf ("%#" PRIx64 "+%#" PRIx64 " ", start, end - start);
2482*7304104dSAndroid Build Coastguard Worker 
2483*7304104dSAndroid Build Coastguard Worker   if (id_len > 0)
2484*7304104dSAndroid Build Coastguard Worker     {
2485*7304104dSAndroid Build Coastguard Worker       do
2486*7304104dSAndroid Build Coastguard Worker 	printf ("%02" PRIx8, *id++);
2487*7304104dSAndroid Build Coastguard Worker       while (--id_len > 0);
2488*7304104dSAndroid Build Coastguard Worker       if (id_vaddr != 0)
2489*7304104dSAndroid Build Coastguard Worker 	printf ("@%#" PRIx64, id_vaddr);
2490*7304104dSAndroid Build Coastguard Worker     }
2491*7304104dSAndroid Build Coastguard Worker   else
2492*7304104dSAndroid Build Coastguard Worker     putchar ('-');
2493*7304104dSAndroid Build Coastguard Worker 
2494*7304104dSAndroid Build Coastguard Worker   printf (" %s %s %s\n",
2495*7304104dSAndroid Build Coastguard Worker 	  file ?: have_elf ? "." : "-",
2496*7304104dSAndroid Build Coastguard Worker 	  debug ?: have_dwarf ? "." : "-",
2497*7304104dSAndroid Build Coastguard Worker 	  name);
2498*7304104dSAndroid Build Coastguard Worker }
2499*7304104dSAndroid Build Coastguard Worker 
2500*7304104dSAndroid Build Coastguard Worker 
2501*7304104dSAndroid Build Coastguard Worker struct match_module_info
2502*7304104dSAndroid Build Coastguard Worker {
2503*7304104dSAndroid Build Coastguard Worker   char **patterns;
2504*7304104dSAndroid Build Coastguard Worker   Dwfl_Module *found;
2505*7304104dSAndroid Build Coastguard Worker   bool match_files;
2506*7304104dSAndroid Build Coastguard Worker };
2507*7304104dSAndroid Build Coastguard Worker 
2508*7304104dSAndroid Build Coastguard Worker static int
match_module(Dwfl_Module * mod,void ** userdata,const char * name,Dwarf_Addr start,void * arg)2509*7304104dSAndroid Build Coastguard Worker match_module (Dwfl_Module *mod,
2510*7304104dSAndroid Build Coastguard Worker 	      void **userdata __attribute__ ((unused)),
2511*7304104dSAndroid Build Coastguard Worker 	      const char *name,
2512*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Addr start __attribute__ ((unused)),
2513*7304104dSAndroid Build Coastguard Worker 	      void *arg)
2514*7304104dSAndroid Build Coastguard Worker {
2515*7304104dSAndroid Build Coastguard Worker   struct match_module_info *info = arg;
2516*7304104dSAndroid Build Coastguard Worker 
2517*7304104dSAndroid Build Coastguard Worker   if (info->patterns[0] == NULL) /* Match all.  */
2518*7304104dSAndroid Build Coastguard Worker     {
2519*7304104dSAndroid Build Coastguard Worker     match:
2520*7304104dSAndroid Build Coastguard Worker       info->found = mod;
2521*7304104dSAndroid Build Coastguard Worker       return DWARF_CB_ABORT;
2522*7304104dSAndroid Build Coastguard Worker     }
2523*7304104dSAndroid Build Coastguard Worker 
2524*7304104dSAndroid Build Coastguard Worker   if (info->match_files)
2525*7304104dSAndroid Build Coastguard Worker     {
2526*7304104dSAndroid Build Coastguard Worker       /* Make sure we've searched for the ELF file.  */
2527*7304104dSAndroid Build Coastguard Worker       GElf_Addr bias;
2528*7304104dSAndroid Build Coastguard Worker       (void) dwfl_module_getelf (mod, &bias);
2529*7304104dSAndroid Build Coastguard Worker 
2530*7304104dSAndroid Build Coastguard Worker       const char *file;
2531*7304104dSAndroid Build Coastguard Worker       const char *check = dwfl_module_info (mod, NULL, NULL, NULL,
2532*7304104dSAndroid Build Coastguard Worker 					    NULL, NULL, &file, NULL);
2533*7304104dSAndroid Build Coastguard Worker       if (check == NULL || strcmp (check, name) != 0 || file == NULL)
2534*7304104dSAndroid Build Coastguard Worker 	return DWARF_CB_OK;
2535*7304104dSAndroid Build Coastguard Worker 
2536*7304104dSAndroid Build Coastguard Worker       name = file;
2537*7304104dSAndroid Build Coastguard Worker     }
2538*7304104dSAndroid Build Coastguard Worker 
2539*7304104dSAndroid Build Coastguard Worker   for (char **p = info->patterns; *p != NULL; ++p)
2540*7304104dSAndroid Build Coastguard Worker     if (fnmatch (*p, name, 0) == 0)
2541*7304104dSAndroid Build Coastguard Worker       goto match;
2542*7304104dSAndroid Build Coastguard Worker 
2543*7304104dSAndroid Build Coastguard Worker   return DWARF_CB_OK;
2544*7304104dSAndroid Build Coastguard Worker }
2545*7304104dSAndroid Build Coastguard Worker 
2546*7304104dSAndroid Build Coastguard Worker /* Handle files opened implicitly via libdwfl.  */
2547*7304104dSAndroid Build Coastguard Worker static void
handle_implicit_modules(const struct arg_info * info)2548*7304104dSAndroid Build Coastguard Worker handle_implicit_modules (const struct arg_info *info)
2549*7304104dSAndroid Build Coastguard Worker {
2550*7304104dSAndroid Build Coastguard Worker   struct match_module_info mmi = { info->args, NULL, info->match_files };
2551*7304104dSAndroid Build Coastguard Worker   ptrdiff_t offset = dwfl_getmodules (info->dwfl, &match_module, &mmi, 0);
2552*7304104dSAndroid Build Coastguard Worker   if (offset == 0)
2553*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("no matching modules found"));
2554*7304104dSAndroid Build Coastguard Worker 
2555*7304104dSAndroid Build Coastguard Worker   if (info->list)
2556*7304104dSAndroid Build Coastguard Worker     do
2557*7304104dSAndroid Build Coastguard Worker       list_module (mmi.found);
2558*7304104dSAndroid Build Coastguard Worker     while ((offset = dwfl_getmodules (info->dwfl, &match_module, &mmi,
2559*7304104dSAndroid Build Coastguard Worker 				      offset)) > 0);
2560*7304104dSAndroid Build Coastguard Worker   else if (info->output_dir == NULL)
2561*7304104dSAndroid Build Coastguard Worker     {
2562*7304104dSAndroid Build Coastguard Worker       if (dwfl_getmodules (info->dwfl, &match_module, &mmi, offset) != 0)
2563*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("matched more than one module"));
2564*7304104dSAndroid Build Coastguard Worker       handle_dwfl_module (info->output_file, false, info->force, mmi.found,
2565*7304104dSAndroid Build Coastguard Worker 			  info->all, info->ignore, info->relocate);
2566*7304104dSAndroid Build Coastguard Worker     }
2567*7304104dSAndroid Build Coastguard Worker   else
2568*7304104dSAndroid Build Coastguard Worker     do
2569*7304104dSAndroid Build Coastguard Worker       handle_output_dir_module (info->output_dir, mmi.found, info->force,
2570*7304104dSAndroid Build Coastguard Worker 				info->all, info->ignore,
2571*7304104dSAndroid Build Coastguard Worker 				info->modnames, info->relocate);
2572*7304104dSAndroid Build Coastguard Worker     while ((offset = dwfl_getmodules (info->dwfl, &match_module, &mmi,
2573*7304104dSAndroid Build Coastguard Worker 				      offset)) > 0);
2574*7304104dSAndroid Build Coastguard Worker }
2575*7304104dSAndroid Build Coastguard Worker 
2576*7304104dSAndroid Build Coastguard Worker int
main(int argc,char ** argv)2577*7304104dSAndroid Build Coastguard Worker main (int argc, char **argv)
2578*7304104dSAndroid Build Coastguard Worker {
2579*7304104dSAndroid Build Coastguard Worker   /* We use no threads here which can interfere with handling a stream.  */
2580*7304104dSAndroid Build Coastguard Worker   __fsetlocking (stdin, FSETLOCKING_BYCALLER);
2581*7304104dSAndroid Build Coastguard Worker   __fsetlocking (stdout, FSETLOCKING_BYCALLER);
2582*7304104dSAndroid Build Coastguard Worker   __fsetlocking (stderr, FSETLOCKING_BYCALLER);
2583*7304104dSAndroid Build Coastguard Worker 
2584*7304104dSAndroid Build Coastguard Worker   /* Set locale.  */
2585*7304104dSAndroid Build Coastguard Worker   setlocale (LC_ALL, "");
2586*7304104dSAndroid Build Coastguard Worker 
2587*7304104dSAndroid Build Coastguard Worker   /* Make sure the message catalog can be found.  */
2588*7304104dSAndroid Build Coastguard Worker   bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
2589*7304104dSAndroid Build Coastguard Worker 
2590*7304104dSAndroid Build Coastguard Worker   /* Initialize the message catalog.  */
2591*7304104dSAndroid Build Coastguard Worker   textdomain (PACKAGE_TARNAME);
2592*7304104dSAndroid Build Coastguard Worker 
2593*7304104dSAndroid Build Coastguard Worker   /* Parse and process arguments.  */
2594*7304104dSAndroid Build Coastguard Worker   const struct argp_child argp_children[] =
2595*7304104dSAndroid Build Coastguard Worker     {
2596*7304104dSAndroid Build Coastguard Worker       {
2597*7304104dSAndroid Build Coastguard Worker 	.argp = dwfl_standard_argp (),
2598*7304104dSAndroid Build Coastguard Worker 	.header = N_("Input selection options:"),
2599*7304104dSAndroid Build Coastguard Worker 	.group = 1,
2600*7304104dSAndroid Build Coastguard Worker       },
2601*7304104dSAndroid Build Coastguard Worker       { .argp = NULL },
2602*7304104dSAndroid Build Coastguard Worker     };
2603*7304104dSAndroid Build Coastguard Worker   const struct argp argp =
2604*7304104dSAndroid Build Coastguard Worker     {
2605*7304104dSAndroid Build Coastguard Worker       .options = options,
2606*7304104dSAndroid Build Coastguard Worker       .parser = parse_opt,
2607*7304104dSAndroid Build Coastguard Worker       .children = argp_children,
2608*7304104dSAndroid Build Coastguard Worker       .args_doc = N_("STRIPPED-FILE DEBUG-FILE\n[MODULE...]"),
2609*7304104dSAndroid Build Coastguard Worker       .doc = N_("\
2610*7304104dSAndroid Build Coastguard Worker Combine stripped files with separate symbols and debug information.\n\
2611*7304104dSAndroid Build Coastguard Worker \n\
2612*7304104dSAndroid Build Coastguard Worker The first form puts the result in DEBUG-FILE if -o was not given.\n\
2613*7304104dSAndroid Build Coastguard Worker \n\
2614*7304104dSAndroid Build Coastguard Worker MODULE arguments give file name patterns matching modules to process.\n\
2615*7304104dSAndroid Build Coastguard Worker With -f these match the file name of the main (stripped) file \
2616*7304104dSAndroid Build Coastguard Worker (slashes are never special), otherwise they match the simple module names.  \
2617*7304104dSAndroid Build Coastguard Worker With no arguments, process all modules found.\n\
2618*7304104dSAndroid Build Coastguard Worker \n\
2619*7304104dSAndroid Build Coastguard Worker Multiple modules are written to files under OUTPUT-DIRECTORY, \
2620*7304104dSAndroid Build Coastguard Worker creating subdirectories as needed.  \
2621*7304104dSAndroid Build Coastguard Worker With -m these files have simple module names, otherwise they have the \
2622*7304104dSAndroid Build Coastguard Worker name of the main file complete with directory underneath OUTPUT-DIRECTORY.\n\
2623*7304104dSAndroid Build Coastguard Worker \n\
2624*7304104dSAndroid Build Coastguard Worker With -n no files are written, but one line to standard output for each module:\
2625*7304104dSAndroid Build Coastguard Worker \n\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n\
2626*7304104dSAndroid Build Coastguard Worker START and SIZE are hexadecimal giving the address bounds of the module.  \
2627*7304104dSAndroid Build Coastguard Worker BUILDID is hexadecimal for the build ID bits, or - if no ID is known; \
2628*7304104dSAndroid Build Coastguard Worker the hexadecimal may be followed by @0xADDR giving the address where the \
2629*7304104dSAndroid Build Coastguard Worker ID resides if that is known.  \
2630*7304104dSAndroid Build Coastguard Worker FILE is the file name found for the module, or - if none was found, \
2631*7304104dSAndroid Build Coastguard Worker or . if an ELF image is available but not from any named file.  \
2632*7304104dSAndroid Build Coastguard Worker DEBUGFILE is the separate debuginfo file name, \
2633*7304104dSAndroid Build Coastguard Worker or - if no debuginfo was found, or . if FILE contains the debug information.\
2634*7304104dSAndroid Build Coastguard Worker ")
2635*7304104dSAndroid Build Coastguard Worker     };
2636*7304104dSAndroid Build Coastguard Worker 
2637*7304104dSAndroid Build Coastguard Worker   int remaining;
2638*7304104dSAndroid Build Coastguard Worker   struct arg_info info = { .args = NULL };
2639*7304104dSAndroid Build Coastguard Worker   error_t result = argp_parse (&argp, argc, argv, 0, &remaining, &info);
2640*7304104dSAndroid Build Coastguard Worker   if (result == ENOSYS)
2641*7304104dSAndroid Build Coastguard Worker     assert (info.dwfl == NULL);
2642*7304104dSAndroid Build Coastguard Worker   else if (result)
2643*7304104dSAndroid Build Coastguard Worker     return EXIT_FAILURE;
2644*7304104dSAndroid Build Coastguard Worker   assert (info.args != NULL);
2645*7304104dSAndroid Build Coastguard Worker 
2646*7304104dSAndroid Build Coastguard Worker   /* Tell the library which version we are expecting.  */
2647*7304104dSAndroid Build Coastguard Worker   elf_version (EV_CURRENT);
2648*7304104dSAndroid Build Coastguard Worker 
2649*7304104dSAndroid Build Coastguard Worker   if (info.dwfl == NULL)
2650*7304104dSAndroid Build Coastguard Worker     {
2651*7304104dSAndroid Build Coastguard Worker       assert (result == ENOSYS);
2652*7304104dSAndroid Build Coastguard Worker 
2653*7304104dSAndroid Build Coastguard Worker       if (info.output_dir != NULL)
2654*7304104dSAndroid Build Coastguard Worker 	{
2655*7304104dSAndroid Build Coastguard Worker 	  char *file = xasprintf ("%s/%s", info.output_dir, info.args[0]);
2656*7304104dSAndroid Build Coastguard Worker 	  handle_explicit_files (file, true, info.force,
2657*7304104dSAndroid Build Coastguard Worker 				 info.args[0], info.args[1]);
2658*7304104dSAndroid Build Coastguard Worker 	  free (file);
2659*7304104dSAndroid Build Coastguard Worker 	}
2660*7304104dSAndroid Build Coastguard Worker       else
2661*7304104dSAndroid Build Coastguard Worker 	handle_explicit_files (info.output_file, false, info.force,
2662*7304104dSAndroid Build Coastguard Worker 			       info.args[0], info.args[1]);
2663*7304104dSAndroid Build Coastguard Worker     }
2664*7304104dSAndroid Build Coastguard Worker   else
2665*7304104dSAndroid Build Coastguard Worker     {
2666*7304104dSAndroid Build Coastguard Worker       /* parse_opt checked this.  */
2667*7304104dSAndroid Build Coastguard Worker       assert (info.output_file != NULL || info.output_dir != NULL || info.list);
2668*7304104dSAndroid Build Coastguard Worker 
2669*7304104dSAndroid Build Coastguard Worker       handle_implicit_modules (&info);
2670*7304104dSAndroid Build Coastguard Worker 
2671*7304104dSAndroid Build Coastguard Worker       dwfl_end (info.dwfl);
2672*7304104dSAndroid Build Coastguard Worker     }
2673*7304104dSAndroid Build Coastguard Worker 
2674*7304104dSAndroid Build Coastguard Worker   return 0;
2675*7304104dSAndroid Build Coastguard Worker }
2676*7304104dSAndroid Build Coastguard Worker 
2677*7304104dSAndroid Build Coastguard Worker 
2678*7304104dSAndroid Build Coastguard Worker #include "debugpred.h"
2679