1*7304104dSAndroid Build Coastguard Worker /* Pedantic checking of ELF files compliance with gABI/psABI spec.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2001-2015, 2017, 2018 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker Copyright (C) 2023 Mark J. Wielaard <[email protected]>
4*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
5*7304104dSAndroid Build Coastguard Worker Written by Ulrich Drepper <[email protected]>, 2001.
6*7304104dSAndroid Build Coastguard Worker
7*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
8*7304104dSAndroid Build Coastguard Worker it under the terms of the GNU General Public License as published by
9*7304104dSAndroid Build Coastguard Worker the Free Software Foundation; either version 3 of the License, or
10*7304104dSAndroid Build Coastguard Worker (at your option) any later version.
11*7304104dSAndroid Build Coastguard Worker
12*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
13*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
14*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*7304104dSAndroid Build Coastguard Worker GNU General Public License for more details.
16*7304104dSAndroid Build Coastguard Worker
17*7304104dSAndroid Build Coastguard Worker You should have received a copy of the GNU General Public License
18*7304104dSAndroid Build Coastguard Worker along with this program. If not, see <http://www.gnu.org/licenses/>. */
19*7304104dSAndroid Build Coastguard Worker
20*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
21*7304104dSAndroid Build Coastguard Worker # include <config.h>
22*7304104dSAndroid Build Coastguard Worker #endif
23*7304104dSAndroid Build Coastguard Worker
24*7304104dSAndroid Build Coastguard Worker #include <argp.h>
25*7304104dSAndroid Build Coastguard Worker #include <assert.h>
26*7304104dSAndroid Build Coastguard Worker #include <byteswap.h>
27*7304104dSAndroid Build Coastguard Worker #include <endian.h>
28*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
29*7304104dSAndroid Build Coastguard Worker #include <gelf.h>
30*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
31*7304104dSAndroid Build Coastguard Worker #include <locale.h>
32*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
33*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
34*7304104dSAndroid Build Coastguard Worker #include <string.h>
35*7304104dSAndroid Build Coastguard Worker #include <unistd.h>
36*7304104dSAndroid Build Coastguard Worker #include <sys/stat.h>
37*7304104dSAndroid Build Coastguard Worker
38*7304104dSAndroid Build Coastguard Worker #include <elf-knowledge.h>
39*7304104dSAndroid Build Coastguard Worker #include <libeu.h>
40*7304104dSAndroid Build Coastguard Worker #include <system.h>
41*7304104dSAndroid Build Coastguard Worker #include <printversion.h>
42*7304104dSAndroid Build Coastguard Worker #include "../libelf/libelfP.h"
43*7304104dSAndroid Build Coastguard Worker #include "../libelf/common.h"
44*7304104dSAndroid Build Coastguard Worker #include "../libebl/libeblP.h"
45*7304104dSAndroid Build Coastguard Worker #include "../libdw/libdwP.h"
46*7304104dSAndroid Build Coastguard Worker #include "../libdwfl/libdwflP.h"
47*7304104dSAndroid Build Coastguard Worker #include "../libdw/memory-access.h"
48*7304104dSAndroid Build Coastguard Worker
49*7304104dSAndroid Build Coastguard Worker
50*7304104dSAndroid Build Coastguard Worker /* Name and version of program. */
51*7304104dSAndroid Build Coastguard Worker ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
52*7304104dSAndroid Build Coastguard Worker
53*7304104dSAndroid Build Coastguard Worker /* Bug report address. */
54*7304104dSAndroid Build Coastguard Worker ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
55*7304104dSAndroid Build Coastguard Worker
56*7304104dSAndroid Build Coastguard Worker #define ARGP_strict 300
57*7304104dSAndroid Build Coastguard Worker #define ARGP_gnuld 301
58*7304104dSAndroid Build Coastguard Worker
59*7304104dSAndroid Build Coastguard Worker /* Definitions of arguments for argp functions. */
60*7304104dSAndroid Build Coastguard Worker static const struct argp_option options[] =
61*7304104dSAndroid Build Coastguard Worker {
62*7304104dSAndroid Build Coastguard Worker { "strict", ARGP_strict, NULL, 0,
63*7304104dSAndroid Build Coastguard Worker N_("Be extremely strict, flag level 2 features."), 0 },
64*7304104dSAndroid Build Coastguard Worker { "quiet", 'q', NULL, 0, N_("Do not print anything if successful"), 0 },
65*7304104dSAndroid Build Coastguard Worker { "debuginfo", 'd', NULL, 0, N_("Binary is a separate debuginfo file"), 0 },
66*7304104dSAndroid Build Coastguard Worker { "gnu-ld", ARGP_gnuld, NULL, 0,
67*7304104dSAndroid Build Coastguard Worker N_("Binary has been created with GNU ld and is therefore known to be \
68*7304104dSAndroid Build Coastguard Worker broken in certain ways"), 0 },
69*7304104dSAndroid Build Coastguard Worker { NULL, 0, NULL, 0, NULL, 0 }
70*7304104dSAndroid Build Coastguard Worker };
71*7304104dSAndroid Build Coastguard Worker
72*7304104dSAndroid Build Coastguard Worker /* Short description of program. */
73*7304104dSAndroid Build Coastguard Worker static const char doc[] = N_("\
74*7304104dSAndroid Build Coastguard Worker Pedantic checking of ELF files compliance with gABI/psABI spec.");
75*7304104dSAndroid Build Coastguard Worker
76*7304104dSAndroid Build Coastguard Worker /* Strings for arguments in help texts. */
77*7304104dSAndroid Build Coastguard Worker static const char args_doc[] = N_("FILE...");
78*7304104dSAndroid Build Coastguard Worker
79*7304104dSAndroid Build Coastguard Worker /* Prototype for option handler. */
80*7304104dSAndroid Build Coastguard Worker static error_t parse_opt (int key, char *arg, struct argp_state *state);
81*7304104dSAndroid Build Coastguard Worker
82*7304104dSAndroid Build Coastguard Worker /* Data structure to communicate with argp functions. */
83*7304104dSAndroid Build Coastguard Worker static struct argp argp =
84*7304104dSAndroid Build Coastguard Worker {
85*7304104dSAndroid Build Coastguard Worker options, parse_opt, args_doc, doc, NULL, NULL, NULL
86*7304104dSAndroid Build Coastguard Worker };
87*7304104dSAndroid Build Coastguard Worker
88*7304104dSAndroid Build Coastguard Worker
89*7304104dSAndroid Build Coastguard Worker /* Declarations of local functions. */
90*7304104dSAndroid Build Coastguard Worker static void process_file (int fd, Elf *elf, const char *prefix,
91*7304104dSAndroid Build Coastguard Worker const char *suffix, const char *fname, size_t size,
92*7304104dSAndroid Build Coastguard Worker bool only_one);
93*7304104dSAndroid Build Coastguard Worker static void process_elf_file (Elf *elf, const char *prefix, const char *suffix,
94*7304104dSAndroid Build Coastguard Worker const char *fname, size_t size, bool only_one);
95*7304104dSAndroid Build Coastguard Worker static void check_note_section (Ebl *ebl, GElf_Ehdr *ehdr,
96*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr, int idx);
97*7304104dSAndroid Build Coastguard Worker
98*7304104dSAndroid Build Coastguard Worker
99*7304104dSAndroid Build Coastguard Worker /* Report an error. */
100*7304104dSAndroid Build Coastguard Worker #define ERROR(str, args...) \
101*7304104dSAndroid Build Coastguard Worker do { \
102*7304104dSAndroid Build Coastguard Worker printf (str, ##args); \
103*7304104dSAndroid Build Coastguard Worker ++error_count; \
104*7304104dSAndroid Build Coastguard Worker } while (0)
105*7304104dSAndroid Build Coastguard Worker static unsigned int error_count;
106*7304104dSAndroid Build Coastguard Worker
107*7304104dSAndroid Build Coastguard Worker /* True if we should perform very strict testing. */
108*7304104dSAndroid Build Coastguard Worker static bool be_strict;
109*7304104dSAndroid Build Coastguard Worker
110*7304104dSAndroid Build Coastguard Worker /* True if no message is to be printed if the run is successful. */
111*7304104dSAndroid Build Coastguard Worker static bool be_quiet;
112*7304104dSAndroid Build Coastguard Worker
113*7304104dSAndroid Build Coastguard Worker /* True if binary is from strip -f, not a normal ELF file. */
114*7304104dSAndroid Build Coastguard Worker static bool is_debuginfo;
115*7304104dSAndroid Build Coastguard Worker
116*7304104dSAndroid Build Coastguard Worker /* True if binary is assumed to be generated with GNU ld. */
117*7304104dSAndroid Build Coastguard Worker static bool gnuld;
118*7304104dSAndroid Build Coastguard Worker
119*7304104dSAndroid Build Coastguard Worker /* Index of section header string table. */
120*7304104dSAndroid Build Coastguard Worker static uint32_t shstrndx;
121*7304104dSAndroid Build Coastguard Worker
122*7304104dSAndroid Build Coastguard Worker /* Array to count references in section groups. */
123*7304104dSAndroid Build Coastguard Worker static int *scnref;
124*7304104dSAndroid Build Coastguard Worker
125*7304104dSAndroid Build Coastguard Worker /* Numbers of sections and program headers. */
126*7304104dSAndroid Build Coastguard Worker static unsigned int shnum;
127*7304104dSAndroid Build Coastguard Worker static unsigned int phnum;
128*7304104dSAndroid Build Coastguard Worker
129*7304104dSAndroid Build Coastguard Worker
130*7304104dSAndroid Build Coastguard Worker int
main(int argc,char * argv[])131*7304104dSAndroid Build Coastguard Worker main (int argc, char *argv[])
132*7304104dSAndroid Build Coastguard Worker {
133*7304104dSAndroid Build Coastguard Worker /* Set locale. */
134*7304104dSAndroid Build Coastguard Worker setlocale (LC_ALL, "");
135*7304104dSAndroid Build Coastguard Worker
136*7304104dSAndroid Build Coastguard Worker /* Initialize the message catalog. */
137*7304104dSAndroid Build Coastguard Worker textdomain (PACKAGE_TARNAME);
138*7304104dSAndroid Build Coastguard Worker
139*7304104dSAndroid Build Coastguard Worker /* Parse and process arguments. */
140*7304104dSAndroid Build Coastguard Worker int remaining;
141*7304104dSAndroid Build Coastguard Worker argp_parse (&argp, argc, argv, 0, &remaining, NULL);
142*7304104dSAndroid Build Coastguard Worker
143*7304104dSAndroid Build Coastguard Worker /* Before we start tell the ELF library which version we are using. */
144*7304104dSAndroid Build Coastguard Worker elf_version (EV_CURRENT);
145*7304104dSAndroid Build Coastguard Worker
146*7304104dSAndroid Build Coastguard Worker /* Now process all the files given at the command line. */
147*7304104dSAndroid Build Coastguard Worker bool only_one = remaining + 1 == argc;
148*7304104dSAndroid Build Coastguard Worker do
149*7304104dSAndroid Build Coastguard Worker {
150*7304104dSAndroid Build Coastguard Worker /* Open the file. */
151*7304104dSAndroid Build Coastguard Worker int fd = open (argv[remaining], O_RDONLY);
152*7304104dSAndroid Build Coastguard Worker if (fd == -1)
153*7304104dSAndroid Build Coastguard Worker {
154*7304104dSAndroid Build Coastguard Worker error (0, errno, _("cannot open input file '%s'"), argv[remaining]);
155*7304104dSAndroid Build Coastguard Worker continue;
156*7304104dSAndroid Build Coastguard Worker }
157*7304104dSAndroid Build Coastguard Worker
158*7304104dSAndroid Build Coastguard Worker /* Create an `Elf' descriptor. */
159*7304104dSAndroid Build Coastguard Worker Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
160*7304104dSAndroid Build Coastguard Worker if (elf == NULL)
161*7304104dSAndroid Build Coastguard Worker ERROR (_("cannot generate Elf descriptor for '%s': %s\n"),
162*7304104dSAndroid Build Coastguard Worker argv[remaining], elf_errmsg (-1));
163*7304104dSAndroid Build Coastguard Worker else
164*7304104dSAndroid Build Coastguard Worker {
165*7304104dSAndroid Build Coastguard Worker unsigned int prev_error_count = error_count;
166*7304104dSAndroid Build Coastguard Worker struct stat st;
167*7304104dSAndroid Build Coastguard Worker
168*7304104dSAndroid Build Coastguard Worker if (fstat (fd, &st) != 0)
169*7304104dSAndroid Build Coastguard Worker {
170*7304104dSAndroid Build Coastguard Worker printf ("cannot stat '%s': %m\n", argv[remaining]);
171*7304104dSAndroid Build Coastguard Worker close (fd);
172*7304104dSAndroid Build Coastguard Worker continue;
173*7304104dSAndroid Build Coastguard Worker }
174*7304104dSAndroid Build Coastguard Worker
175*7304104dSAndroid Build Coastguard Worker process_file (fd, elf, NULL, NULL, argv[remaining], st.st_size,
176*7304104dSAndroid Build Coastguard Worker only_one);
177*7304104dSAndroid Build Coastguard Worker
178*7304104dSAndroid Build Coastguard Worker /* Now we can close the descriptor. */
179*7304104dSAndroid Build Coastguard Worker if (elf_end (elf) != 0)
180*7304104dSAndroid Build Coastguard Worker ERROR (_("error while closing Elf descriptor: %s\n"),
181*7304104dSAndroid Build Coastguard Worker elf_errmsg (-1));
182*7304104dSAndroid Build Coastguard Worker
183*7304104dSAndroid Build Coastguard Worker if (prev_error_count == error_count && !be_quiet)
184*7304104dSAndroid Build Coastguard Worker puts (_("No errors"));
185*7304104dSAndroid Build Coastguard Worker }
186*7304104dSAndroid Build Coastguard Worker
187*7304104dSAndroid Build Coastguard Worker close (fd);
188*7304104dSAndroid Build Coastguard Worker }
189*7304104dSAndroid Build Coastguard Worker while (++remaining < argc);
190*7304104dSAndroid Build Coastguard Worker
191*7304104dSAndroid Build Coastguard Worker return error_count != 0;
192*7304104dSAndroid Build Coastguard Worker }
193*7304104dSAndroid Build Coastguard Worker
194*7304104dSAndroid Build Coastguard Worker
195*7304104dSAndroid Build Coastguard Worker /* Handle program arguments. */
196*7304104dSAndroid Build Coastguard Worker static error_t
parse_opt(int key,char * arg,struct argp_state * state)197*7304104dSAndroid Build Coastguard Worker parse_opt (int key, char *arg __attribute__ ((unused)),
198*7304104dSAndroid Build Coastguard Worker struct argp_state *state __attribute__ ((unused)))
199*7304104dSAndroid Build Coastguard Worker {
200*7304104dSAndroid Build Coastguard Worker switch (key)
201*7304104dSAndroid Build Coastguard Worker {
202*7304104dSAndroid Build Coastguard Worker case ARGP_strict:
203*7304104dSAndroid Build Coastguard Worker be_strict = true;
204*7304104dSAndroid Build Coastguard Worker break;
205*7304104dSAndroid Build Coastguard Worker
206*7304104dSAndroid Build Coastguard Worker case 'q':
207*7304104dSAndroid Build Coastguard Worker be_quiet = true;
208*7304104dSAndroid Build Coastguard Worker break;
209*7304104dSAndroid Build Coastguard Worker
210*7304104dSAndroid Build Coastguard Worker case 'd':
211*7304104dSAndroid Build Coastguard Worker is_debuginfo = true;
212*7304104dSAndroid Build Coastguard Worker break;
213*7304104dSAndroid Build Coastguard Worker
214*7304104dSAndroid Build Coastguard Worker case ARGP_gnuld:
215*7304104dSAndroid Build Coastguard Worker gnuld = true;
216*7304104dSAndroid Build Coastguard Worker break;
217*7304104dSAndroid Build Coastguard Worker
218*7304104dSAndroid Build Coastguard Worker case ARGP_KEY_NO_ARGS:
219*7304104dSAndroid Build Coastguard Worker fputs (_("Missing file name.\n"), stderr);
220*7304104dSAndroid Build Coastguard Worker argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name);
221*7304104dSAndroid Build Coastguard Worker exit (EXIT_FAILURE);
222*7304104dSAndroid Build Coastguard Worker
223*7304104dSAndroid Build Coastguard Worker default:
224*7304104dSAndroid Build Coastguard Worker return ARGP_ERR_UNKNOWN;
225*7304104dSAndroid Build Coastguard Worker }
226*7304104dSAndroid Build Coastguard Worker return 0;
227*7304104dSAndroid Build Coastguard Worker }
228*7304104dSAndroid Build Coastguard Worker
229*7304104dSAndroid Build Coastguard Worker
230*7304104dSAndroid Build Coastguard Worker /* Process one file. */
231*7304104dSAndroid Build Coastguard Worker static void
process_file(int fd,Elf * elf,const char * prefix,const char * suffix,const char * fname,size_t size,bool only_one)232*7304104dSAndroid Build Coastguard Worker process_file (int fd, Elf *elf, const char *prefix, const char *suffix,
233*7304104dSAndroid Build Coastguard Worker const char *fname, size_t size, bool only_one)
234*7304104dSAndroid Build Coastguard Worker {
235*7304104dSAndroid Build Coastguard Worker /* We can handle two types of files: ELF files and archives. */
236*7304104dSAndroid Build Coastguard Worker Elf_Kind kind = elf_kind (elf);
237*7304104dSAndroid Build Coastguard Worker
238*7304104dSAndroid Build Coastguard Worker switch (kind)
239*7304104dSAndroid Build Coastguard Worker {
240*7304104dSAndroid Build Coastguard Worker case ELF_K_ELF:
241*7304104dSAndroid Build Coastguard Worker /* Yes! It's an ELF file. */
242*7304104dSAndroid Build Coastguard Worker process_elf_file (elf, prefix, suffix, fname, size, only_one);
243*7304104dSAndroid Build Coastguard Worker break;
244*7304104dSAndroid Build Coastguard Worker
245*7304104dSAndroid Build Coastguard Worker case ELF_K_AR:
246*7304104dSAndroid Build Coastguard Worker {
247*7304104dSAndroid Build Coastguard Worker Elf *subelf;
248*7304104dSAndroid Build Coastguard Worker Elf_Cmd cmd = ELF_C_READ_MMAP;
249*7304104dSAndroid Build Coastguard Worker size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
250*7304104dSAndroid Build Coastguard Worker size_t fname_len = strlen (fname) + 1;
251*7304104dSAndroid Build Coastguard Worker char new_prefix[prefix_len + 1 + fname_len];
252*7304104dSAndroid Build Coastguard Worker char new_suffix[(suffix == NULL ? 0 : strlen (suffix)) + 2];
253*7304104dSAndroid Build Coastguard Worker char *cp = new_prefix;
254*7304104dSAndroid Build Coastguard Worker
255*7304104dSAndroid Build Coastguard Worker /* Create the full name of the file. */
256*7304104dSAndroid Build Coastguard Worker if (prefix != NULL)
257*7304104dSAndroid Build Coastguard Worker {
258*7304104dSAndroid Build Coastguard Worker cp = mempcpy (cp, prefix, prefix_len);
259*7304104dSAndroid Build Coastguard Worker *cp++ = '(';
260*7304104dSAndroid Build Coastguard Worker strcpy (stpcpy (new_suffix, suffix), ")");
261*7304104dSAndroid Build Coastguard Worker }
262*7304104dSAndroid Build Coastguard Worker else
263*7304104dSAndroid Build Coastguard Worker new_suffix[0] = '\0';
264*7304104dSAndroid Build Coastguard Worker memcpy (cp, fname, fname_len);
265*7304104dSAndroid Build Coastguard Worker
266*7304104dSAndroid Build Coastguard Worker /* It's an archive. We process each file in it. */
267*7304104dSAndroid Build Coastguard Worker while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
268*7304104dSAndroid Build Coastguard Worker {
269*7304104dSAndroid Build Coastguard Worker kind = elf_kind (subelf);
270*7304104dSAndroid Build Coastguard Worker
271*7304104dSAndroid Build Coastguard Worker /* Call this function recursively. */
272*7304104dSAndroid Build Coastguard Worker if (kind == ELF_K_ELF || kind == ELF_K_AR)
273*7304104dSAndroid Build Coastguard Worker {
274*7304104dSAndroid Build Coastguard Worker Elf_Arhdr *arhdr = elf_getarhdr (subelf);
275*7304104dSAndroid Build Coastguard Worker assert (arhdr != NULL);
276*7304104dSAndroid Build Coastguard Worker
277*7304104dSAndroid Build Coastguard Worker process_file (fd, subelf, new_prefix, new_suffix,
278*7304104dSAndroid Build Coastguard Worker arhdr->ar_name, arhdr->ar_size, false);
279*7304104dSAndroid Build Coastguard Worker }
280*7304104dSAndroid Build Coastguard Worker
281*7304104dSAndroid Build Coastguard Worker /* Get next archive element. */
282*7304104dSAndroid Build Coastguard Worker cmd = elf_next (subelf);
283*7304104dSAndroid Build Coastguard Worker if (elf_end (subelf) != 0)
284*7304104dSAndroid Build Coastguard Worker ERROR (_(" error while freeing sub-ELF descriptor: %s\n"),
285*7304104dSAndroid Build Coastguard Worker elf_errmsg (-1));
286*7304104dSAndroid Build Coastguard Worker }
287*7304104dSAndroid Build Coastguard Worker }
288*7304104dSAndroid Build Coastguard Worker break;
289*7304104dSAndroid Build Coastguard Worker
290*7304104dSAndroid Build Coastguard Worker default:
291*7304104dSAndroid Build Coastguard Worker /* We cannot do anything. */
292*7304104dSAndroid Build Coastguard Worker ERROR (_("\
293*7304104dSAndroid Build Coastguard Worker Not an ELF file - it has the wrong magic bytes at the start\n"));
294*7304104dSAndroid Build Coastguard Worker break;
295*7304104dSAndroid Build Coastguard Worker }
296*7304104dSAndroid Build Coastguard Worker }
297*7304104dSAndroid Build Coastguard Worker
298*7304104dSAndroid Build Coastguard Worker
299*7304104dSAndroid Build Coastguard Worker static const char *
section_name(Ebl * ebl,int idx)300*7304104dSAndroid Build Coastguard Worker section_name (Ebl *ebl, int idx)
301*7304104dSAndroid Build Coastguard Worker {
302*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
303*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr;
304*7304104dSAndroid Build Coastguard Worker const char *ret;
305*7304104dSAndroid Build Coastguard Worker
306*7304104dSAndroid Build Coastguard Worker if ((unsigned int) idx > shnum)
307*7304104dSAndroid Build Coastguard Worker return "<invalid>";
308*7304104dSAndroid Build Coastguard Worker
309*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (elf_getscn (ebl->elf, idx), &shdr_mem);
310*7304104dSAndroid Build Coastguard Worker if (shdr == NULL)
311*7304104dSAndroid Build Coastguard Worker return "<invalid>";
312*7304104dSAndroid Build Coastguard Worker
313*7304104dSAndroid Build Coastguard Worker ret = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
314*7304104dSAndroid Build Coastguard Worker if (ret == NULL)
315*7304104dSAndroid Build Coastguard Worker return "<invalid>";
316*7304104dSAndroid Build Coastguard Worker return ret;
317*7304104dSAndroid Build Coastguard Worker }
318*7304104dSAndroid Build Coastguard Worker
319*7304104dSAndroid Build Coastguard Worker
320*7304104dSAndroid Build Coastguard Worker static const int valid_e_machine[] =
321*7304104dSAndroid Build Coastguard Worker {
322*7304104dSAndroid Build Coastguard Worker EM_M32, EM_SPARC, EM_386, EM_68K, EM_88K, EM_860, EM_MIPS, EM_S370,
323*7304104dSAndroid Build Coastguard Worker EM_MIPS_RS3_LE, EM_PARISC, EM_VPP500, EM_SPARC32PLUS, EM_960, EM_PPC,
324*7304104dSAndroid Build Coastguard Worker EM_PPC64, EM_S390, EM_V800, EM_FR20, EM_RH32, EM_RCE, EM_ARM,
325*7304104dSAndroid Build Coastguard Worker EM_FAKE_ALPHA, EM_SH, EM_SPARCV9, EM_TRICORE, EM_ARC, EM_H8_300,
326*7304104dSAndroid Build Coastguard Worker EM_H8_300H, EM_H8S, EM_H8_500, EM_IA_64, EM_MIPS_X, EM_COLDFIRE,
327*7304104dSAndroid Build Coastguard Worker EM_68HC12, EM_MMA, EM_PCP, EM_NCPU, EM_NDR1, EM_STARCORE, EM_ME16,
328*7304104dSAndroid Build Coastguard Worker EM_ST100, EM_TINYJ, EM_X86_64, EM_PDSP, EM_FX66, EM_ST9PLUS, EM_ST7,
329*7304104dSAndroid Build Coastguard Worker EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX,
330*7304104dSAndroid Build Coastguard Worker EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM,
331*7304104dSAndroid Build Coastguard Worker EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300,
332*7304104dSAndroid Build Coastguard Worker EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA, EM_ALPHA,
333*7304104dSAndroid Build Coastguard Worker EM_TILEGX, EM_TILEPRO, EM_AARCH64, EM_BPF, EM_RISCV, EM_CSKY, EM_LOONGARCH,
334*7304104dSAndroid Build Coastguard Worker EM_ARCV2
335*7304104dSAndroid Build Coastguard Worker };
336*7304104dSAndroid Build Coastguard Worker #define nvalid_e_machine \
337*7304104dSAndroid Build Coastguard Worker (sizeof (valid_e_machine) / sizeof (valid_e_machine[0]))
338*7304104dSAndroid Build Coastguard Worker
339*7304104dSAndroid Build Coastguard Worker
340*7304104dSAndroid Build Coastguard Worker static void
check_elf_header(Ebl * ebl,GElf_Ehdr * ehdr,size_t size)341*7304104dSAndroid Build Coastguard Worker check_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size)
342*7304104dSAndroid Build Coastguard Worker {
343*7304104dSAndroid Build Coastguard Worker char buf[512];
344*7304104dSAndroid Build Coastguard Worker size_t cnt;
345*7304104dSAndroid Build Coastguard Worker
346*7304104dSAndroid Build Coastguard Worker /* Check e_ident field. */
347*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ident[EI_MAG0] != ELFMAG0)
348*7304104dSAndroid Build Coastguard Worker ERROR ("e_ident[%d] != '%c'\n", EI_MAG0, ELFMAG0);
349*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ident[EI_MAG1] != ELFMAG1)
350*7304104dSAndroid Build Coastguard Worker ERROR ("e_ident[%d] != '%c'\n", EI_MAG1, ELFMAG1);
351*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ident[EI_MAG2] != ELFMAG2)
352*7304104dSAndroid Build Coastguard Worker ERROR ("e_ident[%d] != '%c'\n", EI_MAG2, ELFMAG2);
353*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ident[EI_MAG3] != ELFMAG3)
354*7304104dSAndroid Build Coastguard Worker ERROR ("e_ident[%d] != '%c'\n", EI_MAG3, ELFMAG3);
355*7304104dSAndroid Build Coastguard Worker
356*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ident[EI_CLASS] != ELFCLASS32
357*7304104dSAndroid Build Coastguard Worker && ehdr->e_ident[EI_CLASS] != ELFCLASS64)
358*7304104dSAndroid Build Coastguard Worker ERROR (_("e_ident[%d] == %d is no known class\n"),
359*7304104dSAndroid Build Coastguard Worker EI_CLASS, ehdr->e_ident[EI_CLASS]);
360*7304104dSAndroid Build Coastguard Worker
361*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB
362*7304104dSAndroid Build Coastguard Worker && ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
363*7304104dSAndroid Build Coastguard Worker ERROR (_("e_ident[%d] == %d is no known data encoding\n"),
364*7304104dSAndroid Build Coastguard Worker EI_DATA, ehdr->e_ident[EI_DATA]);
365*7304104dSAndroid Build Coastguard Worker
366*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ident[EI_VERSION] != EV_CURRENT)
367*7304104dSAndroid Build Coastguard Worker ERROR (_("unknown ELF header version number e_ident[%d] == %d\n"),
368*7304104dSAndroid Build Coastguard Worker EI_VERSION, ehdr->e_ident[EI_VERSION]);
369*7304104dSAndroid Build Coastguard Worker
370*7304104dSAndroid Build Coastguard Worker /* We currently don't handle any OS ABIs other than Linux and the
371*7304104dSAndroid Build Coastguard Worker kFreeBSD variant of Debian. */
372*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE
373*7304104dSAndroid Build Coastguard Worker && ehdr->e_ident[EI_OSABI] != ELFOSABI_LINUX
374*7304104dSAndroid Build Coastguard Worker && ehdr->e_ident[EI_OSABI] != ELFOSABI_FREEBSD)
375*7304104dSAndroid Build Coastguard Worker ERROR (_("unsupported OS ABI e_ident[%d] == '%s'\n"),
376*7304104dSAndroid Build Coastguard Worker EI_OSABI,
377*7304104dSAndroid Build Coastguard Worker ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
378*7304104dSAndroid Build Coastguard Worker
379*7304104dSAndroid Build Coastguard Worker /* No ABI versions other than zero are supported either. */
380*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ident[EI_ABIVERSION] != 0)
381*7304104dSAndroid Build Coastguard Worker ERROR (_("unsupported ABI version e_ident[%d] == %d\n"),
382*7304104dSAndroid Build Coastguard Worker EI_ABIVERSION, ehdr->e_ident[EI_ABIVERSION]);
383*7304104dSAndroid Build Coastguard Worker
384*7304104dSAndroid Build Coastguard Worker for (cnt = EI_PAD; cnt < EI_NIDENT; ++cnt)
385*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ident[cnt] != 0)
386*7304104dSAndroid Build Coastguard Worker ERROR (_("e_ident[%zu] is not zero\n"), cnt);
387*7304104dSAndroid Build Coastguard Worker
388*7304104dSAndroid Build Coastguard Worker /* Check the e_type field. */
389*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_REL && ehdr->e_type != ET_EXEC
390*7304104dSAndroid Build Coastguard Worker && ehdr->e_type != ET_DYN && ehdr->e_type != ET_CORE)
391*7304104dSAndroid Build Coastguard Worker ERROR (_("unknown object file type %d\n"), ehdr->e_type);
392*7304104dSAndroid Build Coastguard Worker
393*7304104dSAndroid Build Coastguard Worker /* Check the e_machine field. */
394*7304104dSAndroid Build Coastguard Worker for (cnt = 0; cnt < nvalid_e_machine; ++cnt)
395*7304104dSAndroid Build Coastguard Worker if (valid_e_machine[cnt] == ehdr->e_machine)
396*7304104dSAndroid Build Coastguard Worker break;
397*7304104dSAndroid Build Coastguard Worker if (cnt == nvalid_e_machine)
398*7304104dSAndroid Build Coastguard Worker ERROR (_("unknown machine type %d\n"), ehdr->e_machine);
399*7304104dSAndroid Build Coastguard Worker
400*7304104dSAndroid Build Coastguard Worker /* Check the e_version field. */
401*7304104dSAndroid Build Coastguard Worker if (ehdr->e_version != EV_CURRENT)
402*7304104dSAndroid Build Coastguard Worker ERROR (_("unknown object file version\n"));
403*7304104dSAndroid Build Coastguard Worker
404*7304104dSAndroid Build Coastguard Worker /* Check the e_phoff and e_phnum fields. */
405*7304104dSAndroid Build Coastguard Worker if (ehdr->e_phoff == 0)
406*7304104dSAndroid Build Coastguard Worker {
407*7304104dSAndroid Build Coastguard Worker if (ehdr->e_phnum != 0)
408*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid program header offset\n"));
409*7304104dSAndroid Build Coastguard Worker else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
410*7304104dSAndroid Build Coastguard Worker ERROR (_("\
411*7304104dSAndroid Build Coastguard Worker executables and DSOs cannot have zero program header offset\n"));
412*7304104dSAndroid Build Coastguard Worker }
413*7304104dSAndroid Build Coastguard Worker else if (ehdr->e_phnum == 0)
414*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid number of program header entries\n"));
415*7304104dSAndroid Build Coastguard Worker
416*7304104dSAndroid Build Coastguard Worker /* Check the e_shoff field. */
417*7304104dSAndroid Build Coastguard Worker shnum = ehdr->e_shnum;
418*7304104dSAndroid Build Coastguard Worker shstrndx = ehdr->e_shstrndx;
419*7304104dSAndroid Build Coastguard Worker if (ehdr->e_shoff == 0)
420*7304104dSAndroid Build Coastguard Worker {
421*7304104dSAndroid Build Coastguard Worker if (ehdr->e_shnum != 0)
422*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid section header table offset\n"));
423*7304104dSAndroid Build Coastguard Worker else if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
424*7304104dSAndroid Build Coastguard Worker && ehdr->e_type != ET_CORE)
425*7304104dSAndroid Build Coastguard Worker ERROR (_("section header table must be present\n"));
426*7304104dSAndroid Build Coastguard Worker }
427*7304104dSAndroid Build Coastguard Worker else
428*7304104dSAndroid Build Coastguard Worker {
429*7304104dSAndroid Build Coastguard Worker if (ehdr->e_shnum == 0)
430*7304104dSAndroid Build Coastguard Worker {
431*7304104dSAndroid Build Coastguard Worker /* Get the header of the zeroth section. The sh_size field
432*7304104dSAndroid Build Coastguard Worker might contain the section number. */
433*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
434*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
435*7304104dSAndroid Build Coastguard Worker if (shdr != NULL)
436*7304104dSAndroid Build Coastguard Worker {
437*7304104dSAndroid Build Coastguard Worker /* The error will be reported later. */
438*7304104dSAndroid Build Coastguard Worker if (shdr->sh_size == 0)
439*7304104dSAndroid Build Coastguard Worker ERROR (_("\
440*7304104dSAndroid Build Coastguard Worker invalid number of section header table entries\n"));
441*7304104dSAndroid Build Coastguard Worker else
442*7304104dSAndroid Build Coastguard Worker shnum = shdr->sh_size;
443*7304104dSAndroid Build Coastguard Worker }
444*7304104dSAndroid Build Coastguard Worker }
445*7304104dSAndroid Build Coastguard Worker
446*7304104dSAndroid Build Coastguard Worker if (ehdr->e_shstrndx == SHN_XINDEX)
447*7304104dSAndroid Build Coastguard Worker {
448*7304104dSAndroid Build Coastguard Worker /* Get the header of the zeroth section. The sh_size field
449*7304104dSAndroid Build Coastguard Worker might contain the section number. */
450*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
451*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
452*7304104dSAndroid Build Coastguard Worker if (shdr != NULL && shdr->sh_link < shnum)
453*7304104dSAndroid Build Coastguard Worker shstrndx = shdr->sh_link;
454*7304104dSAndroid Build Coastguard Worker }
455*7304104dSAndroid Build Coastguard Worker else if (shstrndx >= shnum)
456*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid section header index\n"));
457*7304104dSAndroid Build Coastguard Worker }
458*7304104dSAndroid Build Coastguard Worker
459*7304104dSAndroid Build Coastguard Worker /* Check the shdrs actually exist. And uncompress them before
460*7304104dSAndroid Build Coastguard Worker further checking. Indexes between sections reference the
461*7304104dSAndroid Build Coastguard Worker uncompressed data. */
462*7304104dSAndroid Build Coastguard Worker unsigned int scnt;
463*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = NULL;
464*7304104dSAndroid Build Coastguard Worker for (scnt = 1; scnt < shnum; ++scnt)
465*7304104dSAndroid Build Coastguard Worker {
466*7304104dSAndroid Build Coastguard Worker scn = elf_nextscn (ebl->elf, scn);
467*7304104dSAndroid Build Coastguard Worker if (scn == NULL)
468*7304104dSAndroid Build Coastguard Worker break;
469*7304104dSAndroid Build Coastguard Worker /* If the section wasn't compressed this does nothing, but
470*7304104dSAndroid Build Coastguard Worker returns an error. We don't care. */
471*7304104dSAndroid Build Coastguard Worker if (elf_compress (scn, 0, 0) < 0) { ; }
472*7304104dSAndroid Build Coastguard Worker }
473*7304104dSAndroid Build Coastguard Worker if (scnt < shnum)
474*7304104dSAndroid Build Coastguard Worker ERROR (_("Can only check %u headers, shnum was %u\n"), scnt, shnum);
475*7304104dSAndroid Build Coastguard Worker shnum = scnt;
476*7304104dSAndroid Build Coastguard Worker
477*7304104dSAndroid Build Coastguard Worker phnum = ehdr->e_phnum;
478*7304104dSAndroid Build Coastguard Worker if (ehdr->e_phnum == PN_XNUM)
479*7304104dSAndroid Build Coastguard Worker {
480*7304104dSAndroid Build Coastguard Worker /* Get the header of the zeroth section. The sh_info field
481*7304104dSAndroid Build Coastguard Worker might contain the phnum count. */
482*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
483*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
484*7304104dSAndroid Build Coastguard Worker if (shdr != NULL)
485*7304104dSAndroid Build Coastguard Worker {
486*7304104dSAndroid Build Coastguard Worker /* The error will be reported later. */
487*7304104dSAndroid Build Coastguard Worker if (shdr->sh_info < PN_XNUM)
488*7304104dSAndroid Build Coastguard Worker ERROR (_("\
489*7304104dSAndroid Build Coastguard Worker invalid number of program header table entries\n"));
490*7304104dSAndroid Build Coastguard Worker else
491*7304104dSAndroid Build Coastguard Worker phnum = shdr->sh_info;
492*7304104dSAndroid Build Coastguard Worker }
493*7304104dSAndroid Build Coastguard Worker }
494*7304104dSAndroid Build Coastguard Worker
495*7304104dSAndroid Build Coastguard Worker /* Check the phdrs actually exist. */
496*7304104dSAndroid Build Coastguard Worker unsigned int pcnt;
497*7304104dSAndroid Build Coastguard Worker for (pcnt = 0; pcnt < phnum; ++pcnt)
498*7304104dSAndroid Build Coastguard Worker {
499*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr_mem;
500*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
501*7304104dSAndroid Build Coastguard Worker if (phdr == NULL)
502*7304104dSAndroid Build Coastguard Worker break;
503*7304104dSAndroid Build Coastguard Worker }
504*7304104dSAndroid Build Coastguard Worker if (pcnt < phnum)
505*7304104dSAndroid Build Coastguard Worker ERROR (_("Can only check %u headers, phnum was %u\n"), pcnt, phnum);
506*7304104dSAndroid Build Coastguard Worker phnum = pcnt;
507*7304104dSAndroid Build Coastguard Worker
508*7304104dSAndroid Build Coastguard Worker /* Check the e_flags field. */
509*7304104dSAndroid Build Coastguard Worker if (!ebl_machine_flag_check (ebl, ehdr->e_flags))
510*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid machine flags: %s\n"),
511*7304104dSAndroid Build Coastguard Worker ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
512*7304104dSAndroid Build Coastguard Worker
513*7304104dSAndroid Build Coastguard Worker /* Check e_ehsize, e_phentsize, and e_shentsize fields. */
514*7304104dSAndroid Build Coastguard Worker if (gelf_getclass (ebl->elf) == ELFCLASS32)
515*7304104dSAndroid Build Coastguard Worker {
516*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf32_Ehdr))
517*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
518*7304104dSAndroid Build Coastguard Worker
519*7304104dSAndroid Build Coastguard Worker if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr))
520*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid program header size: %hd\n"),
521*7304104dSAndroid Build Coastguard Worker ehdr->e_phentsize);
522*7304104dSAndroid Build Coastguard Worker else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size)
523*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid program header position or size\n"));
524*7304104dSAndroid Build Coastguard Worker
525*7304104dSAndroid Build Coastguard Worker if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr))
526*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid section header size: %hd\n"),
527*7304104dSAndroid Build Coastguard Worker ehdr->e_shentsize);
528*7304104dSAndroid Build Coastguard Worker else if (ehdr->e_shoff + shnum * ehdr->e_shentsize > size)
529*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid section header position or size\n"));
530*7304104dSAndroid Build Coastguard Worker }
531*7304104dSAndroid Build Coastguard Worker else if (gelf_getclass (ebl->elf) == ELFCLASS64)
532*7304104dSAndroid Build Coastguard Worker {
533*7304104dSAndroid Build Coastguard Worker if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf64_Ehdr))
534*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
535*7304104dSAndroid Build Coastguard Worker
536*7304104dSAndroid Build Coastguard Worker if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr))
537*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid program header size: %hd\n"),
538*7304104dSAndroid Build Coastguard Worker ehdr->e_phentsize);
539*7304104dSAndroid Build Coastguard Worker else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size)
540*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid program header position or size\n"));
541*7304104dSAndroid Build Coastguard Worker
542*7304104dSAndroid Build Coastguard Worker if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr))
543*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid section header size: %hd\n"),
544*7304104dSAndroid Build Coastguard Worker ehdr->e_shentsize);
545*7304104dSAndroid Build Coastguard Worker else if (ehdr->e_shoff + shnum * ehdr->e_shentsize > size)
546*7304104dSAndroid Build Coastguard Worker ERROR (_("invalid section header position or size\n"));
547*7304104dSAndroid Build Coastguard Worker }
548*7304104dSAndroid Build Coastguard Worker }
549*7304104dSAndroid Build Coastguard Worker
550*7304104dSAndroid Build Coastguard Worker
551*7304104dSAndroid Build Coastguard Worker /* Check that there is a section group section with index < IDX which
552*7304104dSAndroid Build Coastguard Worker contains section IDX and that there is exactly one. */
553*7304104dSAndroid Build Coastguard Worker static void
check_scn_group(Ebl * ebl,int idx)554*7304104dSAndroid Build Coastguard Worker check_scn_group (Ebl *ebl, int idx)
555*7304104dSAndroid Build Coastguard Worker {
556*7304104dSAndroid Build Coastguard Worker if (scnref[idx] == 0)
557*7304104dSAndroid Build Coastguard Worker {
558*7304104dSAndroid Build Coastguard Worker /* No reference so far. Search following sections, maybe the
559*7304104dSAndroid Build Coastguard Worker order is wrong. */
560*7304104dSAndroid Build Coastguard Worker size_t cnt;
561*7304104dSAndroid Build Coastguard Worker
562*7304104dSAndroid Build Coastguard Worker for (cnt = idx + 1; cnt < shnum; ++cnt)
563*7304104dSAndroid Build Coastguard Worker {
564*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
565*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
566*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
567*7304104dSAndroid Build Coastguard Worker if (shdr == NULL)
568*7304104dSAndroid Build Coastguard Worker /* We cannot get the section header so we cannot check it.
569*7304104dSAndroid Build Coastguard Worker The error to get the section header will be shown
570*7304104dSAndroid Build Coastguard Worker somewhere else. */
571*7304104dSAndroid Build Coastguard Worker continue;
572*7304104dSAndroid Build Coastguard Worker
573*7304104dSAndroid Build Coastguard Worker if (shdr->sh_type != SHT_GROUP)
574*7304104dSAndroid Build Coastguard Worker continue;
575*7304104dSAndroid Build Coastguard Worker
576*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (scn, NULL);
577*7304104dSAndroid Build Coastguard Worker if (data == NULL || data->d_buf == NULL
578*7304104dSAndroid Build Coastguard Worker || data->d_size < sizeof (Elf32_Word))
579*7304104dSAndroid Build Coastguard Worker /* Cannot check the section. */
580*7304104dSAndroid Build Coastguard Worker continue;
581*7304104dSAndroid Build Coastguard Worker
582*7304104dSAndroid Build Coastguard Worker Elf32_Word *grpdata = (Elf32_Word *) data->d_buf;
583*7304104dSAndroid Build Coastguard Worker for (size_t inner = 1; inner < data->d_size / sizeof (Elf32_Word);
584*7304104dSAndroid Build Coastguard Worker ++inner)
585*7304104dSAndroid Build Coastguard Worker if (grpdata[inner] == (Elf32_Word) idx)
586*7304104dSAndroid Build Coastguard Worker goto out;
587*7304104dSAndroid Build Coastguard Worker }
588*7304104dSAndroid Build Coastguard Worker
589*7304104dSAndroid Build Coastguard Worker out:
590*7304104dSAndroid Build Coastguard Worker if (cnt == shnum)
591*7304104dSAndroid Build Coastguard Worker ERROR (_("\
592*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section with SHF_GROUP flag set not part of a section group\n"),
593*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
594*7304104dSAndroid Build Coastguard Worker else
595*7304104dSAndroid Build Coastguard Worker ERROR (_("\
596*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section group [%2zu] '%s' does not precede group member\n"),
597*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
598*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
599*7304104dSAndroid Build Coastguard Worker }
600*7304104dSAndroid Build Coastguard Worker }
601*7304104dSAndroid Build Coastguard Worker
602*7304104dSAndroid Build Coastguard Worker
603*7304104dSAndroid Build Coastguard Worker static void
check_symtab(Ebl * ebl,GElf_Ehdr * ehdr,GElf_Shdr * shdr,int idx)604*7304104dSAndroid Build Coastguard Worker check_symtab (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
605*7304104dSAndroid Build Coastguard Worker {
606*7304104dSAndroid Build Coastguard Worker bool no_xndx_warned = false;
607*7304104dSAndroid Build Coastguard Worker int no_pt_tls = 0;
608*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
609*7304104dSAndroid Build Coastguard Worker if (data == NULL)
610*7304104dSAndroid Build Coastguard Worker {
611*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
612*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
613*7304104dSAndroid Build Coastguard Worker return;
614*7304104dSAndroid Build Coastguard Worker }
615*7304104dSAndroid Build Coastguard Worker
616*7304104dSAndroid Build Coastguard Worker GElf_Shdr strshdr_mem;
617*7304104dSAndroid Build Coastguard Worker GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
618*7304104dSAndroid Build Coastguard Worker &strshdr_mem);
619*7304104dSAndroid Build Coastguard Worker if (strshdr == NULL)
620*7304104dSAndroid Build Coastguard Worker return;
621*7304104dSAndroid Build Coastguard Worker
622*7304104dSAndroid Build Coastguard Worker if (strshdr->sh_type != SHT_STRTAB)
623*7304104dSAndroid Build Coastguard Worker {
624*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
625*7304104dSAndroid Build Coastguard Worker shdr->sh_link, section_name (ebl, shdr->sh_link),
626*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
627*7304104dSAndroid Build Coastguard Worker strshdr = NULL;
628*7304104dSAndroid Build Coastguard Worker }
629*7304104dSAndroid Build Coastguard Worker
630*7304104dSAndroid Build Coastguard Worker /* Search for an extended section index table section. */
631*7304104dSAndroid Build Coastguard Worker Elf_Data *xndxdata = NULL;
632*7304104dSAndroid Build Coastguard Worker Elf32_Word xndxscnidx = 0;
633*7304104dSAndroid Build Coastguard Worker bool found_xndx = false;
634*7304104dSAndroid Build Coastguard Worker for (size_t cnt = 1; cnt < shnum; ++cnt)
635*7304104dSAndroid Build Coastguard Worker if (cnt != (size_t) idx)
636*7304104dSAndroid Build Coastguard Worker {
637*7304104dSAndroid Build Coastguard Worker Elf_Scn *xndxscn = elf_getscn (ebl->elf, cnt);
638*7304104dSAndroid Build Coastguard Worker GElf_Shdr xndxshdr_mem;
639*7304104dSAndroid Build Coastguard Worker GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
640*7304104dSAndroid Build Coastguard Worker if (xndxshdr == NULL)
641*7304104dSAndroid Build Coastguard Worker continue;
642*7304104dSAndroid Build Coastguard Worker
643*7304104dSAndroid Build Coastguard Worker if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
644*7304104dSAndroid Build Coastguard Worker && xndxshdr->sh_link == (GElf_Word) idx)
645*7304104dSAndroid Build Coastguard Worker {
646*7304104dSAndroid Build Coastguard Worker if (found_xndx)
647*7304104dSAndroid Build Coastguard Worker ERROR (_("\
648*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol table cannot have more than one extended index section\n"),
649*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
650*7304104dSAndroid Build Coastguard Worker
651*7304104dSAndroid Build Coastguard Worker xndxdata = elf_getdata (xndxscn, NULL);
652*7304104dSAndroid Build Coastguard Worker xndxscnidx = elf_ndxscn (xndxscn);
653*7304104dSAndroid Build Coastguard Worker found_xndx = true;
654*7304104dSAndroid Build Coastguard Worker }
655*7304104dSAndroid Build Coastguard Worker }
656*7304104dSAndroid Build Coastguard Worker
657*7304104dSAndroid Build Coastguard Worker size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT);
658*7304104dSAndroid Build Coastguard Worker if (shdr->sh_entsize != sh_entsize)
659*7304104dSAndroid Build Coastguard Worker ERROR (_("\
660*7304104dSAndroid Build Coastguard Worker section [%2u] '%s': entry size is does not match ElfXX_Sym\n"),
661*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
662*7304104dSAndroid Build Coastguard Worker else if (shdr->sh_info > shdr->sh_size / sh_entsize)
663*7304104dSAndroid Build Coastguard Worker ERROR (_("\
664*7304104dSAndroid Build Coastguard Worker section [%2u] '%s': number of local entries in 'st_info' larger than table size\n"),
665*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
666*7304104dSAndroid Build Coastguard Worker
667*7304104dSAndroid Build Coastguard Worker /* Test the zeroth entry. */
668*7304104dSAndroid Build Coastguard Worker GElf_Sym sym_mem;
669*7304104dSAndroid Build Coastguard Worker Elf32_Word xndx;
670*7304104dSAndroid Build Coastguard Worker GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, 0, &sym_mem, &xndx);
671*7304104dSAndroid Build Coastguard Worker if (sym == NULL)
672*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get symbol %d: %s\n"),
673*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), 0, elf_errmsg (-1));
674*7304104dSAndroid Build Coastguard Worker else
675*7304104dSAndroid Build Coastguard Worker {
676*7304104dSAndroid Build Coastguard Worker if (sym->st_name != 0)
677*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
678*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "st_name");
679*7304104dSAndroid Build Coastguard Worker if (sym->st_value != 0)
680*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
681*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "st_value");
682*7304104dSAndroid Build Coastguard Worker if (sym->st_size != 0)
683*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
684*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "st_size");
685*7304104dSAndroid Build Coastguard Worker if (sym->st_info != 0)
686*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
687*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "st_info");
688*7304104dSAndroid Build Coastguard Worker if (sym->st_other != 0)
689*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
690*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "st_other");
691*7304104dSAndroid Build Coastguard Worker if (sym->st_shndx != 0)
692*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
693*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "st_shndx");
694*7304104dSAndroid Build Coastguard Worker if (xndxdata != NULL && xndx != 0)
695*7304104dSAndroid Build Coastguard Worker ERROR (_("\
696*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': XINDEX for zeroth entry not zero\n"),
697*7304104dSAndroid Build Coastguard Worker xndxscnidx, section_name (ebl, xndxscnidx));
698*7304104dSAndroid Build Coastguard Worker }
699*7304104dSAndroid Build Coastguard Worker
700*7304104dSAndroid Build Coastguard Worker for (size_t cnt = 1; cnt < shdr->sh_size / sh_entsize; ++cnt)
701*7304104dSAndroid Build Coastguard Worker {
702*7304104dSAndroid Build Coastguard Worker sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx);
703*7304104dSAndroid Build Coastguard Worker if (sym == NULL)
704*7304104dSAndroid Build Coastguard Worker {
705*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get symbol %zu: %s\n"),
706*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
707*7304104dSAndroid Build Coastguard Worker continue;
708*7304104dSAndroid Build Coastguard Worker }
709*7304104dSAndroid Build Coastguard Worker
710*7304104dSAndroid Build Coastguard Worker const char *name = "<invalid>";
711*7304104dSAndroid Build Coastguard Worker if (strshdr == NULL)
712*7304104dSAndroid Build Coastguard Worker name = "";
713*7304104dSAndroid Build Coastguard Worker else if (sym->st_name >= strshdr->sh_size)
714*7304104dSAndroid Build Coastguard Worker ERROR (_("\
715*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu: invalid name value\n"),
716*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
717*7304104dSAndroid Build Coastguard Worker else
718*7304104dSAndroid Build Coastguard Worker {
719*7304104dSAndroid Build Coastguard Worker name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name);
720*7304104dSAndroid Build Coastguard Worker if (name == NULL)
721*7304104dSAndroid Build Coastguard Worker name = "";
722*7304104dSAndroid Build Coastguard Worker }
723*7304104dSAndroid Build Coastguard Worker
724*7304104dSAndroid Build Coastguard Worker if (sym->st_shndx == SHN_XINDEX)
725*7304104dSAndroid Build Coastguard Worker {
726*7304104dSAndroid Build Coastguard Worker if (xndxdata == NULL)
727*7304104dSAndroid Build Coastguard Worker {
728*7304104dSAndroid Build Coastguard Worker if (!no_xndx_warned)
729*7304104dSAndroid Build Coastguard Worker ERROR (_("\
730*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): too large section index but no extended section index section\n"),
731*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
732*7304104dSAndroid Build Coastguard Worker no_xndx_warned = true;
733*7304104dSAndroid Build Coastguard Worker }
734*7304104dSAndroid Build Coastguard Worker else if (xndx < SHN_LORESERVE)
735*7304104dSAndroid Build Coastguard Worker ERROR (_("\
736*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): XINDEX used for index which would fit in st_shndx (%" PRIu32 ")\n"),
737*7304104dSAndroid Build Coastguard Worker xndxscnidx, section_name (ebl, xndxscnidx), cnt, name,
738*7304104dSAndroid Build Coastguard Worker xndx);
739*7304104dSAndroid Build Coastguard Worker }
740*7304104dSAndroid Build Coastguard Worker else if ((sym->st_shndx >= SHN_LORESERVE
741*7304104dSAndroid Build Coastguard Worker // && sym->st_shndx <= SHN_HIRESERVE always true
742*7304104dSAndroid Build Coastguard Worker && sym->st_shndx != SHN_ABS
743*7304104dSAndroid Build Coastguard Worker && sym->st_shndx != SHN_COMMON)
744*7304104dSAndroid Build Coastguard Worker || (sym->st_shndx >= shnum
745*7304104dSAndroid Build Coastguard Worker && (sym->st_shndx < SHN_LORESERVE
746*7304104dSAndroid Build Coastguard Worker /* || sym->st_shndx > SHN_HIRESERVE always false */)))
747*7304104dSAndroid Build Coastguard Worker ERROR (_("\
748*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): invalid section index\n"),
749*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
750*7304104dSAndroid Build Coastguard Worker else
751*7304104dSAndroid Build Coastguard Worker xndx = sym->st_shndx;
752*7304104dSAndroid Build Coastguard Worker
753*7304104dSAndroid Build Coastguard Worker if (GELF_ST_TYPE (sym->st_info) >= STT_NUM
754*7304104dSAndroid Build Coastguard Worker && !ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), NULL, 0))
755*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': symbol %zu (%s): unknown type\n"),
756*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
757*7304104dSAndroid Build Coastguard Worker
758*7304104dSAndroid Build Coastguard Worker if (GELF_ST_BIND (sym->st_info) >= STB_NUM
759*7304104dSAndroid Build Coastguard Worker && !ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info), NULL,
760*7304104dSAndroid Build Coastguard Worker 0))
761*7304104dSAndroid Build Coastguard Worker ERROR (_("\
762*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): unknown symbol binding\n"),
763*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
764*7304104dSAndroid Build Coastguard Worker if (GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE
765*7304104dSAndroid Build Coastguard Worker && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
766*7304104dSAndroid Build Coastguard Worker ERROR (_("\
767*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): unique symbol not of object type\n"),
768*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
769*7304104dSAndroid Build Coastguard Worker
770*7304104dSAndroid Build Coastguard Worker if (xndx == SHN_COMMON)
771*7304104dSAndroid Build Coastguard Worker {
772*7304104dSAndroid Build Coastguard Worker /* Common symbols can only appear in relocatable files. */
773*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_REL)
774*7304104dSAndroid Build Coastguard Worker ERROR (_("\
775*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): COMMON only allowed in relocatable files\n"),
776*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
777*7304104dSAndroid Build Coastguard Worker if (cnt < shdr->sh_info)
778*7304104dSAndroid Build Coastguard Worker ERROR (_("\
779*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): local COMMON symbols are nonsense\n"),
780*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
781*7304104dSAndroid Build Coastguard Worker if (GELF_R_TYPE (sym->st_info) == STT_FUNC)
782*7304104dSAndroid Build Coastguard Worker ERROR (_("\
783*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): function in COMMON section is nonsense\n"),
784*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
785*7304104dSAndroid Build Coastguard Worker }
786*7304104dSAndroid Build Coastguard Worker else if (xndx > 0 && xndx < shnum)
787*7304104dSAndroid Build Coastguard Worker {
788*7304104dSAndroid Build Coastguard Worker GElf_Shdr destshdr_mem;
789*7304104dSAndroid Build Coastguard Worker GElf_Shdr *destshdr;
790*7304104dSAndroid Build Coastguard Worker
791*7304104dSAndroid Build Coastguard Worker destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), &destshdr_mem);
792*7304104dSAndroid Build Coastguard Worker if (destshdr != NULL)
793*7304104dSAndroid Build Coastguard Worker {
794*7304104dSAndroid Build Coastguard Worker GElf_Addr sh_addr = (ehdr->e_type == ET_REL ? 0
795*7304104dSAndroid Build Coastguard Worker : destshdr->sh_addr);
796*7304104dSAndroid Build Coastguard Worker GElf_Addr st_value;
797*7304104dSAndroid Build Coastguard Worker if (GELF_ST_TYPE (sym->st_info) == STT_FUNC
798*7304104dSAndroid Build Coastguard Worker || (GELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))
799*7304104dSAndroid Build Coastguard Worker st_value = sym->st_value & ebl_func_addr_mask (ebl);
800*7304104dSAndroid Build Coastguard Worker else
801*7304104dSAndroid Build Coastguard Worker st_value = sym->st_value;
802*7304104dSAndroid Build Coastguard Worker if (GELF_ST_TYPE (sym->st_info) != STT_TLS)
803*7304104dSAndroid Build Coastguard Worker {
804*7304104dSAndroid Build Coastguard Worker if (! ebl_check_special_symbol (ebl, sym, name,
805*7304104dSAndroid Build Coastguard Worker destshdr))
806*7304104dSAndroid Build Coastguard Worker {
807*7304104dSAndroid Build Coastguard Worker if (st_value - sh_addr > destshdr->sh_size)
808*7304104dSAndroid Build Coastguard Worker {
809*7304104dSAndroid Build Coastguard Worker /* GNU ld has severe bugs. When it decides to remove
810*7304104dSAndroid Build Coastguard Worker empty sections it leaves symbols referencing them
811*7304104dSAndroid Build Coastguard Worker behind. These are symbols in .symtab or .dynsym
812*7304104dSAndroid Build Coastguard Worker and for the named symbols have zero size. See
813*7304104dSAndroid Build Coastguard Worker sourceware PR13621. */
814*7304104dSAndroid Build Coastguard Worker if (!gnuld
815*7304104dSAndroid Build Coastguard Worker || (strcmp (section_name (ebl, idx), ".symtab")
816*7304104dSAndroid Build Coastguard Worker && strcmp (section_name (ebl, idx),
817*7304104dSAndroid Build Coastguard Worker ".dynsym"))
818*7304104dSAndroid Build Coastguard Worker || sym->st_size != 0
819*7304104dSAndroid Build Coastguard Worker || (strcmp (name, "__preinit_array_start") != 0
820*7304104dSAndroid Build Coastguard Worker && strcmp (name, "__preinit_array_end") != 0
821*7304104dSAndroid Build Coastguard Worker && strcmp (name, "__init_array_start") != 0
822*7304104dSAndroid Build Coastguard Worker && strcmp (name, "__init_array_end") != 0
823*7304104dSAndroid Build Coastguard Worker && strcmp (name, "__fini_array_start") != 0
824*7304104dSAndroid Build Coastguard Worker && strcmp (name, "__fini_array_end") != 0
825*7304104dSAndroid Build Coastguard Worker && strcmp (name, "__bss_start") != 0
826*7304104dSAndroid Build Coastguard Worker && strcmp (name, "__bss_start__") != 0
827*7304104dSAndroid Build Coastguard Worker && strcmp (name, "__TMC_END__") != 0
828*7304104dSAndroid Build Coastguard Worker && strcmp (name, ".TOC.") != 0
829*7304104dSAndroid Build Coastguard Worker && strcmp (name, "_edata") != 0
830*7304104dSAndroid Build Coastguard Worker && strcmp (name, "__edata") != 0
831*7304104dSAndroid Build Coastguard Worker && strcmp (name, "_end") != 0
832*7304104dSAndroid Build Coastguard Worker && strcmp (name, "__end") != 0))
833*7304104dSAndroid Build Coastguard Worker ERROR (_("\
834*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): st_value out of bounds\n"),
835*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
836*7304104dSAndroid Build Coastguard Worker }
837*7304104dSAndroid Build Coastguard Worker else if ((st_value - sh_addr
838*7304104dSAndroid Build Coastguard Worker + sym->st_size) > destshdr->sh_size)
839*7304104dSAndroid Build Coastguard Worker ERROR (_("\
840*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s) does not fit completely in referenced section [%2d] '%s'\n"),
841*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name,
842*7304104dSAndroid Build Coastguard Worker (int) xndx, section_name (ebl, xndx));
843*7304104dSAndroid Build Coastguard Worker }
844*7304104dSAndroid Build Coastguard Worker }
845*7304104dSAndroid Build Coastguard Worker else
846*7304104dSAndroid Build Coastguard Worker {
847*7304104dSAndroid Build Coastguard Worker if ((destshdr->sh_flags & SHF_TLS) == 0)
848*7304104dSAndroid Build Coastguard Worker ERROR (_("\
849*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): referenced section [%2d] '%s' does not have SHF_TLS flag set\n"),
850*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name,
851*7304104dSAndroid Build Coastguard Worker (int) xndx, section_name (ebl, xndx));
852*7304104dSAndroid Build Coastguard Worker
853*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type == ET_REL)
854*7304104dSAndroid Build Coastguard Worker {
855*7304104dSAndroid Build Coastguard Worker /* For object files the symbol value must fall
856*7304104dSAndroid Build Coastguard Worker into the section. */
857*7304104dSAndroid Build Coastguard Worker if (st_value > destshdr->sh_size)
858*7304104dSAndroid Build Coastguard Worker ERROR (_("\
859*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): st_value out of bounds of referenced section [%2d] '%s'\n"),
860*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name,
861*7304104dSAndroid Build Coastguard Worker (int) xndx, section_name (ebl, xndx));
862*7304104dSAndroid Build Coastguard Worker else if (st_value + sym->st_size
863*7304104dSAndroid Build Coastguard Worker > destshdr->sh_size)
864*7304104dSAndroid Build Coastguard Worker ERROR (_("\
865*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s) does not fit completely in referenced section [%2d] '%s'\n"),
866*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name,
867*7304104dSAndroid Build Coastguard Worker (int) xndx, section_name (ebl, xndx));
868*7304104dSAndroid Build Coastguard Worker }
869*7304104dSAndroid Build Coastguard Worker else
870*7304104dSAndroid Build Coastguard Worker {
871*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr_mem;
872*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr = NULL;
873*7304104dSAndroid Build Coastguard Worker unsigned int pcnt;
874*7304104dSAndroid Build Coastguard Worker
875*7304104dSAndroid Build Coastguard Worker for (pcnt = 0; pcnt < phnum; ++pcnt)
876*7304104dSAndroid Build Coastguard Worker {
877*7304104dSAndroid Build Coastguard Worker phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
878*7304104dSAndroid Build Coastguard Worker if (phdr != NULL && phdr->p_type == PT_TLS)
879*7304104dSAndroid Build Coastguard Worker break;
880*7304104dSAndroid Build Coastguard Worker }
881*7304104dSAndroid Build Coastguard Worker
882*7304104dSAndroid Build Coastguard Worker if (pcnt == phnum)
883*7304104dSAndroid Build Coastguard Worker {
884*7304104dSAndroid Build Coastguard Worker if (no_pt_tls++ == 0)
885*7304104dSAndroid Build Coastguard Worker ERROR (_("\
886*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): TLS symbol but no TLS program header entry\n"),
887*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
888*7304104dSAndroid Build Coastguard Worker }
889*7304104dSAndroid Build Coastguard Worker else if (phdr == NULL)
890*7304104dSAndroid Build Coastguard Worker {
891*7304104dSAndroid Build Coastguard Worker ERROR (_("\
892*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): TLS symbol but couldn't get TLS program header entry\n"),
893*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
894*7304104dSAndroid Build Coastguard Worker }
895*7304104dSAndroid Build Coastguard Worker else if (!is_debuginfo)
896*7304104dSAndroid Build Coastguard Worker {
897*7304104dSAndroid Build Coastguard Worker if (st_value
898*7304104dSAndroid Build Coastguard Worker < destshdr->sh_offset - phdr->p_offset)
899*7304104dSAndroid Build Coastguard Worker ERROR (_("\
900*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): st_value short of referenced section [%2d] '%s'\n"),
901*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name,
902*7304104dSAndroid Build Coastguard Worker (int) xndx, section_name (ebl, xndx));
903*7304104dSAndroid Build Coastguard Worker else if (st_value
904*7304104dSAndroid Build Coastguard Worker > (destshdr->sh_offset - phdr->p_offset
905*7304104dSAndroid Build Coastguard Worker + destshdr->sh_size))
906*7304104dSAndroid Build Coastguard Worker ERROR (_("\
907*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): st_value out of bounds of referenced section [%2d] '%s'\n"),
908*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name,
909*7304104dSAndroid Build Coastguard Worker (int) xndx, section_name (ebl, xndx));
910*7304104dSAndroid Build Coastguard Worker else if (st_value + sym->st_size
911*7304104dSAndroid Build Coastguard Worker > (destshdr->sh_offset - phdr->p_offset
912*7304104dSAndroid Build Coastguard Worker + destshdr->sh_size))
913*7304104dSAndroid Build Coastguard Worker ERROR (_("\
914*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s) does not fit completely in referenced section [%2d] '%s'\n"),
915*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name,
916*7304104dSAndroid Build Coastguard Worker (int) xndx, section_name (ebl, xndx));
917*7304104dSAndroid Build Coastguard Worker }
918*7304104dSAndroid Build Coastguard Worker }
919*7304104dSAndroid Build Coastguard Worker }
920*7304104dSAndroid Build Coastguard Worker }
921*7304104dSAndroid Build Coastguard Worker }
922*7304104dSAndroid Build Coastguard Worker
923*7304104dSAndroid Build Coastguard Worker if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
924*7304104dSAndroid Build Coastguard Worker {
925*7304104dSAndroid Build Coastguard Worker if (cnt >= shdr->sh_info)
926*7304104dSAndroid Build Coastguard Worker ERROR (_("\
927*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): local symbol outside range described in sh_info\n"),
928*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
929*7304104dSAndroid Build Coastguard Worker }
930*7304104dSAndroid Build Coastguard Worker else
931*7304104dSAndroid Build Coastguard Worker {
932*7304104dSAndroid Build Coastguard Worker if (cnt < shdr->sh_info)
933*7304104dSAndroid Build Coastguard Worker ERROR (_("\
934*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): non-local symbol outside range described in sh_info\n"),
935*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
936*7304104dSAndroid Build Coastguard Worker }
937*7304104dSAndroid Build Coastguard Worker
938*7304104dSAndroid Build Coastguard Worker if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
939*7304104dSAndroid Build Coastguard Worker && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
940*7304104dSAndroid Build Coastguard Worker ERROR (_("\
941*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"),
942*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
943*7304104dSAndroid Build Coastguard Worker
944*7304104dSAndroid Build Coastguard Worker if (name != NULL)
945*7304104dSAndroid Build Coastguard Worker {
946*7304104dSAndroid Build Coastguard Worker if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
947*7304104dSAndroid Build Coastguard Worker {
948*7304104dSAndroid Build Coastguard Worker /* Check that address and size match the global offset table. */
949*7304104dSAndroid Build Coastguard Worker
950*7304104dSAndroid Build Coastguard Worker GElf_Shdr destshdr_mem;
951*7304104dSAndroid Build Coastguard Worker GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx),
952*7304104dSAndroid Build Coastguard Worker &destshdr_mem);
953*7304104dSAndroid Build Coastguard Worker
954*7304104dSAndroid Build Coastguard Worker if (destshdr == NULL && xndx == SHN_ABS)
955*7304104dSAndroid Build Coastguard Worker {
956*7304104dSAndroid Build Coastguard Worker /* In a DSO, we have to find the GOT section by name. */
957*7304104dSAndroid Build Coastguard Worker Elf_Scn *gotscn = NULL;
958*7304104dSAndroid Build Coastguard Worker Elf_Scn *gscn = NULL;
959*7304104dSAndroid Build Coastguard Worker while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL)
960*7304104dSAndroid Build Coastguard Worker {
961*7304104dSAndroid Build Coastguard Worker destshdr = gelf_getshdr (gscn, &destshdr_mem);
962*7304104dSAndroid Build Coastguard Worker assert (destshdr != NULL);
963*7304104dSAndroid Build Coastguard Worker const char *sname = elf_strptr (ebl->elf,
964*7304104dSAndroid Build Coastguard Worker shstrndx,
965*7304104dSAndroid Build Coastguard Worker destshdr->sh_name);
966*7304104dSAndroid Build Coastguard Worker if (sname != NULL)
967*7304104dSAndroid Build Coastguard Worker {
968*7304104dSAndroid Build Coastguard Worker if (strcmp (sname, ".got.plt") == 0)
969*7304104dSAndroid Build Coastguard Worker break;
970*7304104dSAndroid Build Coastguard Worker if (strcmp (sname, ".got") == 0)
971*7304104dSAndroid Build Coastguard Worker /* Do not stop looking.
972*7304104dSAndroid Build Coastguard Worker There might be a .got.plt section. */
973*7304104dSAndroid Build Coastguard Worker gotscn = gscn;
974*7304104dSAndroid Build Coastguard Worker }
975*7304104dSAndroid Build Coastguard Worker
976*7304104dSAndroid Build Coastguard Worker destshdr = NULL;
977*7304104dSAndroid Build Coastguard Worker }
978*7304104dSAndroid Build Coastguard Worker
979*7304104dSAndroid Build Coastguard Worker if (destshdr == NULL && gotscn != NULL)
980*7304104dSAndroid Build Coastguard Worker destshdr = gelf_getshdr (gotscn, &destshdr_mem);
981*7304104dSAndroid Build Coastguard Worker }
982*7304104dSAndroid Build Coastguard Worker
983*7304104dSAndroid Build Coastguard Worker const char *sname = ((destshdr == NULL || xndx == SHN_UNDEF)
984*7304104dSAndroid Build Coastguard Worker ? NULL
985*7304104dSAndroid Build Coastguard Worker : elf_strptr (ebl->elf, shstrndx,
986*7304104dSAndroid Build Coastguard Worker destshdr->sh_name));
987*7304104dSAndroid Build Coastguard Worker if (sname == NULL)
988*7304104dSAndroid Build Coastguard Worker {
989*7304104dSAndroid Build Coastguard Worker if (xndx != SHN_UNDEF || ehdr->e_type != ET_REL)
990*7304104dSAndroid Build Coastguard Worker ERROR (_("\
991*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
992*7304104dSAndroid Build Coastguard Worker bad section [%2d]\n"),
993*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), xndx);
994*7304104dSAndroid Build Coastguard Worker }
995*7304104dSAndroid Build Coastguard Worker else if (strcmp (sname, ".got.plt") != 0
996*7304104dSAndroid Build Coastguard Worker && strcmp (sname, ".got") != 0)
997*7304104dSAndroid Build Coastguard Worker ERROR (_("\
998*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
999*7304104dSAndroid Build Coastguard Worker section [%2d] '%s'\n"),
1000*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), xndx, sname);
1001*7304104dSAndroid Build Coastguard Worker
1002*7304104dSAndroid Build Coastguard Worker if (destshdr != NULL)
1003*7304104dSAndroid Build Coastguard Worker {
1004*7304104dSAndroid Build Coastguard Worker /* Found it. */
1005*7304104dSAndroid Build Coastguard Worker if (!ebl_check_special_symbol (ebl, sym, name,
1006*7304104dSAndroid Build Coastguard Worker destshdr))
1007*7304104dSAndroid Build Coastguard Worker {
1008*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_REL
1009*7304104dSAndroid Build Coastguard Worker && sym->st_value != destshdr->sh_addr)
1010*7304104dSAndroid Build Coastguard Worker /* This test is more strict than the psABIs which
1011*7304104dSAndroid Build Coastguard Worker usually allow the symbol to be in the middle of
1012*7304104dSAndroid Build Coastguard Worker the .got section, allowing negative offsets. */
1013*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1014*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match %s section address %#" PRIx64 "\n"),
1015*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1016*7304104dSAndroid Build Coastguard Worker (uint64_t) sym->st_value,
1017*7304104dSAndroid Build Coastguard Worker sname, (uint64_t) destshdr->sh_addr);
1018*7304104dSAndroid Build Coastguard Worker
1019*7304104dSAndroid Build Coastguard Worker if (!gnuld && sym->st_size != destshdr->sh_size)
1020*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1021*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match %s section size %" PRIu64 "\n"),
1022*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1023*7304104dSAndroid Build Coastguard Worker (uint64_t) sym->st_size,
1024*7304104dSAndroid Build Coastguard Worker sname, (uint64_t) destshdr->sh_size);
1025*7304104dSAndroid Build Coastguard Worker }
1026*7304104dSAndroid Build Coastguard Worker }
1027*7304104dSAndroid Build Coastguard Worker else
1028*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1029*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"),
1030*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1031*7304104dSAndroid Build Coastguard Worker }
1032*7304104dSAndroid Build Coastguard Worker else if (strcmp (name, "_DYNAMIC") == 0)
1033*7304104dSAndroid Build Coastguard Worker /* Check that address and size match the dynamic section.
1034*7304104dSAndroid Build Coastguard Worker We locate the dynamic section via the program header
1035*7304104dSAndroid Build Coastguard Worker entry. */
1036*7304104dSAndroid Build Coastguard Worker for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt)
1037*7304104dSAndroid Build Coastguard Worker {
1038*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr_mem;
1039*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
1040*7304104dSAndroid Build Coastguard Worker
1041*7304104dSAndroid Build Coastguard Worker if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
1042*7304104dSAndroid Build Coastguard Worker {
1043*7304104dSAndroid Build Coastguard Worker if (sym->st_value != phdr->p_vaddr)
1044*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1045*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"),
1046*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1047*7304104dSAndroid Build Coastguard Worker (uint64_t) sym->st_value,
1048*7304104dSAndroid Build Coastguard Worker (uint64_t) phdr->p_vaddr);
1049*7304104dSAndroid Build Coastguard Worker
1050*7304104dSAndroid Build Coastguard Worker if (!gnuld && sym->st_size != phdr->p_memsz)
1051*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1052*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"),
1053*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1054*7304104dSAndroid Build Coastguard Worker (uint64_t) sym->st_size,
1055*7304104dSAndroid Build Coastguard Worker (uint64_t) phdr->p_memsz);
1056*7304104dSAndroid Build Coastguard Worker
1057*7304104dSAndroid Build Coastguard Worker break;
1058*7304104dSAndroid Build Coastguard Worker }
1059*7304104dSAndroid Build Coastguard Worker }
1060*7304104dSAndroid Build Coastguard Worker }
1061*7304104dSAndroid Build Coastguard Worker
1062*7304104dSAndroid Build Coastguard Worker if (GELF_ST_VISIBILITY (sym->st_other) != STV_DEFAULT
1063*7304104dSAndroid Build Coastguard Worker && shdr->sh_type == SHT_DYNSYM)
1064*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1065*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): symbol in dynamic symbol table with non-default visibility\n"),
1066*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
1067*7304104dSAndroid Build Coastguard Worker if (! ebl_check_st_other_bits (ebl, sym->st_other))
1068*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1069*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %zu (%s): unknown bit set in st_other\n"),
1070*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
1071*7304104dSAndroid Build Coastguard Worker
1072*7304104dSAndroid Build Coastguard Worker }
1073*7304104dSAndroid Build Coastguard Worker }
1074*7304104dSAndroid Build Coastguard Worker
1075*7304104dSAndroid Build Coastguard Worker
1076*7304104dSAndroid Build Coastguard Worker static bool
is_rel_dyn(Ebl * ebl,const GElf_Ehdr * ehdr,int idx,const GElf_Shdr * shdr,bool is_rela)1077*7304104dSAndroid Build Coastguard Worker is_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr,
1078*7304104dSAndroid Build Coastguard Worker bool is_rela)
1079*7304104dSAndroid Build Coastguard Worker {
1080*7304104dSAndroid Build Coastguard Worker /* If this is no executable or DSO it cannot be a .rel.dyn section. */
1081*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1082*7304104dSAndroid Build Coastguard Worker return false;
1083*7304104dSAndroid Build Coastguard Worker
1084*7304104dSAndroid Build Coastguard Worker /* Check the section name. Unfortunately necessary. */
1085*7304104dSAndroid Build Coastguard Worker if (strcmp (section_name (ebl, idx), is_rela ? ".rela.dyn" : ".rel.dyn"))
1086*7304104dSAndroid Build Coastguard Worker return false;
1087*7304104dSAndroid Build Coastguard Worker
1088*7304104dSAndroid Build Coastguard Worker /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section
1089*7304104dSAndroid Build Coastguard Worker entry can be present as well. */
1090*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = NULL;
1091*7304104dSAndroid Build Coastguard Worker while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1092*7304104dSAndroid Build Coastguard Worker {
1093*7304104dSAndroid Build Coastguard Worker GElf_Shdr rcshdr_mem;
1094*7304104dSAndroid Build Coastguard Worker const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem);
1095*7304104dSAndroid Build Coastguard Worker
1096*7304104dSAndroid Build Coastguard Worker if (rcshdr == NULL)
1097*7304104dSAndroid Build Coastguard Worker break;
1098*7304104dSAndroid Build Coastguard Worker
1099*7304104dSAndroid Build Coastguard Worker if (rcshdr->sh_type == SHT_DYNAMIC && rcshdr->sh_entsize != 0)
1100*7304104dSAndroid Build Coastguard Worker {
1101*7304104dSAndroid Build Coastguard Worker /* Found the dynamic section. Look through it. */
1102*7304104dSAndroid Build Coastguard Worker Elf_Data *d = elf_getdata (scn, NULL);
1103*7304104dSAndroid Build Coastguard Worker size_t cnt;
1104*7304104dSAndroid Build Coastguard Worker
1105*7304104dSAndroid Build Coastguard Worker if (d == NULL)
1106*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1107*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': cannot get section data.\n"),
1108*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1109*7304104dSAndroid Build Coastguard Worker
1110*7304104dSAndroid Build Coastguard Worker for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt)
1111*7304104dSAndroid Build Coastguard Worker {
1112*7304104dSAndroid Build Coastguard Worker GElf_Dyn dyn_mem;
1113*7304104dSAndroid Build Coastguard Worker GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem);
1114*7304104dSAndroid Build Coastguard Worker
1115*7304104dSAndroid Build Coastguard Worker if (dyn == NULL)
1116*7304104dSAndroid Build Coastguard Worker break;
1117*7304104dSAndroid Build Coastguard Worker
1118*7304104dSAndroid Build Coastguard Worker if (dyn->d_tag == DT_RELCOUNT)
1119*7304104dSAndroid Build Coastguard Worker {
1120*7304104dSAndroid Build Coastguard Worker /* Found it. Does the type match. */
1121*7304104dSAndroid Build Coastguard Worker if (is_rela)
1122*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1123*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': DT_RELCOUNT used for this RELA section\n"),
1124*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1125*7304104dSAndroid Build Coastguard Worker else
1126*7304104dSAndroid Build Coastguard Worker {
1127*7304104dSAndroid Build Coastguard Worker /* Does the number specified number of relative
1128*7304104dSAndroid Build Coastguard Worker relocations exceed the total number of
1129*7304104dSAndroid Build Coastguard Worker relocations? */
1130*7304104dSAndroid Build Coastguard Worker if (shdr->sh_entsize != 0
1131*7304104dSAndroid Build Coastguard Worker && dyn->d_un.d_val > (shdr->sh_size
1132*7304104dSAndroid Build Coastguard Worker / shdr->sh_entsize))
1133*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1134*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
1135*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1136*7304104dSAndroid Build Coastguard Worker (int) dyn->d_un.d_val);
1137*7304104dSAndroid Build Coastguard Worker
1138*7304104dSAndroid Build Coastguard Worker /* Make sure the specified number of relocations are
1139*7304104dSAndroid Build Coastguard Worker relative. */
1140*7304104dSAndroid Build Coastguard Worker Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
1141*7304104dSAndroid Build Coastguard Worker idx), NULL);
1142*7304104dSAndroid Build Coastguard Worker if (reldata != NULL && shdr->sh_entsize != 0)
1143*7304104dSAndroid Build Coastguard Worker for (size_t inner = 0;
1144*7304104dSAndroid Build Coastguard Worker inner < shdr->sh_size / shdr->sh_entsize;
1145*7304104dSAndroid Build Coastguard Worker ++inner)
1146*7304104dSAndroid Build Coastguard Worker {
1147*7304104dSAndroid Build Coastguard Worker GElf_Rel rel_mem;
1148*7304104dSAndroid Build Coastguard Worker GElf_Rel *rel = gelf_getrel (reldata, inner,
1149*7304104dSAndroid Build Coastguard Worker &rel_mem);
1150*7304104dSAndroid Build Coastguard Worker if (rel == NULL)
1151*7304104dSAndroid Build Coastguard Worker /* The problem will be reported elsewhere. */
1152*7304104dSAndroid Build Coastguard Worker break;
1153*7304104dSAndroid Build Coastguard Worker
1154*7304104dSAndroid Build Coastguard Worker if (ebl_relative_reloc_p (ebl,
1155*7304104dSAndroid Build Coastguard Worker GELF_R_TYPE (rel->r_info)))
1156*7304104dSAndroid Build Coastguard Worker {
1157*7304104dSAndroid Build Coastguard Worker if (inner >= dyn->d_un.d_val)
1158*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1159*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
1160*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1161*7304104dSAndroid Build Coastguard Worker (int) dyn->d_un.d_val);
1162*7304104dSAndroid Build Coastguard Worker }
1163*7304104dSAndroid Build Coastguard Worker else if (inner < dyn->d_un.d_val)
1164*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1165*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
1166*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1167*7304104dSAndroid Build Coastguard Worker inner, (int) dyn->d_un.d_val);
1168*7304104dSAndroid Build Coastguard Worker }
1169*7304104dSAndroid Build Coastguard Worker }
1170*7304104dSAndroid Build Coastguard Worker }
1171*7304104dSAndroid Build Coastguard Worker
1172*7304104dSAndroid Build Coastguard Worker if (dyn->d_tag == DT_RELACOUNT)
1173*7304104dSAndroid Build Coastguard Worker {
1174*7304104dSAndroid Build Coastguard Worker /* Found it. Does the type match. */
1175*7304104dSAndroid Build Coastguard Worker if (!is_rela)
1176*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1177*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': DT_RELACOUNT used for this REL section\n"),
1178*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1179*7304104dSAndroid Build Coastguard Worker else
1180*7304104dSAndroid Build Coastguard Worker {
1181*7304104dSAndroid Build Coastguard Worker /* Does the number specified number of relative
1182*7304104dSAndroid Build Coastguard Worker relocations exceed the total number of
1183*7304104dSAndroid Build Coastguard Worker relocations? */
1184*7304104dSAndroid Build Coastguard Worker if (shdr->sh_entsize != 0
1185*7304104dSAndroid Build Coastguard Worker && dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
1186*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1187*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
1188*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1189*7304104dSAndroid Build Coastguard Worker (int) dyn->d_un.d_val);
1190*7304104dSAndroid Build Coastguard Worker
1191*7304104dSAndroid Build Coastguard Worker /* Make sure the specified number of relocations are
1192*7304104dSAndroid Build Coastguard Worker relative. */
1193*7304104dSAndroid Build Coastguard Worker Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
1194*7304104dSAndroid Build Coastguard Worker idx), NULL);
1195*7304104dSAndroid Build Coastguard Worker if (reldata != NULL && shdr->sh_entsize != 0)
1196*7304104dSAndroid Build Coastguard Worker for (size_t inner = 0;
1197*7304104dSAndroid Build Coastguard Worker inner < shdr->sh_size / shdr->sh_entsize;
1198*7304104dSAndroid Build Coastguard Worker ++inner)
1199*7304104dSAndroid Build Coastguard Worker {
1200*7304104dSAndroid Build Coastguard Worker GElf_Rela rela_mem;
1201*7304104dSAndroid Build Coastguard Worker GElf_Rela *rela = gelf_getrela (reldata, inner,
1202*7304104dSAndroid Build Coastguard Worker &rela_mem);
1203*7304104dSAndroid Build Coastguard Worker if (rela == NULL)
1204*7304104dSAndroid Build Coastguard Worker /* The problem will be reported elsewhere. */
1205*7304104dSAndroid Build Coastguard Worker break;
1206*7304104dSAndroid Build Coastguard Worker
1207*7304104dSAndroid Build Coastguard Worker if (ebl_relative_reloc_p (ebl,
1208*7304104dSAndroid Build Coastguard Worker GELF_R_TYPE (rela->r_info)))
1209*7304104dSAndroid Build Coastguard Worker {
1210*7304104dSAndroid Build Coastguard Worker if (inner >= dyn->d_un.d_val)
1211*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1212*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
1213*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1214*7304104dSAndroid Build Coastguard Worker (int) dyn->d_un.d_val);
1215*7304104dSAndroid Build Coastguard Worker }
1216*7304104dSAndroid Build Coastguard Worker else if (inner < dyn->d_un.d_val)
1217*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1218*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
1219*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1220*7304104dSAndroid Build Coastguard Worker inner, (int) dyn->d_un.d_val);
1221*7304104dSAndroid Build Coastguard Worker }
1222*7304104dSAndroid Build Coastguard Worker }
1223*7304104dSAndroid Build Coastguard Worker }
1224*7304104dSAndroid Build Coastguard Worker }
1225*7304104dSAndroid Build Coastguard Worker
1226*7304104dSAndroid Build Coastguard Worker break;
1227*7304104dSAndroid Build Coastguard Worker }
1228*7304104dSAndroid Build Coastguard Worker }
1229*7304104dSAndroid Build Coastguard Worker
1230*7304104dSAndroid Build Coastguard Worker return true;
1231*7304104dSAndroid Build Coastguard Worker }
1232*7304104dSAndroid Build Coastguard Worker
1233*7304104dSAndroid Build Coastguard Worker
1234*7304104dSAndroid Build Coastguard Worker struct loaded_segment
1235*7304104dSAndroid Build Coastguard Worker {
1236*7304104dSAndroid Build Coastguard Worker GElf_Addr from;
1237*7304104dSAndroid Build Coastguard Worker GElf_Addr to;
1238*7304104dSAndroid Build Coastguard Worker bool read_only;
1239*7304104dSAndroid Build Coastguard Worker struct loaded_segment *next;
1240*7304104dSAndroid Build Coastguard Worker };
1241*7304104dSAndroid Build Coastguard Worker
1242*7304104dSAndroid Build Coastguard Worker
1243*7304104dSAndroid Build Coastguard Worker /* Check whether binary has text relocation flag set. */
1244*7304104dSAndroid Build Coastguard Worker static bool textrel;
1245*7304104dSAndroid Build Coastguard Worker
1246*7304104dSAndroid Build Coastguard Worker /* Keep track of whether text relocation flag is needed. */
1247*7304104dSAndroid Build Coastguard Worker static bool needed_textrel;
1248*7304104dSAndroid Build Coastguard Worker
1249*7304104dSAndroid Build Coastguard Worker
1250*7304104dSAndroid Build Coastguard Worker static bool
check_reloc_shdr(Ebl * ebl,const GElf_Ehdr * ehdr,const GElf_Shdr * shdr,int idx,int reltype,GElf_Shdr ** destshdrp,GElf_Shdr * destshdr_memp,struct loaded_segment ** loadedp)1251*7304104dSAndroid Build Coastguard Worker check_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr,
1252*7304104dSAndroid Build Coastguard Worker int idx, int reltype, GElf_Shdr **destshdrp,
1253*7304104dSAndroid Build Coastguard Worker GElf_Shdr *destshdr_memp, struct loaded_segment **loadedp)
1254*7304104dSAndroid Build Coastguard Worker {
1255*7304104dSAndroid Build Coastguard Worker bool reldyn = false;
1256*7304104dSAndroid Build Coastguard Worker
1257*7304104dSAndroid Build Coastguard Worker /* Check whether the link to the section we relocate is reasonable. */
1258*7304104dSAndroid Build Coastguard Worker if (shdr->sh_info >= shnum)
1259*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': invalid destination section index\n"),
1260*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1261*7304104dSAndroid Build Coastguard Worker else if (shdr->sh_info != 0)
1262*7304104dSAndroid Build Coastguard Worker {
1263*7304104dSAndroid Build Coastguard Worker *destshdrp = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1264*7304104dSAndroid Build Coastguard Worker destshdr_memp);
1265*7304104dSAndroid Build Coastguard Worker if (*destshdrp != NULL)
1266*7304104dSAndroid Build Coastguard Worker {
1267*7304104dSAndroid Build Coastguard Worker if(! ebl_check_reloc_target_type (ebl, (*destshdrp)->sh_type))
1268*7304104dSAndroid Build Coastguard Worker {
1269*7304104dSAndroid Build Coastguard Worker reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true);
1270*7304104dSAndroid Build Coastguard Worker if (!reldyn)
1271*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1272*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': invalid destination section type\n"),
1273*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1274*7304104dSAndroid Build Coastguard Worker else
1275*7304104dSAndroid Build Coastguard Worker {
1276*7304104dSAndroid Build Coastguard Worker /* There is no standard, but we require that .rel{,a}.dyn
1277*7304104dSAndroid Build Coastguard Worker sections have a sh_info value of zero. */
1278*7304104dSAndroid Build Coastguard Worker if (shdr->sh_info != 0)
1279*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1280*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': sh_info should be zero\n"),
1281*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1282*7304104dSAndroid Build Coastguard Worker }
1283*7304104dSAndroid Build Coastguard Worker }
1284*7304104dSAndroid Build Coastguard Worker
1285*7304104dSAndroid Build Coastguard Worker if ((((*destshdrp)->sh_flags & SHF_MERGE) != 0)
1286*7304104dSAndroid Build Coastguard Worker && ((*destshdrp)->sh_flags & SHF_STRINGS) != 0)
1287*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1288*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': no relocations for merge-able string sections possible\n"),
1289*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1290*7304104dSAndroid Build Coastguard Worker }
1291*7304104dSAndroid Build Coastguard Worker }
1292*7304104dSAndroid Build Coastguard Worker
1293*7304104dSAndroid Build Coastguard Worker size_t sh_entsize = gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT);
1294*7304104dSAndroid Build Coastguard Worker if (shdr->sh_entsize != sh_entsize)
1295*7304104dSAndroid Build Coastguard Worker {
1296*7304104dSAndroid Build Coastguard Worker if (reltype == ELF_T_RELA)
1297*7304104dSAndroid Build Coastguard Worker ERROR ("\
1298*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section entry size does not match ElfXX_Rela\n",
1299*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1300*7304104dSAndroid Build Coastguard Worker else if (reltype == ELF_T_REL)
1301*7304104dSAndroid Build Coastguard Worker ERROR ("\
1302*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section entry size does not match ElfXX_Rel\n",
1303*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1304*7304104dSAndroid Build Coastguard Worker else
1305*7304104dSAndroid Build Coastguard Worker ERROR ("\
1306*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section entry size does not match ElfXX_Relr\n",
1307*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1308*7304104dSAndroid Build Coastguard Worker }
1309*7304104dSAndroid Build Coastguard Worker
1310*7304104dSAndroid Build Coastguard Worker /* In preparation of checking whether relocations are text
1311*7304104dSAndroid Build Coastguard Worker relocations or not we need to determine whether the file is
1312*7304104dSAndroid Build Coastguard Worker flagged to have text relocation and we need to determine a) what
1313*7304104dSAndroid Build Coastguard Worker the loaded segments are and b) which are read-only. This will
1314*7304104dSAndroid Build Coastguard Worker also allow us to determine whether the same reloc section is
1315*7304104dSAndroid Build Coastguard Worker modifying loaded and not loaded segments. */
1316*7304104dSAndroid Build Coastguard Worker for (unsigned int i = 0; i < phnum; ++i)
1317*7304104dSAndroid Build Coastguard Worker {
1318*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr_mem;
1319*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
1320*7304104dSAndroid Build Coastguard Worker if (phdr == NULL)
1321*7304104dSAndroid Build Coastguard Worker continue;
1322*7304104dSAndroid Build Coastguard Worker
1323*7304104dSAndroid Build Coastguard Worker if (phdr->p_type == PT_LOAD)
1324*7304104dSAndroid Build Coastguard Worker {
1325*7304104dSAndroid Build Coastguard Worker struct loaded_segment *newp = xmalloc (sizeof (*newp));
1326*7304104dSAndroid Build Coastguard Worker newp->from = phdr->p_vaddr;
1327*7304104dSAndroid Build Coastguard Worker newp->to = phdr->p_vaddr + phdr->p_memsz;
1328*7304104dSAndroid Build Coastguard Worker newp->read_only = (phdr->p_flags & PF_W) == 0;
1329*7304104dSAndroid Build Coastguard Worker newp->next = *loadedp;
1330*7304104dSAndroid Build Coastguard Worker *loadedp = newp;
1331*7304104dSAndroid Build Coastguard Worker }
1332*7304104dSAndroid Build Coastguard Worker else if (phdr->p_type == PT_DYNAMIC)
1333*7304104dSAndroid Build Coastguard Worker {
1334*7304104dSAndroid Build Coastguard Worker Elf_Scn *dynscn = gelf_offscn (ebl->elf, phdr->p_offset);
1335*7304104dSAndroid Build Coastguard Worker GElf_Shdr dynshdr_mem;
1336*7304104dSAndroid Build Coastguard Worker GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem);
1337*7304104dSAndroid Build Coastguard Worker Elf_Data *dyndata = elf_getdata (dynscn, NULL);
1338*7304104dSAndroid Build Coastguard Worker if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC
1339*7304104dSAndroid Build Coastguard Worker && dyndata != NULL && dynshdr->sh_entsize != 0)
1340*7304104dSAndroid Build Coastguard Worker for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j)
1341*7304104dSAndroid Build Coastguard Worker {
1342*7304104dSAndroid Build Coastguard Worker GElf_Dyn dyn_mem;
1343*7304104dSAndroid Build Coastguard Worker GElf_Dyn *dyn = gelf_getdyn (dyndata, j, &dyn_mem);
1344*7304104dSAndroid Build Coastguard Worker if (dyn != NULL
1345*7304104dSAndroid Build Coastguard Worker && (dyn->d_tag == DT_TEXTREL
1346*7304104dSAndroid Build Coastguard Worker || (dyn->d_tag == DT_FLAGS
1347*7304104dSAndroid Build Coastguard Worker && (dyn->d_un.d_val & DF_TEXTREL) != 0)))
1348*7304104dSAndroid Build Coastguard Worker {
1349*7304104dSAndroid Build Coastguard Worker textrel = true;
1350*7304104dSAndroid Build Coastguard Worker break;
1351*7304104dSAndroid Build Coastguard Worker }
1352*7304104dSAndroid Build Coastguard Worker }
1353*7304104dSAndroid Build Coastguard Worker }
1354*7304104dSAndroid Build Coastguard Worker }
1355*7304104dSAndroid Build Coastguard Worker
1356*7304104dSAndroid Build Coastguard Worker /* A quick test which can be easily done here (although it is a bit
1357*7304104dSAndroid Build Coastguard Worker out of place): the text relocation flag makes only sense if there
1358*7304104dSAndroid Build Coastguard Worker is a segment which is not writable. */
1359*7304104dSAndroid Build Coastguard Worker if (textrel)
1360*7304104dSAndroid Build Coastguard Worker {
1361*7304104dSAndroid Build Coastguard Worker struct loaded_segment *seg = *loadedp;
1362*7304104dSAndroid Build Coastguard Worker while (seg != NULL && !seg->read_only)
1363*7304104dSAndroid Build Coastguard Worker seg = seg->next;
1364*7304104dSAndroid Build Coastguard Worker if (seg == NULL)
1365*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1366*7304104dSAndroid Build Coastguard Worker text relocation flag set but there is no read-only segment\n"));
1367*7304104dSAndroid Build Coastguard Worker }
1368*7304104dSAndroid Build Coastguard Worker
1369*7304104dSAndroid Build Coastguard Worker return reldyn;
1370*7304104dSAndroid Build Coastguard Worker }
1371*7304104dSAndroid Build Coastguard Worker
1372*7304104dSAndroid Build Coastguard Worker
1373*7304104dSAndroid Build Coastguard Worker enum load_state
1374*7304104dSAndroid Build Coastguard Worker {
1375*7304104dSAndroid Build Coastguard Worker state_undecided,
1376*7304104dSAndroid Build Coastguard Worker state_loaded,
1377*7304104dSAndroid Build Coastguard Worker state_unloaded,
1378*7304104dSAndroid Build Coastguard Worker state_error
1379*7304104dSAndroid Build Coastguard Worker };
1380*7304104dSAndroid Build Coastguard Worker
1381*7304104dSAndroid Build Coastguard Worker
1382*7304104dSAndroid Build Coastguard Worker static void
check_one_reloc(Ebl * ebl,GElf_Ehdr * ehdr,GElf_Shdr * relshdr,int idx,size_t cnt,const GElf_Shdr * symshdr,Elf_Data * symdata,GElf_Addr r_offset,GElf_Xword r_info,const GElf_Shdr * destshdr,bool reldyn,struct loaded_segment * loaded,enum load_state * statep)1383*7304104dSAndroid Build Coastguard Worker check_one_reloc (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *relshdr, int idx,
1384*7304104dSAndroid Build Coastguard Worker size_t cnt, const GElf_Shdr *symshdr, Elf_Data *symdata,
1385*7304104dSAndroid Build Coastguard Worker GElf_Addr r_offset, GElf_Xword r_info,
1386*7304104dSAndroid Build Coastguard Worker const GElf_Shdr *destshdr, bool reldyn,
1387*7304104dSAndroid Build Coastguard Worker struct loaded_segment *loaded, enum load_state *statep)
1388*7304104dSAndroid Build Coastguard Worker {
1389*7304104dSAndroid Build Coastguard Worker bool known_broken = gnuld;
1390*7304104dSAndroid Build Coastguard Worker
1391*7304104dSAndroid Build Coastguard Worker if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (r_info)))
1392*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': relocation %zu: invalid type\n"),
1393*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
1394*7304104dSAndroid Build Coastguard Worker else if (((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1395*7304104dSAndroid Build Coastguard Worker /* The executable/DSO can contain relocation sections with
1396*7304104dSAndroid Build Coastguard Worker all the relocations the linker has applied. Those sections
1397*7304104dSAndroid Build Coastguard Worker are marked non-loaded, though. */
1398*7304104dSAndroid Build Coastguard Worker || (relshdr->sh_flags & SHF_ALLOC) != 0)
1399*7304104dSAndroid Build Coastguard Worker && !ebl_reloc_valid_use (ebl, GELF_R_TYPE (r_info)))
1400*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1401*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
1402*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
1403*7304104dSAndroid Build Coastguard Worker
1404*7304104dSAndroid Build Coastguard Worker if (symshdr != NULL
1405*7304104dSAndroid Build Coastguard Worker && ((GELF_R_SYM (r_info) + 1)
1406*7304104dSAndroid Build Coastguard Worker * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
1407*7304104dSAndroid Build Coastguard Worker > symshdr->sh_size))
1408*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1409*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': relocation %zu: invalid symbol index\n"),
1410*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
1411*7304104dSAndroid Build Coastguard Worker
1412*7304104dSAndroid Build Coastguard Worker /* No more tests if this is a no-op relocation. */
1413*7304104dSAndroid Build Coastguard Worker if (ebl_none_reloc_p (ebl, GELF_R_TYPE (r_info)))
1414*7304104dSAndroid Build Coastguard Worker return;
1415*7304104dSAndroid Build Coastguard Worker
1416*7304104dSAndroid Build Coastguard Worker if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (r_info)))
1417*7304104dSAndroid Build Coastguard Worker {
1418*7304104dSAndroid Build Coastguard Worker const char *name;
1419*7304104dSAndroid Build Coastguard Worker char buf[64];
1420*7304104dSAndroid Build Coastguard Worker GElf_Sym sym_mem;
1421*7304104dSAndroid Build Coastguard Worker GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
1422*7304104dSAndroid Build Coastguard Worker if (sym != NULL
1423*7304104dSAndroid Build Coastguard Worker /* Get the name for the symbol. */
1424*7304104dSAndroid Build Coastguard Worker && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1425*7304104dSAndroid Build Coastguard Worker && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
1426*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1427*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
1428*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt,
1429*7304104dSAndroid Build Coastguard Worker ebl_reloc_type_name (ebl, GELF_R_SYM (r_info),
1430*7304104dSAndroid Build Coastguard Worker buf, sizeof (buf)));
1431*7304104dSAndroid Build Coastguard Worker }
1432*7304104dSAndroid Build Coastguard Worker
1433*7304104dSAndroid Build Coastguard Worker if (reldyn)
1434*7304104dSAndroid Build Coastguard Worker {
1435*7304104dSAndroid Build Coastguard Worker // XXX TODO Check .rel.dyn section addresses.
1436*7304104dSAndroid Build Coastguard Worker }
1437*7304104dSAndroid Build Coastguard Worker else if (!known_broken)
1438*7304104dSAndroid Build Coastguard Worker {
1439*7304104dSAndroid Build Coastguard Worker if (destshdr != NULL
1440*7304104dSAndroid Build Coastguard Worker && GELF_R_TYPE (r_info) != 0
1441*7304104dSAndroid Build Coastguard Worker && (r_offset - (ehdr->e_type == ET_REL ? 0
1442*7304104dSAndroid Build Coastguard Worker : destshdr->sh_addr)) >= destshdr->sh_size)
1443*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1444*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': relocation %zu: offset out of bounds\n"),
1445*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
1446*7304104dSAndroid Build Coastguard Worker }
1447*7304104dSAndroid Build Coastguard Worker
1448*7304104dSAndroid Build Coastguard Worker GElf_Sym sym_mem;
1449*7304104dSAndroid Build Coastguard Worker GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
1450*7304104dSAndroid Build Coastguard Worker
1451*7304104dSAndroid Build Coastguard Worker if (ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info))
1452*7304104dSAndroid Build Coastguard Worker /* Make sure the referenced symbol is an object or unspecified. */
1453*7304104dSAndroid Build Coastguard Worker && sym != NULL
1454*7304104dSAndroid Build Coastguard Worker && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE
1455*7304104dSAndroid Build Coastguard Worker && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
1456*7304104dSAndroid Build Coastguard Worker {
1457*7304104dSAndroid Build Coastguard Worker char buf[64];
1458*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"),
1459*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt,
1460*7304104dSAndroid Build Coastguard Worker ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
1461*7304104dSAndroid Build Coastguard Worker buf, sizeof (buf)));
1462*7304104dSAndroid Build Coastguard Worker }
1463*7304104dSAndroid Build Coastguard Worker
1464*7304104dSAndroid Build Coastguard Worker if ((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1465*7304104dSAndroid Build Coastguard Worker || (relshdr->sh_flags & SHF_ALLOC) != 0)
1466*7304104dSAndroid Build Coastguard Worker {
1467*7304104dSAndroid Build Coastguard Worker bool in_loaded_seg = false;
1468*7304104dSAndroid Build Coastguard Worker while (loaded != NULL)
1469*7304104dSAndroid Build Coastguard Worker {
1470*7304104dSAndroid Build Coastguard Worker if (r_offset < loaded->to
1471*7304104dSAndroid Build Coastguard Worker && r_offset + (sym == NULL ? 0 : sym->st_size) >= loaded->from)
1472*7304104dSAndroid Build Coastguard Worker {
1473*7304104dSAndroid Build Coastguard Worker /* The symbol is in this segment. */
1474*7304104dSAndroid Build Coastguard Worker if (loaded->read_only)
1475*7304104dSAndroid Build Coastguard Worker {
1476*7304104dSAndroid Build Coastguard Worker if (textrel)
1477*7304104dSAndroid Build Coastguard Worker needed_textrel = true;
1478*7304104dSAndroid Build Coastguard Worker else
1479*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': relocation %zu: read-only section modified but text relocation flag not set\n"),
1480*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
1481*7304104dSAndroid Build Coastguard Worker }
1482*7304104dSAndroid Build Coastguard Worker
1483*7304104dSAndroid Build Coastguard Worker in_loaded_seg = true;
1484*7304104dSAndroid Build Coastguard Worker }
1485*7304104dSAndroid Build Coastguard Worker
1486*7304104dSAndroid Build Coastguard Worker loaded = loaded->next;
1487*7304104dSAndroid Build Coastguard Worker }
1488*7304104dSAndroid Build Coastguard Worker
1489*7304104dSAndroid Build Coastguard Worker if (*statep == state_undecided)
1490*7304104dSAndroid Build Coastguard Worker *statep = in_loaded_seg ? state_loaded : state_unloaded;
1491*7304104dSAndroid Build Coastguard Worker else if ((*statep == state_unloaded && in_loaded_seg)
1492*7304104dSAndroid Build Coastguard Worker || (*statep == state_loaded && !in_loaded_seg))
1493*7304104dSAndroid Build Coastguard Worker {
1494*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1495*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': relocations are against loaded and unloaded data\n"),
1496*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1497*7304104dSAndroid Build Coastguard Worker *statep = state_error;
1498*7304104dSAndroid Build Coastguard Worker }
1499*7304104dSAndroid Build Coastguard Worker }
1500*7304104dSAndroid Build Coastguard Worker }
1501*7304104dSAndroid Build Coastguard Worker
1502*7304104dSAndroid Build Coastguard Worker
1503*7304104dSAndroid Build Coastguard Worker static void
check_rela(Ebl * ebl,GElf_Ehdr * ehdr,GElf_Shdr * shdr,int idx)1504*7304104dSAndroid Build Coastguard Worker check_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1505*7304104dSAndroid Build Coastguard Worker {
1506*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1507*7304104dSAndroid Build Coastguard Worker if (data == NULL)
1508*7304104dSAndroid Build Coastguard Worker {
1509*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
1510*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1511*7304104dSAndroid Build Coastguard Worker return;
1512*7304104dSAndroid Build Coastguard Worker }
1513*7304104dSAndroid Build Coastguard Worker
1514*7304104dSAndroid Build Coastguard Worker /* Check the fields of the section header. */
1515*7304104dSAndroid Build Coastguard Worker GElf_Shdr destshdr_mem;
1516*7304104dSAndroid Build Coastguard Worker GElf_Shdr *destshdr = NULL;
1517*7304104dSAndroid Build Coastguard Worker struct loaded_segment *loaded = NULL;
1518*7304104dSAndroid Build Coastguard Worker bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELA, &destshdr,
1519*7304104dSAndroid Build Coastguard Worker &destshdr_mem, &loaded);
1520*7304104dSAndroid Build Coastguard Worker
1521*7304104dSAndroid Build Coastguard Worker Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1522*7304104dSAndroid Build Coastguard Worker GElf_Shdr symshdr_mem;
1523*7304104dSAndroid Build Coastguard Worker GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1524*7304104dSAndroid Build Coastguard Worker Elf_Data *symdata = elf_getdata (symscn, NULL);
1525*7304104dSAndroid Build Coastguard Worker enum load_state state = state_undecided;
1526*7304104dSAndroid Build Coastguard Worker
1527*7304104dSAndroid Build Coastguard Worker size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
1528*7304104dSAndroid Build Coastguard Worker for (size_t cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1529*7304104dSAndroid Build Coastguard Worker {
1530*7304104dSAndroid Build Coastguard Worker GElf_Rela rela_mem;
1531*7304104dSAndroid Build Coastguard Worker GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem);
1532*7304104dSAndroid Build Coastguard Worker if (rela == NULL)
1533*7304104dSAndroid Build Coastguard Worker {
1534*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1535*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': cannot get relocation %zu: %s\n"),
1536*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1537*7304104dSAndroid Build Coastguard Worker continue;
1538*7304104dSAndroid Build Coastguard Worker }
1539*7304104dSAndroid Build Coastguard Worker
1540*7304104dSAndroid Build Coastguard Worker check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1541*7304104dSAndroid Build Coastguard Worker rela->r_offset, rela->r_info, destshdr, reldyn, loaded,
1542*7304104dSAndroid Build Coastguard Worker &state);
1543*7304104dSAndroid Build Coastguard Worker }
1544*7304104dSAndroid Build Coastguard Worker
1545*7304104dSAndroid Build Coastguard Worker while (loaded != NULL)
1546*7304104dSAndroid Build Coastguard Worker {
1547*7304104dSAndroid Build Coastguard Worker struct loaded_segment *old = loaded;
1548*7304104dSAndroid Build Coastguard Worker loaded = loaded->next;
1549*7304104dSAndroid Build Coastguard Worker free (old);
1550*7304104dSAndroid Build Coastguard Worker }
1551*7304104dSAndroid Build Coastguard Worker }
1552*7304104dSAndroid Build Coastguard Worker
1553*7304104dSAndroid Build Coastguard Worker
1554*7304104dSAndroid Build Coastguard Worker static void
check_rel(Ebl * ebl,GElf_Ehdr * ehdr,GElf_Shdr * shdr,int idx)1555*7304104dSAndroid Build Coastguard Worker check_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1556*7304104dSAndroid Build Coastguard Worker {
1557*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1558*7304104dSAndroid Build Coastguard Worker if (data == NULL)
1559*7304104dSAndroid Build Coastguard Worker {
1560*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
1561*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1562*7304104dSAndroid Build Coastguard Worker return;
1563*7304104dSAndroid Build Coastguard Worker }
1564*7304104dSAndroid Build Coastguard Worker
1565*7304104dSAndroid Build Coastguard Worker /* Check the fields of the section header. */
1566*7304104dSAndroid Build Coastguard Worker GElf_Shdr destshdr_mem;
1567*7304104dSAndroid Build Coastguard Worker GElf_Shdr *destshdr = NULL;
1568*7304104dSAndroid Build Coastguard Worker struct loaded_segment *loaded = NULL;
1569*7304104dSAndroid Build Coastguard Worker bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_REL, &destshdr,
1570*7304104dSAndroid Build Coastguard Worker &destshdr_mem, &loaded);
1571*7304104dSAndroid Build Coastguard Worker
1572*7304104dSAndroid Build Coastguard Worker Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1573*7304104dSAndroid Build Coastguard Worker GElf_Shdr symshdr_mem;
1574*7304104dSAndroid Build Coastguard Worker GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1575*7304104dSAndroid Build Coastguard Worker Elf_Data *symdata = elf_getdata (symscn, NULL);
1576*7304104dSAndroid Build Coastguard Worker enum load_state state = state_undecided;
1577*7304104dSAndroid Build Coastguard Worker
1578*7304104dSAndroid Build Coastguard Worker size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
1579*7304104dSAndroid Build Coastguard Worker for (size_t cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1580*7304104dSAndroid Build Coastguard Worker {
1581*7304104dSAndroid Build Coastguard Worker GElf_Rel rel_mem;
1582*7304104dSAndroid Build Coastguard Worker GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem);
1583*7304104dSAndroid Build Coastguard Worker if (rel == NULL)
1584*7304104dSAndroid Build Coastguard Worker {
1585*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1586*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': cannot get relocation %zu: %s\n"),
1587*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1588*7304104dSAndroid Build Coastguard Worker continue;
1589*7304104dSAndroid Build Coastguard Worker }
1590*7304104dSAndroid Build Coastguard Worker
1591*7304104dSAndroid Build Coastguard Worker check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1592*7304104dSAndroid Build Coastguard Worker rel->r_offset, rel->r_info, destshdr, reldyn, loaded,
1593*7304104dSAndroid Build Coastguard Worker &state);
1594*7304104dSAndroid Build Coastguard Worker }
1595*7304104dSAndroid Build Coastguard Worker
1596*7304104dSAndroid Build Coastguard Worker while (loaded != NULL)
1597*7304104dSAndroid Build Coastguard Worker {
1598*7304104dSAndroid Build Coastguard Worker struct loaded_segment *old = loaded;
1599*7304104dSAndroid Build Coastguard Worker loaded = loaded->next;
1600*7304104dSAndroid Build Coastguard Worker free (old);
1601*7304104dSAndroid Build Coastguard Worker }
1602*7304104dSAndroid Build Coastguard Worker }
1603*7304104dSAndroid Build Coastguard Worker
1604*7304104dSAndroid Build Coastguard Worker static void
check_relr(Ebl * ebl,GElf_Ehdr * ehdr,GElf_Shdr * shdr,int idx)1605*7304104dSAndroid Build Coastguard Worker check_relr (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1606*7304104dSAndroid Build Coastguard Worker {
1607*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1608*7304104dSAndroid Build Coastguard Worker if (data == NULL)
1609*7304104dSAndroid Build Coastguard Worker {
1610*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
1611*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1612*7304104dSAndroid Build Coastguard Worker return;
1613*7304104dSAndroid Build Coastguard Worker }
1614*7304104dSAndroid Build Coastguard Worker
1615*7304104dSAndroid Build Coastguard Worker /* Check the fields of the section header. */
1616*7304104dSAndroid Build Coastguard Worker GElf_Shdr destshdr_mem;
1617*7304104dSAndroid Build Coastguard Worker GElf_Shdr *destshdr = NULL;
1618*7304104dSAndroid Build Coastguard Worker struct loaded_segment *loaded = NULL;
1619*7304104dSAndroid Build Coastguard Worker check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELR, &destshdr,
1620*7304104dSAndroid Build Coastguard Worker &destshdr_mem, &loaded);
1621*7304104dSAndroid Build Coastguard Worker
1622*7304104dSAndroid Build Coastguard Worker /* Just throw them away. */
1623*7304104dSAndroid Build Coastguard Worker while (loaded != NULL)
1624*7304104dSAndroid Build Coastguard Worker {
1625*7304104dSAndroid Build Coastguard Worker struct loaded_segment *old = loaded;
1626*7304104dSAndroid Build Coastguard Worker loaded = loaded->next;
1627*7304104dSAndroid Build Coastguard Worker free (old);
1628*7304104dSAndroid Build Coastguard Worker }
1629*7304104dSAndroid Build Coastguard Worker }
1630*7304104dSAndroid Build Coastguard Worker
1631*7304104dSAndroid Build Coastguard Worker /* Number of dynamic sections. */
1632*7304104dSAndroid Build Coastguard Worker static int ndynamic;
1633*7304104dSAndroid Build Coastguard Worker
1634*7304104dSAndroid Build Coastguard Worker
1635*7304104dSAndroid Build Coastguard Worker static void
check_dynamic(Ebl * ebl,GElf_Ehdr * ehdr,GElf_Shdr * shdr,int idx)1636*7304104dSAndroid Build Coastguard Worker check_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1637*7304104dSAndroid Build Coastguard Worker {
1638*7304104dSAndroid Build Coastguard Worker Elf_Data *data;
1639*7304104dSAndroid Build Coastguard Worker GElf_Shdr strshdr_mem;
1640*7304104dSAndroid Build Coastguard Worker GElf_Shdr *strshdr;
1641*7304104dSAndroid Build Coastguard Worker size_t cnt;
1642*7304104dSAndroid Build Coastguard Worker static const bool dependencies[DT_NUM][DT_NUM] =
1643*7304104dSAndroid Build Coastguard Worker {
1644*7304104dSAndroid Build Coastguard Worker [DT_NEEDED] = { [DT_STRTAB] = true },
1645*7304104dSAndroid Build Coastguard Worker [DT_PLTRELSZ] = { [DT_JMPREL] = true },
1646*7304104dSAndroid Build Coastguard Worker [DT_HASH] = { [DT_SYMTAB] = true },
1647*7304104dSAndroid Build Coastguard Worker [DT_STRTAB] = { [DT_STRSZ] = true },
1648*7304104dSAndroid Build Coastguard Worker [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_SYMENT] = true },
1649*7304104dSAndroid Build Coastguard Worker [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true },
1650*7304104dSAndroid Build Coastguard Worker [DT_RELASZ] = { [DT_RELA] = true },
1651*7304104dSAndroid Build Coastguard Worker [DT_RELAENT] = { [DT_RELA] = true },
1652*7304104dSAndroid Build Coastguard Worker [DT_STRSZ] = { [DT_STRTAB] = true },
1653*7304104dSAndroid Build Coastguard Worker [DT_SYMENT] = { [DT_SYMTAB] = true },
1654*7304104dSAndroid Build Coastguard Worker [DT_SONAME] = { [DT_STRTAB] = true },
1655*7304104dSAndroid Build Coastguard Worker [DT_RPATH] = { [DT_STRTAB] = true },
1656*7304104dSAndroid Build Coastguard Worker [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true },
1657*7304104dSAndroid Build Coastguard Worker [DT_RELSZ] = { [DT_REL] = true },
1658*7304104dSAndroid Build Coastguard Worker [DT_RELENT] = { [DT_REL] = true },
1659*7304104dSAndroid Build Coastguard Worker [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true },
1660*7304104dSAndroid Build Coastguard Worker [DT_RUNPATH] = { [DT_STRTAB] = true },
1661*7304104dSAndroid Build Coastguard Worker [DT_PLTREL] = { [DT_JMPREL] = true },
1662*7304104dSAndroid Build Coastguard Worker };
1663*7304104dSAndroid Build Coastguard Worker bool has_dt[DT_NUM];
1664*7304104dSAndroid Build Coastguard Worker bool has_val_dt[DT_VALNUM];
1665*7304104dSAndroid Build Coastguard Worker bool has_addr_dt[DT_ADDRNUM];
1666*7304104dSAndroid Build Coastguard Worker static const bool level2[DT_NUM] =
1667*7304104dSAndroid Build Coastguard Worker {
1668*7304104dSAndroid Build Coastguard Worker [DT_RPATH] = true,
1669*7304104dSAndroid Build Coastguard Worker [DT_SYMBOLIC] = true,
1670*7304104dSAndroid Build Coastguard Worker [DT_TEXTREL] = true,
1671*7304104dSAndroid Build Coastguard Worker [DT_BIND_NOW] = true
1672*7304104dSAndroid Build Coastguard Worker };
1673*7304104dSAndroid Build Coastguard Worker static const bool mandatory[DT_NUM] =
1674*7304104dSAndroid Build Coastguard Worker {
1675*7304104dSAndroid Build Coastguard Worker [DT_NULL] = true,
1676*7304104dSAndroid Build Coastguard Worker [DT_STRTAB] = true,
1677*7304104dSAndroid Build Coastguard Worker [DT_SYMTAB] = true,
1678*7304104dSAndroid Build Coastguard Worker [DT_STRSZ] = true,
1679*7304104dSAndroid Build Coastguard Worker [DT_SYMENT] = true
1680*7304104dSAndroid Build Coastguard Worker };
1681*7304104dSAndroid Build Coastguard Worker
1682*7304104dSAndroid Build Coastguard Worker memset (has_dt, '\0', sizeof (has_dt));
1683*7304104dSAndroid Build Coastguard Worker memset (has_val_dt, '\0', sizeof (has_val_dt));
1684*7304104dSAndroid Build Coastguard Worker memset (has_addr_dt, '\0', sizeof (has_addr_dt));
1685*7304104dSAndroid Build Coastguard Worker
1686*7304104dSAndroid Build Coastguard Worker if (++ndynamic == 2)
1687*7304104dSAndroid Build Coastguard Worker ERROR (_("more than one dynamic section present\n"));
1688*7304104dSAndroid Build Coastguard Worker
1689*7304104dSAndroid Build Coastguard Worker data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1690*7304104dSAndroid Build Coastguard Worker if (data == NULL)
1691*7304104dSAndroid Build Coastguard Worker {
1692*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
1693*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1694*7304104dSAndroid Build Coastguard Worker return;
1695*7304104dSAndroid Build Coastguard Worker }
1696*7304104dSAndroid Build Coastguard Worker
1697*7304104dSAndroid Build Coastguard Worker strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem);
1698*7304104dSAndroid Build Coastguard Worker if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB)
1699*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1700*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
1701*7304104dSAndroid Build Coastguard Worker shdr->sh_link, section_name (ebl, shdr->sh_link),
1702*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1703*7304104dSAndroid Build Coastguard Worker else if (strshdr == NULL)
1704*7304104dSAndroid Build Coastguard Worker {
1705*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1706*7304104dSAndroid Build Coastguard Worker section [%2d]: referenced as string table for section [%2d] '%s' but section link value is invalid\n"),
1707*7304104dSAndroid Build Coastguard Worker shdr->sh_link, idx, section_name (ebl, idx));
1708*7304104dSAndroid Build Coastguard Worker return;
1709*7304104dSAndroid Build Coastguard Worker }
1710*7304104dSAndroid Build Coastguard Worker
1711*7304104dSAndroid Build Coastguard Worker size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
1712*7304104dSAndroid Build Coastguard Worker if (shdr->sh_entsize != sh_entsize)
1713*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1714*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section entry size does not match ElfXX_Dyn\n"),
1715*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1716*7304104dSAndroid Build Coastguard Worker
1717*7304104dSAndroid Build Coastguard Worker if (shdr->sh_info != 0)
1718*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': sh_info not zero\n"),
1719*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1720*7304104dSAndroid Build Coastguard Worker
1721*7304104dSAndroid Build Coastguard Worker bool non_null_warned = false;
1722*7304104dSAndroid Build Coastguard Worker for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1723*7304104dSAndroid Build Coastguard Worker {
1724*7304104dSAndroid Build Coastguard Worker GElf_Dyn dyn_mem;
1725*7304104dSAndroid Build Coastguard Worker GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dyn_mem);
1726*7304104dSAndroid Build Coastguard Worker if (dyn == NULL)
1727*7304104dSAndroid Build Coastguard Worker {
1728*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1729*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': cannot get dynamic section entry %zu: %s\n"),
1730*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1731*7304104dSAndroid Build Coastguard Worker continue;
1732*7304104dSAndroid Build Coastguard Worker }
1733*7304104dSAndroid Build Coastguard Worker
1734*7304104dSAndroid Build Coastguard Worker if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned)
1735*7304104dSAndroid Build Coastguard Worker {
1736*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1737*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"),
1738*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1739*7304104dSAndroid Build Coastguard Worker non_null_warned = true;
1740*7304104dSAndroid Build Coastguard Worker }
1741*7304104dSAndroid Build Coastguard Worker
1742*7304104dSAndroid Build Coastguard Worker if (!ebl_dynamic_tag_check (ebl, dyn->d_tag))
1743*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': entry %zu: unknown tag\n"),
1744*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
1745*7304104dSAndroid Build Coastguard Worker
1746*7304104dSAndroid Build Coastguard Worker if (dyn->d_tag >= 0 && dyn->d_tag < DT_NUM)
1747*7304104dSAndroid Build Coastguard Worker {
1748*7304104dSAndroid Build Coastguard Worker if (has_dt[dyn->d_tag]
1749*7304104dSAndroid Build Coastguard Worker && dyn->d_tag != DT_NEEDED
1750*7304104dSAndroid Build Coastguard Worker && dyn->d_tag != DT_NULL
1751*7304104dSAndroid Build Coastguard Worker && dyn->d_tag != DT_POSFLAG_1)
1752*7304104dSAndroid Build Coastguard Worker {
1753*7304104dSAndroid Build Coastguard Worker char buf[50];
1754*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1755*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %zu: more than one entry with tag %s\n"),
1756*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt,
1757*7304104dSAndroid Build Coastguard Worker ebl_dynamic_tag_name (ebl, dyn->d_tag,
1758*7304104dSAndroid Build Coastguard Worker buf, sizeof (buf)));
1759*7304104dSAndroid Build Coastguard Worker }
1760*7304104dSAndroid Build Coastguard Worker
1761*7304104dSAndroid Build Coastguard Worker if (be_strict && level2[dyn->d_tag])
1762*7304104dSAndroid Build Coastguard Worker {
1763*7304104dSAndroid Build Coastguard Worker char buf[50];
1764*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1765*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %zu: level 2 tag %s used\n"),
1766*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt,
1767*7304104dSAndroid Build Coastguard Worker ebl_dynamic_tag_name (ebl, dyn->d_tag,
1768*7304104dSAndroid Build Coastguard Worker buf, sizeof (buf)));
1769*7304104dSAndroid Build Coastguard Worker }
1770*7304104dSAndroid Build Coastguard Worker
1771*7304104dSAndroid Build Coastguard Worker has_dt[dyn->d_tag] = true;
1772*7304104dSAndroid Build Coastguard Worker }
1773*7304104dSAndroid Build Coastguard Worker else if (dyn->d_tag >= 0 && dyn->d_tag <= DT_VALRNGHI
1774*7304104dSAndroid Build Coastguard Worker && DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
1775*7304104dSAndroid Build Coastguard Worker has_val_dt[DT_VALTAGIDX (dyn->d_tag)] = true;
1776*7304104dSAndroid Build Coastguard Worker else if (dyn->d_tag >= 0 && dyn->d_tag <= DT_ADDRRNGHI
1777*7304104dSAndroid Build Coastguard Worker && DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
1778*7304104dSAndroid Build Coastguard Worker has_addr_dt[DT_ADDRTAGIDX (dyn->d_tag)] = true;
1779*7304104dSAndroid Build Coastguard Worker
1780*7304104dSAndroid Build Coastguard Worker if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL
1781*7304104dSAndroid Build Coastguard Worker && dyn->d_un.d_val != DT_RELA)
1782*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1783*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"),
1784*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
1785*7304104dSAndroid Build Coastguard Worker
1786*7304104dSAndroid Build Coastguard Worker /* Check that addresses for entries are in loaded segments. */
1787*7304104dSAndroid Build Coastguard Worker switch (dyn->d_tag)
1788*7304104dSAndroid Build Coastguard Worker {
1789*7304104dSAndroid Build Coastguard Worker size_t n;
1790*7304104dSAndroid Build Coastguard Worker case DT_STRTAB:
1791*7304104dSAndroid Build Coastguard Worker /* We require the referenced section is the same as the one
1792*7304104dSAndroid Build Coastguard Worker specified in sh_link. */
1793*7304104dSAndroid Build Coastguard Worker if (strshdr->sh_addr != dyn->d_un.d_val)
1794*7304104dSAndroid Build Coastguard Worker {
1795*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1796*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %zu: pointer does not match address of section [%2d] '%s' referenced by sh_link\n"),
1797*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt,
1798*7304104dSAndroid Build Coastguard Worker shdr->sh_link, section_name (ebl, shdr->sh_link));
1799*7304104dSAndroid Build Coastguard Worker break;
1800*7304104dSAndroid Build Coastguard Worker }
1801*7304104dSAndroid Build Coastguard Worker goto check_addr;
1802*7304104dSAndroid Build Coastguard Worker
1803*7304104dSAndroid Build Coastguard Worker default:
1804*7304104dSAndroid Build Coastguard Worker if (dyn->d_tag < DT_ADDRRNGLO || dyn->d_tag > DT_ADDRRNGHI)
1805*7304104dSAndroid Build Coastguard Worker /* Value is no pointer. */
1806*7304104dSAndroid Build Coastguard Worker break;
1807*7304104dSAndroid Build Coastguard Worker FALLTHROUGH;
1808*7304104dSAndroid Build Coastguard Worker
1809*7304104dSAndroid Build Coastguard Worker case DT_AUXILIARY:
1810*7304104dSAndroid Build Coastguard Worker case DT_FILTER:
1811*7304104dSAndroid Build Coastguard Worker case DT_FINI:
1812*7304104dSAndroid Build Coastguard Worker case DT_FINI_ARRAY:
1813*7304104dSAndroid Build Coastguard Worker case DT_HASH:
1814*7304104dSAndroid Build Coastguard Worker case DT_INIT:
1815*7304104dSAndroid Build Coastguard Worker case DT_INIT_ARRAY:
1816*7304104dSAndroid Build Coastguard Worker case DT_JMPREL:
1817*7304104dSAndroid Build Coastguard Worker case DT_PLTGOT:
1818*7304104dSAndroid Build Coastguard Worker case DT_REL:
1819*7304104dSAndroid Build Coastguard Worker case DT_RELA:
1820*7304104dSAndroid Build Coastguard Worker case DT_RELR:
1821*7304104dSAndroid Build Coastguard Worker case DT_SYMBOLIC:
1822*7304104dSAndroid Build Coastguard Worker case DT_SYMTAB:
1823*7304104dSAndroid Build Coastguard Worker case DT_VERDEF:
1824*7304104dSAndroid Build Coastguard Worker case DT_VERNEED:
1825*7304104dSAndroid Build Coastguard Worker case DT_VERSYM:
1826*7304104dSAndroid Build Coastguard Worker check_addr:
1827*7304104dSAndroid Build Coastguard Worker for (n = 0; n < phnum; ++n)
1828*7304104dSAndroid Build Coastguard Worker {
1829*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr_mem;
1830*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr = gelf_getphdr (ebl->elf, n, &phdr_mem);
1831*7304104dSAndroid Build Coastguard Worker if (phdr != NULL && phdr->p_type == PT_LOAD
1832*7304104dSAndroid Build Coastguard Worker && phdr->p_vaddr <= dyn->d_un.d_ptr
1833*7304104dSAndroid Build Coastguard Worker && phdr->p_vaddr + phdr->p_memsz > dyn->d_un.d_ptr)
1834*7304104dSAndroid Build Coastguard Worker break;
1835*7304104dSAndroid Build Coastguard Worker }
1836*7304104dSAndroid Build Coastguard Worker if (unlikely (n >= phnum))
1837*7304104dSAndroid Build Coastguard Worker {
1838*7304104dSAndroid Build Coastguard Worker char buf[50];
1839*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1840*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %zu: %s value must point into loaded segment\n"),
1841*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt,
1842*7304104dSAndroid Build Coastguard Worker ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1843*7304104dSAndroid Build Coastguard Worker sizeof (buf)));
1844*7304104dSAndroid Build Coastguard Worker }
1845*7304104dSAndroid Build Coastguard Worker break;
1846*7304104dSAndroid Build Coastguard Worker
1847*7304104dSAndroid Build Coastguard Worker case DT_NEEDED:
1848*7304104dSAndroid Build Coastguard Worker case DT_RPATH:
1849*7304104dSAndroid Build Coastguard Worker case DT_RUNPATH:
1850*7304104dSAndroid Build Coastguard Worker case DT_SONAME:
1851*7304104dSAndroid Build Coastguard Worker if (dyn->d_un.d_ptr >= strshdr->sh_size)
1852*7304104dSAndroid Build Coastguard Worker {
1853*7304104dSAndroid Build Coastguard Worker char buf[50];
1854*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1855*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %zu: %s value must be valid offset in section [%2d] '%s'\n"),
1856*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt,
1857*7304104dSAndroid Build Coastguard Worker ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1858*7304104dSAndroid Build Coastguard Worker sizeof (buf)),
1859*7304104dSAndroid Build Coastguard Worker shdr->sh_link, section_name (ebl, shdr->sh_link));
1860*7304104dSAndroid Build Coastguard Worker }
1861*7304104dSAndroid Build Coastguard Worker break;
1862*7304104dSAndroid Build Coastguard Worker }
1863*7304104dSAndroid Build Coastguard Worker }
1864*7304104dSAndroid Build Coastguard Worker
1865*7304104dSAndroid Build Coastguard Worker for (cnt = 1; cnt < DT_NUM; ++cnt)
1866*7304104dSAndroid Build Coastguard Worker if (has_dt[cnt])
1867*7304104dSAndroid Build Coastguard Worker {
1868*7304104dSAndroid Build Coastguard Worker for (int inner = 0; inner < DT_NUM; ++inner)
1869*7304104dSAndroid Build Coastguard Worker if (dependencies[cnt][inner] && ! has_dt[inner])
1870*7304104dSAndroid Build Coastguard Worker {
1871*7304104dSAndroid Build Coastguard Worker char buf1[50];
1872*7304104dSAndroid Build Coastguard Worker char buf2[50];
1873*7304104dSAndroid Build Coastguard Worker
1874*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1875*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': contains %s entry but not %s\n"),
1876*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1877*7304104dSAndroid Build Coastguard Worker ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)),
1878*7304104dSAndroid Build Coastguard Worker ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2)));
1879*7304104dSAndroid Build Coastguard Worker }
1880*7304104dSAndroid Build Coastguard Worker }
1881*7304104dSAndroid Build Coastguard Worker else
1882*7304104dSAndroid Build Coastguard Worker {
1883*7304104dSAndroid Build Coastguard Worker if (mandatory[cnt])
1884*7304104dSAndroid Build Coastguard Worker {
1885*7304104dSAndroid Build Coastguard Worker char buf[50];
1886*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1887*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': mandatory tag %s not present\n"),
1888*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1889*7304104dSAndroid Build Coastguard Worker ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf)));
1890*7304104dSAndroid Build Coastguard Worker }
1891*7304104dSAndroid Build Coastguard Worker }
1892*7304104dSAndroid Build Coastguard Worker
1893*7304104dSAndroid Build Coastguard Worker /* Make sure we have an hash table. */
1894*7304104dSAndroid Build Coastguard Worker if (!has_dt[DT_HASH] && !has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)])
1895*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1896*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': no hash section present\n"),
1897*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1898*7304104dSAndroid Build Coastguard Worker
1899*7304104dSAndroid Build Coastguard Worker /* The GNU-style hash table also needs a symbol table. */
1900*7304104dSAndroid Build Coastguard Worker if (!has_dt[DT_HASH] && has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)]
1901*7304104dSAndroid Build Coastguard Worker && !has_dt[DT_SYMTAB])
1902*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1903*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': contains %s entry but not %s\n"),
1904*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1905*7304104dSAndroid Build Coastguard Worker "DT_GNU_HASH", "DT_SYMTAB");
1906*7304104dSAndroid Build Coastguard Worker
1907*7304104dSAndroid Build Coastguard Worker /* Check the rel/rela tags. At least one group must be available. */
1908*7304104dSAndroid Build Coastguard Worker if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT])
1909*7304104dSAndroid Build Coastguard Worker && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT]))
1910*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1911*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': not all of %s, %s, and %s are present\n"),
1912*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1913*7304104dSAndroid Build Coastguard Worker "DT_RELA", "DT_RELASZ", "DT_RELAENT");
1914*7304104dSAndroid Build Coastguard Worker
1915*7304104dSAndroid Build Coastguard Worker if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT])
1916*7304104dSAndroid Build Coastguard Worker && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT]))
1917*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1918*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': not all of %s, %s, and %s are present\n"),
1919*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
1920*7304104dSAndroid Build Coastguard Worker "DT_REL", "DT_RELSZ", "DT_RELENT");
1921*7304104dSAndroid Build Coastguard Worker
1922*7304104dSAndroid Build Coastguard Worker /* Check that all prelink sections are present if any of them is. */
1923*7304104dSAndroid Build Coastguard Worker if (has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)]
1924*7304104dSAndroid Build Coastguard Worker || has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1925*7304104dSAndroid Build Coastguard Worker {
1926*7304104dSAndroid Build Coastguard Worker if (!has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)])
1927*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1928*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1929*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "DT_GNU_PRELINKED");
1930*7304104dSAndroid Build Coastguard Worker if (!has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1931*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1932*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1933*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "DT_CHECKSUM");
1934*7304104dSAndroid Build Coastguard Worker
1935*7304104dSAndroid Build Coastguard Worker /* Only DSOs can be marked like this. */
1936*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_DYN)
1937*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1938*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': non-DSO file marked as dependency during prelink\n"),
1939*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1940*7304104dSAndroid Build Coastguard Worker }
1941*7304104dSAndroid Build Coastguard Worker
1942*7304104dSAndroid Build Coastguard Worker if (has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)]
1943*7304104dSAndroid Build Coastguard Worker || has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)]
1944*7304104dSAndroid Build Coastguard Worker || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)]
1945*7304104dSAndroid Build Coastguard Worker || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1946*7304104dSAndroid Build Coastguard Worker {
1947*7304104dSAndroid Build Coastguard Worker if (!has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)])
1948*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1949*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': %s tag missing in prelinked executable\n"),
1950*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "DT_GNU_CONFLICTSZ");
1951*7304104dSAndroid Build Coastguard Worker if (!has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)])
1952*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1953*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': %s tag missing in prelinked executable\n"),
1954*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "DT_GNU_LIBLISTSZ");
1955*7304104dSAndroid Build Coastguard Worker if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)])
1956*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1957*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': %s tag missing in prelinked executable\n"),
1958*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "DT_GNU_CONFLICT");
1959*7304104dSAndroid Build Coastguard Worker if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1960*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1961*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': %s tag missing in prelinked executable\n"),
1962*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), "DT_GNU_LIBLIST");
1963*7304104dSAndroid Build Coastguard Worker }
1964*7304104dSAndroid Build Coastguard Worker }
1965*7304104dSAndroid Build Coastguard Worker
1966*7304104dSAndroid Build Coastguard Worker
1967*7304104dSAndroid Build Coastguard Worker static void
check_symtab_shndx(Ebl * ebl,GElf_Ehdr * ehdr,GElf_Shdr * shdr,int idx)1968*7304104dSAndroid Build Coastguard Worker check_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1969*7304104dSAndroid Build Coastguard Worker {
1970*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_REL)
1971*7304104dSAndroid Build Coastguard Worker {
1972*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1973*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': only relocatable files can have extended section index\n"),
1974*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1975*7304104dSAndroid Build Coastguard Worker return;
1976*7304104dSAndroid Build Coastguard Worker }
1977*7304104dSAndroid Build Coastguard Worker
1978*7304104dSAndroid Build Coastguard Worker Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1979*7304104dSAndroid Build Coastguard Worker GElf_Shdr symshdr_mem;
1980*7304104dSAndroid Build Coastguard Worker GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1981*7304104dSAndroid Build Coastguard Worker if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB)
1982*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1983*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': extended section index section not for symbol table\n"),
1984*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1985*7304104dSAndroid Build Coastguard Worker else if (symshdr == NULL)
1986*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1987*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': sh_link extended section index [%2d] is invalid\n"),
1988*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), shdr->sh_link);
1989*7304104dSAndroid Build Coastguard Worker Elf_Data *symdata = elf_getdata (symscn, NULL);
1990*7304104dSAndroid Build Coastguard Worker if (symdata == NULL)
1991*7304104dSAndroid Build Coastguard Worker ERROR (_("cannot get data for symbol section\n"));
1992*7304104dSAndroid Build Coastguard Worker
1993*7304104dSAndroid Build Coastguard Worker if (shdr->sh_entsize != sizeof (Elf32_Word))
1994*7304104dSAndroid Build Coastguard Worker ERROR (_("\
1995*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry size does not match Elf32_Word\n"),
1996*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
1997*7304104dSAndroid Build Coastguard Worker
1998*7304104dSAndroid Build Coastguard Worker if (symshdr != NULL
1999*7304104dSAndroid Build Coastguard Worker && shdr->sh_entsize != 0
2000*7304104dSAndroid Build Coastguard Worker && symshdr->sh_entsize != 0
2001*7304104dSAndroid Build Coastguard Worker && (shdr->sh_size / shdr->sh_entsize
2002*7304104dSAndroid Build Coastguard Worker < symshdr->sh_size / symshdr->sh_entsize))
2003*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2004*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': extended index table too small for symbol table\n"),
2005*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2006*7304104dSAndroid Build Coastguard Worker
2007*7304104dSAndroid Build Coastguard Worker if (shdr->sh_info != 0)
2008*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': sh_info not zero\n"),
2009*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2010*7304104dSAndroid Build Coastguard Worker
2011*7304104dSAndroid Build Coastguard Worker for (size_t cnt = idx + 1; cnt < shnum; ++cnt)
2012*7304104dSAndroid Build Coastguard Worker {
2013*7304104dSAndroid Build Coastguard Worker GElf_Shdr rshdr_mem;
2014*7304104dSAndroid Build Coastguard Worker GElf_Shdr *rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem);
2015*7304104dSAndroid Build Coastguard Worker if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX
2016*7304104dSAndroid Build Coastguard Worker && rshdr->sh_link == shdr->sh_link)
2017*7304104dSAndroid Build Coastguard Worker {
2018*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2019*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"),
2020*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
2021*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
2022*7304104dSAndroid Build Coastguard Worker break;
2023*7304104dSAndroid Build Coastguard Worker }
2024*7304104dSAndroid Build Coastguard Worker }
2025*7304104dSAndroid Build Coastguard Worker
2026*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2027*7304104dSAndroid Build Coastguard Worker if (data == NULL || data->d_buf == NULL)
2028*7304104dSAndroid Build Coastguard Worker {
2029*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
2030*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2031*7304104dSAndroid Build Coastguard Worker return;
2032*7304104dSAndroid Build Coastguard Worker }
2033*7304104dSAndroid Build Coastguard Worker
2034*7304104dSAndroid Build Coastguard Worker if (data->d_size < sizeof (Elf32_Word)
2035*7304104dSAndroid Build Coastguard Worker || *((Elf32_Word *) data->d_buf) != 0)
2036*7304104dSAndroid Build Coastguard Worker ERROR (_("symbol 0 should have zero extended section index\n"));
2037*7304104dSAndroid Build Coastguard Worker
2038*7304104dSAndroid Build Coastguard Worker for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
2039*7304104dSAndroid Build Coastguard Worker {
2040*7304104dSAndroid Build Coastguard Worker Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt];
2041*7304104dSAndroid Build Coastguard Worker
2042*7304104dSAndroid Build Coastguard Worker if (xndx != 0)
2043*7304104dSAndroid Build Coastguard Worker {
2044*7304104dSAndroid Build Coastguard Worker GElf_Sym sym_data;
2045*7304104dSAndroid Build Coastguard Worker GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data);
2046*7304104dSAndroid Build Coastguard Worker if (sym == NULL)
2047*7304104dSAndroid Build Coastguard Worker {
2048*7304104dSAndroid Build Coastguard Worker ERROR (_("cannot get data for symbol %zu\n"), cnt);
2049*7304104dSAndroid Build Coastguard Worker continue;
2050*7304104dSAndroid Build Coastguard Worker }
2051*7304104dSAndroid Build Coastguard Worker
2052*7304104dSAndroid Build Coastguard Worker if (sym->st_shndx != SHN_XINDEX)
2053*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2054*7304104dSAndroid Build Coastguard Worker extended section index is %" PRIu32 " but symbol index is not XINDEX\n"),
2055*7304104dSAndroid Build Coastguard Worker (uint32_t) xndx);
2056*7304104dSAndroid Build Coastguard Worker }
2057*7304104dSAndroid Build Coastguard Worker }
2058*7304104dSAndroid Build Coastguard Worker }
2059*7304104dSAndroid Build Coastguard Worker
2060*7304104dSAndroid Build Coastguard Worker
2061*7304104dSAndroid Build Coastguard Worker static void
check_sysv_hash(Ebl * ebl,GElf_Shdr * shdr,Elf_Data * data,int idx,GElf_Shdr * symshdr)2062*7304104dSAndroid Build Coastguard Worker check_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
2063*7304104dSAndroid Build Coastguard Worker GElf_Shdr *symshdr)
2064*7304104dSAndroid Build Coastguard Worker {
2065*7304104dSAndroid Build Coastguard Worker Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
2066*7304104dSAndroid Build Coastguard Worker Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
2067*7304104dSAndroid Build Coastguard Worker
2068*7304104dSAndroid Build Coastguard Worker if (shdr->sh_size < (2ULL + nbucket + nchain) * sizeof (Elf32_Word))
2069*7304104dSAndroid Build Coastguard Worker {
2070*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2071*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
2072*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), (long int) shdr->sh_size,
2073*7304104dSAndroid Build Coastguard Worker (long int) ((2 + nbucket + nchain) * sizeof (Elf32_Word)));
2074*7304104dSAndroid Build Coastguard Worker return;
2075*7304104dSAndroid Build Coastguard Worker }
2076*7304104dSAndroid Build Coastguard Worker
2077*7304104dSAndroid Build Coastguard Worker size_t maxidx = nchain;
2078*7304104dSAndroid Build Coastguard Worker
2079*7304104dSAndroid Build Coastguard Worker if (symshdr != NULL && symshdr->sh_entsize != 0)
2080*7304104dSAndroid Build Coastguard Worker {
2081*7304104dSAndroid Build Coastguard Worker size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
2082*7304104dSAndroid Build Coastguard Worker
2083*7304104dSAndroid Build Coastguard Worker if (nchain > symshdr->sh_size / symshdr->sh_entsize)
2084*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': chain array too large\n"),
2085*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2086*7304104dSAndroid Build Coastguard Worker
2087*7304104dSAndroid Build Coastguard Worker maxidx = symsize;
2088*7304104dSAndroid Build Coastguard Worker }
2089*7304104dSAndroid Build Coastguard Worker
2090*7304104dSAndroid Build Coastguard Worker Elf32_Word *buf = (Elf32_Word *) data->d_buf;
2091*7304104dSAndroid Build Coastguard Worker Elf32_Word *end = (Elf32_Word *) ((char *) data->d_buf + shdr->sh_size);
2092*7304104dSAndroid Build Coastguard Worker size_t cnt;
2093*7304104dSAndroid Build Coastguard Worker for (cnt = 2; cnt < 2 + nbucket; ++cnt)
2094*7304104dSAndroid Build Coastguard Worker {
2095*7304104dSAndroid Build Coastguard Worker if (buf + cnt >= end)
2096*7304104dSAndroid Build Coastguard Worker break;
2097*7304104dSAndroid Build Coastguard Worker else if (buf[cnt] >= maxidx)
2098*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2099*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash bucket reference %zu out of bounds\n"),
2100*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt - 2);
2101*7304104dSAndroid Build Coastguard Worker }
2102*7304104dSAndroid Build Coastguard Worker
2103*7304104dSAndroid Build Coastguard Worker for (; cnt < 2 + nbucket + nchain; ++cnt)
2104*7304104dSAndroid Build Coastguard Worker {
2105*7304104dSAndroid Build Coastguard Worker if (buf + cnt >= end)
2106*7304104dSAndroid Build Coastguard Worker break;
2107*7304104dSAndroid Build Coastguard Worker else if (buf[cnt] >= maxidx)
2108*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2109*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash chain reference %zu out of bounds\n"),
2110*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt - 2 - nbucket);
2111*7304104dSAndroid Build Coastguard Worker }
2112*7304104dSAndroid Build Coastguard Worker }
2113*7304104dSAndroid Build Coastguard Worker
2114*7304104dSAndroid Build Coastguard Worker
2115*7304104dSAndroid Build Coastguard Worker static void
check_sysv_hash64(Ebl * ebl,GElf_Shdr * shdr,Elf_Data * data,int idx,GElf_Shdr * symshdr)2116*7304104dSAndroid Build Coastguard Worker check_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
2117*7304104dSAndroid Build Coastguard Worker GElf_Shdr *symshdr)
2118*7304104dSAndroid Build Coastguard Worker {
2119*7304104dSAndroid Build Coastguard Worker Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
2120*7304104dSAndroid Build Coastguard Worker Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
2121*7304104dSAndroid Build Coastguard Worker
2122*7304104dSAndroid Build Coastguard Worker uint64_t maxwords = shdr->sh_size / sizeof (Elf64_Xword);
2123*7304104dSAndroid Build Coastguard Worker if (maxwords < 2
2124*7304104dSAndroid Build Coastguard Worker || maxwords - 2 < nbucket
2125*7304104dSAndroid Build Coastguard Worker || maxwords - 2 - nbucket < nchain)
2126*7304104dSAndroid Build Coastguard Worker {
2127*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2128*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
2129*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), (long int) shdr->sh_size,
2130*7304104dSAndroid Build Coastguard Worker (long int) ((2 + nbucket + nchain) * sizeof (Elf64_Xword)));
2131*7304104dSAndroid Build Coastguard Worker return;
2132*7304104dSAndroid Build Coastguard Worker }
2133*7304104dSAndroid Build Coastguard Worker
2134*7304104dSAndroid Build Coastguard Worker size_t maxidx = nchain;
2135*7304104dSAndroid Build Coastguard Worker
2136*7304104dSAndroid Build Coastguard Worker if (symshdr != NULL && symshdr->sh_entsize != 0)
2137*7304104dSAndroid Build Coastguard Worker {
2138*7304104dSAndroid Build Coastguard Worker size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
2139*7304104dSAndroid Build Coastguard Worker
2140*7304104dSAndroid Build Coastguard Worker if (nchain > symshdr->sh_size / symshdr->sh_entsize)
2141*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': chain array too large\n"),
2142*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2143*7304104dSAndroid Build Coastguard Worker
2144*7304104dSAndroid Build Coastguard Worker maxidx = symsize;
2145*7304104dSAndroid Build Coastguard Worker }
2146*7304104dSAndroid Build Coastguard Worker
2147*7304104dSAndroid Build Coastguard Worker Elf64_Xword *buf = (Elf64_Xword *) data->d_buf;
2148*7304104dSAndroid Build Coastguard Worker Elf64_Xword *end = (Elf64_Xword *) ((char *) data->d_buf + shdr->sh_size);
2149*7304104dSAndroid Build Coastguard Worker size_t cnt;
2150*7304104dSAndroid Build Coastguard Worker for (cnt = 2; cnt < 2 + nbucket; ++cnt)
2151*7304104dSAndroid Build Coastguard Worker {
2152*7304104dSAndroid Build Coastguard Worker if (buf + cnt >= end)
2153*7304104dSAndroid Build Coastguard Worker break;
2154*7304104dSAndroid Build Coastguard Worker else if (buf[cnt] >= maxidx)
2155*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2156*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash bucket reference %zu out of bounds\n"),
2157*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt - 2);
2158*7304104dSAndroid Build Coastguard Worker }
2159*7304104dSAndroid Build Coastguard Worker
2160*7304104dSAndroid Build Coastguard Worker for (; cnt < 2 + nbucket + nchain; ++cnt)
2161*7304104dSAndroid Build Coastguard Worker {
2162*7304104dSAndroid Build Coastguard Worker if (buf + cnt >= end)
2163*7304104dSAndroid Build Coastguard Worker break;
2164*7304104dSAndroid Build Coastguard Worker else if (buf[cnt] >= maxidx)
2165*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2166*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash chain reference %" PRIu64 " out of bounds\n"),
2167*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), (uint64_t) cnt - 2 - nbucket);
2168*7304104dSAndroid Build Coastguard Worker }
2169*7304104dSAndroid Build Coastguard Worker }
2170*7304104dSAndroid Build Coastguard Worker
2171*7304104dSAndroid Build Coastguard Worker
2172*7304104dSAndroid Build Coastguard Worker static void
check_gnu_hash(Ebl * ebl,GElf_Shdr * shdr,Elf_Data * data,int idx,GElf_Shdr * symshdr)2173*7304104dSAndroid Build Coastguard Worker check_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
2174*7304104dSAndroid Build Coastguard Worker GElf_Shdr *symshdr)
2175*7304104dSAndroid Build Coastguard Worker {
2176*7304104dSAndroid Build Coastguard Worker if (data->d_size < 4 * sizeof (Elf32_Word))
2177*7304104dSAndroid Build Coastguard Worker {
2178*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2179*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': not enough data\n"),
2180*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2181*7304104dSAndroid Build Coastguard Worker return;
2182*7304104dSAndroid Build Coastguard Worker }
2183*7304104dSAndroid Build Coastguard Worker
2184*7304104dSAndroid Build Coastguard Worker Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0];
2185*7304104dSAndroid Build Coastguard Worker Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
2186*7304104dSAndroid Build Coastguard Worker Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
2187*7304104dSAndroid Build Coastguard Worker
2188*7304104dSAndroid Build Coastguard Worker if (bitmask_words == 0 || !powerof2 (bitmask_words))
2189*7304104dSAndroid Build Coastguard Worker {
2190*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2191*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': bitmask size zero or not power of 2: %u\n"),
2192*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), bitmask_words);
2193*7304104dSAndroid Build Coastguard Worker return;
2194*7304104dSAndroid Build Coastguard Worker }
2195*7304104dSAndroid Build Coastguard Worker
2196*7304104dSAndroid Build Coastguard Worker size_t bitmask_idxmask = bitmask_words - 1;
2197*7304104dSAndroid Build Coastguard Worker if (gelf_getclass (ebl->elf) == ELFCLASS64)
2198*7304104dSAndroid Build Coastguard Worker bitmask_words *= 2;
2199*7304104dSAndroid Build Coastguard Worker Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
2200*7304104dSAndroid Build Coastguard Worker
2201*7304104dSAndroid Build Coastguard Worker /* Is there still room for the sym chain?
2202*7304104dSAndroid Build Coastguard Worker Use uint64_t calculation to prevent 32bit overflow. */
2203*7304104dSAndroid Build Coastguard Worker uint64_t used_buf = (4ULL + bitmask_words + nbuckets) * sizeof (Elf32_Word);
2204*7304104dSAndroid Build Coastguard Worker if (used_buf > data->d_size)
2205*7304104dSAndroid Build Coastguard Worker {
2206*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2207*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash table section is too small (is %ld, expected at least %ld)\n"),
2208*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), (long int) shdr->sh_size,
2209*7304104dSAndroid Build Coastguard Worker (long int) used_buf);
2210*7304104dSAndroid Build Coastguard Worker return;
2211*7304104dSAndroid Build Coastguard Worker }
2212*7304104dSAndroid Build Coastguard Worker
2213*7304104dSAndroid Build Coastguard Worker if (shift > 31)
2214*7304104dSAndroid Build Coastguard Worker {
2215*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2216*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': 2nd hash function shift too big: %u\n"),
2217*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), shift);
2218*7304104dSAndroid Build Coastguard Worker return;
2219*7304104dSAndroid Build Coastguard Worker }
2220*7304104dSAndroid Build Coastguard Worker
2221*7304104dSAndroid Build Coastguard Worker size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words
2222*7304104dSAndroid Build Coastguard Worker + nbuckets);
2223*7304104dSAndroid Build Coastguard Worker
2224*7304104dSAndroid Build Coastguard Worker if (symshdr != NULL && symshdr->sh_entsize != 0)
2225*7304104dSAndroid Build Coastguard Worker maxidx = MIN (maxidx, symshdr->sh_size / symshdr->sh_entsize);
2226*7304104dSAndroid Build Coastguard Worker
2227*7304104dSAndroid Build Coastguard Worker /* We need the symbol section data. */
2228*7304104dSAndroid Build Coastguard Worker Elf_Data *symdata = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link), NULL);
2229*7304104dSAndroid Build Coastguard Worker
2230*7304104dSAndroid Build Coastguard Worker union
2231*7304104dSAndroid Build Coastguard Worker {
2232*7304104dSAndroid Build Coastguard Worker Elf32_Word *p32;
2233*7304104dSAndroid Build Coastguard Worker Elf64_Xword *p64;
2234*7304104dSAndroid Build Coastguard Worker } bitmask = { .p32 = &((Elf32_Word *) data->d_buf)[4] },
2235*7304104dSAndroid Build Coastguard Worker collected = { .p32 = xcalloc (bitmask_words, sizeof (Elf32_Word)) };
2236*7304104dSAndroid Build Coastguard Worker
2237*7304104dSAndroid Build Coastguard Worker size_t classbits = gelf_getclass (ebl->elf) == ELFCLASS32 ? 32 : 64;
2238*7304104dSAndroid Build Coastguard Worker
2239*7304104dSAndroid Build Coastguard Worker size_t cnt;
2240*7304104dSAndroid Build Coastguard Worker for (cnt = 4 + bitmask_words; cnt < 4 + bitmask_words + nbuckets; ++cnt)
2241*7304104dSAndroid Build Coastguard Worker {
2242*7304104dSAndroid Build Coastguard Worker Elf32_Word symidx = ((Elf32_Word *) data->d_buf)[cnt];
2243*7304104dSAndroid Build Coastguard Worker
2244*7304104dSAndroid Build Coastguard Worker if (symidx == 0)
2245*7304104dSAndroid Build Coastguard Worker continue;
2246*7304104dSAndroid Build Coastguard Worker
2247*7304104dSAndroid Build Coastguard Worker if (symidx < symbias)
2248*7304104dSAndroid Build Coastguard Worker {
2249*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2250*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"),
2251*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
2252*7304104dSAndroid Build Coastguard Worker continue;
2253*7304104dSAndroid Build Coastguard Worker }
2254*7304104dSAndroid Build Coastguard Worker
2255*7304104dSAndroid Build Coastguard Worker while (symidx - symbias < maxidx)
2256*7304104dSAndroid Build Coastguard Worker {
2257*7304104dSAndroid Build Coastguard Worker Elf32_Word chainhash = ((Elf32_Word *) data->d_buf)[4
2258*7304104dSAndroid Build Coastguard Worker + bitmask_words
2259*7304104dSAndroid Build Coastguard Worker + nbuckets
2260*7304104dSAndroid Build Coastguard Worker + symidx
2261*7304104dSAndroid Build Coastguard Worker - symbias];
2262*7304104dSAndroid Build Coastguard Worker
2263*7304104dSAndroid Build Coastguard Worker if (symdata != NULL)
2264*7304104dSAndroid Build Coastguard Worker {
2265*7304104dSAndroid Build Coastguard Worker /* Check that the referenced symbol is not undefined. */
2266*7304104dSAndroid Build Coastguard Worker GElf_Sym sym_mem;
2267*7304104dSAndroid Build Coastguard Worker GElf_Sym *sym = gelf_getsym (symdata, symidx, &sym_mem);
2268*7304104dSAndroid Build Coastguard Worker if (sym != NULL && sym->st_shndx == SHN_UNDEF
2269*7304104dSAndroid Build Coastguard Worker && GELF_ST_TYPE (sym->st_info) != STT_FUNC)
2270*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2271*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %u referenced in chain for bucket %zu is undefined\n"),
2272*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), symidx,
2273*7304104dSAndroid Build Coastguard Worker cnt - (4 + bitmask_words));
2274*7304104dSAndroid Build Coastguard Worker
2275*7304104dSAndroid Build Coastguard Worker const char *symname = (sym != NULL
2276*7304104dSAndroid Build Coastguard Worker ? elf_strptr (ebl->elf, symshdr->sh_link,
2277*7304104dSAndroid Build Coastguard Worker sym->st_name)
2278*7304104dSAndroid Build Coastguard Worker : NULL);
2279*7304104dSAndroid Build Coastguard Worker if (symname != NULL)
2280*7304104dSAndroid Build Coastguard Worker {
2281*7304104dSAndroid Build Coastguard Worker Elf32_Word hval = elf_gnu_hash (symname);
2282*7304104dSAndroid Build Coastguard Worker if ((hval & ~1u) != (chainhash & ~1u))
2283*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2284*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"),
2285*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), symidx,
2286*7304104dSAndroid Build Coastguard Worker cnt - (4 + bitmask_words));
2287*7304104dSAndroid Build Coastguard Worker
2288*7304104dSAndroid Build Coastguard Worker /* Set the bits in the bitmask. */
2289*7304104dSAndroid Build Coastguard Worker size_t maskidx = (hval / classbits) & bitmask_idxmask;
2290*7304104dSAndroid Build Coastguard Worker if (maskidx >= bitmask_words)
2291*7304104dSAndroid Build Coastguard Worker {
2292*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2293*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n"),
2294*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), symidx,
2295*7304104dSAndroid Build Coastguard Worker cnt - (4 + bitmask_words));
2296*7304104dSAndroid Build Coastguard Worker return;
2297*7304104dSAndroid Build Coastguard Worker }
2298*7304104dSAndroid Build Coastguard Worker if (classbits == 32)
2299*7304104dSAndroid Build Coastguard Worker {
2300*7304104dSAndroid Build Coastguard Worker collected.p32[maskidx]
2301*7304104dSAndroid Build Coastguard Worker |= UINT32_C (1) << (hval & (classbits - 1));
2302*7304104dSAndroid Build Coastguard Worker collected.p32[maskidx]
2303*7304104dSAndroid Build Coastguard Worker |= UINT32_C (1) << ((hval >> shift) & (classbits - 1));
2304*7304104dSAndroid Build Coastguard Worker }
2305*7304104dSAndroid Build Coastguard Worker else
2306*7304104dSAndroid Build Coastguard Worker {
2307*7304104dSAndroid Build Coastguard Worker collected.p64[maskidx]
2308*7304104dSAndroid Build Coastguard Worker |= UINT64_C (1) << (hval & (classbits - 1));
2309*7304104dSAndroid Build Coastguard Worker collected.p64[maskidx]
2310*7304104dSAndroid Build Coastguard Worker |= UINT64_C (1) << ((hval >> shift) & (classbits - 1));
2311*7304104dSAndroid Build Coastguard Worker }
2312*7304104dSAndroid Build Coastguard Worker }
2313*7304104dSAndroid Build Coastguard Worker }
2314*7304104dSAndroid Build Coastguard Worker
2315*7304104dSAndroid Build Coastguard Worker if ((chainhash & 1) != 0)
2316*7304104dSAndroid Build Coastguard Worker break;
2317*7304104dSAndroid Build Coastguard Worker
2318*7304104dSAndroid Build Coastguard Worker ++symidx;
2319*7304104dSAndroid Build Coastguard Worker }
2320*7304104dSAndroid Build Coastguard Worker
2321*7304104dSAndroid Build Coastguard Worker if (symidx - symbias >= maxidx)
2322*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2323*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash chain for bucket %zu out of bounds\n"),
2324*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
2325*7304104dSAndroid Build Coastguard Worker else if (symshdr != NULL && symshdr->sh_entsize != 0
2326*7304104dSAndroid Build Coastguard Worker && symidx > symshdr->sh_size / symshdr->sh_entsize)
2327*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2328*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"),
2329*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
2330*7304104dSAndroid Build Coastguard Worker }
2331*7304104dSAndroid Build Coastguard Worker
2332*7304104dSAndroid Build Coastguard Worker if (memcmp (collected.p32, bitmask.p32, bitmask_words * sizeof (Elf32_Word)))
2333*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2334*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': bitmask does not match names in the hash table\n"),
2335*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2336*7304104dSAndroid Build Coastguard Worker
2337*7304104dSAndroid Build Coastguard Worker free (collected.p32);
2338*7304104dSAndroid Build Coastguard Worker }
2339*7304104dSAndroid Build Coastguard Worker
2340*7304104dSAndroid Build Coastguard Worker
2341*7304104dSAndroid Build Coastguard Worker static void
check_hash(int tag,Ebl * ebl,GElf_Ehdr * ehdr,GElf_Shdr * shdr,int idx)2342*7304104dSAndroid Build Coastguard Worker check_hash (int tag, Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2343*7304104dSAndroid Build Coastguard Worker {
2344*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type == ET_REL)
2345*7304104dSAndroid Build Coastguard Worker {
2346*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2347*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': relocatable files cannot have hash tables\n"),
2348*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2349*7304104dSAndroid Build Coastguard Worker return;
2350*7304104dSAndroid Build Coastguard Worker }
2351*7304104dSAndroid Build Coastguard Worker
2352*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2353*7304104dSAndroid Build Coastguard Worker if (data == NULL || data->d_buf == NULL)
2354*7304104dSAndroid Build Coastguard Worker {
2355*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
2356*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2357*7304104dSAndroid Build Coastguard Worker return;
2358*7304104dSAndroid Build Coastguard Worker }
2359*7304104dSAndroid Build Coastguard Worker
2360*7304104dSAndroid Build Coastguard Worker GElf_Shdr symshdr_mem;
2361*7304104dSAndroid Build Coastguard Worker GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2362*7304104dSAndroid Build Coastguard Worker &symshdr_mem);
2363*7304104dSAndroid Build Coastguard Worker if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM)
2364*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2365*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash table not for dynamic symbol table\n"),
2366*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2367*7304104dSAndroid Build Coastguard Worker else if (symshdr == NULL)
2368*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2369*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n"),
2370*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), shdr->sh_link);
2371*7304104dSAndroid Build Coastguard Worker
2372*7304104dSAndroid Build Coastguard Worker size_t expect_entsize = (tag == SHT_GNU_HASH
2373*7304104dSAndroid Build Coastguard Worker ? (gelf_getclass (ebl->elf) == ELFCLASS32
2374*7304104dSAndroid Build Coastguard Worker ? sizeof (Elf32_Word) : 0)
2375*7304104dSAndroid Build Coastguard Worker : (size_t) ebl_sysvhash_entrysize (ebl));
2376*7304104dSAndroid Build Coastguard Worker
2377*7304104dSAndroid Build Coastguard Worker if (shdr->sh_entsize != expect_entsize)
2378*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2379*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash table entry size incorrect\n"),
2380*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2381*7304104dSAndroid Build Coastguard Worker
2382*7304104dSAndroid Build Coastguard Worker if ((shdr->sh_flags & SHF_ALLOC) == 0)
2383*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': not marked to be allocated\n"),
2384*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2385*7304104dSAndroid Build Coastguard Worker
2386*7304104dSAndroid Build Coastguard Worker if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (expect_entsize ?: 4))
2387*7304104dSAndroid Build Coastguard Worker {
2388*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2389*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': hash table has not even room for initial administrative entries\n"),
2390*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2391*7304104dSAndroid Build Coastguard Worker return;
2392*7304104dSAndroid Build Coastguard Worker }
2393*7304104dSAndroid Build Coastguard Worker
2394*7304104dSAndroid Build Coastguard Worker switch (tag)
2395*7304104dSAndroid Build Coastguard Worker {
2396*7304104dSAndroid Build Coastguard Worker case SHT_HASH:
2397*7304104dSAndroid Build Coastguard Worker if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
2398*7304104dSAndroid Build Coastguard Worker check_sysv_hash64 (ebl, shdr, data, idx, symshdr);
2399*7304104dSAndroid Build Coastguard Worker else
2400*7304104dSAndroid Build Coastguard Worker check_sysv_hash (ebl, shdr, data, idx, symshdr);
2401*7304104dSAndroid Build Coastguard Worker break;
2402*7304104dSAndroid Build Coastguard Worker
2403*7304104dSAndroid Build Coastguard Worker case SHT_GNU_HASH:
2404*7304104dSAndroid Build Coastguard Worker check_gnu_hash (ebl, shdr, data, idx, symshdr);
2405*7304104dSAndroid Build Coastguard Worker break;
2406*7304104dSAndroid Build Coastguard Worker
2407*7304104dSAndroid Build Coastguard Worker default:
2408*7304104dSAndroid Build Coastguard Worker assert (! "should not happen");
2409*7304104dSAndroid Build Coastguard Worker }
2410*7304104dSAndroid Build Coastguard Worker }
2411*7304104dSAndroid Build Coastguard Worker
2412*7304104dSAndroid Build Coastguard Worker
2413*7304104dSAndroid Build Coastguard Worker /* Compare content of both hash tables, it must be identical. */
2414*7304104dSAndroid Build Coastguard Worker static void
compare_hash_gnu_hash(Ebl * ebl,GElf_Ehdr * ehdr,size_t hash_idx,size_t gnu_hash_idx)2415*7304104dSAndroid Build Coastguard Worker compare_hash_gnu_hash (Ebl *ebl, GElf_Ehdr *ehdr, size_t hash_idx,
2416*7304104dSAndroid Build Coastguard Worker size_t gnu_hash_idx)
2417*7304104dSAndroid Build Coastguard Worker {
2418*7304104dSAndroid Build Coastguard Worker Elf_Scn *hash_scn = elf_getscn (ebl->elf, hash_idx);
2419*7304104dSAndroid Build Coastguard Worker Elf_Data *hash_data = elf_getdata (hash_scn, NULL);
2420*7304104dSAndroid Build Coastguard Worker GElf_Shdr hash_shdr_mem;
2421*7304104dSAndroid Build Coastguard Worker GElf_Shdr *hash_shdr = gelf_getshdr (hash_scn, &hash_shdr_mem);
2422*7304104dSAndroid Build Coastguard Worker Elf_Scn *gnu_hash_scn = elf_getscn (ebl->elf, gnu_hash_idx);
2423*7304104dSAndroid Build Coastguard Worker Elf_Data *gnu_hash_data = elf_getdata (gnu_hash_scn, NULL);
2424*7304104dSAndroid Build Coastguard Worker GElf_Shdr gnu_hash_shdr_mem;
2425*7304104dSAndroid Build Coastguard Worker GElf_Shdr *gnu_hash_shdr = gelf_getshdr (gnu_hash_scn, &gnu_hash_shdr_mem);
2426*7304104dSAndroid Build Coastguard Worker
2427*7304104dSAndroid Build Coastguard Worker if (hash_shdr == NULL || gnu_hash_shdr == NULL
2428*7304104dSAndroid Build Coastguard Worker || hash_data == NULL || hash_data->d_buf == NULL
2429*7304104dSAndroid Build Coastguard Worker || gnu_hash_data == NULL || gnu_hash_data->d_buf == NULL)
2430*7304104dSAndroid Build Coastguard Worker /* None of these pointers should be NULL since we used the
2431*7304104dSAndroid Build Coastguard Worker sections already. We are careful nonetheless. */
2432*7304104dSAndroid Build Coastguard Worker return;
2433*7304104dSAndroid Build Coastguard Worker
2434*7304104dSAndroid Build Coastguard Worker /* The link must point to the same symbol table. */
2435*7304104dSAndroid Build Coastguard Worker if (hash_shdr->sh_link != gnu_hash_shdr->sh_link)
2436*7304104dSAndroid Build Coastguard Worker {
2437*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2438*7304104dSAndroid Build Coastguard Worker sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"),
2439*7304104dSAndroid Build Coastguard Worker hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
2440*7304104dSAndroid Build Coastguard Worker gnu_hash_idx,
2441*7304104dSAndroid Build Coastguard Worker elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
2442*7304104dSAndroid Build Coastguard Worker return;
2443*7304104dSAndroid Build Coastguard Worker }
2444*7304104dSAndroid Build Coastguard Worker
2445*7304104dSAndroid Build Coastguard Worker Elf_Scn *sym_scn = elf_getscn (ebl->elf, hash_shdr->sh_link);
2446*7304104dSAndroid Build Coastguard Worker Elf_Data *sym_data = elf_getdata (sym_scn, NULL);
2447*7304104dSAndroid Build Coastguard Worker GElf_Shdr sym_shdr_mem;
2448*7304104dSAndroid Build Coastguard Worker GElf_Shdr *sym_shdr = gelf_getshdr (sym_scn, &sym_shdr_mem);
2449*7304104dSAndroid Build Coastguard Worker
2450*7304104dSAndroid Build Coastguard Worker if (sym_data == NULL || sym_data->d_buf == NULL
2451*7304104dSAndroid Build Coastguard Worker || sym_shdr == NULL || sym_shdr->sh_entsize == 0)
2452*7304104dSAndroid Build Coastguard Worker return;
2453*7304104dSAndroid Build Coastguard Worker
2454*7304104dSAndroid Build Coastguard Worker const char *hash_name;
2455*7304104dSAndroid Build Coastguard Worker const char *gnu_hash_name;
2456*7304104dSAndroid Build Coastguard Worker hash_name = elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name);
2457*7304104dSAndroid Build Coastguard Worker gnu_hash_name = elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name);
2458*7304104dSAndroid Build Coastguard Worker
2459*7304104dSAndroid Build Coastguard Worker if (gnu_hash_data->d_size < 4 * sizeof (Elf32_Word))
2460*7304104dSAndroid Build Coastguard Worker {
2461*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2462*7304104dSAndroid Build Coastguard Worker hash section [%2zu] '%s' does not contain enough data\n"),
2463*7304104dSAndroid Build Coastguard Worker gnu_hash_idx, gnu_hash_name);
2464*7304104dSAndroid Build Coastguard Worker return;
2465*7304104dSAndroid Build Coastguard Worker }
2466*7304104dSAndroid Build Coastguard Worker
2467*7304104dSAndroid Build Coastguard Worker uint32_t nentries = sym_shdr->sh_size / sym_shdr->sh_entsize;
2468*7304104dSAndroid Build Coastguard Worker char *used = alloca (nentries);
2469*7304104dSAndroid Build Coastguard Worker memset (used, '\0', nentries);
2470*7304104dSAndroid Build Coastguard Worker
2471*7304104dSAndroid Build Coastguard Worker /* First go over the GNU_HASH table and mark the entries as used. */
2472*7304104dSAndroid Build Coastguard Worker const Elf32_Word *gnu_hasharr = (Elf32_Word *) gnu_hash_data->d_buf;
2473*7304104dSAndroid Build Coastguard Worker Elf32_Word gnu_nbucket = gnu_hasharr[0];
2474*7304104dSAndroid Build Coastguard Worker Elf32_Word gnu_symbias = gnu_hasharr[1];
2475*7304104dSAndroid Build Coastguard Worker const int bitmap_factor = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 1 : 2;
2476*7304104dSAndroid Build Coastguard Worker const Elf32_Word *gnu_bucket = (gnu_hasharr
2477*7304104dSAndroid Build Coastguard Worker + (4 + gnu_hasharr[2] * bitmap_factor));
2478*7304104dSAndroid Build Coastguard Worker const Elf32_Word *gnu_chain = gnu_bucket + gnu_hasharr[0];
2479*7304104dSAndroid Build Coastguard Worker
2480*7304104dSAndroid Build Coastguard Worker if (gnu_hasharr[2] == 0)
2481*7304104dSAndroid Build Coastguard Worker {
2482*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2483*7304104dSAndroid Build Coastguard Worker hash section [%2zu] '%s' has zero bit mask words\n"),
2484*7304104dSAndroid Build Coastguard Worker gnu_hash_idx, gnu_hash_name);
2485*7304104dSAndroid Build Coastguard Worker return;
2486*7304104dSAndroid Build Coastguard Worker }
2487*7304104dSAndroid Build Coastguard Worker
2488*7304104dSAndroid Build Coastguard Worker uint64_t used_buf = ((4ULL + gnu_hasharr[2] * bitmap_factor + gnu_nbucket)
2489*7304104dSAndroid Build Coastguard Worker * sizeof (Elf32_Word));
2490*7304104dSAndroid Build Coastguard Worker uint32_t max_nsyms = (gnu_hash_data->d_size - used_buf) / sizeof (Elf32_Word);
2491*7304104dSAndroid Build Coastguard Worker if (used_buf > gnu_hash_data->d_size)
2492*7304104dSAndroid Build Coastguard Worker {
2493*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2494*7304104dSAndroid Build Coastguard Worker hash section [%2zu] '%s' uses too much data\n"),
2495*7304104dSAndroid Build Coastguard Worker gnu_hash_idx, gnu_hash_name);
2496*7304104dSAndroid Build Coastguard Worker return;
2497*7304104dSAndroid Build Coastguard Worker }
2498*7304104dSAndroid Build Coastguard Worker
2499*7304104dSAndroid Build Coastguard Worker for (Elf32_Word cnt = 0; cnt < gnu_nbucket; ++cnt)
2500*7304104dSAndroid Build Coastguard Worker {
2501*7304104dSAndroid Build Coastguard Worker if (gnu_bucket[cnt] != STN_UNDEF)
2502*7304104dSAndroid Build Coastguard Worker {
2503*7304104dSAndroid Build Coastguard Worker Elf32_Word symidx = gnu_bucket[cnt] - gnu_symbias;
2504*7304104dSAndroid Build Coastguard Worker do
2505*7304104dSAndroid Build Coastguard Worker {
2506*7304104dSAndroid Build Coastguard Worker if (symidx >= max_nsyms || symidx + gnu_symbias >= nentries)
2507*7304104dSAndroid Build Coastguard Worker {
2508*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2509*7304104dSAndroid Build Coastguard Worker hash section [%2zu] '%s' invalid symbol index %" PRIu32 " (max_nsyms: %" PRIu32 ", nentries: %" PRIu32 "\n"),
2510*7304104dSAndroid Build Coastguard Worker gnu_hash_idx, gnu_hash_name, symidx, max_nsyms, nentries);
2511*7304104dSAndroid Build Coastguard Worker return;
2512*7304104dSAndroid Build Coastguard Worker }
2513*7304104dSAndroid Build Coastguard Worker used[symidx + gnu_symbias] |= 1;
2514*7304104dSAndroid Build Coastguard Worker }
2515*7304104dSAndroid Build Coastguard Worker while ((gnu_chain[symidx++] & 1u) == 0);
2516*7304104dSAndroid Build Coastguard Worker }
2517*7304104dSAndroid Build Coastguard Worker }
2518*7304104dSAndroid Build Coastguard Worker
2519*7304104dSAndroid Build Coastguard Worker /* Now go over the old hash table and check that we cover the same
2520*7304104dSAndroid Build Coastguard Worker entries. */
2521*7304104dSAndroid Build Coastguard Worker if (hash_shdr->sh_entsize == sizeof (Elf32_Word))
2522*7304104dSAndroid Build Coastguard Worker {
2523*7304104dSAndroid Build Coastguard Worker const Elf32_Word *hasharr = (Elf32_Word *) hash_data->d_buf;
2524*7304104dSAndroid Build Coastguard Worker if (hash_data->d_size < 2 * sizeof (Elf32_Word))
2525*7304104dSAndroid Build Coastguard Worker {
2526*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2527*7304104dSAndroid Build Coastguard Worker hash section [%2zu] '%s' does not contain enough data\n"),
2528*7304104dSAndroid Build Coastguard Worker hash_idx, hash_name);
2529*7304104dSAndroid Build Coastguard Worker return;
2530*7304104dSAndroid Build Coastguard Worker }
2531*7304104dSAndroid Build Coastguard Worker
2532*7304104dSAndroid Build Coastguard Worker Elf32_Word nbucket = hasharr[0];
2533*7304104dSAndroid Build Coastguard Worker Elf32_Word nchain = hasharr[1];
2534*7304104dSAndroid Build Coastguard Worker uint64_t hash_used = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
2535*7304104dSAndroid Build Coastguard Worker if (hash_used > hash_data->d_size)
2536*7304104dSAndroid Build Coastguard Worker {
2537*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2538*7304104dSAndroid Build Coastguard Worker hash section [%2zu] '%s' uses too much data\n"),
2539*7304104dSAndroid Build Coastguard Worker hash_idx, hash_name);
2540*7304104dSAndroid Build Coastguard Worker return;
2541*7304104dSAndroid Build Coastguard Worker }
2542*7304104dSAndroid Build Coastguard Worker
2543*7304104dSAndroid Build Coastguard Worker const Elf32_Word *bucket = &hasharr[2];
2544*7304104dSAndroid Build Coastguard Worker const Elf32_Word *chain = &hasharr[2 + nbucket];
2545*7304104dSAndroid Build Coastguard Worker
2546*7304104dSAndroid Build Coastguard Worker for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2547*7304104dSAndroid Build Coastguard Worker {
2548*7304104dSAndroid Build Coastguard Worker Elf32_Word symidx = bucket[cnt];
2549*7304104dSAndroid Build Coastguard Worker while (symidx != STN_UNDEF && symidx < nentries && symidx < nchain)
2550*7304104dSAndroid Build Coastguard Worker {
2551*7304104dSAndroid Build Coastguard Worker used[symidx] |= 2;
2552*7304104dSAndroid Build Coastguard Worker symidx = chain[symidx];
2553*7304104dSAndroid Build Coastguard Worker }
2554*7304104dSAndroid Build Coastguard Worker }
2555*7304104dSAndroid Build Coastguard Worker }
2556*7304104dSAndroid Build Coastguard Worker else if (hash_shdr->sh_entsize == sizeof (Elf64_Xword))
2557*7304104dSAndroid Build Coastguard Worker {
2558*7304104dSAndroid Build Coastguard Worker const Elf64_Xword *hasharr = (Elf64_Xword *) hash_data->d_buf;
2559*7304104dSAndroid Build Coastguard Worker if (hash_data->d_size < 2 * sizeof (Elf32_Word))
2560*7304104dSAndroid Build Coastguard Worker {
2561*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2562*7304104dSAndroid Build Coastguard Worker hash section [%2zu] '%s' does not contain enough data\n"),
2563*7304104dSAndroid Build Coastguard Worker hash_idx, hash_name);
2564*7304104dSAndroid Build Coastguard Worker return;
2565*7304104dSAndroid Build Coastguard Worker }
2566*7304104dSAndroid Build Coastguard Worker
2567*7304104dSAndroid Build Coastguard Worker Elf64_Xword nbucket = hasharr[0];
2568*7304104dSAndroid Build Coastguard Worker Elf64_Xword nchain = hasharr[1];
2569*7304104dSAndroid Build Coastguard Worker uint64_t maxwords = hash_data->d_size / sizeof (Elf64_Xword);
2570*7304104dSAndroid Build Coastguard Worker if (maxwords < 2
2571*7304104dSAndroid Build Coastguard Worker || maxwords - 2 < nbucket
2572*7304104dSAndroid Build Coastguard Worker || maxwords - 2 - nbucket < nchain)
2573*7304104dSAndroid Build Coastguard Worker {
2574*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2575*7304104dSAndroid Build Coastguard Worker hash section [%2zu] '%s' uses too much data\n"),
2576*7304104dSAndroid Build Coastguard Worker hash_idx, hash_name);
2577*7304104dSAndroid Build Coastguard Worker return;
2578*7304104dSAndroid Build Coastguard Worker }
2579*7304104dSAndroid Build Coastguard Worker
2580*7304104dSAndroid Build Coastguard Worker const Elf64_Xword *bucket = &hasharr[2];
2581*7304104dSAndroid Build Coastguard Worker const Elf64_Xword *chain = &hasharr[2 + nbucket];
2582*7304104dSAndroid Build Coastguard Worker
2583*7304104dSAndroid Build Coastguard Worker for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
2584*7304104dSAndroid Build Coastguard Worker {
2585*7304104dSAndroid Build Coastguard Worker Elf64_Xword symidx = bucket[cnt];
2586*7304104dSAndroid Build Coastguard Worker while (symidx != STN_UNDEF && symidx < nentries && symidx < nchain)
2587*7304104dSAndroid Build Coastguard Worker {
2588*7304104dSAndroid Build Coastguard Worker used[symidx] |= 2;
2589*7304104dSAndroid Build Coastguard Worker symidx = chain[symidx];
2590*7304104dSAndroid Build Coastguard Worker }
2591*7304104dSAndroid Build Coastguard Worker }
2592*7304104dSAndroid Build Coastguard Worker }
2593*7304104dSAndroid Build Coastguard Worker else
2594*7304104dSAndroid Build Coastguard Worker {
2595*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2596*7304104dSAndroid Build Coastguard Worker hash section [%2zu] '%s' invalid sh_entsize\n"),
2597*7304104dSAndroid Build Coastguard Worker hash_idx, hash_name);
2598*7304104dSAndroid Build Coastguard Worker return;
2599*7304104dSAndroid Build Coastguard Worker }
2600*7304104dSAndroid Build Coastguard Worker
2601*7304104dSAndroid Build Coastguard Worker /* Now see which entries are not set in one or both hash tables
2602*7304104dSAndroid Build Coastguard Worker (unless the symbol is undefined in which case it can be omitted
2603*7304104dSAndroid Build Coastguard Worker in the new table format). */
2604*7304104dSAndroid Build Coastguard Worker if ((used[0] & 1) != 0)
2605*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2zu] '%s': reference to symbol index 0\n"),
2606*7304104dSAndroid Build Coastguard Worker gnu_hash_idx,
2607*7304104dSAndroid Build Coastguard Worker elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
2608*7304104dSAndroid Build Coastguard Worker if ((used[0] & 2) != 0)
2609*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2zu] '%s': reference to symbol index 0\n"),
2610*7304104dSAndroid Build Coastguard Worker hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
2611*7304104dSAndroid Build Coastguard Worker
2612*7304104dSAndroid Build Coastguard Worker for (uint32_t cnt = 1; cnt < nentries; ++cnt)
2613*7304104dSAndroid Build Coastguard Worker if (used[cnt] != 0 && used[cnt] != 3)
2614*7304104dSAndroid Build Coastguard Worker {
2615*7304104dSAndroid Build Coastguard Worker if (used[cnt] == 1)
2616*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2617*7304104dSAndroid Build Coastguard Worker symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash table in [%2zu] '%s'\n"),
2618*7304104dSAndroid Build Coastguard Worker cnt, gnu_hash_idx,
2619*7304104dSAndroid Build Coastguard Worker elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name),
2620*7304104dSAndroid Build Coastguard Worker hash_idx,
2621*7304104dSAndroid Build Coastguard Worker elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
2622*7304104dSAndroid Build Coastguard Worker else
2623*7304104dSAndroid Build Coastguard Worker {
2624*7304104dSAndroid Build Coastguard Worker GElf_Sym sym_mem;
2625*7304104dSAndroid Build Coastguard Worker GElf_Sym *sym = gelf_getsym (sym_data, cnt, &sym_mem);
2626*7304104dSAndroid Build Coastguard Worker
2627*7304104dSAndroid Build Coastguard Worker if (sym != NULL && sym->st_shndx != STN_UNDEF)
2628*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2629*7304104dSAndroid Build Coastguard Worker symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash table in [%2zu] '%s'\n"),
2630*7304104dSAndroid Build Coastguard Worker cnt, hash_idx,
2631*7304104dSAndroid Build Coastguard Worker elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
2632*7304104dSAndroid Build Coastguard Worker gnu_hash_idx,
2633*7304104dSAndroid Build Coastguard Worker elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
2634*7304104dSAndroid Build Coastguard Worker }
2635*7304104dSAndroid Build Coastguard Worker }
2636*7304104dSAndroid Build Coastguard Worker }
2637*7304104dSAndroid Build Coastguard Worker
2638*7304104dSAndroid Build Coastguard Worker
2639*7304104dSAndroid Build Coastguard Worker static void
check_null(Ebl * ebl,GElf_Shdr * shdr,int idx)2640*7304104dSAndroid Build Coastguard Worker check_null (Ebl *ebl, GElf_Shdr *shdr, int idx)
2641*7304104dSAndroid Build Coastguard Worker {
2642*7304104dSAndroid Build Coastguard Worker #define TEST(name, extra) \
2643*7304104dSAndroid Build Coastguard Worker if (extra && shdr->sh_##name != 0) \
2644*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': nonzero sh_%s for NULL section\n"), \
2645*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), #name)
2646*7304104dSAndroid Build Coastguard Worker
2647*7304104dSAndroid Build Coastguard Worker TEST (name, 1);
2648*7304104dSAndroid Build Coastguard Worker TEST (flags, 1);
2649*7304104dSAndroid Build Coastguard Worker TEST (addr, 1);
2650*7304104dSAndroid Build Coastguard Worker TEST (offset, 1);
2651*7304104dSAndroid Build Coastguard Worker TEST (size, idx != 0);
2652*7304104dSAndroid Build Coastguard Worker TEST (link, idx != 0);
2653*7304104dSAndroid Build Coastguard Worker TEST (info, 1);
2654*7304104dSAndroid Build Coastguard Worker TEST (addralign, 1);
2655*7304104dSAndroid Build Coastguard Worker TEST (entsize, 1);
2656*7304104dSAndroid Build Coastguard Worker }
2657*7304104dSAndroid Build Coastguard Worker
2658*7304104dSAndroid Build Coastguard Worker
2659*7304104dSAndroid Build Coastguard Worker static void
check_group(Ebl * ebl,GElf_Ehdr * ehdr,GElf_Shdr * shdr,int idx)2660*7304104dSAndroid Build Coastguard Worker check_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2661*7304104dSAndroid Build Coastguard Worker {
2662*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_REL)
2663*7304104dSAndroid Build Coastguard Worker {
2664*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2665*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section groups only allowed in relocatable object files\n"),
2666*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2667*7304104dSAndroid Build Coastguard Worker return;
2668*7304104dSAndroid Build Coastguard Worker }
2669*7304104dSAndroid Build Coastguard Worker
2670*7304104dSAndroid Build Coastguard Worker /* Check that sh_link is an index of a symbol table. */
2671*7304104dSAndroid Build Coastguard Worker Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2672*7304104dSAndroid Build Coastguard Worker GElf_Shdr symshdr_mem;
2673*7304104dSAndroid Build Coastguard Worker GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2674*7304104dSAndroid Build Coastguard Worker if (symshdr == NULL)
2675*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get symbol table: %s\n"),
2676*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), elf_errmsg (-1));
2677*7304104dSAndroid Build Coastguard Worker else
2678*7304104dSAndroid Build Coastguard Worker {
2679*7304104dSAndroid Build Coastguard Worker if (symshdr->sh_type != SHT_SYMTAB)
2680*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2681*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section reference in sh_link is no symbol table\n"),
2682*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2683*7304104dSAndroid Build Coastguard Worker
2684*7304104dSAndroid Build Coastguard Worker if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM,
2685*7304104dSAndroid Build Coastguard Worker 1, EV_CURRENT))
2686*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2687*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': invalid symbol index in sh_info\n"),
2688*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2689*7304104dSAndroid Build Coastguard Worker
2690*7304104dSAndroid Build Coastguard Worker if (shdr->sh_flags != 0)
2691*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': sh_flags not zero\n"),
2692*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2693*7304104dSAndroid Build Coastguard Worker
2694*7304104dSAndroid Build Coastguard Worker GElf_Sym sym_data;
2695*7304104dSAndroid Build Coastguard Worker GElf_Sym *sym = gelf_getsym (elf_getdata (symscn, NULL), shdr->sh_info,
2696*7304104dSAndroid Build Coastguard Worker &sym_data);
2697*7304104dSAndroid Build Coastguard Worker if (sym == NULL)
2698*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2699*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': cannot get symbol for signature\n"),
2700*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2701*7304104dSAndroid Build Coastguard Worker else if (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name) == NULL)
2702*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2703*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': cannot get symbol name for signature\n"),
2704*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2705*7304104dSAndroid Build Coastguard Worker else if (strcmp (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name),
2706*7304104dSAndroid Build Coastguard Worker "") == 0)
2707*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2708*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': signature symbol cannot be empty string\n"),
2709*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2710*7304104dSAndroid Build Coastguard Worker
2711*7304104dSAndroid Build Coastguard Worker if (be_strict
2712*7304104dSAndroid Build Coastguard Worker && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT))
2713*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': sh_flags not set correctly\n"),
2714*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2715*7304104dSAndroid Build Coastguard Worker }
2716*7304104dSAndroid Build Coastguard Worker
2717*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2718*7304104dSAndroid Build Coastguard Worker if (data == NULL || data->d_buf == NULL)
2719*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get data: %s\n"),
2720*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), elf_errmsg (-1));
2721*7304104dSAndroid Build Coastguard Worker else
2722*7304104dSAndroid Build Coastguard Worker {
2723*7304104dSAndroid Build Coastguard Worker size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
2724*7304104dSAndroid Build Coastguard Worker size_t cnt;
2725*7304104dSAndroid Build Coastguard Worker Elf32_Word val;
2726*7304104dSAndroid Build Coastguard Worker
2727*7304104dSAndroid Build Coastguard Worker if (data->d_size % elsize != 0)
2728*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2729*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"),
2730*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2731*7304104dSAndroid Build Coastguard Worker
2732*7304104dSAndroid Build Coastguard Worker if (data->d_size < elsize)
2733*7304104dSAndroid Build Coastguard Worker {
2734*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2735*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section group without flags word\n"),
2736*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2737*7304104dSAndroid Build Coastguard Worker return;
2738*7304104dSAndroid Build Coastguard Worker }
2739*7304104dSAndroid Build Coastguard Worker else if (be_strict)
2740*7304104dSAndroid Build Coastguard Worker {
2741*7304104dSAndroid Build Coastguard Worker if (data->d_size < 2 * elsize)
2742*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2743*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section group without member\n"),
2744*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2745*7304104dSAndroid Build Coastguard Worker else if (data->d_size < 3 * elsize)
2746*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2747*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section group with only one member\n"),
2748*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2749*7304104dSAndroid Build Coastguard Worker }
2750*7304104dSAndroid Build Coastguard Worker
2751*7304104dSAndroid Build Coastguard Worker #if ALLOW_UNALIGNED
2752*7304104dSAndroid Build Coastguard Worker val = *((Elf32_Word *) data->d_buf);
2753*7304104dSAndroid Build Coastguard Worker #else
2754*7304104dSAndroid Build Coastguard Worker memcpy (&val, data->d_buf, elsize);
2755*7304104dSAndroid Build Coastguard Worker #endif
2756*7304104dSAndroid Build Coastguard Worker if ((val & ~GRP_COMDAT) != 0)
2757*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': unknown section group flags\n"),
2758*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2759*7304104dSAndroid Build Coastguard Worker
2760*7304104dSAndroid Build Coastguard Worker for (cnt = elsize; cnt + elsize <= data->d_size; cnt += elsize)
2761*7304104dSAndroid Build Coastguard Worker {
2762*7304104dSAndroid Build Coastguard Worker #if ALLOW_UNALIGNED
2763*7304104dSAndroid Build Coastguard Worker val = *((Elf32_Word *) ((char *) data->d_buf + cnt));
2764*7304104dSAndroid Build Coastguard Worker #else
2765*7304104dSAndroid Build Coastguard Worker memcpy (&val, (char *) data->d_buf + cnt, elsize);
2766*7304104dSAndroid Build Coastguard Worker #endif
2767*7304104dSAndroid Build Coastguard Worker
2768*7304104dSAndroid Build Coastguard Worker if (val > shnum)
2769*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2770*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section index %zu out of range\n"),
2771*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt / elsize);
2772*7304104dSAndroid Build Coastguard Worker else
2773*7304104dSAndroid Build Coastguard Worker {
2774*7304104dSAndroid Build Coastguard Worker GElf_Shdr refshdr_mem;
2775*7304104dSAndroid Build Coastguard Worker GElf_Shdr *refshdr = gelf_getshdr (elf_getscn (ebl->elf, val),
2776*7304104dSAndroid Build Coastguard Worker &refshdr_mem);
2777*7304104dSAndroid Build Coastguard Worker if (refshdr == NULL)
2778*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2779*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': cannot get section header for element %zu: %s\n"),
2780*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt / elsize,
2781*7304104dSAndroid Build Coastguard Worker elf_errmsg (-1));
2782*7304104dSAndroid Build Coastguard Worker else
2783*7304104dSAndroid Build Coastguard Worker {
2784*7304104dSAndroid Build Coastguard Worker if (refshdr->sh_type == SHT_GROUP)
2785*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2786*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': section group contains another group [%2d] '%s'\n"),
2787*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
2788*7304104dSAndroid Build Coastguard Worker val, section_name (ebl, val));
2789*7304104dSAndroid Build Coastguard Worker
2790*7304104dSAndroid Build Coastguard Worker if ((refshdr->sh_flags & SHF_GROUP) == 0)
2791*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2792*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': element %zu references section [%2d] '%s' without SHF_GROUP flag set\n"),
2793*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt / elsize,
2794*7304104dSAndroid Build Coastguard Worker val, section_name (ebl, val));
2795*7304104dSAndroid Build Coastguard Worker }
2796*7304104dSAndroid Build Coastguard Worker
2797*7304104dSAndroid Build Coastguard Worker if (val < shnum && ++scnref[val] == 2)
2798*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2799*7304104dSAndroid Build Coastguard Worker section [%2d] '%s' is contained in more than one section group\n"),
2800*7304104dSAndroid Build Coastguard Worker val, section_name (ebl, val));
2801*7304104dSAndroid Build Coastguard Worker }
2802*7304104dSAndroid Build Coastguard Worker }
2803*7304104dSAndroid Build Coastguard Worker }
2804*7304104dSAndroid Build Coastguard Worker }
2805*7304104dSAndroid Build Coastguard Worker
2806*7304104dSAndroid Build Coastguard Worker
2807*7304104dSAndroid Build Coastguard Worker static const char *
section_flags_string(GElf_Word flags,char * buf,size_t len)2808*7304104dSAndroid Build Coastguard Worker section_flags_string (GElf_Word flags, char *buf, size_t len)
2809*7304104dSAndroid Build Coastguard Worker {
2810*7304104dSAndroid Build Coastguard Worker if (flags == 0)
2811*7304104dSAndroid Build Coastguard Worker return "none";
2812*7304104dSAndroid Build Coastguard Worker
2813*7304104dSAndroid Build Coastguard Worker static const struct
2814*7304104dSAndroid Build Coastguard Worker {
2815*7304104dSAndroid Build Coastguard Worker GElf_Word flag;
2816*7304104dSAndroid Build Coastguard Worker const char *name;
2817*7304104dSAndroid Build Coastguard Worker } known_flags[] =
2818*7304104dSAndroid Build Coastguard Worker {
2819*7304104dSAndroid Build Coastguard Worker #define NEWFLAG(name) { SHF_##name, #name }
2820*7304104dSAndroid Build Coastguard Worker NEWFLAG (WRITE),
2821*7304104dSAndroid Build Coastguard Worker NEWFLAG (ALLOC),
2822*7304104dSAndroid Build Coastguard Worker NEWFLAG (EXECINSTR),
2823*7304104dSAndroid Build Coastguard Worker NEWFLAG (MERGE),
2824*7304104dSAndroid Build Coastguard Worker NEWFLAG (STRINGS),
2825*7304104dSAndroid Build Coastguard Worker NEWFLAG (INFO_LINK),
2826*7304104dSAndroid Build Coastguard Worker NEWFLAG (LINK_ORDER),
2827*7304104dSAndroid Build Coastguard Worker NEWFLAG (OS_NONCONFORMING),
2828*7304104dSAndroid Build Coastguard Worker NEWFLAG (GROUP),
2829*7304104dSAndroid Build Coastguard Worker NEWFLAG (TLS),
2830*7304104dSAndroid Build Coastguard Worker NEWFLAG (COMPRESSED),
2831*7304104dSAndroid Build Coastguard Worker NEWFLAG (GNU_RETAIN),
2832*7304104dSAndroid Build Coastguard Worker NEWFLAG (ORDERED),
2833*7304104dSAndroid Build Coastguard Worker NEWFLAG (EXCLUDE)
2834*7304104dSAndroid Build Coastguard Worker };
2835*7304104dSAndroid Build Coastguard Worker #undef NEWFLAG
2836*7304104dSAndroid Build Coastguard Worker const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
2837*7304104dSAndroid Build Coastguard Worker
2838*7304104dSAndroid Build Coastguard Worker char *cp = buf;
2839*7304104dSAndroid Build Coastguard Worker
2840*7304104dSAndroid Build Coastguard Worker for (size_t cnt = 0; cnt < nknown_flags; ++cnt)
2841*7304104dSAndroid Build Coastguard Worker if (flags & known_flags[cnt].flag)
2842*7304104dSAndroid Build Coastguard Worker {
2843*7304104dSAndroid Build Coastguard Worker if (cp != buf && len > 1)
2844*7304104dSAndroid Build Coastguard Worker {
2845*7304104dSAndroid Build Coastguard Worker *cp++ = '|';
2846*7304104dSAndroid Build Coastguard Worker --len;
2847*7304104dSAndroid Build Coastguard Worker }
2848*7304104dSAndroid Build Coastguard Worker
2849*7304104dSAndroid Build Coastguard Worker size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name));
2850*7304104dSAndroid Build Coastguard Worker cp = mempcpy (cp, known_flags[cnt].name, ncopy);
2851*7304104dSAndroid Build Coastguard Worker len -= ncopy;
2852*7304104dSAndroid Build Coastguard Worker
2853*7304104dSAndroid Build Coastguard Worker flags ^= known_flags[cnt].flag;
2854*7304104dSAndroid Build Coastguard Worker }
2855*7304104dSAndroid Build Coastguard Worker
2856*7304104dSAndroid Build Coastguard Worker if (flags != 0 || cp == buf)
2857*7304104dSAndroid Build Coastguard Worker {
2858*7304104dSAndroid Build Coastguard Worker int r = snprintf (cp, len - 1, "%s%" PRIx64,
2859*7304104dSAndroid Build Coastguard Worker (cp == buf) ? "" : "|", (uint64_t) flags);
2860*7304104dSAndroid Build Coastguard Worker if (r > 0)
2861*7304104dSAndroid Build Coastguard Worker cp += r;
2862*7304104dSAndroid Build Coastguard Worker }
2863*7304104dSAndroid Build Coastguard Worker *cp = '\0';
2864*7304104dSAndroid Build Coastguard Worker
2865*7304104dSAndroid Build Coastguard Worker return buf;
2866*7304104dSAndroid Build Coastguard Worker }
2867*7304104dSAndroid Build Coastguard Worker
2868*7304104dSAndroid Build Coastguard Worker
2869*7304104dSAndroid Build Coastguard Worker static int
has_copy_reloc(Ebl * ebl,unsigned int symscnndx,unsigned int symndx)2870*7304104dSAndroid Build Coastguard Worker has_copy_reloc (Ebl *ebl, unsigned int symscnndx, unsigned int symndx)
2871*7304104dSAndroid Build Coastguard Worker {
2872*7304104dSAndroid Build Coastguard Worker /* First find the relocation section for the symbol table. */
2873*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = NULL;
2874*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
2875*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = NULL;
2876*7304104dSAndroid Build Coastguard Worker while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2877*7304104dSAndroid Build Coastguard Worker {
2878*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (scn, &shdr_mem);
2879*7304104dSAndroid Build Coastguard Worker if (shdr != NULL
2880*7304104dSAndroid Build Coastguard Worker && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
2881*7304104dSAndroid Build Coastguard Worker && shdr->sh_link == symscnndx)
2882*7304104dSAndroid Build Coastguard Worker /* Found the section. */
2883*7304104dSAndroid Build Coastguard Worker break;
2884*7304104dSAndroid Build Coastguard Worker }
2885*7304104dSAndroid Build Coastguard Worker
2886*7304104dSAndroid Build Coastguard Worker if (scn == NULL)
2887*7304104dSAndroid Build Coastguard Worker return 0;
2888*7304104dSAndroid Build Coastguard Worker
2889*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (scn, NULL);
2890*7304104dSAndroid Build Coastguard Worker if (data == NULL || shdr->sh_entsize == 0)
2891*7304104dSAndroid Build Coastguard Worker return 0;
2892*7304104dSAndroid Build Coastguard Worker
2893*7304104dSAndroid Build Coastguard Worker if (shdr->sh_type == SHT_REL)
2894*7304104dSAndroid Build Coastguard Worker for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2895*7304104dSAndroid Build Coastguard Worker {
2896*7304104dSAndroid Build Coastguard Worker GElf_Rel rel_mem;
2897*7304104dSAndroid Build Coastguard Worker GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
2898*7304104dSAndroid Build Coastguard Worker if (rel == NULL)
2899*7304104dSAndroid Build Coastguard Worker continue;
2900*7304104dSAndroid Build Coastguard Worker
2901*7304104dSAndroid Build Coastguard Worker if (GELF_R_SYM (rel->r_info) == symndx
2902*7304104dSAndroid Build Coastguard Worker && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info)))
2903*7304104dSAndroid Build Coastguard Worker return 1;
2904*7304104dSAndroid Build Coastguard Worker }
2905*7304104dSAndroid Build Coastguard Worker else
2906*7304104dSAndroid Build Coastguard Worker for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2907*7304104dSAndroid Build Coastguard Worker {
2908*7304104dSAndroid Build Coastguard Worker GElf_Rela rela_mem;
2909*7304104dSAndroid Build Coastguard Worker GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
2910*7304104dSAndroid Build Coastguard Worker if (rela == NULL)
2911*7304104dSAndroid Build Coastguard Worker continue;
2912*7304104dSAndroid Build Coastguard Worker
2913*7304104dSAndroid Build Coastguard Worker if (GELF_R_SYM (rela->r_info) == symndx
2914*7304104dSAndroid Build Coastguard Worker && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info)))
2915*7304104dSAndroid Build Coastguard Worker return 1;
2916*7304104dSAndroid Build Coastguard Worker }
2917*7304104dSAndroid Build Coastguard Worker
2918*7304104dSAndroid Build Coastguard Worker return 0;
2919*7304104dSAndroid Build Coastguard Worker }
2920*7304104dSAndroid Build Coastguard Worker
2921*7304104dSAndroid Build Coastguard Worker
2922*7304104dSAndroid Build Coastguard Worker static int
in_nobits_scn(Ebl * ebl,unsigned int shndx)2923*7304104dSAndroid Build Coastguard Worker in_nobits_scn (Ebl *ebl, unsigned int shndx)
2924*7304104dSAndroid Build Coastguard Worker {
2925*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
2926*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, shndx), &shdr_mem);
2927*7304104dSAndroid Build Coastguard Worker return shdr != NULL && shdr->sh_type == SHT_NOBITS;
2928*7304104dSAndroid Build Coastguard Worker }
2929*7304104dSAndroid Build Coastguard Worker
2930*7304104dSAndroid Build Coastguard Worker
2931*7304104dSAndroid Build Coastguard Worker static struct version_namelist
2932*7304104dSAndroid Build Coastguard Worker {
2933*7304104dSAndroid Build Coastguard Worker const char *objname;
2934*7304104dSAndroid Build Coastguard Worker const char *name;
2935*7304104dSAndroid Build Coastguard Worker GElf_Versym ndx;
2936*7304104dSAndroid Build Coastguard Worker enum { ver_def, ver_need } type;
2937*7304104dSAndroid Build Coastguard Worker struct version_namelist *next;
2938*7304104dSAndroid Build Coastguard Worker } *version_namelist;
2939*7304104dSAndroid Build Coastguard Worker
2940*7304104dSAndroid Build Coastguard Worker
2941*7304104dSAndroid Build Coastguard Worker static int
add_version(const char * objname,const char * name,GElf_Versym ndx,int type)2942*7304104dSAndroid Build Coastguard Worker add_version (const char *objname, const char *name, GElf_Versym ndx, int type)
2943*7304104dSAndroid Build Coastguard Worker {
2944*7304104dSAndroid Build Coastguard Worker /* Check that there are no duplications. */
2945*7304104dSAndroid Build Coastguard Worker struct version_namelist *nlp = version_namelist;
2946*7304104dSAndroid Build Coastguard Worker while (nlp != NULL)
2947*7304104dSAndroid Build Coastguard Worker {
2948*7304104dSAndroid Build Coastguard Worker if (((nlp->objname == NULL && objname == NULL)
2949*7304104dSAndroid Build Coastguard Worker || (nlp->objname != NULL && objname != NULL
2950*7304104dSAndroid Build Coastguard Worker && strcmp (nlp->objname, objname) == 0))
2951*7304104dSAndroid Build Coastguard Worker && strcmp (nlp->name, name) == 0)
2952*7304104dSAndroid Build Coastguard Worker return nlp->type == ver_def ? 1 : -1;
2953*7304104dSAndroid Build Coastguard Worker nlp = nlp->next;
2954*7304104dSAndroid Build Coastguard Worker }
2955*7304104dSAndroid Build Coastguard Worker
2956*7304104dSAndroid Build Coastguard Worker nlp = xmalloc (sizeof (*nlp));
2957*7304104dSAndroid Build Coastguard Worker nlp->objname = objname;
2958*7304104dSAndroid Build Coastguard Worker nlp->name = name;
2959*7304104dSAndroid Build Coastguard Worker nlp->ndx = ndx;
2960*7304104dSAndroid Build Coastguard Worker nlp->type = type;
2961*7304104dSAndroid Build Coastguard Worker nlp->next = version_namelist;
2962*7304104dSAndroid Build Coastguard Worker version_namelist = nlp;
2963*7304104dSAndroid Build Coastguard Worker
2964*7304104dSAndroid Build Coastguard Worker return 0;
2965*7304104dSAndroid Build Coastguard Worker }
2966*7304104dSAndroid Build Coastguard Worker
2967*7304104dSAndroid Build Coastguard Worker
2968*7304104dSAndroid Build Coastguard Worker static void
check_versym(Ebl * ebl,int idx)2969*7304104dSAndroid Build Coastguard Worker check_versym (Ebl *ebl, int idx)
2970*7304104dSAndroid Build Coastguard Worker {
2971*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = elf_getscn (ebl->elf, idx);
2972*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
2973*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2974*7304104dSAndroid Build Coastguard Worker if (shdr == NULL)
2975*7304104dSAndroid Build Coastguard Worker /* The error has already been reported. */
2976*7304104dSAndroid Build Coastguard Worker return;
2977*7304104dSAndroid Build Coastguard Worker
2978*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (scn, NULL);
2979*7304104dSAndroid Build Coastguard Worker if (data == NULL)
2980*7304104dSAndroid Build Coastguard Worker {
2981*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
2982*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
2983*7304104dSAndroid Build Coastguard Worker return;
2984*7304104dSAndroid Build Coastguard Worker }
2985*7304104dSAndroid Build Coastguard Worker
2986*7304104dSAndroid Build Coastguard Worker Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2987*7304104dSAndroid Build Coastguard Worker GElf_Shdr symshdr_mem;
2988*7304104dSAndroid Build Coastguard Worker GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2989*7304104dSAndroid Build Coastguard Worker if (symshdr == NULL)
2990*7304104dSAndroid Build Coastguard Worker /* The error has already been reported. */
2991*7304104dSAndroid Build Coastguard Worker return;
2992*7304104dSAndroid Build Coastguard Worker
2993*7304104dSAndroid Build Coastguard Worker if (symshdr->sh_type != SHT_DYNSYM)
2994*7304104dSAndroid Build Coastguard Worker {
2995*7304104dSAndroid Build Coastguard Worker ERROR (_("\
2996*7304104dSAndroid Build Coastguard Worker section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"),
2997*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
2998*7304104dSAndroid Build Coastguard Worker shdr->sh_link, section_name (ebl, shdr->sh_link));
2999*7304104dSAndroid Build Coastguard Worker return;
3000*7304104dSAndroid Build Coastguard Worker }
3001*7304104dSAndroid Build Coastguard Worker
3002*7304104dSAndroid Build Coastguard Worker /* The number of elements in the version symbol table must be the
3003*7304104dSAndroid Build Coastguard Worker same as the number of symbols. */
3004*7304104dSAndroid Build Coastguard Worker if (shdr->sh_entsize != 0 && symshdr->sh_entsize != 0
3005*7304104dSAndroid Build Coastguard Worker && (shdr->sh_size / shdr->sh_entsize
3006*7304104dSAndroid Build Coastguard Worker != symshdr->sh_size / symshdr->sh_entsize))
3007*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3008*7304104dSAndroid Build Coastguard Worker section [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"),
3009*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx),
3010*7304104dSAndroid Build Coastguard Worker shdr->sh_link, section_name (ebl, shdr->sh_link));
3011*7304104dSAndroid Build Coastguard Worker
3012*7304104dSAndroid Build Coastguard Worker Elf_Data *symdata = elf_getdata (symscn, NULL);
3013*7304104dSAndroid Build Coastguard Worker if (symdata == NULL || shdr->sh_entsize == 0)
3014*7304104dSAndroid Build Coastguard Worker /* The error has already been reported. */
3015*7304104dSAndroid Build Coastguard Worker return;
3016*7304104dSAndroid Build Coastguard Worker
3017*7304104dSAndroid Build Coastguard Worker for (int cnt = 1; (size_t) cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
3018*7304104dSAndroid Build Coastguard Worker {
3019*7304104dSAndroid Build Coastguard Worker GElf_Versym versym_mem;
3020*7304104dSAndroid Build Coastguard Worker GElf_Versym *versym = gelf_getversym (data, cnt, &versym_mem);
3021*7304104dSAndroid Build Coastguard Worker if (versym == NULL)
3022*7304104dSAndroid Build Coastguard Worker {
3023*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3024*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %d: cannot read version data\n"),
3025*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3026*7304104dSAndroid Build Coastguard Worker break;
3027*7304104dSAndroid Build Coastguard Worker }
3028*7304104dSAndroid Build Coastguard Worker
3029*7304104dSAndroid Build Coastguard Worker GElf_Sym sym_mem;
3030*7304104dSAndroid Build Coastguard Worker GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_mem);
3031*7304104dSAndroid Build Coastguard Worker if (sym == NULL)
3032*7304104dSAndroid Build Coastguard Worker /* Already reported elsewhere. */
3033*7304104dSAndroid Build Coastguard Worker continue;
3034*7304104dSAndroid Build Coastguard Worker
3035*7304104dSAndroid Build Coastguard Worker if (*versym == VER_NDX_GLOBAL)
3036*7304104dSAndroid Build Coastguard Worker {
3037*7304104dSAndroid Build Coastguard Worker /* Global symbol. Make sure it is not defined as local. */
3038*7304104dSAndroid Build Coastguard Worker if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
3039*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3040*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %d: local symbol with global scope\n"),
3041*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3042*7304104dSAndroid Build Coastguard Worker }
3043*7304104dSAndroid Build Coastguard Worker else if (*versym != VER_NDX_LOCAL)
3044*7304104dSAndroid Build Coastguard Worker {
3045*7304104dSAndroid Build Coastguard Worker /* Versioned symbol. Make sure it is not defined as local. */
3046*7304104dSAndroid Build Coastguard Worker if (!gnuld && GELF_ST_BIND (sym->st_info) == STB_LOCAL)
3047*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3048*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %d: local symbol with version\n"),
3049*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3050*7304104dSAndroid Build Coastguard Worker
3051*7304104dSAndroid Build Coastguard Worker /* Look through the list of defined versions and locate the
3052*7304104dSAndroid Build Coastguard Worker index we need for this symbol. */
3053*7304104dSAndroid Build Coastguard Worker struct version_namelist *runp = version_namelist;
3054*7304104dSAndroid Build Coastguard Worker while (runp != NULL)
3055*7304104dSAndroid Build Coastguard Worker if (runp->ndx == (*versym & (GElf_Versym) 0x7fff))
3056*7304104dSAndroid Build Coastguard Worker break;
3057*7304104dSAndroid Build Coastguard Worker else
3058*7304104dSAndroid Build Coastguard Worker runp = runp->next;
3059*7304104dSAndroid Build Coastguard Worker
3060*7304104dSAndroid Build Coastguard Worker if (runp == NULL)
3061*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3062*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %d: invalid version index %d\n"),
3063*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, (int) *versym);
3064*7304104dSAndroid Build Coastguard Worker else if (sym->st_shndx == SHN_UNDEF
3065*7304104dSAndroid Build Coastguard Worker && runp->type == ver_def)
3066*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3067*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %d: version index %d is for defined version\n"),
3068*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, (int) *versym);
3069*7304104dSAndroid Build Coastguard Worker else if (sym->st_shndx != SHN_UNDEF
3070*7304104dSAndroid Build Coastguard Worker && runp->type == ver_need)
3071*7304104dSAndroid Build Coastguard Worker {
3072*7304104dSAndroid Build Coastguard Worker /* Unless this symbol has a copy relocation associated
3073*7304104dSAndroid Build Coastguard Worker this must not happen. */
3074*7304104dSAndroid Build Coastguard Worker if (!has_copy_reloc (ebl, shdr->sh_link, cnt)
3075*7304104dSAndroid Build Coastguard Worker && !in_nobits_scn (ebl, sym->st_shndx))
3076*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3077*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': symbol %d: version index %d is for requested version\n"),
3078*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, (int) *versym);
3079*7304104dSAndroid Build Coastguard Worker }
3080*7304104dSAndroid Build Coastguard Worker }
3081*7304104dSAndroid Build Coastguard Worker }
3082*7304104dSAndroid Build Coastguard Worker }
3083*7304104dSAndroid Build Coastguard Worker
3084*7304104dSAndroid Build Coastguard Worker
3085*7304104dSAndroid Build Coastguard Worker static int
unknown_dependency_p(Elf * elf,const char * fname)3086*7304104dSAndroid Build Coastguard Worker unknown_dependency_p (Elf *elf, const char *fname)
3087*7304104dSAndroid Build Coastguard Worker {
3088*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr_mem;
3089*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr = NULL;
3090*7304104dSAndroid Build Coastguard Worker
3091*7304104dSAndroid Build Coastguard Worker unsigned int i;
3092*7304104dSAndroid Build Coastguard Worker for (i = 0; i < phnum; ++i)
3093*7304104dSAndroid Build Coastguard Worker if ((phdr = gelf_getphdr (elf, i, &phdr_mem)) != NULL
3094*7304104dSAndroid Build Coastguard Worker && phdr->p_type == PT_DYNAMIC)
3095*7304104dSAndroid Build Coastguard Worker break;
3096*7304104dSAndroid Build Coastguard Worker
3097*7304104dSAndroid Build Coastguard Worker if (i == phnum)
3098*7304104dSAndroid Build Coastguard Worker return 1;
3099*7304104dSAndroid Build Coastguard Worker assert (phdr != NULL);
3100*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
3101*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
3102*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3103*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (scn, NULL);
3104*7304104dSAndroid Build Coastguard Worker if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC
3105*7304104dSAndroid Build Coastguard Worker && data != NULL && shdr->sh_entsize != 0)
3106*7304104dSAndroid Build Coastguard Worker for (size_t j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
3107*7304104dSAndroid Build Coastguard Worker {
3108*7304104dSAndroid Build Coastguard Worker GElf_Dyn dyn_mem;
3109*7304104dSAndroid Build Coastguard Worker GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
3110*7304104dSAndroid Build Coastguard Worker if (dyn != NULL && dyn->d_tag == DT_NEEDED)
3111*7304104dSAndroid Build Coastguard Worker {
3112*7304104dSAndroid Build Coastguard Worker const char *str = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
3113*7304104dSAndroid Build Coastguard Worker if (str != NULL && strcmp (str, fname) == 0)
3114*7304104dSAndroid Build Coastguard Worker /* Found it. */
3115*7304104dSAndroid Build Coastguard Worker return 0;
3116*7304104dSAndroid Build Coastguard Worker }
3117*7304104dSAndroid Build Coastguard Worker }
3118*7304104dSAndroid Build Coastguard Worker
3119*7304104dSAndroid Build Coastguard Worker return 1;
3120*7304104dSAndroid Build Coastguard Worker }
3121*7304104dSAndroid Build Coastguard Worker
3122*7304104dSAndroid Build Coastguard Worker
3123*7304104dSAndroid Build Coastguard Worker static unsigned int nverneed;
3124*7304104dSAndroid Build Coastguard Worker
3125*7304104dSAndroid Build Coastguard Worker static void
check_verneed(Ebl * ebl,GElf_Shdr * shdr,int idx)3126*7304104dSAndroid Build Coastguard Worker check_verneed (Ebl *ebl, GElf_Shdr *shdr, int idx)
3127*7304104dSAndroid Build Coastguard Worker {
3128*7304104dSAndroid Build Coastguard Worker if (++nverneed == 2)
3129*7304104dSAndroid Build Coastguard Worker ERROR (_("more than one version reference section present\n"));
3130*7304104dSAndroid Build Coastguard Worker
3131*7304104dSAndroid Build Coastguard Worker GElf_Shdr strshdr_mem;
3132*7304104dSAndroid Build Coastguard Worker GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
3133*7304104dSAndroid Build Coastguard Worker &strshdr_mem);
3134*7304104dSAndroid Build Coastguard Worker if (strshdr == NULL)
3135*7304104dSAndroid Build Coastguard Worker return;
3136*7304104dSAndroid Build Coastguard Worker if (strshdr->sh_type != SHT_STRTAB)
3137*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3138*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': sh_link does not link to string table\n"),
3139*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
3140*7304104dSAndroid Build Coastguard Worker
3141*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
3142*7304104dSAndroid Build Coastguard Worker if (data == NULL)
3143*7304104dSAndroid Build Coastguard Worker {
3144*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
3145*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
3146*7304104dSAndroid Build Coastguard Worker return;
3147*7304104dSAndroid Build Coastguard Worker }
3148*7304104dSAndroid Build Coastguard Worker unsigned int offset = 0;
3149*7304104dSAndroid Build Coastguard Worker for (Elf64_Word cnt = shdr->sh_info; cnt > 0; )
3150*7304104dSAndroid Build Coastguard Worker {
3151*7304104dSAndroid Build Coastguard Worker cnt--;
3152*7304104dSAndroid Build Coastguard Worker
3153*7304104dSAndroid Build Coastguard Worker /* Get the data at the next offset. */
3154*7304104dSAndroid Build Coastguard Worker GElf_Verneed needmem;
3155*7304104dSAndroid Build Coastguard Worker GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
3156*7304104dSAndroid Build Coastguard Worker if (need == NULL)
3157*7304104dSAndroid Build Coastguard Worker break;
3158*7304104dSAndroid Build Coastguard Worker
3159*7304104dSAndroid Build Coastguard Worker unsigned int auxoffset = offset + need->vn_aux;
3160*7304104dSAndroid Build Coastguard Worker
3161*7304104dSAndroid Build Coastguard Worker if (need->vn_version != EV_CURRENT)
3162*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3163*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has wrong version %d\n"),
3164*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, (int) need->vn_version);
3165*7304104dSAndroid Build Coastguard Worker
3166*7304104dSAndroid Build Coastguard Worker if (need->vn_cnt > 0 && need->vn_aux < gelf_fsize (ebl->elf, ELF_T_VNEED,
3167*7304104dSAndroid Build Coastguard Worker 1, EV_CURRENT))
3168*7304104dSAndroid Build Coastguard Worker {
3169*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3170*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
3171*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3172*7304104dSAndroid Build Coastguard Worker break;
3173*7304104dSAndroid Build Coastguard Worker }
3174*7304104dSAndroid Build Coastguard Worker
3175*7304104dSAndroid Build Coastguard Worker const char *libname = elf_strptr (ebl->elf, shdr->sh_link,
3176*7304104dSAndroid Build Coastguard Worker need->vn_file);
3177*7304104dSAndroid Build Coastguard Worker if (libname == NULL)
3178*7304104dSAndroid Build Coastguard Worker {
3179*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3180*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has invalid file reference\n"),
3181*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3182*7304104dSAndroid Build Coastguard Worker goto next_need;
3183*7304104dSAndroid Build Coastguard Worker }
3184*7304104dSAndroid Build Coastguard Worker
3185*7304104dSAndroid Build Coastguard Worker /* Check that there is a DT_NEEDED entry for the referenced library. */
3186*7304104dSAndroid Build Coastguard Worker if (unknown_dependency_p (ebl->elf, libname))
3187*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3188*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d references unknown dependency\n"),
3189*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3190*7304104dSAndroid Build Coastguard Worker
3191*7304104dSAndroid Build Coastguard Worker for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
3192*7304104dSAndroid Build Coastguard Worker {
3193*7304104dSAndroid Build Coastguard Worker GElf_Vernaux auxmem;
3194*7304104dSAndroid Build Coastguard Worker GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
3195*7304104dSAndroid Build Coastguard Worker if (aux == NULL)
3196*7304104dSAndroid Build Coastguard Worker break;
3197*7304104dSAndroid Build Coastguard Worker
3198*7304104dSAndroid Build Coastguard Worker if ((aux->vna_flags & ~VER_FLG_WEAK) != 0)
3199*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3200*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"),
3201*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
3202*7304104dSAndroid Build Coastguard Worker
3203*7304104dSAndroid Build Coastguard Worker const char *verstr = elf_strptr (ebl->elf, shdr->sh_link,
3204*7304104dSAndroid Build Coastguard Worker aux->vna_name);
3205*7304104dSAndroid Build Coastguard Worker if (verstr == NULL)
3206*7304104dSAndroid Build Coastguard Worker {
3207*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3208*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': auxiliary entry %d of entry %d has invalid name reference\n"),
3209*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
3210*7304104dSAndroid Build Coastguard Worker break;
3211*7304104dSAndroid Build Coastguard Worker }
3212*7304104dSAndroid Build Coastguard Worker else
3213*7304104dSAndroid Build Coastguard Worker {
3214*7304104dSAndroid Build Coastguard Worker GElf_Word hashval = elf_hash (verstr);
3215*7304104dSAndroid Build Coastguard Worker if (hashval != aux->vna_hash)
3216*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3217*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: %#x, expected %#x\n"),
3218*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), need->vn_cnt - cnt2,
3219*7304104dSAndroid Build Coastguard Worker cnt, (int) hashval, (int) aux->vna_hash);
3220*7304104dSAndroid Build Coastguard Worker
3221*7304104dSAndroid Build Coastguard Worker int res = add_version (libname, verstr, aux->vna_other,
3222*7304104dSAndroid Build Coastguard Worker ver_need);
3223*7304104dSAndroid Build Coastguard Worker if (unlikely (res !=0))
3224*7304104dSAndroid Build Coastguard Worker {
3225*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3226*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version name '%s'\n"),
3227*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), need->vn_cnt - cnt2,
3228*7304104dSAndroid Build Coastguard Worker cnt, verstr);
3229*7304104dSAndroid Build Coastguard Worker }
3230*7304104dSAndroid Build Coastguard Worker }
3231*7304104dSAndroid Build Coastguard Worker
3232*7304104dSAndroid Build Coastguard Worker if ((aux->vna_next != 0 || cnt2 > 0)
3233*7304104dSAndroid Build Coastguard Worker && aux->vna_next < gelf_fsize (ebl->elf, ELF_T_VNAUX, 1,
3234*7304104dSAndroid Build Coastguard Worker EV_CURRENT))
3235*7304104dSAndroid Build Coastguard Worker {
3236*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3237*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"),
3238*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
3239*7304104dSAndroid Build Coastguard Worker break;
3240*7304104dSAndroid Build Coastguard Worker }
3241*7304104dSAndroid Build Coastguard Worker
3242*7304104dSAndroid Build Coastguard Worker auxoffset += MAX (aux->vna_next,
3243*7304104dSAndroid Build Coastguard Worker gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, EV_CURRENT));
3244*7304104dSAndroid Build Coastguard Worker }
3245*7304104dSAndroid Build Coastguard Worker
3246*7304104dSAndroid Build Coastguard Worker /* Find the next offset. */
3247*7304104dSAndroid Build Coastguard Worker next_need:
3248*7304104dSAndroid Build Coastguard Worker offset += need->vn_next;
3249*7304104dSAndroid Build Coastguard Worker
3250*7304104dSAndroid Build Coastguard Worker if ((need->vn_next != 0 || cnt > 0)
3251*7304104dSAndroid Build Coastguard Worker && offset < auxoffset)
3252*7304104dSAndroid Build Coastguard Worker {
3253*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3254*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has invalid offset to next entry\n"),
3255*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3256*7304104dSAndroid Build Coastguard Worker break;
3257*7304104dSAndroid Build Coastguard Worker }
3258*7304104dSAndroid Build Coastguard Worker
3259*7304104dSAndroid Build Coastguard Worker if (need->vn_next == 0 && cnt > 0)
3260*7304104dSAndroid Build Coastguard Worker {
3261*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3262*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says there are more entries\n"),
3263*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3264*7304104dSAndroid Build Coastguard Worker break;
3265*7304104dSAndroid Build Coastguard Worker }
3266*7304104dSAndroid Build Coastguard Worker }
3267*7304104dSAndroid Build Coastguard Worker }
3268*7304104dSAndroid Build Coastguard Worker
3269*7304104dSAndroid Build Coastguard Worker
3270*7304104dSAndroid Build Coastguard Worker static unsigned int nverdef;
3271*7304104dSAndroid Build Coastguard Worker
3272*7304104dSAndroid Build Coastguard Worker static void
check_verdef(Ebl * ebl,GElf_Shdr * shdr,int idx)3273*7304104dSAndroid Build Coastguard Worker check_verdef (Ebl *ebl, GElf_Shdr *shdr, int idx)
3274*7304104dSAndroid Build Coastguard Worker {
3275*7304104dSAndroid Build Coastguard Worker if (++nverdef == 2)
3276*7304104dSAndroid Build Coastguard Worker ERROR (_("more than one version definition section present\n"));
3277*7304104dSAndroid Build Coastguard Worker
3278*7304104dSAndroid Build Coastguard Worker GElf_Shdr strshdr_mem;
3279*7304104dSAndroid Build Coastguard Worker GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
3280*7304104dSAndroid Build Coastguard Worker &strshdr_mem);
3281*7304104dSAndroid Build Coastguard Worker if (strshdr == NULL)
3282*7304104dSAndroid Build Coastguard Worker return;
3283*7304104dSAndroid Build Coastguard Worker if (strshdr->sh_type != SHT_STRTAB)
3284*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3285*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': sh_link does not link to string table\n"),
3286*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
3287*7304104dSAndroid Build Coastguard Worker
3288*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
3289*7304104dSAndroid Build Coastguard Worker if (data == NULL)
3290*7304104dSAndroid Build Coastguard Worker {
3291*7304104dSAndroid Build Coastguard Worker no_data:
3292*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
3293*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
3294*7304104dSAndroid Build Coastguard Worker return;
3295*7304104dSAndroid Build Coastguard Worker }
3296*7304104dSAndroid Build Coastguard Worker
3297*7304104dSAndroid Build Coastguard Worker /* Iterate over all version definition entries. We check that there
3298*7304104dSAndroid Build Coastguard Worker is a BASE entry and that each index is unique. To do the later
3299*7304104dSAndroid Build Coastguard Worker we collection the information in a list which is later
3300*7304104dSAndroid Build Coastguard Worker examined. */
3301*7304104dSAndroid Build Coastguard Worker struct namelist
3302*7304104dSAndroid Build Coastguard Worker {
3303*7304104dSAndroid Build Coastguard Worker const char *name;
3304*7304104dSAndroid Build Coastguard Worker struct namelist *next;
3305*7304104dSAndroid Build Coastguard Worker } *namelist = NULL;
3306*7304104dSAndroid Build Coastguard Worker struct namelist *refnamelist = NULL;
3307*7304104dSAndroid Build Coastguard Worker
3308*7304104dSAndroid Build Coastguard Worker bool has_base = false;
3309*7304104dSAndroid Build Coastguard Worker unsigned int offset = 0;
3310*7304104dSAndroid Build Coastguard Worker for (Elf64_Word cnt = shdr->sh_info; cnt > 0; )
3311*7304104dSAndroid Build Coastguard Worker {
3312*7304104dSAndroid Build Coastguard Worker cnt--;
3313*7304104dSAndroid Build Coastguard Worker
3314*7304104dSAndroid Build Coastguard Worker /* Get the data at the next offset. */
3315*7304104dSAndroid Build Coastguard Worker GElf_Verdef defmem;
3316*7304104dSAndroid Build Coastguard Worker GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
3317*7304104dSAndroid Build Coastguard Worker if (def == NULL)
3318*7304104dSAndroid Build Coastguard Worker goto no_data;
3319*7304104dSAndroid Build Coastguard Worker
3320*7304104dSAndroid Build Coastguard Worker if ((def->vd_flags & VER_FLG_BASE) != 0)
3321*7304104dSAndroid Build Coastguard Worker {
3322*7304104dSAndroid Build Coastguard Worker if (has_base)
3323*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3324*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': more than one BASE definition\n"),
3325*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
3326*7304104dSAndroid Build Coastguard Worker if (def->vd_ndx != VER_NDX_GLOBAL)
3327*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3328*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"),
3329*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
3330*7304104dSAndroid Build Coastguard Worker has_base = true;
3331*7304104dSAndroid Build Coastguard Worker }
3332*7304104dSAndroid Build Coastguard Worker if ((def->vd_flags & ~(VER_FLG_BASE|VER_FLG_WEAK)) != 0)
3333*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3334*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has unknown flag\n"),
3335*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3336*7304104dSAndroid Build Coastguard Worker
3337*7304104dSAndroid Build Coastguard Worker if (def->vd_version != EV_CURRENT)
3338*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3339*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has wrong version %d\n"),
3340*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, (int) def->vd_version);
3341*7304104dSAndroid Build Coastguard Worker
3342*7304104dSAndroid Build Coastguard Worker if (def->vd_cnt > 0 && def->vd_aux < gelf_fsize (ebl->elf, ELF_T_VDEF,
3343*7304104dSAndroid Build Coastguard Worker 1, EV_CURRENT))
3344*7304104dSAndroid Build Coastguard Worker {
3345*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3346*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
3347*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3348*7304104dSAndroid Build Coastguard Worker break;
3349*7304104dSAndroid Build Coastguard Worker }
3350*7304104dSAndroid Build Coastguard Worker
3351*7304104dSAndroid Build Coastguard Worker unsigned int auxoffset = offset + def->vd_aux;
3352*7304104dSAndroid Build Coastguard Worker GElf_Verdaux auxmem;
3353*7304104dSAndroid Build Coastguard Worker GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
3354*7304104dSAndroid Build Coastguard Worker if (aux == NULL)
3355*7304104dSAndroid Build Coastguard Worker goto no_data;
3356*7304104dSAndroid Build Coastguard Worker
3357*7304104dSAndroid Build Coastguard Worker const char *name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
3358*7304104dSAndroid Build Coastguard Worker if (name == NULL)
3359*7304104dSAndroid Build Coastguard Worker {
3360*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3361*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has invalid name reference\n"),
3362*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3363*7304104dSAndroid Build Coastguard Worker goto next_def;
3364*7304104dSAndroid Build Coastguard Worker }
3365*7304104dSAndroid Build Coastguard Worker GElf_Word hashval = elf_hash (name);
3366*7304104dSAndroid Build Coastguard Worker if (def->vd_hash != hashval)
3367*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3368*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"),
3369*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, (int) hashval,
3370*7304104dSAndroid Build Coastguard Worker (int) def->vd_hash);
3371*7304104dSAndroid Build Coastguard Worker
3372*7304104dSAndroid Build Coastguard Worker int res = add_version (NULL, name, def->vd_ndx, ver_def);
3373*7304104dSAndroid Build Coastguard Worker if (unlikely (res !=0))
3374*7304104dSAndroid Build Coastguard Worker {
3375*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3376*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has duplicate version name '%s'\n"),
3377*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt, name);
3378*7304104dSAndroid Build Coastguard Worker }
3379*7304104dSAndroid Build Coastguard Worker
3380*7304104dSAndroid Build Coastguard Worker struct namelist *newname = alloca (sizeof (*newname));
3381*7304104dSAndroid Build Coastguard Worker newname->name = name;
3382*7304104dSAndroid Build Coastguard Worker newname->next = namelist;
3383*7304104dSAndroid Build Coastguard Worker namelist = newname;
3384*7304104dSAndroid Build Coastguard Worker
3385*7304104dSAndroid Build Coastguard Worker auxoffset += aux->vda_next;
3386*7304104dSAndroid Build Coastguard Worker for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
3387*7304104dSAndroid Build Coastguard Worker {
3388*7304104dSAndroid Build Coastguard Worker aux = gelf_getverdaux (data, auxoffset, &auxmem);
3389*7304104dSAndroid Build Coastguard Worker if (aux == NULL)
3390*7304104dSAndroid Build Coastguard Worker goto no_data;
3391*7304104dSAndroid Build Coastguard Worker
3392*7304104dSAndroid Build Coastguard Worker name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
3393*7304104dSAndroid Build Coastguard Worker if (name == NULL)
3394*7304104dSAndroid Build Coastguard Worker {
3395*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3396*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"),
3397*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3398*7304104dSAndroid Build Coastguard Worker break;
3399*7304104dSAndroid Build Coastguard Worker }
3400*7304104dSAndroid Build Coastguard Worker else
3401*7304104dSAndroid Build Coastguard Worker {
3402*7304104dSAndroid Build Coastguard Worker newname = alloca (sizeof (*newname));
3403*7304104dSAndroid Build Coastguard Worker newname->name = name;
3404*7304104dSAndroid Build Coastguard Worker newname->next = refnamelist;
3405*7304104dSAndroid Build Coastguard Worker refnamelist = newname;
3406*7304104dSAndroid Build Coastguard Worker }
3407*7304104dSAndroid Build Coastguard Worker
3408*7304104dSAndroid Build Coastguard Worker if ((aux->vda_next != 0 || cnt2 + 1 < def->vd_cnt)
3409*7304104dSAndroid Build Coastguard Worker && aux->vda_next < gelf_fsize (ebl->elf, ELF_T_VDAUX, 1,
3410*7304104dSAndroid Build Coastguard Worker EV_CURRENT))
3411*7304104dSAndroid Build Coastguard Worker {
3412*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3413*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has wrong next field in auxiliary data\n"),
3414*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3415*7304104dSAndroid Build Coastguard Worker break;
3416*7304104dSAndroid Build Coastguard Worker }
3417*7304104dSAndroid Build Coastguard Worker
3418*7304104dSAndroid Build Coastguard Worker auxoffset += MAX (aux->vda_next,
3419*7304104dSAndroid Build Coastguard Worker gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, EV_CURRENT));
3420*7304104dSAndroid Build Coastguard Worker }
3421*7304104dSAndroid Build Coastguard Worker
3422*7304104dSAndroid Build Coastguard Worker /* Find the next offset. */
3423*7304104dSAndroid Build Coastguard Worker next_def:
3424*7304104dSAndroid Build Coastguard Worker offset += def->vd_next;
3425*7304104dSAndroid Build Coastguard Worker
3426*7304104dSAndroid Build Coastguard Worker if ((def->vd_next != 0 || cnt > 0)
3427*7304104dSAndroid Build Coastguard Worker && offset < auxoffset)
3428*7304104dSAndroid Build Coastguard Worker {
3429*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3430*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has invalid offset to next entry\n"),
3431*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3432*7304104dSAndroid Build Coastguard Worker break;
3433*7304104dSAndroid Build Coastguard Worker }
3434*7304104dSAndroid Build Coastguard Worker
3435*7304104dSAndroid Build Coastguard Worker if (def->vd_next == 0 && cnt > 0)
3436*7304104dSAndroid Build Coastguard Worker {
3437*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3438*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says there are more entries\n"),
3439*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), cnt);
3440*7304104dSAndroid Build Coastguard Worker break;
3441*7304104dSAndroid Build Coastguard Worker }
3442*7304104dSAndroid Build Coastguard Worker }
3443*7304104dSAndroid Build Coastguard Worker
3444*7304104dSAndroid Build Coastguard Worker if (!has_base)
3445*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': no BASE definition\n"),
3446*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
3447*7304104dSAndroid Build Coastguard Worker
3448*7304104dSAndroid Build Coastguard Worker /* Check whether the referenced names are available. */
3449*7304104dSAndroid Build Coastguard Worker while (namelist != NULL)
3450*7304104dSAndroid Build Coastguard Worker {
3451*7304104dSAndroid Build Coastguard Worker struct version_namelist *runp = version_namelist;
3452*7304104dSAndroid Build Coastguard Worker while (runp != NULL)
3453*7304104dSAndroid Build Coastguard Worker {
3454*7304104dSAndroid Build Coastguard Worker if (runp->type == ver_def
3455*7304104dSAndroid Build Coastguard Worker && strcmp (runp->name, namelist->name) == 0)
3456*7304104dSAndroid Build Coastguard Worker break;
3457*7304104dSAndroid Build Coastguard Worker runp = runp->next;
3458*7304104dSAndroid Build Coastguard Worker }
3459*7304104dSAndroid Build Coastguard Worker
3460*7304104dSAndroid Build Coastguard Worker if (runp == NULL)
3461*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3462*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': unknown parent version '%s'\n"),
3463*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), namelist->name);
3464*7304104dSAndroid Build Coastguard Worker
3465*7304104dSAndroid Build Coastguard Worker namelist = namelist->next;
3466*7304104dSAndroid Build Coastguard Worker }
3467*7304104dSAndroid Build Coastguard Worker }
3468*7304104dSAndroid Build Coastguard Worker
3469*7304104dSAndroid Build Coastguard Worker static inline size_t
buffer_pos(Elf_Data * data,const unsigned char * p)3470*7304104dSAndroid Build Coastguard Worker buffer_pos (Elf_Data *data, const unsigned char *p)
3471*7304104dSAndroid Build Coastguard Worker {
3472*7304104dSAndroid Build Coastguard Worker return p - (const unsigned char *) data->d_buf;
3473*7304104dSAndroid Build Coastguard Worker }
3474*7304104dSAndroid Build Coastguard Worker
3475*7304104dSAndroid Build Coastguard Worker static inline size_t
buffer_left(Elf_Data * data,const unsigned char * p)3476*7304104dSAndroid Build Coastguard Worker buffer_left (Elf_Data *data, const unsigned char *p)
3477*7304104dSAndroid Build Coastguard Worker {
3478*7304104dSAndroid Build Coastguard Worker return (const unsigned char *) data->d_buf + data->d_size - p;
3479*7304104dSAndroid Build Coastguard Worker }
3480*7304104dSAndroid Build Coastguard Worker
3481*7304104dSAndroid Build Coastguard Worker static void
check_attributes(Ebl * ebl,GElf_Ehdr * ehdr,GElf_Shdr * shdr,int idx)3482*7304104dSAndroid Build Coastguard Worker check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
3483*7304104dSAndroid Build Coastguard Worker {
3484*7304104dSAndroid Build Coastguard Worker if (shdr->sh_size == 0)
3485*7304104dSAndroid Build Coastguard Worker {
3486*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': empty object attributes section\n"),
3487*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
3488*7304104dSAndroid Build Coastguard Worker return;
3489*7304104dSAndroid Build Coastguard Worker }
3490*7304104dSAndroid Build Coastguard Worker
3491*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL);
3492*7304104dSAndroid Build Coastguard Worker if (data == NULL || data->d_size == 0 || data->d_buf == NULL)
3493*7304104dSAndroid Build Coastguard Worker {
3494*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
3495*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
3496*7304104dSAndroid Build Coastguard Worker return;
3497*7304104dSAndroid Build Coastguard Worker }
3498*7304104dSAndroid Build Coastguard Worker
3499*7304104dSAndroid Build Coastguard Worker const unsigned char *p = data->d_buf;
3500*7304104dSAndroid Build Coastguard Worker if (*p++ != 'A')
3501*7304104dSAndroid Build Coastguard Worker {
3502*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': unrecognized attribute format\n"),
3503*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
3504*7304104dSAndroid Build Coastguard Worker return;
3505*7304104dSAndroid Build Coastguard Worker }
3506*7304104dSAndroid Build Coastguard Worker
3507*7304104dSAndroid Build Coastguard Worker while (buffer_left (data, p) >= 4)
3508*7304104dSAndroid Build Coastguard Worker {
3509*7304104dSAndroid Build Coastguard Worker uint32_t len;
3510*7304104dSAndroid Build Coastguard Worker memcpy (&len, p, sizeof len);
3511*7304104dSAndroid Build Coastguard Worker
3512*7304104dSAndroid Build Coastguard Worker if (len == 0)
3513*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3514*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: zero length field in attribute section\n"),
3515*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, p));
3516*7304104dSAndroid Build Coastguard Worker
3517*7304104dSAndroid Build Coastguard Worker if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3518*7304104dSAndroid Build Coastguard Worker CONVERT (len);
3519*7304104dSAndroid Build Coastguard Worker
3520*7304104dSAndroid Build Coastguard Worker if (len > buffer_left (data, p))
3521*7304104dSAndroid Build Coastguard Worker {
3522*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3523*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: invalid length in attribute section\n"),
3524*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, p));
3525*7304104dSAndroid Build Coastguard Worker break;
3526*7304104dSAndroid Build Coastguard Worker }
3527*7304104dSAndroid Build Coastguard Worker
3528*7304104dSAndroid Build Coastguard Worker const unsigned char *name = p + sizeof len;
3529*7304104dSAndroid Build Coastguard Worker p += len;
3530*7304104dSAndroid Build Coastguard Worker
3531*7304104dSAndroid Build Coastguard Worker unsigned const char *q = memchr (name, '\0', len);
3532*7304104dSAndroid Build Coastguard Worker if (q == NULL)
3533*7304104dSAndroid Build Coastguard Worker {
3534*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3535*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: unterminated vendor name string\n"),
3536*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, p));
3537*7304104dSAndroid Build Coastguard Worker break;
3538*7304104dSAndroid Build Coastguard Worker }
3539*7304104dSAndroid Build Coastguard Worker ++q;
3540*7304104dSAndroid Build Coastguard Worker
3541*7304104dSAndroid Build Coastguard Worker if (q - name == sizeof "gnu" && !memcmp (name, "gnu", sizeof "gnu"))
3542*7304104dSAndroid Build Coastguard Worker while (q < p)
3543*7304104dSAndroid Build Coastguard Worker {
3544*7304104dSAndroid Build Coastguard Worker unsigned const char *chunk = q;
3545*7304104dSAndroid Build Coastguard Worker
3546*7304104dSAndroid Build Coastguard Worker unsigned int subsection_tag;
3547*7304104dSAndroid Build Coastguard Worker get_uleb128 (subsection_tag, q, p);
3548*7304104dSAndroid Build Coastguard Worker
3549*7304104dSAndroid Build Coastguard Worker if (q >= p)
3550*7304104dSAndroid Build Coastguard Worker {
3551*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3552*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"),
3553*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, chunk));
3554*7304104dSAndroid Build Coastguard Worker break;
3555*7304104dSAndroid Build Coastguard Worker }
3556*7304104dSAndroid Build Coastguard Worker
3557*7304104dSAndroid Build Coastguard Worker uint32_t subsection_len;
3558*7304104dSAndroid Build Coastguard Worker if (p - q < (ptrdiff_t) sizeof subsection_len)
3559*7304104dSAndroid Build Coastguard Worker {
3560*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3561*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: truncated attribute section\n"),
3562*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, q));
3563*7304104dSAndroid Build Coastguard Worker break;
3564*7304104dSAndroid Build Coastguard Worker }
3565*7304104dSAndroid Build Coastguard Worker
3566*7304104dSAndroid Build Coastguard Worker memcpy (&subsection_len, q, sizeof subsection_len);
3567*7304104dSAndroid Build Coastguard Worker if (subsection_len == 0)
3568*7304104dSAndroid Build Coastguard Worker {
3569*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3570*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
3571*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, q));
3572*7304104dSAndroid Build Coastguard Worker
3573*7304104dSAndroid Build Coastguard Worker q += sizeof subsection_len;
3574*7304104dSAndroid Build Coastguard Worker continue;
3575*7304104dSAndroid Build Coastguard Worker }
3576*7304104dSAndroid Build Coastguard Worker
3577*7304104dSAndroid Build Coastguard Worker if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3578*7304104dSAndroid Build Coastguard Worker CONVERT (subsection_len);
3579*7304104dSAndroid Build Coastguard Worker
3580*7304104dSAndroid Build Coastguard Worker /* Don't overflow, ptrdiff_t might be 32bits, but signed. */
3581*7304104dSAndroid Build Coastguard Worker if (p - chunk < (ptrdiff_t) subsection_len
3582*7304104dSAndroid Build Coastguard Worker || subsection_len >= (uint32_t) PTRDIFF_MAX)
3583*7304104dSAndroid Build Coastguard Worker {
3584*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3585*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
3586*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, q));
3587*7304104dSAndroid Build Coastguard Worker break;
3588*7304104dSAndroid Build Coastguard Worker }
3589*7304104dSAndroid Build Coastguard Worker
3590*7304104dSAndroid Build Coastguard Worker const unsigned char *subsection_end = chunk + subsection_len;
3591*7304104dSAndroid Build Coastguard Worker chunk = q;
3592*7304104dSAndroid Build Coastguard Worker q = subsection_end;
3593*7304104dSAndroid Build Coastguard Worker
3594*7304104dSAndroid Build Coastguard Worker if (subsection_tag != 1) /* Tag_File */
3595*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3596*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
3597*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, chunk), subsection_tag);
3598*7304104dSAndroid Build Coastguard Worker else
3599*7304104dSAndroid Build Coastguard Worker {
3600*7304104dSAndroid Build Coastguard Worker chunk += sizeof subsection_len;
3601*7304104dSAndroid Build Coastguard Worker while (chunk < q)
3602*7304104dSAndroid Build Coastguard Worker {
3603*7304104dSAndroid Build Coastguard Worker unsigned int tag;
3604*7304104dSAndroid Build Coastguard Worker get_uleb128 (tag, chunk, q);
3605*7304104dSAndroid Build Coastguard Worker
3606*7304104dSAndroid Build Coastguard Worker uint64_t value = 0;
3607*7304104dSAndroid Build Coastguard Worker const unsigned char *r = chunk;
3608*7304104dSAndroid Build Coastguard Worker if (tag == 32 || (tag & 1) == 0)
3609*7304104dSAndroid Build Coastguard Worker {
3610*7304104dSAndroid Build Coastguard Worker if (r >= q)
3611*7304104dSAndroid Build Coastguard Worker goto invalid_uleb;
3612*7304104dSAndroid Build Coastguard Worker get_uleb128 (value, r, q);
3613*7304104dSAndroid Build Coastguard Worker if (r > q)
3614*7304104dSAndroid Build Coastguard Worker {
3615*7304104dSAndroid Build Coastguard Worker invalid_uleb:
3616*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3617*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"),
3618*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, chunk));
3619*7304104dSAndroid Build Coastguard Worker break;
3620*7304104dSAndroid Build Coastguard Worker }
3621*7304104dSAndroid Build Coastguard Worker }
3622*7304104dSAndroid Build Coastguard Worker if (tag == 32 || (tag & 1) != 0)
3623*7304104dSAndroid Build Coastguard Worker {
3624*7304104dSAndroid Build Coastguard Worker r = memchr (r, '\0', q - r);
3625*7304104dSAndroid Build Coastguard Worker if (r == NULL)
3626*7304104dSAndroid Build Coastguard Worker {
3627*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3628*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: unterminated string in attribute\n"),
3629*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, chunk));
3630*7304104dSAndroid Build Coastguard Worker break;
3631*7304104dSAndroid Build Coastguard Worker }
3632*7304104dSAndroid Build Coastguard Worker ++r;
3633*7304104dSAndroid Build Coastguard Worker }
3634*7304104dSAndroid Build Coastguard Worker
3635*7304104dSAndroid Build Coastguard Worker const char *tag_name = NULL;
3636*7304104dSAndroid Build Coastguard Worker const char *value_name = NULL;
3637*7304104dSAndroid Build Coastguard Worker if (!ebl_check_object_attribute (ebl, (const char *) name,
3638*7304104dSAndroid Build Coastguard Worker tag, value,
3639*7304104dSAndroid Build Coastguard Worker &tag_name, &value_name))
3640*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3641*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"),
3642*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, chunk), tag);
3643*7304104dSAndroid Build Coastguard Worker else if ((tag & 1) == 0 && value_name == NULL)
3644*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3645*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"),
3646*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, chunk),
3647*7304104dSAndroid Build Coastguard Worker tag_name, value);
3648*7304104dSAndroid Build Coastguard Worker
3649*7304104dSAndroid Build Coastguard Worker chunk = r;
3650*7304104dSAndroid Build Coastguard Worker }
3651*7304104dSAndroid Build Coastguard Worker }
3652*7304104dSAndroid Build Coastguard Worker }
3653*7304104dSAndroid Build Coastguard Worker else
3654*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3655*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: vendor '%s' unknown\n"),
3656*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, p), name);
3657*7304104dSAndroid Build Coastguard Worker }
3658*7304104dSAndroid Build Coastguard Worker
3659*7304104dSAndroid Build Coastguard Worker if (buffer_left (data, p) != 0)
3660*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3661*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': offset %zu: extra bytes after last attribute section\n"),
3662*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), buffer_pos (data, p));
3663*7304104dSAndroid Build Coastguard Worker }
3664*7304104dSAndroid Build Coastguard Worker
3665*7304104dSAndroid Build Coastguard Worker static bool has_loadable_segment;
3666*7304104dSAndroid Build Coastguard Worker static bool has_interp_segment;
3667*7304104dSAndroid Build Coastguard Worker
3668*7304104dSAndroid Build Coastguard Worker static const struct
3669*7304104dSAndroid Build Coastguard Worker {
3670*7304104dSAndroid Build Coastguard Worker const char *name;
3671*7304104dSAndroid Build Coastguard Worker size_t namelen;
3672*7304104dSAndroid Build Coastguard Worker GElf_Word type;
3673*7304104dSAndroid Build Coastguard Worker enum { unused, exact, atleast, exact_or_gnuld } attrflag;
3674*7304104dSAndroid Build Coastguard Worker GElf_Word attr;
3675*7304104dSAndroid Build Coastguard Worker GElf_Word attr2;
3676*7304104dSAndroid Build Coastguard Worker } special_sections[] =
3677*7304104dSAndroid Build Coastguard Worker {
3678*7304104dSAndroid Build Coastguard Worker /* See figure 4-14 in the gABI. */
3679*7304104dSAndroid Build Coastguard Worker { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3680*7304104dSAndroid Build Coastguard Worker { ".comment", 8, SHT_PROGBITS, atleast, 0, SHF_MERGE | SHF_STRINGS },
3681*7304104dSAndroid Build Coastguard Worker { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3682*7304104dSAndroid Build Coastguard Worker { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3683*7304104dSAndroid Build Coastguard Worker { ".debug_str", 11, SHT_PROGBITS, exact_or_gnuld, SHF_MERGE | SHF_STRINGS, 0 },
3684*7304104dSAndroid Build Coastguard Worker { ".debug_line_str", 16, SHT_PROGBITS, exact_or_gnuld, SHF_MERGE | SHF_STRINGS, 0 },
3685*7304104dSAndroid Build Coastguard Worker { ".debug", 6, SHT_PROGBITS, exact, 0, 0 },
3686*7304104dSAndroid Build Coastguard Worker { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE },
3687*7304104dSAndroid Build Coastguard Worker { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 },
3688*7304104dSAndroid Build Coastguard Worker { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 },
3689*7304104dSAndroid Build Coastguard Worker { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3690*7304104dSAndroid Build Coastguard Worker { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3691*7304104dSAndroid Build Coastguard Worker { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info?
3692*7304104dSAndroid Build Coastguard Worker { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 },
3693*7304104dSAndroid Build Coastguard Worker { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3694*7304104dSAndroid Build Coastguard Worker { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3695*7304104dSAndroid Build Coastguard Worker { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests?
3696*7304104dSAndroid Build Coastguard Worker { ".line", 6, SHT_PROGBITS, exact, 0, 0 },
3697*7304104dSAndroid Build Coastguard Worker { ".note", 6, SHT_NOTE, atleast, 0, SHF_ALLOC },
3698*7304104dSAndroid Build Coastguard Worker { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
3699*7304104dSAndroid Build Coastguard Worker { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3700*7304104dSAndroid Build Coastguard Worker { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests
3701*7304104dSAndroid Build Coastguard Worker { ".relr", 5, SHT_RELR, atleast, 0, SHF_ALLOC }, // XXX more tests
3702*7304104dSAndroid Build Coastguard Worker { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests
3703*7304104dSAndroid Build Coastguard Worker { ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3704*7304104dSAndroid Build Coastguard Worker { ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3705*7304104dSAndroid Build Coastguard Worker { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 },
3706*7304104dSAndroid Build Coastguard Worker { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3707*7304104dSAndroid Build Coastguard Worker { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3708*7304104dSAndroid Build Coastguard Worker { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests
3709*7304104dSAndroid Build Coastguard Worker { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3710*7304104dSAndroid Build Coastguard Worker { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3711*7304104dSAndroid Build Coastguard Worker { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3712*7304104dSAndroid Build Coastguard Worker { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3713*7304104dSAndroid Build Coastguard Worker
3714*7304104dSAndroid Build Coastguard Worker /* The following are GNU extensions. */
3715*7304104dSAndroid Build Coastguard Worker { ".gnu.version", 13, SHT_GNU_versym, exact, SHF_ALLOC, 0 },
3716*7304104dSAndroid Build Coastguard Worker { ".gnu.version_d", 15, SHT_GNU_verdef, exact, SHF_ALLOC, 0 },
3717*7304104dSAndroid Build Coastguard Worker { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 },
3718*7304104dSAndroid Build Coastguard Worker { ".gnu.attributes", 16, SHT_GNU_ATTRIBUTES, exact, 0, 0 },
3719*7304104dSAndroid Build Coastguard Worker };
3720*7304104dSAndroid Build Coastguard Worker #define nspecial_sections \
3721*7304104dSAndroid Build Coastguard Worker (sizeof (special_sections) / sizeof (special_sections[0]))
3722*7304104dSAndroid Build Coastguard Worker
3723*7304104dSAndroid Build Coastguard Worker #define IS_KNOWN_SPECIAL(idx, string, prefix) \
3724*7304104dSAndroid Build Coastguard Worker (special_sections[idx].namelen == sizeof string - (prefix ? 1 : 0) \
3725*7304104dSAndroid Build Coastguard Worker && !memcmp (special_sections[idx].name, string, \
3726*7304104dSAndroid Build Coastguard Worker sizeof string - (prefix ? 1 : 0)))
3727*7304104dSAndroid Build Coastguard Worker
3728*7304104dSAndroid Build Coastguard Worker /* Extra section flags that might or might not be added to the section
3729*7304104dSAndroid Build Coastguard Worker and have to be ignored. */
3730*7304104dSAndroid Build Coastguard Worker #define EXTRA_SHFLAGS (SHF_LINK_ORDER \
3731*7304104dSAndroid Build Coastguard Worker | SHF_GNU_RETAIN \
3732*7304104dSAndroid Build Coastguard Worker | SHF_GROUP \
3733*7304104dSAndroid Build Coastguard Worker | SHF_COMPRESSED)
3734*7304104dSAndroid Build Coastguard Worker
3735*7304104dSAndroid Build Coastguard Worker
3736*7304104dSAndroid Build Coastguard Worker /* Indices of some sections we need later. */
3737*7304104dSAndroid Build Coastguard Worker static size_t eh_frame_hdr_scnndx;
3738*7304104dSAndroid Build Coastguard Worker static size_t eh_frame_scnndx;
3739*7304104dSAndroid Build Coastguard Worker static size_t gcc_except_table_scnndx;
3740*7304104dSAndroid Build Coastguard Worker
3741*7304104dSAndroid Build Coastguard Worker
3742*7304104dSAndroid Build Coastguard Worker static void
check_sections(Ebl * ebl,GElf_Ehdr * ehdr)3743*7304104dSAndroid Build Coastguard Worker check_sections (Ebl *ebl, GElf_Ehdr *ehdr)
3744*7304104dSAndroid Build Coastguard Worker {
3745*7304104dSAndroid Build Coastguard Worker if (ehdr->e_shoff == 0)
3746*7304104dSAndroid Build Coastguard Worker /* No section header. */
3747*7304104dSAndroid Build Coastguard Worker return;
3748*7304104dSAndroid Build Coastguard Worker
3749*7304104dSAndroid Build Coastguard Worker /* Allocate array to count references in section groups. */
3750*7304104dSAndroid Build Coastguard Worker scnref = xcalloc (shnum, sizeof (int));
3751*7304104dSAndroid Build Coastguard Worker
3752*7304104dSAndroid Build Coastguard Worker /* Check the zeroth section first. It must not have any contents
3753*7304104dSAndroid Build Coastguard Worker and the section header must contain nonzero value at most in the
3754*7304104dSAndroid Build Coastguard Worker sh_size and sh_link fields. */
3755*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
3756*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
3757*7304104dSAndroid Build Coastguard Worker if (shdr == NULL)
3758*7304104dSAndroid Build Coastguard Worker ERROR (_("cannot get section header of zeroth section\n"));
3759*7304104dSAndroid Build Coastguard Worker else
3760*7304104dSAndroid Build Coastguard Worker {
3761*7304104dSAndroid Build Coastguard Worker if (shdr->sh_name != 0)
3762*7304104dSAndroid Build Coastguard Worker ERROR (_("zeroth section has nonzero name\n"));
3763*7304104dSAndroid Build Coastguard Worker if (shdr->sh_type != 0)
3764*7304104dSAndroid Build Coastguard Worker ERROR (_("zeroth section has nonzero type\n"));
3765*7304104dSAndroid Build Coastguard Worker if (shdr->sh_flags != 0)
3766*7304104dSAndroid Build Coastguard Worker ERROR (_("zeroth section has nonzero flags\n"));
3767*7304104dSAndroid Build Coastguard Worker if (shdr->sh_addr != 0)
3768*7304104dSAndroid Build Coastguard Worker ERROR (_("zeroth section has nonzero address\n"));
3769*7304104dSAndroid Build Coastguard Worker if (shdr->sh_offset != 0)
3770*7304104dSAndroid Build Coastguard Worker ERROR (_("zeroth section has nonzero offset\n"));
3771*7304104dSAndroid Build Coastguard Worker if (shdr->sh_addralign != 0)
3772*7304104dSAndroid Build Coastguard Worker ERROR (_("zeroth section has nonzero align value\n"));
3773*7304104dSAndroid Build Coastguard Worker if (shdr->sh_entsize != 0)
3774*7304104dSAndroid Build Coastguard Worker ERROR (_("zeroth section has nonzero entry size value\n"));
3775*7304104dSAndroid Build Coastguard Worker
3776*7304104dSAndroid Build Coastguard Worker if (shdr->sh_size != 0 && ehdr->e_shnum != 0)
3777*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3778*7304104dSAndroid Build Coastguard Worker zeroth section has nonzero size value while ELF header has nonzero shnum value\n"));
3779*7304104dSAndroid Build Coastguard Worker
3780*7304104dSAndroid Build Coastguard Worker if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX)
3781*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3782*7304104dSAndroid Build Coastguard Worker zeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n"));
3783*7304104dSAndroid Build Coastguard Worker
3784*7304104dSAndroid Build Coastguard Worker if (shdr->sh_info != 0 && ehdr->e_phnum != PN_XNUM)
3785*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3786*7304104dSAndroid Build Coastguard Worker zeroth section has nonzero link value while ELF header does not signal overflow in phnum\n"));
3787*7304104dSAndroid Build Coastguard Worker }
3788*7304104dSAndroid Build Coastguard Worker
3789*7304104dSAndroid Build Coastguard Worker int *segment_flags = xcalloc (phnum, sizeof segment_flags[0]);
3790*7304104dSAndroid Build Coastguard Worker
3791*7304104dSAndroid Build Coastguard Worker bool dot_interp_section = false;
3792*7304104dSAndroid Build Coastguard Worker
3793*7304104dSAndroid Build Coastguard Worker size_t hash_idx = 0;
3794*7304104dSAndroid Build Coastguard Worker size_t gnu_hash_idx = 0;
3795*7304104dSAndroid Build Coastguard Worker
3796*7304104dSAndroid Build Coastguard Worker size_t versym_scnndx = 0;
3797*7304104dSAndroid Build Coastguard Worker for (size_t cnt = 1; cnt < shnum; ++cnt)
3798*7304104dSAndroid Build Coastguard Worker {
3799*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
3800*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (scn, &shdr_mem);
3801*7304104dSAndroid Build Coastguard Worker if (shdr == NULL)
3802*7304104dSAndroid Build Coastguard Worker {
3803*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3804*7304104dSAndroid Build Coastguard Worker cannot get section header for section [%2zu] '%s': %s\n"),
3805*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt), elf_errmsg (-1));
3806*7304104dSAndroid Build Coastguard Worker continue;
3807*7304104dSAndroid Build Coastguard Worker }
3808*7304104dSAndroid Build Coastguard Worker
3809*7304104dSAndroid Build Coastguard Worker const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
3810*7304104dSAndroid Build Coastguard Worker
3811*7304104dSAndroid Build Coastguard Worker if (scnname == NULL)
3812*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2zu]: invalid name\n"), cnt);
3813*7304104dSAndroid Build Coastguard Worker else
3814*7304104dSAndroid Build Coastguard Worker {
3815*7304104dSAndroid Build Coastguard Worker /* Check whether it is one of the special sections defined in
3816*7304104dSAndroid Build Coastguard Worker the gABI. */
3817*7304104dSAndroid Build Coastguard Worker size_t s;
3818*7304104dSAndroid Build Coastguard Worker for (s = 0; s < nspecial_sections; ++s)
3819*7304104dSAndroid Build Coastguard Worker if (strncmp (scnname, special_sections[s].name,
3820*7304104dSAndroid Build Coastguard Worker special_sections[s].namelen) == 0)
3821*7304104dSAndroid Build Coastguard Worker {
3822*7304104dSAndroid Build Coastguard Worker char stbuf1[100];
3823*7304104dSAndroid Build Coastguard Worker char stbuf2[100];
3824*7304104dSAndroid Build Coastguard Worker char stbuf3[100];
3825*7304104dSAndroid Build Coastguard Worker
3826*7304104dSAndroid Build Coastguard Worker GElf_Word good_type = special_sections[s].type;
3827*7304104dSAndroid Build Coastguard Worker if (IS_KNOWN_SPECIAL (s, ".plt", false)
3828*7304104dSAndroid Build Coastguard Worker && ebl_bss_plt_p (ebl))
3829*7304104dSAndroid Build Coastguard Worker good_type = SHT_NOBITS;
3830*7304104dSAndroid Build Coastguard Worker
3831*7304104dSAndroid Build Coastguard Worker /* In a debuginfo file, any normal section can be SHT_NOBITS.
3832*7304104dSAndroid Build Coastguard Worker This is only invalid for DWARF sections and .shstrtab. */
3833*7304104dSAndroid Build Coastguard Worker if (shdr->sh_type != good_type
3834*7304104dSAndroid Build Coastguard Worker && (shdr->sh_type != SHT_NOBITS
3835*7304104dSAndroid Build Coastguard Worker || !is_debuginfo
3836*7304104dSAndroid Build Coastguard Worker || IS_KNOWN_SPECIAL (s, ".debug_str", false)
3837*7304104dSAndroid Build Coastguard Worker || IS_KNOWN_SPECIAL (s, ".debug", true)
3838*7304104dSAndroid Build Coastguard Worker || IS_KNOWN_SPECIAL (s, ".shstrtab", false)))
3839*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3840*7304104dSAndroid Build Coastguard Worker section [%2d] '%s' has wrong type: expected %s, is %s\n"),
3841*7304104dSAndroid Build Coastguard Worker (int) cnt, scnname,
3842*7304104dSAndroid Build Coastguard Worker ebl_section_type_name (ebl, special_sections[s].type,
3843*7304104dSAndroid Build Coastguard Worker stbuf1, sizeof (stbuf1)),
3844*7304104dSAndroid Build Coastguard Worker ebl_section_type_name (ebl, shdr->sh_type,
3845*7304104dSAndroid Build Coastguard Worker stbuf2, sizeof (stbuf2)));
3846*7304104dSAndroid Build Coastguard Worker
3847*7304104dSAndroid Build Coastguard Worker if (special_sections[s].attrflag == exact
3848*7304104dSAndroid Build Coastguard Worker || special_sections[s].attrflag == exact_or_gnuld)
3849*7304104dSAndroid Build Coastguard Worker {
3850*7304104dSAndroid Build Coastguard Worker /* Except for the link order, retain, group bit and
3851*7304104dSAndroid Build Coastguard Worker compression flag all the other bits should
3852*7304104dSAndroid Build Coastguard Worker match exactly. */
3853*7304104dSAndroid Build Coastguard Worker if ((shdr->sh_flags & ~EXTRA_SHFLAGS)
3854*7304104dSAndroid Build Coastguard Worker != special_sections[s].attr
3855*7304104dSAndroid Build Coastguard Worker && (special_sections[s].attrflag == exact || !gnuld))
3856*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3857*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' has wrong flags: expected %s, is %s\n"),
3858*7304104dSAndroid Build Coastguard Worker cnt, scnname,
3859*7304104dSAndroid Build Coastguard Worker section_flags_string (special_sections[s].attr,
3860*7304104dSAndroid Build Coastguard Worker stbuf1, sizeof (stbuf1)),
3861*7304104dSAndroid Build Coastguard Worker section_flags_string (shdr->sh_flags
3862*7304104dSAndroid Build Coastguard Worker & ~EXTRA_SHFLAGS,
3863*7304104dSAndroid Build Coastguard Worker stbuf2, sizeof (stbuf2)));
3864*7304104dSAndroid Build Coastguard Worker }
3865*7304104dSAndroid Build Coastguard Worker else if (special_sections[s].attrflag == atleast)
3866*7304104dSAndroid Build Coastguard Worker {
3867*7304104dSAndroid Build Coastguard Worker if ((shdr->sh_flags & special_sections[s].attr)
3868*7304104dSAndroid Build Coastguard Worker != special_sections[s].attr
3869*7304104dSAndroid Build Coastguard Worker || ((shdr->sh_flags
3870*7304104dSAndroid Build Coastguard Worker & ~(EXTRA_SHFLAGS
3871*7304104dSAndroid Build Coastguard Worker | special_sections[s].attr
3872*7304104dSAndroid Build Coastguard Worker | special_sections[s].attr2))
3873*7304104dSAndroid Build Coastguard Worker != 0))
3874*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3875*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"),
3876*7304104dSAndroid Build Coastguard Worker cnt, scnname,
3877*7304104dSAndroid Build Coastguard Worker section_flags_string (special_sections[s].attr,
3878*7304104dSAndroid Build Coastguard Worker stbuf1, sizeof (stbuf1)),
3879*7304104dSAndroid Build Coastguard Worker section_flags_string (special_sections[s].attr2,
3880*7304104dSAndroid Build Coastguard Worker stbuf2, sizeof (stbuf2)),
3881*7304104dSAndroid Build Coastguard Worker section_flags_string (shdr->sh_flags
3882*7304104dSAndroid Build Coastguard Worker & ~EXTRA_SHFLAGS,
3883*7304104dSAndroid Build Coastguard Worker stbuf3, sizeof (stbuf3)));
3884*7304104dSAndroid Build Coastguard Worker }
3885*7304104dSAndroid Build Coastguard Worker
3886*7304104dSAndroid Build Coastguard Worker if (strcmp (scnname, ".interp") == 0)
3887*7304104dSAndroid Build Coastguard Worker {
3888*7304104dSAndroid Build Coastguard Worker dot_interp_section = true;
3889*7304104dSAndroid Build Coastguard Worker
3890*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type == ET_REL)
3891*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3892*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' present in object file\n"),
3893*7304104dSAndroid Build Coastguard Worker cnt, scnname);
3894*7304104dSAndroid Build Coastguard Worker
3895*7304104dSAndroid Build Coastguard Worker if ((shdr->sh_flags & SHF_ALLOC) != 0
3896*7304104dSAndroid Build Coastguard Worker && !has_loadable_segment)
3897*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3898*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3899*7304104dSAndroid Build Coastguard Worker cnt, scnname);
3900*7304104dSAndroid Build Coastguard Worker else if ((shdr->sh_flags & SHF_ALLOC) == 0
3901*7304104dSAndroid Build Coastguard Worker && has_loadable_segment)
3902*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3903*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3904*7304104dSAndroid Build Coastguard Worker cnt, scnname);
3905*7304104dSAndroid Build Coastguard Worker }
3906*7304104dSAndroid Build Coastguard Worker else
3907*7304104dSAndroid Build Coastguard Worker {
3908*7304104dSAndroid Build Coastguard Worker if (strcmp (scnname, ".symtab_shndx") == 0
3909*7304104dSAndroid Build Coastguard Worker && ehdr->e_type != ET_REL)
3910*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3911*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' is extension section index table in non-object file\n"),
3912*7304104dSAndroid Build Coastguard Worker cnt, scnname);
3913*7304104dSAndroid Build Coastguard Worker
3914*7304104dSAndroid Build Coastguard Worker /* These sections must have the SHF_ALLOC flag set iff
3915*7304104dSAndroid Build Coastguard Worker a loadable segment is available.
3916*7304104dSAndroid Build Coastguard Worker
3917*7304104dSAndroid Build Coastguard Worker .relxxx
3918*7304104dSAndroid Build Coastguard Worker .strtab
3919*7304104dSAndroid Build Coastguard Worker .symtab
3920*7304104dSAndroid Build Coastguard Worker .symtab_shndx
3921*7304104dSAndroid Build Coastguard Worker
3922*7304104dSAndroid Build Coastguard Worker Check that if there is a reference from the
3923*7304104dSAndroid Build Coastguard Worker loaded section these sections also have the
3924*7304104dSAndroid Build Coastguard Worker ALLOC flag set. */
3925*7304104dSAndroid Build Coastguard Worker #if 0
3926*7304104dSAndroid Build Coastguard Worker // XXX TODO
3927*7304104dSAndroid Build Coastguard Worker if ((shdr->sh_flags & SHF_ALLOC) != 0
3928*7304104dSAndroid Build Coastguard Worker && !has_loadable_segment)
3929*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3930*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3931*7304104dSAndroid Build Coastguard Worker cnt, scnname);
3932*7304104dSAndroid Build Coastguard Worker else if ((shdr->sh_flags & SHF_ALLOC) == 0
3933*7304104dSAndroid Build Coastguard Worker && has_loadable_segment)
3934*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3935*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3936*7304104dSAndroid Build Coastguard Worker cnt, scnname);
3937*7304104dSAndroid Build Coastguard Worker #endif
3938*7304104dSAndroid Build Coastguard Worker }
3939*7304104dSAndroid Build Coastguard Worker
3940*7304104dSAndroid Build Coastguard Worker break;
3941*7304104dSAndroid Build Coastguard Worker }
3942*7304104dSAndroid Build Coastguard Worker
3943*7304104dSAndroid Build Coastguard Worker /* Remember a few special sections for later. */
3944*7304104dSAndroid Build Coastguard Worker if (strcmp (scnname, ".eh_frame_hdr") == 0)
3945*7304104dSAndroid Build Coastguard Worker eh_frame_hdr_scnndx = cnt;
3946*7304104dSAndroid Build Coastguard Worker else if (strcmp (scnname, ".eh_frame") == 0)
3947*7304104dSAndroid Build Coastguard Worker eh_frame_scnndx = cnt;
3948*7304104dSAndroid Build Coastguard Worker else if (strcmp (scnname, ".gcc_except_table") == 0)
3949*7304104dSAndroid Build Coastguard Worker gcc_except_table_scnndx = cnt;
3950*7304104dSAndroid Build Coastguard Worker }
3951*7304104dSAndroid Build Coastguard Worker
3952*7304104dSAndroid Build Coastguard Worker if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize)
3953*7304104dSAndroid Build Coastguard Worker ERROR (_("\
3954*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': size not multiple of entry size\n"),
3955*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
3956*7304104dSAndroid Build Coastguard Worker
3957*7304104dSAndroid Build Coastguard Worker if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL)
3958*7304104dSAndroid Build Coastguard Worker ERROR (_("cannot get section header\n"));
3959*7304104dSAndroid Build Coastguard Worker
3960*7304104dSAndroid Build Coastguard Worker if (shdr->sh_type >= SHT_NUM
3961*7304104dSAndroid Build Coastguard Worker && shdr->sh_type != SHT_GNU_ATTRIBUTES
3962*7304104dSAndroid Build Coastguard Worker && shdr->sh_type != SHT_GNU_LIBLIST
3963*7304104dSAndroid Build Coastguard Worker && shdr->sh_type != SHT_CHECKSUM
3964*7304104dSAndroid Build Coastguard Worker && shdr->sh_type != SHT_GNU_verdef
3965*7304104dSAndroid Build Coastguard Worker && shdr->sh_type != SHT_GNU_verneed
3966*7304104dSAndroid Build Coastguard Worker && shdr->sh_type != SHT_GNU_versym
3967*7304104dSAndroid Build Coastguard Worker && ebl_section_type_name (ebl, shdr->sh_type, NULL, 0) == NULL)
3968*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2zu] '%s' has unsupported type %d\n"),
3969*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt),
3970*7304104dSAndroid Build Coastguard Worker (int) shdr->sh_type);
3971*7304104dSAndroid Build Coastguard Worker
3972*7304104dSAndroid Build Coastguard Worker #define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \
3973*7304104dSAndroid Build Coastguard Worker | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \
3974*7304104dSAndroid Build Coastguard Worker | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS \
3975*7304104dSAndroid Build Coastguard Worker | SHF_COMPRESSED | SHF_GNU_RETAIN)
3976*7304104dSAndroid Build Coastguard Worker if (shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS)
3977*7304104dSAndroid Build Coastguard Worker {
3978*7304104dSAndroid Build Coastguard Worker GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS;
3979*7304104dSAndroid Build Coastguard Worker if (sh_flags & SHF_MASKPROC)
3980*7304104dSAndroid Build Coastguard Worker {
3981*7304104dSAndroid Build Coastguard Worker /* Strictly speaking SHF_EXCLUDE is a processor specific
3982*7304104dSAndroid Build Coastguard Worker section flag, but it is used generically in the GNU
3983*7304104dSAndroid Build Coastguard Worker toolchain. */
3984*7304104dSAndroid Build Coastguard Worker if (gnuld)
3985*7304104dSAndroid Build Coastguard Worker sh_flags &= ~(GElf_Xword) SHF_EXCLUDE;
3986*7304104dSAndroid Build Coastguard Worker if (!ebl_machine_section_flag_check (ebl,
3987*7304104dSAndroid Build Coastguard Worker sh_flags & SHF_MASKPROC))
3988*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2zu] '%s'"
3989*7304104dSAndroid Build Coastguard Worker " contains invalid processor-specific flag(s)"
3990*7304104dSAndroid Build Coastguard Worker " %#" PRIx64 "\n"),
3991*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
3992*7304104dSAndroid Build Coastguard Worker sh_flags &= ~(GElf_Xword) SHF_MASKPROC;
3993*7304104dSAndroid Build Coastguard Worker }
3994*7304104dSAndroid Build Coastguard Worker if (sh_flags & SHF_MASKOS)
3995*7304104dSAndroid Build Coastguard Worker if (gnuld)
3996*7304104dSAndroid Build Coastguard Worker sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN;
3997*7304104dSAndroid Build Coastguard Worker if (sh_flags != 0)
3998*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2zu] '%s' contains unknown flag(s)"
3999*7304104dSAndroid Build Coastguard Worker " %#" PRIx64 "\n"),
4000*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt), sh_flags);
4001*7304104dSAndroid Build Coastguard Worker }
4002*7304104dSAndroid Build Coastguard Worker if (shdr->sh_flags & SHF_TLS)
4003*7304104dSAndroid Build Coastguard Worker {
4004*7304104dSAndroid Build Coastguard Worker // XXX Correct?
4005*7304104dSAndroid Build Coastguard Worker if (shdr->sh_addr != 0 && !gnuld)
4006*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4007*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': thread-local data sections address not zero\n"),
4008*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4009*7304104dSAndroid Build Coastguard Worker
4010*7304104dSAndroid Build Coastguard Worker // XXX TODO more tests!?
4011*7304104dSAndroid Build Coastguard Worker }
4012*7304104dSAndroid Build Coastguard Worker
4013*7304104dSAndroid Build Coastguard Worker if (shdr->sh_flags & SHF_COMPRESSED)
4014*7304104dSAndroid Build Coastguard Worker {
4015*7304104dSAndroid Build Coastguard Worker if (shdr->sh_flags & SHF_ALLOC)
4016*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4017*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': allocated section cannot be compressed\n"),
4018*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4019*7304104dSAndroid Build Coastguard Worker
4020*7304104dSAndroid Build Coastguard Worker if (shdr->sh_type == SHT_NOBITS)
4021*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4022*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': nobits section cannot be compressed\n"),
4023*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4024*7304104dSAndroid Build Coastguard Worker
4025*7304104dSAndroid Build Coastguard Worker GElf_Chdr chdr;
4026*7304104dSAndroid Build Coastguard Worker if (gelf_getchdr (scn, &chdr) == NULL)
4027*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4028*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': compressed section with no compression header: %s\n"),
4029*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt), elf_errmsg (-1));
4030*7304104dSAndroid Build Coastguard Worker }
4031*7304104dSAndroid Build Coastguard Worker
4032*7304104dSAndroid Build Coastguard Worker if (shdr->sh_link >= shnum)
4033*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4034*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': invalid section reference in link value\n"),
4035*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4036*7304104dSAndroid Build Coastguard Worker
4037*7304104dSAndroid Build Coastguard Worker if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum)
4038*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4039*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': invalid section reference in info value\n"),
4040*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4041*7304104dSAndroid Build Coastguard Worker
4042*7304104dSAndroid Build Coastguard Worker if ((shdr->sh_flags & SHF_MERGE) == 0
4043*7304104dSAndroid Build Coastguard Worker && (shdr->sh_flags & SHF_STRINGS) != 0
4044*7304104dSAndroid Build Coastguard Worker && be_strict)
4045*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4046*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': strings flag set without merge flag\n"),
4047*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4048*7304104dSAndroid Build Coastguard Worker
4049*7304104dSAndroid Build Coastguard Worker if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0)
4050*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4051*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': merge flag set but entry size is zero\n"),
4052*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4053*7304104dSAndroid Build Coastguard Worker
4054*7304104dSAndroid Build Coastguard Worker if (shdr->sh_flags & SHF_GROUP)
4055*7304104dSAndroid Build Coastguard Worker check_scn_group (ebl, cnt);
4056*7304104dSAndroid Build Coastguard Worker
4057*7304104dSAndroid Build Coastguard Worker if (shdr->sh_flags & SHF_EXECINSTR)
4058*7304104dSAndroid Build Coastguard Worker {
4059*7304104dSAndroid Build Coastguard Worker switch (shdr->sh_type)
4060*7304104dSAndroid Build Coastguard Worker {
4061*7304104dSAndroid Build Coastguard Worker case SHT_PROGBITS:
4062*7304104dSAndroid Build Coastguard Worker break;
4063*7304104dSAndroid Build Coastguard Worker
4064*7304104dSAndroid Build Coastguard Worker case SHT_NOBITS:
4065*7304104dSAndroid Build Coastguard Worker if (is_debuginfo)
4066*7304104dSAndroid Build Coastguard Worker break;
4067*7304104dSAndroid Build Coastguard Worker FALLTHROUGH;
4068*7304104dSAndroid Build Coastguard Worker default:
4069*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4070*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' has unexpected type %d for an executable section\n"),
4071*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt), shdr->sh_type);
4072*7304104dSAndroid Build Coastguard Worker break;
4073*7304104dSAndroid Build Coastguard Worker }
4074*7304104dSAndroid Build Coastguard Worker
4075*7304104dSAndroid Build Coastguard Worker if (shdr->sh_flags & SHF_WRITE)
4076*7304104dSAndroid Build Coastguard Worker {
4077*7304104dSAndroid Build Coastguard Worker if (is_debuginfo && shdr->sh_type != SHT_NOBITS)
4078*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4079*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' must be of type NOBITS in debuginfo files\n"),
4080*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4081*7304104dSAndroid Build Coastguard Worker
4082*7304104dSAndroid Build Coastguard Worker if (!is_debuginfo
4083*7304104dSAndroid Build Coastguard Worker && !ebl_check_special_section (ebl, cnt, shdr,
4084*7304104dSAndroid Build Coastguard Worker section_name (ebl, cnt)))
4085*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4086*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' is both executable and writable\n"),
4087*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4088*7304104dSAndroid Build Coastguard Worker }
4089*7304104dSAndroid Build Coastguard Worker }
4090*7304104dSAndroid Build Coastguard Worker
4091*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0
4092*7304104dSAndroid Build Coastguard Worker && !is_debuginfo)
4093*7304104dSAndroid Build Coastguard Worker {
4094*7304104dSAndroid Build Coastguard Worker /* Make sure the section is contained in a loaded segment
4095*7304104dSAndroid Build Coastguard Worker and that the initialization part matches NOBITS sections. */
4096*7304104dSAndroid Build Coastguard Worker unsigned int pcnt;
4097*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr_mem;
4098*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr;
4099*7304104dSAndroid Build Coastguard Worker
4100*7304104dSAndroid Build Coastguard Worker for (pcnt = 0; pcnt < phnum; ++pcnt)
4101*7304104dSAndroid Build Coastguard Worker if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL
4102*7304104dSAndroid Build Coastguard Worker && ((phdr->p_type == PT_LOAD
4103*7304104dSAndroid Build Coastguard Worker && (shdr->sh_flags & SHF_TLS) == 0)
4104*7304104dSAndroid Build Coastguard Worker || (phdr->p_type == PT_TLS
4105*7304104dSAndroid Build Coastguard Worker && (shdr->sh_flags & SHF_TLS) != 0))
4106*7304104dSAndroid Build Coastguard Worker && phdr->p_offset <= shdr->sh_offset
4107*7304104dSAndroid Build Coastguard Worker && ((shdr->sh_offset - phdr->p_offset <= phdr->p_filesz
4108*7304104dSAndroid Build Coastguard Worker && (shdr->sh_offset - phdr->p_offset < phdr->p_filesz
4109*7304104dSAndroid Build Coastguard Worker || shdr->sh_size == 0))
4110*7304104dSAndroid Build Coastguard Worker || (shdr->sh_offset - phdr->p_offset < phdr->p_memsz
4111*7304104dSAndroid Build Coastguard Worker && shdr->sh_type == SHT_NOBITS)))
4112*7304104dSAndroid Build Coastguard Worker {
4113*7304104dSAndroid Build Coastguard Worker /* Found the segment. */
4114*7304104dSAndroid Build Coastguard Worker if (phdr->p_offset + phdr->p_memsz
4115*7304104dSAndroid Build Coastguard Worker < shdr->sh_offset + shdr->sh_size)
4116*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4117*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' not fully contained in segment of program header entry %d\n"),
4118*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt), pcnt);
4119*7304104dSAndroid Build Coastguard Worker
4120*7304104dSAndroid Build Coastguard Worker if (shdr->sh_type == SHT_NOBITS)
4121*7304104dSAndroid Build Coastguard Worker {
4122*7304104dSAndroid Build Coastguard Worker if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz
4123*7304104dSAndroid Build Coastguard Worker && !is_debuginfo)
4124*7304104dSAndroid Build Coastguard Worker {
4125*7304104dSAndroid Build Coastguard Worker if (!gnuld)
4126*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4127*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"),
4128*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt), pcnt);
4129*7304104dSAndroid Build Coastguard Worker else
4130*7304104dSAndroid Build Coastguard Worker {
4131*7304104dSAndroid Build Coastguard Worker /* This is truly horrible. GNU ld might put a
4132*7304104dSAndroid Build Coastguard Worker NOBITS section in the middle of a PT_LOAD
4133*7304104dSAndroid Build Coastguard Worker segment, assuming the next gap in the file
4134*7304104dSAndroid Build Coastguard Worker actually consists of zero bits...
4135*7304104dSAndroid Build Coastguard Worker So it really is like a PROGBITS section
4136*7304104dSAndroid Build Coastguard Worker where the data is all zeros. Check those
4137*7304104dSAndroid Build Coastguard Worker zero bytes are really there. */
4138*7304104dSAndroid Build Coastguard Worker bool bad;
4139*7304104dSAndroid Build Coastguard Worker Elf_Data *databits;
4140*7304104dSAndroid Build Coastguard Worker databits = elf_getdata_rawchunk (ebl->elf,
4141*7304104dSAndroid Build Coastguard Worker shdr->sh_offset,
4142*7304104dSAndroid Build Coastguard Worker shdr->sh_size,
4143*7304104dSAndroid Build Coastguard Worker ELF_T_BYTE);
4144*7304104dSAndroid Build Coastguard Worker bad = (databits == NULL
4145*7304104dSAndroid Build Coastguard Worker || databits->d_size != shdr->sh_size);
4146*7304104dSAndroid Build Coastguard Worker for (size_t idx = 0;
4147*7304104dSAndroid Build Coastguard Worker ! bad && idx < databits->d_size;
4148*7304104dSAndroid Build Coastguard Worker idx++)
4149*7304104dSAndroid Build Coastguard Worker bad = ((char *) databits->d_buf)[idx] != 0;
4150*7304104dSAndroid Build Coastguard Worker
4151*7304104dSAndroid Build Coastguard Worker if (bad)
4152*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4153*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d and file contents is non-zero\n"),
4154*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt), pcnt);
4155*7304104dSAndroid Build Coastguard Worker }
4156*7304104dSAndroid Build Coastguard Worker }
4157*7304104dSAndroid Build Coastguard Worker }
4158*7304104dSAndroid Build Coastguard Worker else
4159*7304104dSAndroid Build Coastguard Worker {
4160*7304104dSAndroid Build Coastguard Worker const GElf_Off end = phdr->p_offset + phdr->p_filesz;
4161*7304104dSAndroid Build Coastguard Worker if (shdr->sh_offset > end ||
4162*7304104dSAndroid Build Coastguard Worker (shdr->sh_offset == end && shdr->sh_size != 0))
4163*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4164*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"),
4165*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt), pcnt);
4166*7304104dSAndroid Build Coastguard Worker }
4167*7304104dSAndroid Build Coastguard Worker
4168*7304104dSAndroid Build Coastguard Worker if (shdr->sh_type != SHT_NOBITS)
4169*7304104dSAndroid Build Coastguard Worker {
4170*7304104dSAndroid Build Coastguard Worker if ((shdr->sh_flags & SHF_EXECINSTR) != 0)
4171*7304104dSAndroid Build Coastguard Worker {
4172*7304104dSAndroid Build Coastguard Worker segment_flags[pcnt] |= PF_X;
4173*7304104dSAndroid Build Coastguard Worker if ((phdr->p_flags & PF_X) == 0)
4174*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4175*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' is executable in nonexecutable segment %d\n"),
4176*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt), pcnt);
4177*7304104dSAndroid Build Coastguard Worker }
4178*7304104dSAndroid Build Coastguard Worker
4179*7304104dSAndroid Build Coastguard Worker if ((shdr->sh_flags & SHF_WRITE) != 0)
4180*7304104dSAndroid Build Coastguard Worker {
4181*7304104dSAndroid Build Coastguard Worker segment_flags[pcnt] |= PF_W;
4182*7304104dSAndroid Build Coastguard Worker if (0 /* XXX vdso images have this */
4183*7304104dSAndroid Build Coastguard Worker && (phdr->p_flags & PF_W) == 0)
4184*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4185*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' is writable in unwritable segment %d\n"),
4186*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt), pcnt);
4187*7304104dSAndroid Build Coastguard Worker }
4188*7304104dSAndroid Build Coastguard Worker }
4189*7304104dSAndroid Build Coastguard Worker
4190*7304104dSAndroid Build Coastguard Worker break;
4191*7304104dSAndroid Build Coastguard Worker }
4192*7304104dSAndroid Build Coastguard Worker
4193*7304104dSAndroid Build Coastguard Worker if (pcnt == phnum)
4194*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4195*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': alloc flag set but section not in any loaded segment\n"),
4196*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4197*7304104dSAndroid Build Coastguard Worker }
4198*7304104dSAndroid Build Coastguard Worker
4199*7304104dSAndroid Build Coastguard Worker if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB)
4200*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4201*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"),
4202*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4203*7304104dSAndroid Build Coastguard Worker
4204*7304104dSAndroid Build Coastguard Worker switch (shdr->sh_type)
4205*7304104dSAndroid Build Coastguard Worker {
4206*7304104dSAndroid Build Coastguard Worker case SHT_DYNSYM:
4207*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type == ET_REL)
4208*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4209*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"),
4210*7304104dSAndroid Build Coastguard Worker cnt, section_name (ebl, cnt));
4211*7304104dSAndroid Build Coastguard Worker FALLTHROUGH;
4212*7304104dSAndroid Build Coastguard Worker case SHT_SYMTAB:
4213*7304104dSAndroid Build Coastguard Worker check_symtab (ebl, ehdr, shdr, cnt);
4214*7304104dSAndroid Build Coastguard Worker break;
4215*7304104dSAndroid Build Coastguard Worker
4216*7304104dSAndroid Build Coastguard Worker case SHT_RELA:
4217*7304104dSAndroid Build Coastguard Worker check_rela (ebl, ehdr, shdr, cnt);
4218*7304104dSAndroid Build Coastguard Worker break;
4219*7304104dSAndroid Build Coastguard Worker
4220*7304104dSAndroid Build Coastguard Worker case SHT_REL:
4221*7304104dSAndroid Build Coastguard Worker check_rel (ebl, ehdr, shdr, cnt);
4222*7304104dSAndroid Build Coastguard Worker break;
4223*7304104dSAndroid Build Coastguard Worker
4224*7304104dSAndroid Build Coastguard Worker case SHT_RELR:
4225*7304104dSAndroid Build Coastguard Worker check_relr (ebl, ehdr, shdr, cnt);
4226*7304104dSAndroid Build Coastguard Worker break;
4227*7304104dSAndroid Build Coastguard Worker
4228*7304104dSAndroid Build Coastguard Worker case SHT_DYNAMIC:
4229*7304104dSAndroid Build Coastguard Worker check_dynamic (ebl, ehdr, shdr, cnt);
4230*7304104dSAndroid Build Coastguard Worker break;
4231*7304104dSAndroid Build Coastguard Worker
4232*7304104dSAndroid Build Coastguard Worker case SHT_SYMTAB_SHNDX:
4233*7304104dSAndroid Build Coastguard Worker check_symtab_shndx (ebl, ehdr, shdr, cnt);
4234*7304104dSAndroid Build Coastguard Worker break;
4235*7304104dSAndroid Build Coastguard Worker
4236*7304104dSAndroid Build Coastguard Worker case SHT_HASH:
4237*7304104dSAndroid Build Coastguard Worker check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
4238*7304104dSAndroid Build Coastguard Worker hash_idx = cnt;
4239*7304104dSAndroid Build Coastguard Worker break;
4240*7304104dSAndroid Build Coastguard Worker
4241*7304104dSAndroid Build Coastguard Worker case SHT_GNU_HASH:
4242*7304104dSAndroid Build Coastguard Worker check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
4243*7304104dSAndroid Build Coastguard Worker gnu_hash_idx = cnt;
4244*7304104dSAndroid Build Coastguard Worker break;
4245*7304104dSAndroid Build Coastguard Worker
4246*7304104dSAndroid Build Coastguard Worker case SHT_NULL:
4247*7304104dSAndroid Build Coastguard Worker check_null (ebl, shdr, cnt);
4248*7304104dSAndroid Build Coastguard Worker break;
4249*7304104dSAndroid Build Coastguard Worker
4250*7304104dSAndroid Build Coastguard Worker case SHT_GROUP:
4251*7304104dSAndroid Build Coastguard Worker check_group (ebl, ehdr, shdr, cnt);
4252*7304104dSAndroid Build Coastguard Worker break;
4253*7304104dSAndroid Build Coastguard Worker
4254*7304104dSAndroid Build Coastguard Worker case SHT_NOTE:
4255*7304104dSAndroid Build Coastguard Worker check_note_section (ebl, ehdr, shdr, cnt);
4256*7304104dSAndroid Build Coastguard Worker break;
4257*7304104dSAndroid Build Coastguard Worker
4258*7304104dSAndroid Build Coastguard Worker case SHT_GNU_versym:
4259*7304104dSAndroid Build Coastguard Worker /* We cannot process this section now since we have no guarantee
4260*7304104dSAndroid Build Coastguard Worker that the verneed and verdef sections have already been read.
4261*7304104dSAndroid Build Coastguard Worker Just remember the section index. */
4262*7304104dSAndroid Build Coastguard Worker if (versym_scnndx != 0)
4263*7304104dSAndroid Build Coastguard Worker ERROR (_("more than one version symbol table present\n"));
4264*7304104dSAndroid Build Coastguard Worker versym_scnndx = cnt;
4265*7304104dSAndroid Build Coastguard Worker break;
4266*7304104dSAndroid Build Coastguard Worker
4267*7304104dSAndroid Build Coastguard Worker case SHT_GNU_verneed:
4268*7304104dSAndroid Build Coastguard Worker check_verneed (ebl, shdr, cnt);
4269*7304104dSAndroid Build Coastguard Worker break;
4270*7304104dSAndroid Build Coastguard Worker
4271*7304104dSAndroid Build Coastguard Worker case SHT_GNU_verdef:
4272*7304104dSAndroid Build Coastguard Worker check_verdef (ebl, shdr, cnt);
4273*7304104dSAndroid Build Coastguard Worker break;
4274*7304104dSAndroid Build Coastguard Worker
4275*7304104dSAndroid Build Coastguard Worker case SHT_GNU_ATTRIBUTES:
4276*7304104dSAndroid Build Coastguard Worker check_attributes (ebl, ehdr, shdr, cnt);
4277*7304104dSAndroid Build Coastguard Worker break;
4278*7304104dSAndroid Build Coastguard Worker
4279*7304104dSAndroid Build Coastguard Worker default:
4280*7304104dSAndroid Build Coastguard Worker /* Nothing. */
4281*7304104dSAndroid Build Coastguard Worker break;
4282*7304104dSAndroid Build Coastguard Worker }
4283*7304104dSAndroid Build Coastguard Worker }
4284*7304104dSAndroid Build Coastguard Worker
4285*7304104dSAndroid Build Coastguard Worker if (has_interp_segment && !dot_interp_section)
4286*7304104dSAndroid Build Coastguard Worker ERROR (_("INTERP program header entry but no .interp section\n"));
4287*7304104dSAndroid Build Coastguard Worker
4288*7304104dSAndroid Build Coastguard Worker if (!is_debuginfo)
4289*7304104dSAndroid Build Coastguard Worker for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt)
4290*7304104dSAndroid Build Coastguard Worker {
4291*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr_mem;
4292*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
4293*7304104dSAndroid Build Coastguard Worker if (phdr != NULL && (phdr->p_type == PT_LOAD || phdr->p_type == PT_TLS))
4294*7304104dSAndroid Build Coastguard Worker {
4295*7304104dSAndroid Build Coastguard Worker if ((phdr->p_flags & PF_X) != 0
4296*7304104dSAndroid Build Coastguard Worker && (segment_flags[pcnt] & PF_X) == 0)
4297*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4298*7304104dSAndroid Build Coastguard Worker loadable segment [%u] is executable but contains no executable sections\n"),
4299*7304104dSAndroid Build Coastguard Worker pcnt);
4300*7304104dSAndroid Build Coastguard Worker
4301*7304104dSAndroid Build Coastguard Worker if ((phdr->p_flags & PF_W) != 0
4302*7304104dSAndroid Build Coastguard Worker && (segment_flags[pcnt] & PF_W) == 0)
4303*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4304*7304104dSAndroid Build Coastguard Worker loadable segment [%u] is writable but contains no writable sections\n"),
4305*7304104dSAndroid Build Coastguard Worker pcnt);
4306*7304104dSAndroid Build Coastguard Worker }
4307*7304104dSAndroid Build Coastguard Worker }
4308*7304104dSAndroid Build Coastguard Worker
4309*7304104dSAndroid Build Coastguard Worker free (segment_flags);
4310*7304104dSAndroid Build Coastguard Worker
4311*7304104dSAndroid Build Coastguard Worker if (version_namelist != NULL)
4312*7304104dSAndroid Build Coastguard Worker {
4313*7304104dSAndroid Build Coastguard Worker if (versym_scnndx == 0)
4314*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4315*7304104dSAndroid Build Coastguard Worker no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section exist\n"));
4316*7304104dSAndroid Build Coastguard Worker else
4317*7304104dSAndroid Build Coastguard Worker check_versym (ebl, versym_scnndx);
4318*7304104dSAndroid Build Coastguard Worker
4319*7304104dSAndroid Build Coastguard Worker /* Check for duplicate index numbers. */
4320*7304104dSAndroid Build Coastguard Worker do
4321*7304104dSAndroid Build Coastguard Worker {
4322*7304104dSAndroid Build Coastguard Worker struct version_namelist *runp = version_namelist->next;
4323*7304104dSAndroid Build Coastguard Worker while (runp != NULL)
4324*7304104dSAndroid Build Coastguard Worker {
4325*7304104dSAndroid Build Coastguard Worker if (version_namelist->ndx == runp->ndx)
4326*7304104dSAndroid Build Coastguard Worker {
4327*7304104dSAndroid Build Coastguard Worker ERROR (_("duplicate version index %d\n"),
4328*7304104dSAndroid Build Coastguard Worker (int) version_namelist->ndx);
4329*7304104dSAndroid Build Coastguard Worker break;
4330*7304104dSAndroid Build Coastguard Worker }
4331*7304104dSAndroid Build Coastguard Worker runp = runp->next;
4332*7304104dSAndroid Build Coastguard Worker }
4333*7304104dSAndroid Build Coastguard Worker
4334*7304104dSAndroid Build Coastguard Worker struct version_namelist *old = version_namelist;
4335*7304104dSAndroid Build Coastguard Worker version_namelist = version_namelist->next;
4336*7304104dSAndroid Build Coastguard Worker free (old);
4337*7304104dSAndroid Build Coastguard Worker }
4338*7304104dSAndroid Build Coastguard Worker while (version_namelist != NULL);
4339*7304104dSAndroid Build Coastguard Worker }
4340*7304104dSAndroid Build Coastguard Worker else if (versym_scnndx != 0)
4341*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4342*7304104dSAndroid Build Coastguard Worker .gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"));
4343*7304104dSAndroid Build Coastguard Worker
4344*7304104dSAndroid Build Coastguard Worker if (hash_idx != 0 && gnu_hash_idx != 0)
4345*7304104dSAndroid Build Coastguard Worker compare_hash_gnu_hash (ebl, ehdr, hash_idx, gnu_hash_idx);
4346*7304104dSAndroid Build Coastguard Worker
4347*7304104dSAndroid Build Coastguard Worker free (scnref);
4348*7304104dSAndroid Build Coastguard Worker }
4349*7304104dSAndroid Build Coastguard Worker
4350*7304104dSAndroid Build Coastguard Worker
4351*7304104dSAndroid Build Coastguard Worker static GElf_Off
check_note_data(Ebl * ebl,const GElf_Ehdr * ehdr,Elf_Data * data,int shndx,int phndx,GElf_Off start)4352*7304104dSAndroid Build Coastguard Worker check_note_data (Ebl *ebl, const GElf_Ehdr *ehdr,
4353*7304104dSAndroid Build Coastguard Worker Elf_Data *data, int shndx, int phndx, GElf_Off start)
4354*7304104dSAndroid Build Coastguard Worker {
4355*7304104dSAndroid Build Coastguard Worker size_t offset = 0;
4356*7304104dSAndroid Build Coastguard Worker size_t last_offset = 0;
4357*7304104dSAndroid Build Coastguard Worker GElf_Nhdr nhdr;
4358*7304104dSAndroid Build Coastguard Worker size_t name_offset;
4359*7304104dSAndroid Build Coastguard Worker size_t desc_offset;
4360*7304104dSAndroid Build Coastguard Worker while (offset < data->d_size
4361*7304104dSAndroid Build Coastguard Worker && (offset = gelf_getnote (data, offset,
4362*7304104dSAndroid Build Coastguard Worker &nhdr, &name_offset, &desc_offset)) > 0)
4363*7304104dSAndroid Build Coastguard Worker {
4364*7304104dSAndroid Build Coastguard Worker last_offset = offset;
4365*7304104dSAndroid Build Coastguard Worker
4366*7304104dSAndroid Build Coastguard Worker /* Make sure it is one of the note types we know about. */
4367*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type == ET_CORE)
4368*7304104dSAndroid Build Coastguard Worker switch (nhdr.n_type)
4369*7304104dSAndroid Build Coastguard Worker {
4370*7304104dSAndroid Build Coastguard Worker case NT_PRSTATUS:
4371*7304104dSAndroid Build Coastguard Worker case NT_FPREGSET:
4372*7304104dSAndroid Build Coastguard Worker case NT_PRPSINFO:
4373*7304104dSAndroid Build Coastguard Worker case NT_TASKSTRUCT: /* NT_PRXREG on Solaris. */
4374*7304104dSAndroid Build Coastguard Worker case NT_PLATFORM:
4375*7304104dSAndroid Build Coastguard Worker case NT_AUXV:
4376*7304104dSAndroid Build Coastguard Worker case NT_GWINDOWS:
4377*7304104dSAndroid Build Coastguard Worker case NT_ASRS:
4378*7304104dSAndroid Build Coastguard Worker case NT_PSTATUS:
4379*7304104dSAndroid Build Coastguard Worker case NT_PSINFO:
4380*7304104dSAndroid Build Coastguard Worker case NT_PRCRED:
4381*7304104dSAndroid Build Coastguard Worker case NT_UTSNAME:
4382*7304104dSAndroid Build Coastguard Worker case NT_LWPSTATUS:
4383*7304104dSAndroid Build Coastguard Worker case NT_LWPSINFO:
4384*7304104dSAndroid Build Coastguard Worker case NT_PRFPXREG:
4385*7304104dSAndroid Build Coastguard Worker /* Known type. */
4386*7304104dSAndroid Build Coastguard Worker break;
4387*7304104dSAndroid Build Coastguard Worker
4388*7304104dSAndroid Build Coastguard Worker default:
4389*7304104dSAndroid Build Coastguard Worker if (shndx == 0)
4390*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4391*7304104dSAndroid Build Coastguard Worker phdr[%d]: unknown core file note type %" PRIu32 " at offset %" PRIu64 "\n"),
4392*7304104dSAndroid Build Coastguard Worker phndx, (uint32_t) nhdr.n_type, start + offset);
4393*7304104dSAndroid Build Coastguard Worker else
4394*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4395*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': unknown core file note type %" PRIu32
4396*7304104dSAndroid Build Coastguard Worker " at offset %zu\n"),
4397*7304104dSAndroid Build Coastguard Worker shndx, section_name (ebl, shndx),
4398*7304104dSAndroid Build Coastguard Worker (uint32_t) nhdr.n_type, offset);
4399*7304104dSAndroid Build Coastguard Worker }
4400*7304104dSAndroid Build Coastguard Worker else
4401*7304104dSAndroid Build Coastguard Worker switch (nhdr.n_type)
4402*7304104dSAndroid Build Coastguard Worker {
4403*7304104dSAndroid Build Coastguard Worker case NT_GNU_ABI_TAG:
4404*7304104dSAndroid Build Coastguard Worker case NT_GNU_HWCAP:
4405*7304104dSAndroid Build Coastguard Worker case NT_GNU_BUILD_ID:
4406*7304104dSAndroid Build Coastguard Worker case NT_GNU_GOLD_VERSION:
4407*7304104dSAndroid Build Coastguard Worker case NT_GNU_PROPERTY_TYPE_0:
4408*7304104dSAndroid Build Coastguard Worker if (nhdr.n_namesz == sizeof ELF_NOTE_GNU
4409*7304104dSAndroid Build Coastguard Worker && strcmp (data->d_buf + name_offset, ELF_NOTE_GNU) == 0)
4410*7304104dSAndroid Build Coastguard Worker break;
4411*7304104dSAndroid Build Coastguard Worker else
4412*7304104dSAndroid Build Coastguard Worker {
4413*7304104dSAndroid Build Coastguard Worker /* NT_VERSION is 1, same as NT_GNU_ABI_TAG. It has no
4414*7304104dSAndroid Build Coastguard Worker descriptor and (ab)uses the name as version string. */
4415*7304104dSAndroid Build Coastguard Worker if (nhdr.n_descsz == 0 && nhdr.n_type == NT_VERSION)
4416*7304104dSAndroid Build Coastguard Worker break;
4417*7304104dSAndroid Build Coastguard Worker }
4418*7304104dSAndroid Build Coastguard Worker goto unknown_note;
4419*7304104dSAndroid Build Coastguard Worker
4420*7304104dSAndroid Build Coastguard Worker case NT_GNU_BUILD_ATTRIBUTE_OPEN:
4421*7304104dSAndroid Build Coastguard Worker case NT_GNU_BUILD_ATTRIBUTE_FUNC:
4422*7304104dSAndroid Build Coastguard Worker /* GNU Build Attributes store most data in the owner
4423*7304104dSAndroid Build Coastguard Worker name, which must start with the
4424*7304104dSAndroid Build Coastguard Worker ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX "GA". */
4425*7304104dSAndroid Build Coastguard Worker if (nhdr.n_namesz >= sizeof ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX
4426*7304104dSAndroid Build Coastguard Worker && strncmp (data->d_buf + name_offset,
4427*7304104dSAndroid Build Coastguard Worker ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX,
4428*7304104dSAndroid Build Coastguard Worker strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0)
4429*7304104dSAndroid Build Coastguard Worker break;
4430*7304104dSAndroid Build Coastguard Worker else
4431*7304104dSAndroid Build Coastguard Worker goto unknown_note;
4432*7304104dSAndroid Build Coastguard Worker
4433*7304104dSAndroid Build Coastguard Worker case NT_FDO_PACKAGING_METADATA:
4434*7304104dSAndroid Build Coastguard Worker if (nhdr.n_namesz == sizeof ELF_NOTE_FDO
4435*7304104dSAndroid Build Coastguard Worker && strcmp (data->d_buf + name_offset, ELF_NOTE_FDO) == 0)
4436*7304104dSAndroid Build Coastguard Worker break;
4437*7304104dSAndroid Build Coastguard Worker else
4438*7304104dSAndroid Build Coastguard Worker goto unknown_note;
4439*7304104dSAndroid Build Coastguard Worker
4440*7304104dSAndroid Build Coastguard Worker case 0:
4441*7304104dSAndroid Build Coastguard Worker /* Linux vDSOs use a type 0 note for the kernel version word. */
4442*7304104dSAndroid Build Coastguard Worker if (nhdr.n_namesz == sizeof "Linux"
4443*7304104dSAndroid Build Coastguard Worker && !memcmp (data->d_buf + name_offset, "Linux", sizeof "Linux"))
4444*7304104dSAndroid Build Coastguard Worker break;
4445*7304104dSAndroid Build Coastguard Worker FALLTHROUGH;
4446*7304104dSAndroid Build Coastguard Worker default:
4447*7304104dSAndroid Build Coastguard Worker {
4448*7304104dSAndroid Build Coastguard Worker unknown_note:
4449*7304104dSAndroid Build Coastguard Worker if (shndx == 0)
4450*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4451*7304104dSAndroid Build Coastguard Worker phdr[%d]: unknown object file note type %" PRIu32 " with owner name '%s' at offset %zu\n"),
4452*7304104dSAndroid Build Coastguard Worker phndx, (uint32_t) nhdr.n_type,
4453*7304104dSAndroid Build Coastguard Worker (char *) data->d_buf + name_offset, offset);
4454*7304104dSAndroid Build Coastguard Worker else
4455*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4456*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': unknown object file note type %" PRIu32
4457*7304104dSAndroid Build Coastguard Worker " with owner name '%s' at offset %zu\n"),
4458*7304104dSAndroid Build Coastguard Worker shndx, section_name (ebl, shndx),
4459*7304104dSAndroid Build Coastguard Worker (uint32_t) nhdr.n_type,
4460*7304104dSAndroid Build Coastguard Worker (char *) data->d_buf + name_offset, offset);
4461*7304104dSAndroid Build Coastguard Worker }
4462*7304104dSAndroid Build Coastguard Worker }
4463*7304104dSAndroid Build Coastguard Worker }
4464*7304104dSAndroid Build Coastguard Worker
4465*7304104dSAndroid Build Coastguard Worker return last_offset;
4466*7304104dSAndroid Build Coastguard Worker }
4467*7304104dSAndroid Build Coastguard Worker
4468*7304104dSAndroid Build Coastguard Worker
4469*7304104dSAndroid Build Coastguard Worker static void
check_note(Ebl * ebl,GElf_Ehdr * ehdr,GElf_Phdr * phdr,int cnt)4470*7304104dSAndroid Build Coastguard Worker check_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt)
4471*7304104dSAndroid Build Coastguard Worker {
4472*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
4473*7304104dSAndroid Build Coastguard Worker && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
4474*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4475*7304104dSAndroid Build Coastguard Worker phdr[%d]: no note entries defined for the type of file\n"),
4476*7304104dSAndroid Build Coastguard Worker cnt);
4477*7304104dSAndroid Build Coastguard Worker
4478*7304104dSAndroid Build Coastguard Worker if (is_debuginfo)
4479*7304104dSAndroid Build Coastguard Worker /* The p_offset values in a separate debug file are bogus. */
4480*7304104dSAndroid Build Coastguard Worker return;
4481*7304104dSAndroid Build Coastguard Worker
4482*7304104dSAndroid Build Coastguard Worker if (phdr->p_filesz == 0)
4483*7304104dSAndroid Build Coastguard Worker return;
4484*7304104dSAndroid Build Coastguard Worker
4485*7304104dSAndroid Build Coastguard Worker GElf_Off notes_size = 0;
4486*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata_rawchunk (ebl->elf,
4487*7304104dSAndroid Build Coastguard Worker phdr->p_offset, phdr->p_filesz,
4488*7304104dSAndroid Build Coastguard Worker (phdr->p_align == 8
4489*7304104dSAndroid Build Coastguard Worker ? ELF_T_NHDR8 : ELF_T_NHDR));
4490*7304104dSAndroid Build Coastguard Worker if (data != NULL && data->d_buf != NULL)
4491*7304104dSAndroid Build Coastguard Worker notes_size = check_note_data (ebl, ehdr, data, 0, cnt, phdr->p_offset);
4492*7304104dSAndroid Build Coastguard Worker
4493*7304104dSAndroid Build Coastguard Worker if (notes_size == 0)
4494*7304104dSAndroid Build Coastguard Worker ERROR (_("phdr[%d]: cannot get content of note section: %s\n"),
4495*7304104dSAndroid Build Coastguard Worker cnt, elf_errmsg (-1));
4496*7304104dSAndroid Build Coastguard Worker else if (notes_size != phdr->p_filesz)
4497*7304104dSAndroid Build Coastguard Worker ERROR (_("phdr[%d]: extra %" PRIu64 " bytes after last note\n"),
4498*7304104dSAndroid Build Coastguard Worker cnt, phdr->p_filesz - notes_size);
4499*7304104dSAndroid Build Coastguard Worker }
4500*7304104dSAndroid Build Coastguard Worker
4501*7304104dSAndroid Build Coastguard Worker
4502*7304104dSAndroid Build Coastguard Worker static void
check_note_section(Ebl * ebl,GElf_Ehdr * ehdr,GElf_Shdr * shdr,int idx)4503*7304104dSAndroid Build Coastguard Worker check_note_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
4504*7304104dSAndroid Build Coastguard Worker {
4505*7304104dSAndroid Build Coastguard Worker if (shdr->sh_size == 0)
4506*7304104dSAndroid Build Coastguard Worker return;
4507*7304104dSAndroid Build Coastguard Worker
4508*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
4509*7304104dSAndroid Build Coastguard Worker if (data == NULL || data->d_buf == NULL)
4510*7304104dSAndroid Build Coastguard Worker {
4511*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get section data\n"),
4512*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
4513*7304104dSAndroid Build Coastguard Worker return;
4514*7304104dSAndroid Build Coastguard Worker }
4515*7304104dSAndroid Build Coastguard Worker
4516*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
4517*7304104dSAndroid Build Coastguard Worker && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
4518*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4519*7304104dSAndroid Build Coastguard Worker section [%2d] '%s': no note entries defined for the type of file\n"),
4520*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
4521*7304104dSAndroid Build Coastguard Worker
4522*7304104dSAndroid Build Coastguard Worker GElf_Off notes_size = check_note_data (ebl, ehdr, data, idx, 0, 0);
4523*7304104dSAndroid Build Coastguard Worker
4524*7304104dSAndroid Build Coastguard Worker if (notes_size == 0)
4525*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': cannot get content of note section\n"),
4526*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx));
4527*7304104dSAndroid Build Coastguard Worker else if (notes_size != shdr->sh_size)
4528*7304104dSAndroid Build Coastguard Worker ERROR (_("section [%2d] '%s': extra %" PRIu64
4529*7304104dSAndroid Build Coastguard Worker " bytes after last note\n"),
4530*7304104dSAndroid Build Coastguard Worker idx, section_name (ebl, idx), shdr->sh_size - notes_size);
4531*7304104dSAndroid Build Coastguard Worker }
4532*7304104dSAndroid Build Coastguard Worker
4533*7304104dSAndroid Build Coastguard Worker
4534*7304104dSAndroid Build Coastguard Worker /* Index of the PT_GNU_EH_FRAME program eader entry. */
4535*7304104dSAndroid Build Coastguard Worker static int pt_gnu_eh_frame_pndx;
4536*7304104dSAndroid Build Coastguard Worker
4537*7304104dSAndroid Build Coastguard Worker
4538*7304104dSAndroid Build Coastguard Worker static void
check_program_header(Ebl * ebl,GElf_Ehdr * ehdr)4539*7304104dSAndroid Build Coastguard Worker check_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
4540*7304104dSAndroid Build Coastguard Worker {
4541*7304104dSAndroid Build Coastguard Worker if (ehdr->e_phoff == 0)
4542*7304104dSAndroid Build Coastguard Worker return;
4543*7304104dSAndroid Build Coastguard Worker
4544*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
4545*7304104dSAndroid Build Coastguard Worker && ehdr->e_type != ET_CORE)
4546*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4547*7304104dSAndroid Build Coastguard Worker only executables, shared objects, and core files can have program headers\n"));
4548*7304104dSAndroid Build Coastguard Worker
4549*7304104dSAndroid Build Coastguard Worker int num_pt_interp = 0;
4550*7304104dSAndroid Build Coastguard Worker int num_pt_tls = 0;
4551*7304104dSAndroid Build Coastguard Worker int num_pt_relro = 0;
4552*7304104dSAndroid Build Coastguard Worker
4553*7304104dSAndroid Build Coastguard Worker for (unsigned int cnt = 0; cnt < phnum; ++cnt)
4554*7304104dSAndroid Build Coastguard Worker {
4555*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr_mem;
4556*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr;
4557*7304104dSAndroid Build Coastguard Worker
4558*7304104dSAndroid Build Coastguard Worker phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
4559*7304104dSAndroid Build Coastguard Worker if (phdr == NULL)
4560*7304104dSAndroid Build Coastguard Worker {
4561*7304104dSAndroid Build Coastguard Worker ERROR (_("cannot get program header entry %d: %s\n"),
4562*7304104dSAndroid Build Coastguard Worker cnt, elf_errmsg (-1));
4563*7304104dSAndroid Build Coastguard Worker continue;
4564*7304104dSAndroid Build Coastguard Worker }
4565*7304104dSAndroid Build Coastguard Worker
4566*7304104dSAndroid Build Coastguard Worker if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME
4567*7304104dSAndroid Build Coastguard Worker && phdr->p_type != PT_GNU_STACK && phdr->p_type != PT_GNU_RELRO
4568*7304104dSAndroid Build Coastguard Worker && phdr->p_type != PT_GNU_PROPERTY
4569*7304104dSAndroid Build Coastguard Worker /* Check for a known machine-specific type. */
4570*7304104dSAndroid Build Coastguard Worker && ebl_segment_type_name (ebl, phdr->p_type, NULL, 0) == NULL)
4571*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4572*7304104dSAndroid Build Coastguard Worker program header entry %d: unknown program header entry type %#" PRIx64 "\n"),
4573*7304104dSAndroid Build Coastguard Worker cnt, (uint64_t) phdr->p_type);
4574*7304104dSAndroid Build Coastguard Worker
4575*7304104dSAndroid Build Coastguard Worker if (phdr->p_type == PT_LOAD)
4576*7304104dSAndroid Build Coastguard Worker has_loadable_segment = true;
4577*7304104dSAndroid Build Coastguard Worker else if (phdr->p_type == PT_INTERP)
4578*7304104dSAndroid Build Coastguard Worker {
4579*7304104dSAndroid Build Coastguard Worker if (++num_pt_interp != 1)
4580*7304104dSAndroid Build Coastguard Worker {
4581*7304104dSAndroid Build Coastguard Worker if (num_pt_interp == 2)
4582*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4583*7304104dSAndroid Build Coastguard Worker more than one INTERP entry in program header\n"));
4584*7304104dSAndroid Build Coastguard Worker }
4585*7304104dSAndroid Build Coastguard Worker has_interp_segment = true;
4586*7304104dSAndroid Build Coastguard Worker }
4587*7304104dSAndroid Build Coastguard Worker else if (phdr->p_type == PT_TLS)
4588*7304104dSAndroid Build Coastguard Worker {
4589*7304104dSAndroid Build Coastguard Worker if (++num_pt_tls == 2)
4590*7304104dSAndroid Build Coastguard Worker ERROR (_("more than one TLS entry in program header\n"));
4591*7304104dSAndroid Build Coastguard Worker }
4592*7304104dSAndroid Build Coastguard Worker else if (phdr->p_type == PT_NOTE)
4593*7304104dSAndroid Build Coastguard Worker check_note (ebl, ehdr, phdr, cnt);
4594*7304104dSAndroid Build Coastguard Worker else if (phdr->p_type == PT_DYNAMIC)
4595*7304104dSAndroid Build Coastguard Worker {
4596*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type == ET_EXEC && ! has_interp_segment)
4597*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4598*7304104dSAndroid Build Coastguard Worker static executable cannot have dynamic sections\n"));
4599*7304104dSAndroid Build Coastguard Worker else
4600*7304104dSAndroid Build Coastguard Worker {
4601*7304104dSAndroid Build Coastguard Worker /* Check that the .dynamic section, if it exists, has
4602*7304104dSAndroid Build Coastguard Worker the same address. */
4603*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = NULL;
4604*7304104dSAndroid Build Coastguard Worker while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
4605*7304104dSAndroid Build Coastguard Worker {
4606*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
4607*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
4608*7304104dSAndroid Build Coastguard Worker if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
4609*7304104dSAndroid Build Coastguard Worker {
4610*7304104dSAndroid Build Coastguard Worker if (phdr->p_offset != shdr->sh_offset)
4611*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4612*7304104dSAndroid Build Coastguard Worker dynamic section reference in program header has wrong offset\n"));
4613*7304104dSAndroid Build Coastguard Worker if (phdr->p_memsz != shdr->sh_size)
4614*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4615*7304104dSAndroid Build Coastguard Worker dynamic section size mismatch in program and section header\n"));
4616*7304104dSAndroid Build Coastguard Worker break;
4617*7304104dSAndroid Build Coastguard Worker }
4618*7304104dSAndroid Build Coastguard Worker }
4619*7304104dSAndroid Build Coastguard Worker }
4620*7304104dSAndroid Build Coastguard Worker }
4621*7304104dSAndroid Build Coastguard Worker else if (phdr->p_type == PT_GNU_RELRO)
4622*7304104dSAndroid Build Coastguard Worker {
4623*7304104dSAndroid Build Coastguard Worker if (++num_pt_relro == 2)
4624*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4625*7304104dSAndroid Build Coastguard Worker more than one GNU_RELRO entry in program header\n"));
4626*7304104dSAndroid Build Coastguard Worker else
4627*7304104dSAndroid Build Coastguard Worker {
4628*7304104dSAndroid Build Coastguard Worker /* Check that the region is in a writable segment. */
4629*7304104dSAndroid Build Coastguard Worker unsigned int inner;
4630*7304104dSAndroid Build Coastguard Worker for (inner = 0; inner < phnum; ++inner)
4631*7304104dSAndroid Build Coastguard Worker {
4632*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr2_mem;
4633*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr2;
4634*7304104dSAndroid Build Coastguard Worker
4635*7304104dSAndroid Build Coastguard Worker phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
4636*7304104dSAndroid Build Coastguard Worker if (phdr2 == NULL)
4637*7304104dSAndroid Build Coastguard Worker continue;
4638*7304104dSAndroid Build Coastguard Worker
4639*7304104dSAndroid Build Coastguard Worker if (phdr2->p_type == PT_LOAD
4640*7304104dSAndroid Build Coastguard Worker && phdr->p_vaddr >= phdr2->p_vaddr
4641*7304104dSAndroid Build Coastguard Worker && (phdr->p_vaddr + phdr->p_memsz
4642*7304104dSAndroid Build Coastguard Worker <= phdr2->p_vaddr + phdr2->p_memsz))
4643*7304104dSAndroid Build Coastguard Worker {
4644*7304104dSAndroid Build Coastguard Worker if ((phdr2->p_flags & PF_W) == 0)
4645*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4646*7304104dSAndroid Build Coastguard Worker loadable segment GNU_RELRO applies to is not writable\n"));
4647*7304104dSAndroid Build Coastguard Worker /* Unless fully covered, relro flags could be a
4648*7304104dSAndroid Build Coastguard Worker subset of the phdrs2 flags. For example the load
4649*7304104dSAndroid Build Coastguard Worker segment could also have PF_X set. */
4650*7304104dSAndroid Build Coastguard Worker if (phdr->p_vaddr == phdr2->p_vaddr
4651*7304104dSAndroid Build Coastguard Worker && (phdr->p_vaddr + phdr->p_memsz
4652*7304104dSAndroid Build Coastguard Worker == phdr2->p_vaddr + phdr2->p_memsz))
4653*7304104dSAndroid Build Coastguard Worker {
4654*7304104dSAndroid Build Coastguard Worker if ((phdr2->p_flags & ~PF_W)
4655*7304104dSAndroid Build Coastguard Worker != (phdr->p_flags & ~PF_W))
4656*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4657*7304104dSAndroid Build Coastguard Worker loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"),
4658*7304104dSAndroid Build Coastguard Worker cnt, inner);
4659*7304104dSAndroid Build Coastguard Worker }
4660*7304104dSAndroid Build Coastguard Worker else
4661*7304104dSAndroid Build Coastguard Worker {
4662*7304104dSAndroid Build Coastguard Worker if ((phdr->p_flags & ~phdr2->p_flags) != 0)
4663*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4664*7304104dSAndroid Build Coastguard Worker GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n"),
4665*7304104dSAndroid Build Coastguard Worker inner, cnt);
4666*7304104dSAndroid Build Coastguard Worker }
4667*7304104dSAndroid Build Coastguard Worker break;
4668*7304104dSAndroid Build Coastguard Worker }
4669*7304104dSAndroid Build Coastguard Worker }
4670*7304104dSAndroid Build Coastguard Worker
4671*7304104dSAndroid Build Coastguard Worker if (inner >= phnum)
4672*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4673*7304104dSAndroid Build Coastguard Worker %s segment not contained in a loaded segment\n"), "GNU_RELRO");
4674*7304104dSAndroid Build Coastguard Worker }
4675*7304104dSAndroid Build Coastguard Worker }
4676*7304104dSAndroid Build Coastguard Worker else if (phdr->p_type == PT_PHDR)
4677*7304104dSAndroid Build Coastguard Worker {
4678*7304104dSAndroid Build Coastguard Worker /* Check that the region is in a writable segment. */
4679*7304104dSAndroid Build Coastguard Worker unsigned int inner;
4680*7304104dSAndroid Build Coastguard Worker for (inner = 0; inner < phnum; ++inner)
4681*7304104dSAndroid Build Coastguard Worker {
4682*7304104dSAndroid Build Coastguard Worker GElf_Phdr phdr2_mem;
4683*7304104dSAndroid Build Coastguard Worker GElf_Phdr *phdr2;
4684*7304104dSAndroid Build Coastguard Worker
4685*7304104dSAndroid Build Coastguard Worker phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
4686*7304104dSAndroid Build Coastguard Worker if (phdr2 != NULL
4687*7304104dSAndroid Build Coastguard Worker && phdr2->p_type == PT_LOAD
4688*7304104dSAndroid Build Coastguard Worker && phdr->p_vaddr >= phdr2->p_vaddr
4689*7304104dSAndroid Build Coastguard Worker && (phdr->p_vaddr + phdr->p_memsz
4690*7304104dSAndroid Build Coastguard Worker <= phdr2->p_vaddr + phdr2->p_memsz))
4691*7304104dSAndroid Build Coastguard Worker break;
4692*7304104dSAndroid Build Coastguard Worker }
4693*7304104dSAndroid Build Coastguard Worker
4694*7304104dSAndroid Build Coastguard Worker if (inner >= phnum)
4695*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4696*7304104dSAndroid Build Coastguard Worker %s segment not contained in a loaded segment\n"), "PHDR");
4697*7304104dSAndroid Build Coastguard Worker
4698*7304104dSAndroid Build Coastguard Worker /* Check that offset in segment corresponds to offset in ELF
4699*7304104dSAndroid Build Coastguard Worker header. */
4700*7304104dSAndroid Build Coastguard Worker if (phdr->p_offset != ehdr->e_phoff)
4701*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4702*7304104dSAndroid Build Coastguard Worker program header offset in ELF header and PHDR entry do not match"));
4703*7304104dSAndroid Build Coastguard Worker }
4704*7304104dSAndroid Build Coastguard Worker else if (phdr->p_type == PT_GNU_EH_FRAME)
4705*7304104dSAndroid Build Coastguard Worker {
4706*7304104dSAndroid Build Coastguard Worker /* If there is an .eh_frame_hdr section it must be
4707*7304104dSAndroid Build Coastguard Worker referenced by this program header entry. */
4708*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = NULL;
4709*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
4710*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = NULL;
4711*7304104dSAndroid Build Coastguard Worker bool any = false;
4712*7304104dSAndroid Build Coastguard Worker while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
4713*7304104dSAndroid Build Coastguard Worker {
4714*7304104dSAndroid Build Coastguard Worker any = true;
4715*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (scn, &shdr_mem);
4716*7304104dSAndroid Build Coastguard Worker if (shdr != NULL
4717*7304104dSAndroid Build Coastguard Worker && ((is_debuginfo && shdr->sh_type == SHT_NOBITS)
4718*7304104dSAndroid Build Coastguard Worker || (! is_debuginfo
4719*7304104dSAndroid Build Coastguard Worker && (shdr->sh_type == SHT_PROGBITS
4720*7304104dSAndroid Build Coastguard Worker || shdr->sh_type == SHT_X86_64_UNWIND)))
4721*7304104dSAndroid Build Coastguard Worker && elf_strptr (ebl->elf, shstrndx, shdr->sh_name) != NULL
4722*7304104dSAndroid Build Coastguard Worker && ! strcmp (".eh_frame_hdr",
4723*7304104dSAndroid Build Coastguard Worker elf_strptr (ebl->elf, shstrndx, shdr->sh_name)))
4724*7304104dSAndroid Build Coastguard Worker {
4725*7304104dSAndroid Build Coastguard Worker if (! is_debuginfo)
4726*7304104dSAndroid Build Coastguard Worker {
4727*7304104dSAndroid Build Coastguard Worker if (phdr->p_offset != shdr->sh_offset)
4728*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4729*7304104dSAndroid Build Coastguard Worker call frame search table reference in program header has wrong offset\n"));
4730*7304104dSAndroid Build Coastguard Worker if (phdr->p_memsz != shdr->sh_size)
4731*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4732*7304104dSAndroid Build Coastguard Worker call frame search table size mismatch in program and section header\n"));
4733*7304104dSAndroid Build Coastguard Worker }
4734*7304104dSAndroid Build Coastguard Worker break;
4735*7304104dSAndroid Build Coastguard Worker }
4736*7304104dSAndroid Build Coastguard Worker }
4737*7304104dSAndroid Build Coastguard Worker
4738*7304104dSAndroid Build Coastguard Worker if (scn == NULL)
4739*7304104dSAndroid Build Coastguard Worker {
4740*7304104dSAndroid Build Coastguard Worker /* If there is no section header table we don't
4741*7304104dSAndroid Build Coastguard Worker complain. But if there is one there should be an
4742*7304104dSAndroid Build Coastguard Worker entry for .eh_frame_hdr. */
4743*7304104dSAndroid Build Coastguard Worker if (any)
4744*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4745*7304104dSAndroid Build Coastguard Worker PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n"));
4746*7304104dSAndroid Build Coastguard Worker }
4747*7304104dSAndroid Build Coastguard Worker else
4748*7304104dSAndroid Build Coastguard Worker {
4749*7304104dSAndroid Build Coastguard Worker /* The section must be allocated and not be writable and
4750*7304104dSAndroid Build Coastguard Worker executable. */
4751*7304104dSAndroid Build Coastguard Worker if ((phdr->p_flags & PF_R) == 0)
4752*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4753*7304104dSAndroid Build Coastguard Worker call frame search table must be allocated\n"));
4754*7304104dSAndroid Build Coastguard Worker else if (shdr != NULL && (shdr->sh_flags & SHF_ALLOC) == 0)
4755*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4756*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' must be allocated\n"), elf_ndxscn (scn), ".eh_frame_hdr");
4757*7304104dSAndroid Build Coastguard Worker
4758*7304104dSAndroid Build Coastguard Worker if ((phdr->p_flags & PF_W) != 0)
4759*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4760*7304104dSAndroid Build Coastguard Worker call frame search table must not be writable\n"));
4761*7304104dSAndroid Build Coastguard Worker else if (shdr != NULL && (shdr->sh_flags & SHF_WRITE) != 0)
4762*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4763*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' must not be writable\n"),
4764*7304104dSAndroid Build Coastguard Worker elf_ndxscn (scn), ".eh_frame_hdr");
4765*7304104dSAndroid Build Coastguard Worker
4766*7304104dSAndroid Build Coastguard Worker if ((phdr->p_flags & PF_X) != 0)
4767*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4768*7304104dSAndroid Build Coastguard Worker call frame search table must not be executable\n"));
4769*7304104dSAndroid Build Coastguard Worker else if (shdr != NULL && (shdr->sh_flags & SHF_EXECINSTR) != 0)
4770*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4771*7304104dSAndroid Build Coastguard Worker section [%2zu] '%s' must not be executable\n"),
4772*7304104dSAndroid Build Coastguard Worker elf_ndxscn (scn), ".eh_frame_hdr");
4773*7304104dSAndroid Build Coastguard Worker }
4774*7304104dSAndroid Build Coastguard Worker
4775*7304104dSAndroid Build Coastguard Worker /* Remember which entry this is. */
4776*7304104dSAndroid Build Coastguard Worker pt_gnu_eh_frame_pndx = cnt;
4777*7304104dSAndroid Build Coastguard Worker }
4778*7304104dSAndroid Build Coastguard Worker
4779*7304104dSAndroid Build Coastguard Worker if (phdr->p_filesz > phdr->p_memsz
4780*7304104dSAndroid Build Coastguard Worker && (phdr->p_memsz != 0
4781*7304104dSAndroid Build Coastguard Worker || (phdr->p_type != PT_NOTE
4782*7304104dSAndroid Build Coastguard Worker && !(ehdr->e_machine == EM_RISCV
4783*7304104dSAndroid Build Coastguard Worker && phdr->p_type == PT_RISCV_ATTRIBUTES))))
4784*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4785*7304104dSAndroid Build Coastguard Worker program header entry %d: file size greater than memory size\n"),
4786*7304104dSAndroid Build Coastguard Worker cnt);
4787*7304104dSAndroid Build Coastguard Worker
4788*7304104dSAndroid Build Coastguard Worker if (phdr->p_align > 1)
4789*7304104dSAndroid Build Coastguard Worker {
4790*7304104dSAndroid Build Coastguard Worker if (!powerof2 (phdr->p_align))
4791*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4792*7304104dSAndroid Build Coastguard Worker program header entry %d: alignment not a power of 2\n"), cnt);
4793*7304104dSAndroid Build Coastguard Worker else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0)
4794*7304104dSAndroid Build Coastguard Worker ERROR (_("\
4795*7304104dSAndroid Build Coastguard Worker program header entry %d: file offset and virtual address not module of alignment\n"), cnt);
4796*7304104dSAndroid Build Coastguard Worker }
4797*7304104dSAndroid Build Coastguard Worker }
4798*7304104dSAndroid Build Coastguard Worker }
4799*7304104dSAndroid Build Coastguard Worker
4800*7304104dSAndroid Build Coastguard Worker
4801*7304104dSAndroid Build Coastguard Worker static void
check_exception_data(Ebl * ebl,GElf_Ehdr * ehdr)4802*7304104dSAndroid Build Coastguard Worker check_exception_data (Ebl *ebl __attribute__ ((unused)),
4803*7304104dSAndroid Build Coastguard Worker GElf_Ehdr *ehdr __attribute__ ((unused)))
4804*7304104dSAndroid Build Coastguard Worker {
4805*7304104dSAndroid Build Coastguard Worker if ((ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
4806*7304104dSAndroid Build Coastguard Worker && pt_gnu_eh_frame_pndx == 0 && eh_frame_hdr_scnndx != 0)
4807*7304104dSAndroid Build Coastguard Worker ERROR (_("executable/DSO with .eh_frame_hdr section does not have "
4808*7304104dSAndroid Build Coastguard Worker "a PT_GNU_EH_FRAME program header entry"));
4809*7304104dSAndroid Build Coastguard Worker }
4810*7304104dSAndroid Build Coastguard Worker
4811*7304104dSAndroid Build Coastguard Worker
4812*7304104dSAndroid Build Coastguard Worker /* Process one file. */
4813*7304104dSAndroid Build Coastguard Worker static void
process_elf_file(Elf * elf,const char * prefix,const char * suffix,const char * fname,size_t size,bool only_one)4814*7304104dSAndroid Build Coastguard Worker process_elf_file (Elf *elf, const char *prefix, const char *suffix,
4815*7304104dSAndroid Build Coastguard Worker const char *fname, size_t size, bool only_one)
4816*7304104dSAndroid Build Coastguard Worker {
4817*7304104dSAndroid Build Coastguard Worker /* Reset variables. */
4818*7304104dSAndroid Build Coastguard Worker ndynamic = 0;
4819*7304104dSAndroid Build Coastguard Worker nverneed = 0;
4820*7304104dSAndroid Build Coastguard Worker nverdef = 0;
4821*7304104dSAndroid Build Coastguard Worker textrel = false;
4822*7304104dSAndroid Build Coastguard Worker needed_textrel = false;
4823*7304104dSAndroid Build Coastguard Worker has_loadable_segment = false;
4824*7304104dSAndroid Build Coastguard Worker has_interp_segment = false;
4825*7304104dSAndroid Build Coastguard Worker
4826*7304104dSAndroid Build Coastguard Worker GElf_Ehdr ehdr_mem;
4827*7304104dSAndroid Build Coastguard Worker GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
4828*7304104dSAndroid Build Coastguard Worker Ebl *ebl;
4829*7304104dSAndroid Build Coastguard Worker
4830*7304104dSAndroid Build Coastguard Worker /* Print the file name. */
4831*7304104dSAndroid Build Coastguard Worker if (!only_one)
4832*7304104dSAndroid Build Coastguard Worker {
4833*7304104dSAndroid Build Coastguard Worker if (prefix != NULL)
4834*7304104dSAndroid Build Coastguard Worker printf ("\n%s(%s)%s:\n", prefix, fname, suffix);
4835*7304104dSAndroid Build Coastguard Worker else
4836*7304104dSAndroid Build Coastguard Worker printf ("\n%s:\n", fname);
4837*7304104dSAndroid Build Coastguard Worker }
4838*7304104dSAndroid Build Coastguard Worker
4839*7304104dSAndroid Build Coastguard Worker if (ehdr == NULL)
4840*7304104dSAndroid Build Coastguard Worker {
4841*7304104dSAndroid Build Coastguard Worker ERROR (_("cannot read ELF header: %s\n"), elf_errmsg (-1));
4842*7304104dSAndroid Build Coastguard Worker return;
4843*7304104dSAndroid Build Coastguard Worker }
4844*7304104dSAndroid Build Coastguard Worker
4845*7304104dSAndroid Build Coastguard Worker ebl = ebl_openbackend (elf);
4846*7304104dSAndroid Build Coastguard Worker /* If there is no appropriate backend library we cannot test
4847*7304104dSAndroid Build Coastguard Worker architecture and OS specific features. Any encountered extension
4848*7304104dSAndroid Build Coastguard Worker is an error. Often we'll get a "dummy" ebl, except if something
4849*7304104dSAndroid Build Coastguard Worker really bad happen, like a totally corrupted ELF file or out of
4850*7304104dSAndroid Build Coastguard Worker memory situation. */
4851*7304104dSAndroid Build Coastguard Worker if (ebl == NULL)
4852*7304104dSAndroid Build Coastguard Worker {
4853*7304104dSAndroid Build Coastguard Worker ERROR (_("cannot create backend for ELF file\n"));
4854*7304104dSAndroid Build Coastguard Worker return;
4855*7304104dSAndroid Build Coastguard Worker }
4856*7304104dSAndroid Build Coastguard Worker
4857*7304104dSAndroid Build Coastguard Worker /* Go straight by the gABI, check all the parts in turn. */
4858*7304104dSAndroid Build Coastguard Worker check_elf_header (ebl, ehdr, size);
4859*7304104dSAndroid Build Coastguard Worker
4860*7304104dSAndroid Build Coastguard Worker /* Check the program header. */
4861*7304104dSAndroid Build Coastguard Worker check_program_header (ebl, ehdr);
4862*7304104dSAndroid Build Coastguard Worker
4863*7304104dSAndroid Build Coastguard Worker /* Next the section headers. It is OK if there are no section
4864*7304104dSAndroid Build Coastguard Worker headers at all. */
4865*7304104dSAndroid Build Coastguard Worker check_sections (ebl, ehdr);
4866*7304104dSAndroid Build Coastguard Worker
4867*7304104dSAndroid Build Coastguard Worker /* Check the exception handling data, if it exists. */
4868*7304104dSAndroid Build Coastguard Worker if (pt_gnu_eh_frame_pndx != 0 || eh_frame_hdr_scnndx != 0
4869*7304104dSAndroid Build Coastguard Worker || eh_frame_scnndx != 0 || gcc_except_table_scnndx != 0)
4870*7304104dSAndroid Build Coastguard Worker check_exception_data (ebl, ehdr);
4871*7304104dSAndroid Build Coastguard Worker
4872*7304104dSAndroid Build Coastguard Worker /* Report if no relocation section needed the text relocation flag. */
4873*7304104dSAndroid Build Coastguard Worker if (textrel && !needed_textrel)
4874*7304104dSAndroid Build Coastguard Worker ERROR (_("text relocation flag set but not needed\n"));
4875*7304104dSAndroid Build Coastguard Worker
4876*7304104dSAndroid Build Coastguard Worker /* Free the resources. */
4877*7304104dSAndroid Build Coastguard Worker ebl_closebackend (ebl);
4878*7304104dSAndroid Build Coastguard Worker }
4879*7304104dSAndroid Build Coastguard Worker
4880*7304104dSAndroid Build Coastguard Worker
4881*7304104dSAndroid Build Coastguard Worker #include "debugpred.h"
4882