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 (§ions[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 §ions[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 = §ions[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 = §ions[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 < §ions[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, §ions[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 = §ions[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 = §ions[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 = §ions[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 = §ions[i];
1564*7304104dSAndroid Build Coastguard Worker int cmp = compare_unalloc_sections (shdr, §ion->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 < §ions[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 < §ions[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 < §ions[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