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