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