1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Pedantic checking of ELF files compliance with gABI/psABI spec.
2e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard   Copyright (C) 2001-2015 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of the GNU General Public License as published by
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the Free Software Foundation; either version 3 of the License, or
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   (at your option) any later version.
10b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
12361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   GNU General Public License for more details.
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received a copy of the GNU General Public License
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
19b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#ifdef HAVE_CONFIG_H
20b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper# include <config.h>
21b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
22b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
23b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <argp.h>
24b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <assert.h>
25b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <byteswap.h>
26b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <endian.h>
27b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <error.h>
28b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <fcntl.h>
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <gelf.h>
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <inttypes.h>
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libintl.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <locale.h>
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdbool.h>
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdlib.h>
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <string.h>
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <unistd.h>
37b337b1fd5f3b3410fe522a690ccee70bce8519eeRoland McGrath#include <sys/stat.h>
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/param.h>
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <elf-knowledge.h>
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <system.h>
42059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#include "../libelf/libelfP.h"
43059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#include "../libelf/common.h"
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "../libebl/libeblP.h"
45059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#include "../libdw/libdwP.h"
46059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#include "../libdwfl/libdwflP.h"
47059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#include "../libdw/memory-access.h"
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Name and version of program.  */
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void print_version (FILE *stream, struct argp_state *state);
52fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
54b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Bug report address.  */
55fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ARGP_strict	300
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ARGP_gnuld	301
59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
60b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Definitions of arguments for argp functions.  */
61b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const struct argp_option options[] =
62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "strict", ARGP_strict, NULL, 0,
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Be extremely strict, flag level 2 features."), 0 },
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "quiet", 'q', NULL, 0, N_("Do not print anything if successful"), 0 },
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "debuginfo", 'd', NULL, 0, N_("Binary is a separate debuginfo file"), 0 },
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "gnu-ld", ARGP_gnuld, NULL, 0,
68b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Binary has been created with GNU ld and is therefore known to be \
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperbroken in certain ways"), 0 },
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, NULL, 0 }
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Short description of program.  */
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char doc[] = N_("\
75b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperPedantic checking of ELF files compliance with gABI/psABI spec.");
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Strings for arguments in help texts.  */
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char args_doc[] = N_("FILE...");
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Prototype for option handler.  */
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Data structure to communicate with argp functions.  */
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic struct argp argp =
85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  options, parse_opt, args_doc, doc, NULL, NULL, NULL
87b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Declarations of local functions.  */
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void process_file (int fd, Elf *elf, const char *prefix,
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  const char *suffix, const char *fname, size_t size,
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  bool only_one);
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void process_elf_file (Elf *elf, const char *prefix, const char *suffix,
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      const char *fname, size_t size, bool only_one);
9659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic void check_note_section (Ebl *ebl, GElf_Ehdr *ehdr,
9759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath				GElf_Shdr *shdr, int idx);
9859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Report an error.  */
101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ERROR(str, args...) \
102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  do {									      \
103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    printf (str, ##args);						      \
104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ++error_count;							      \
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  } while (0)
106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic unsigned int error_count;
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* True if we should perform very strict testing.  */
109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool be_strict;
110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* True if no message is to be printed if the run is succesful.  */
112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool be_quiet;
113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* True if binary is from strip -f, not a normal ELF file.  */
115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool is_debuginfo;
116b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
117b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* True if binary is assumed to be generated with GNU ld.  */
118b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool gnuld;
119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Index of section header string table.  */
121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic uint32_t shstrndx;
122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Array to count references in section groups.  */
124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int *scnref;
125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
12671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek/* Numbers of sections and program headers.  */
12771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinekstatic unsigned int shnum;
12871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinekstatic unsigned int phnum;
12971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek
130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermain (int argc, char *argv[])
133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Set locale.  */
135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  setlocale (LC_ALL, "");
136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Initialize the message catalog.  */
138b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  textdomain (PACKAGE_TARNAME);
139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Parse and process arguments.  */
141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int remaining;
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Before we start tell the ELF library which version we are using.  */
145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_version (EV_CURRENT);
146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now process all the files given at the command line.  */
148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool only_one = remaining + 1 == argc;
149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  do
150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Open the file.  */
152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      int fd = open (argv[remaining], O_RDONLY);
153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (fd == -1)
154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("cannot open input file"));
156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Create an `Elf' descriptor.  */
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf == NULL)
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("cannot generate Elf descriptor: %s\n"),
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       elf_errmsg (-1));
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  unsigned int prev_error_count = error_count;
1673425454a10d307fae891fb667cf7969e945cde79Josh Stone	  struct stat st;
168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1693425454a10d307fae891fb667cf7969e945cde79Josh Stone	  if (fstat (fd, &st) != 0)
170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      printf ("cannot stat '%s': %m\n", argv[remaining]);
172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      close (fd);
173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  process_file (fd, elf, NULL, NULL, argv[remaining], st.st_size,
177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			only_one);
178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Now we can close the descriptor.  */
180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (elf_end (elf) != 0)
181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("error while closing Elf descriptor: %s\n"),
182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   elf_errmsg (-1));
183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (prev_error_count == error_count && !be_quiet)
185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    puts (gettext ("No errors"));
186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      close (fd);
189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (++remaining < argc);
191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return error_count != 0;
193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle program arguments.  */
197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t
198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperparse_opt (int key, char *arg __attribute__ ((unused)),
199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   struct argp_state *state __attribute__ ((unused)))
200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (key)
202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ARGP_strict:
204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      be_strict = true;
205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'q':
208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      be_quiet = true;
209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'd':
212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      is_debuginfo = true;
213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ARGP_gnuld:
215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      gnuld = true;
216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ARGP_KEY_NO_ARGS:
219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      fputs (gettext ("Missing file name.\n"), stderr);
2205ee720c60a298352b52513d03ede85814ab63ad5Ulrich Drepper      argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name);
2215ee720c60a298352b52513d03ede85814ab63ad5Ulrich Drepper      exit (EXIT_FAILURE);
222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ARGP_ERR_UNKNOWN;
225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print the version information.  */
231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
234b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  fprintf (stream, "elflint (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("\
236b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperCopyright (C) %s Red Hat, Inc.\n\
237b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperThis is free software; see the source for copying conditions.  There is NO\n\
238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
2393a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper"), "2012");
240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Process one file.  */
245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprocess_file (int fd, Elf *elf, const char *prefix, const char *suffix,
247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      const char *fname, size_t size, bool only_one)
248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We can handle two types of files: ELF files and archives.  */
250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Kind kind = elf_kind (elf);
251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (kind)
253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_ELF:
255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Yes!  It's an ELF file.  */
256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      process_elf_file (elf, prefix, suffix, fname, size, only_one);
257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_AR:
260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf *subelf;
262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf_Cmd cmd = ELF_C_READ_MMAP;
263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size_t fname_len = strlen (fname) + 1;
265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char new_prefix[prefix_len + 1 + fname_len];
266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char new_suffix[(suffix == NULL ? 0 : strlen (suffix)) + 2];
267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char *cp = new_prefix;
268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Create the full name of the file.  */
270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (prefix != NULL)
271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    cp = mempcpy (cp, prefix, prefix_len);
273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    *cp++ = '(';
274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    strcpy (stpcpy (new_suffix, suffix), ")");
275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	else
277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  new_suffix[0] = '\0';
278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	memcpy (cp, fname, fname_len);
279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* It's an archive.  We process each file in it.  */
281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    kind = elf_kind (subelf);
284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Call this function recursively.  */
286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (kind == ELF_K_ELF || kind == ELF_K_AR)
287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		Elf_Arhdr *arhdr = elf_getarhdr (subelf);
289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		assert (arhdr != NULL);
290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
291b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		process_file (fd, subelf, new_prefix, new_suffix,
292b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      arhdr->ar_name, arhdr->ar_size, false);
293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Get next archive element.  */
296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    cmd = elf_next (subelf);
297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (elf_end (subelf) != 0)
298b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext (" error while freeing sub-ELF descriptor: %s\n"),
299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     elf_errmsg (-1));
300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We cannot do anything.  */
306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
30741de488a0ad6679e816dbab960351e5f62ab8eadUlrich DrepperNot an ELF file - it has the wrong magic bytes at the start\n"));
308b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *
314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection_name (Ebl *ebl, int idx)
315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr shdr_mem;
317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *shdr;
31871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  const char *ret;
31971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek
32071c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  if ((unsigned int) idx > shnum)
32171c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    return "<invalid>";
322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr = gelf_getshdr (elf_getscn (ebl->elf, idx), &shdr_mem);
32471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  if (shdr == NULL)
32571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    return "<invalid>";
326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
32771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  ret = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
32871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  if (ret == NULL)
32971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    return "<invalid>";
33071c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  return ret;
331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const int valid_e_machine[] =
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_M32, EM_SPARC, EM_386, EM_68K, EM_88K, EM_860, EM_MIPS, EM_S370,
337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_MIPS_RS3_LE, EM_PARISC, EM_VPP500, EM_SPARC32PLUS, EM_960, EM_PPC,
338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_PPC64, EM_S390, EM_V800, EM_FR20, EM_RH32, EM_RCE, EM_ARM,
339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_FAKE_ALPHA, EM_SH, EM_SPARCV9, EM_TRICORE, EM_ARC, EM_H8_300,
340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_H8_300H, EM_H8S, EM_H8_500, EM_IA_64, EM_MIPS_X, EM_COLDFIRE,
341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_68HC12, EM_MMA, EM_PCP, EM_NCPU, EM_NDR1, EM_STARCORE, EM_ME16,
342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_ST100, EM_TINYJ, EM_X86_64, EM_PDSP, EM_FX66, EM_ST9PLUS, EM_ST7,
343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX,
344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM,
345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300,
346257dcf47ed0cf57bcd2ad225cc7aaa6a8dfeb2abJeff Kenton    EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA, EM_ALPHA,
34798c8a7395b4e5e7bed233397148b15c1f8c66490Petr Machata    EM_TILEGX, EM_TILEPRO, EM_AARCH64
348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  };
349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define nvalid_e_machine \
350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (sizeof (valid_e_machine) / sizeof (valid_e_machine[0]))
351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size)
355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char buf[512];
357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cnt;
358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check e_ident field.  */
360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG0] != ELFMAG0)
361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG0, ELFMAG0);
362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG1] != ELFMAG1)
363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG1, ELFMAG1);
364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG2] != ELFMAG2)
365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG2, ELFMAG2);
366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG3] != ELFMAG3)
367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG3, ELFMAG3);
368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_CLASS] != ELFCLASS32
370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_ident[EI_CLASS] != ELFCLASS64)
371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("e_ident[%d] == %d is no known class\n"),
372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_CLASS, ehdr->e_ident[EI_CLASS]);
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB
375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("e_ident[%d] == %d is no known data encoding\n"),
377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_DATA, ehdr->e_ident[EI_DATA]);
378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_VERSION] != EV_CURRENT)
380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown ELF header version number e_ident[%d] == %d\n"),
381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_VERSION, ehdr->e_ident[EI_VERSION]);
382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
383624e3cb81d436282fa9f6ce4fa63203bad236057Mark Wielaard  /* We currently don't handle any OS ABIs other than Linux and the
384624e3cb81d436282fa9f6ce4fa63203bad236057Mark Wielaard     kFreeBSD variant of Debian.  */
38596d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper  if (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE
386624e3cb81d436282fa9f6ce4fa63203bad236057Mark Wielaard      && ehdr->e_ident[EI_OSABI] != ELFOSABI_LINUX
387624e3cb81d436282fa9f6ce4fa63203bad236057Mark Wielaard      && ehdr->e_ident[EI_OSABI] != ELFOSABI_FREEBSD)
388e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper    ERROR (gettext ("unsupported OS ABI e_ident[%d] == '%s'\n"),
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_OSABI,
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* No ABI versions other than zero supported either.  */
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_ABIVERSION] != 0)
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unsupport ABI version e_ident[%d] == %d\n"),
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_ABIVERSION, ehdr->e_ident[EI_ABIVERSION]);
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = EI_PAD; cnt < EI_NIDENT; ++cnt)
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (ehdr->e_ident[cnt] != 0)
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("e_ident[%zu] is not zero\n"), cnt);
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_type field.  */
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_REL && ehdr->e_type != ET_EXEC
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_DYN && ehdr->e_type != ET_CORE)
404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown object file type %d\n"), ehdr->e_type);
405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_machine field.  */
407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 0; cnt < nvalid_e_machine; ++cnt)
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (valid_e_machine[cnt] == ehdr->e_machine)
409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (cnt == nvalid_e_machine)
411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown machine type %d\n"), ehdr->e_machine);
412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_version field.  */
414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_version != EV_CURRENT)
415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown object file version\n"));
416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_phoff and e_phnum fields.  */
418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_phoff == 0)
419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phnum != 0)
421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header offset\n"));
422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperexecutables and DSOs cannot have zero program header offset\n"));
425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else if (ehdr->e_phnum == 0)
427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("invalid number of program header entries\n"));
428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_shoff field.  */
430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shnum = ehdr->e_shnum;
431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shstrndx = ehdr->e_shstrndx;
432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_shoff == 0)
433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shnum != 0)
435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header table offset\n"));
436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       && ehdr->e_type != ET_CORE)
438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section header table must be present\n"));
439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shnum == 0)
443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Get the header of the zeroth section.  The sh_size field
445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     might contain the section number.  */
446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
447acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr != NULL)
449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* The error will be reported later.  */
451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (shdr->sh_size == 0)
452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperinvalid number of section header table entries\n"));
454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		shnum = shdr->sh_size;
456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shstrndx == SHN_XINDEX)
460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Get the header of the zeroth section.  The sh_size field
462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     might contain the section number.  */
463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
464acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
465acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  if (shdr != NULL && shdr->sh_link < shnum)
466acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    shstrndx = shdr->sh_link;
467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (shstrndx >= shnum)
469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header index\n"));
470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
472bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  phnum = ehdr->e_phnum;
473bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  if (ehdr->e_phnum == PN_XNUM)
474bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    {
475bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      /* Get the header of the zeroth section.  The sh_info field
476bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	 might contain the phnum count.  */
477bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      GElf_Shdr shdr_mem;
478bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
479bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      if (shdr != NULL)
480bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	{
481bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  /* The error will be reported later.  */
482bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  if (shdr->sh_info < PN_XNUM)
483bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	    ERROR (gettext ("\
484bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrathinvalid number of program header table entries\n"));
485bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  else
486bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	    phnum = shdr->sh_info;
487bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	}
488bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    }
489bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath
490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_flags field.  */
491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (!ebl_machine_flag_check (ebl, ehdr->e_flags))
492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("invalid machine flags: %s\n"),
493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check e_ehsize, e_phentsize, and e_shentsize fields.  */
496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (gelf_getclass (ebl->elf) == ELFCLASS32)
497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf32_Ehdr))
499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr))
502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header size: %hd\n"),
503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_phentsize);
504bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size)
505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header position or size\n"));
506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr))
508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header size: %hd\n"),
509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_shentsize);
510bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      else if (ehdr->e_shoff + shnum * ehdr->e_shentsize > size)
511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header position or size\n"));
512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else if (gelf_getclass (ebl->elf) == ELFCLASS64)
514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf64_Ehdr))
516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr))
519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header size: %hd\n"),
520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_phentsize);
521bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size)
522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header position or size\n"));
523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr))
525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header size: %hd\n"),
526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_shentsize);
527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header position or size\n"));
529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Check that there is a section group section with index < IDX which
534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   contains section IDX and that there is exactly one.  */
535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_scn_group (Ebl *ebl, int idx)
537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (scnref[idx] == 0)
539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* No reference so far.  Search following sections, maybe the
541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 order is wrong.  */
542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t cnt;
543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = idx + 1; cnt < shnum; ++cnt)
545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
546acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
548acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr == NULL)
550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* We cannot get the section header so we cannot check it.
551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       The error to get the section header will be shown
552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       somewhere else.  */
553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr->sh_type != SHT_GROUP)
556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
558acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf_Data *data = elf_getdata (scn, NULL);
5590a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  if (data == NULL || data->d_buf == NULL
5600a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      || data->d_size < sizeof (Elf32_Word))
561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Cannot check the section.  */
562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
564acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf32_Word *grpdata = (Elf32_Word *) data->d_buf;
565acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  for (size_t inner = 1; inner < data->d_size / sizeof (Elf32_Word);
566acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	       ++inner)
567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (grpdata[inner] == (Elf32_Word) idx)
568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      goto out;
569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    out:
572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (cnt == shnum)
573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section with SHF_GROUP flag set not part of a section group\n"),
575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
5783b495d8e963eead963a37b5be5b063c96bb58c63Roland McGrathsection [%2d] '%s': section group [%2zu] '%s' does not precede group member\n"),
579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx),
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
586dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_symtab (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool no_xndx_warned = false;
589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int no_pt_tls = 0;
590dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
598dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr strshdr_mem;
599dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
600dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper				     &strshdr_mem);
601dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (strshdr == NULL)
602dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
603dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
605521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath    {
606521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      ERROR (gettext ("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
607521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	     shdr->sh_link, section_name (ebl, shdr->sh_link),
608521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	     idx, section_name (ebl, idx));
609521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      strshdr = NULL;
610521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath    }
611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Search for an extended section index table section.  */
613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *xndxdata = NULL;
614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf32_Word xndxscnidx = 0;
615acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  bool found_xndx = false;
6163cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper  for (size_t cnt = 1; cnt < shnum; ++cnt)
617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (cnt != (size_t) idx)
618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf_Scn *xndxscn = elf_getscn (ebl->elf, cnt);
620acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	GElf_Shdr xndxshdr_mem;
621acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
622acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	if (xndxshdr == NULL)
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    && xndxshdr->sh_link == (GElf_Word) idx)
627acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  {
628acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    if (found_xndx)
629acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	      ERROR (gettext ("\
630acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': symbol table cannot have more than one extended index section\n"),
631acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper		     idx, section_name (ebl, idx));
632acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
633acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    xndxdata = elf_getdata (xndxscn, NULL);
634acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    xndxscnidx = elf_ndxscn (xndxscn);
635acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    found_xndx = true;
636acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  }
637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
63971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT);
64071c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  if (shdr->sh_entsize != sh_entsize)
641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
6423cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Dreppersection [%2u] '%s': entry size is does not match ElfXX_Sym\n"),
6433cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	   idx, section_name (ebl, idx));
644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Test the zeroth entry.  */
646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Sym sym_mem;
647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf32_Word xndx;
648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, 0, &sym_mem, &xndx);
649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (sym == NULL)
650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get symbol %d: %s\n"),
651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx), 0, elf_errmsg (-1));
652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_name != 0)
655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_name");
657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_value != 0)
658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_value");
660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_size != 0)
661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_size");
663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_info != 0)
664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_info");
666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_other != 0)
667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_other");
669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_shndx != 0)
670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_shndx");
672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndxdata != NULL && xndx != 0)
673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': XINDEX for zeroth entry not zero\n"),
675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       xndxscnidx, section_name (ebl, xndxscnidx));
676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
67871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  for (size_t cnt = 1; cnt < shdr->sh_size / sh_entsize; ++cnt)
679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx);
681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym == NULL)
682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("section [%2d] '%s': cannot get symbol %zu: %s\n"),
684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *name = NULL;
689521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      if (strshdr == NULL)
690521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	name = "";
691521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      else if (sym->st_name >= strshdr->sh_size)
692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: invalid name value\n"),
694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name);
6980a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  if (name == NULL)
6990a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    name = "";
700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_shndx == SHN_XINDEX)
703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (xndxdata == NULL)
705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
706fd992543185126eb0280c1ee0883e073020499b4Roland McGrath	      if (!no_xndx_warned)
707fd992543185126eb0280c1ee0883e073020499b4Roland McGrath		ERROR (gettext ("\
708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: too large section index but no extended section index section\n"),
709fd992543185126eb0280c1ee0883e073020499b4Roland McGrath		       idx, section_name (ebl, idx), cnt);
710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      no_xndx_warned = true;
711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (xndx < SHN_LORESERVE)
713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: XINDEX used for index which would fit in st_shndx (%" PRIu32 ")\n"),
715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   xndxscnidx, section_name (ebl, xndxscnidx), cnt,
716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   xndx);
717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if ((sym->st_shndx >= SHN_LORESERVE
719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		// && sym->st_shndx <= SHN_HIRESERVE    always true
720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& sym->st_shndx != SHN_ABS
721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& sym->st_shndx != SHN_COMMON)
722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       || (sym->st_shndx >= shnum
723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   && (sym->st_shndx < SHN_LORESERVE
724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       /* || sym->st_shndx > SHN_HIRESERVE  always false */)))
725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: invalid section index\n"),
727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
729b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	xndx = sym->st_shndx;
730b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
73118e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath      if (GELF_ST_TYPE (sym->st_info) >= STT_NUM
73218e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && !ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), NULL, 0))
733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': symbol %zu: unknown type\n"),
734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
73696d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper      if (GELF_ST_BIND (sym->st_info) >= STB_NUM
73796d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper	  && !ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info), NULL,
73896d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper				       0))
739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: unknown symbol binding\n"),
741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
74296d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper      if (GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE
74396d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper	  && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
74496d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper	ERROR (gettext ("\
74596d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Dreppersection [%2d] '%s': symbol %zu: unique symbol not of object type\n"),
74696d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper	       idx, section_name (ebl, idx), cnt);
747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndx == SHN_COMMON)
749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Common symbols can only appear in relocatable files.  */
751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (ehdr->e_type != ET_REL)
752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n"),
754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt < shdr->sh_info)
756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n"),
758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (GELF_R_TYPE (sym->st_info) == STT_FUNC)
760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"),
762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (xndx > 0 && xndx < shnum)
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr destshdr_mem;
767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr *destshdr;
768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), &destshdr_mem);
770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (destshdr != NULL)
771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
772b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      GElf_Addr sh_addr = (ehdr->e_type == ET_REL ? 0
773b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				   : destshdr->sh_addr);
774c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard	      GElf_Addr st_value;
775c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard	      if (GELF_ST_TYPE (sym->st_info) == STT_FUNC
776c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		  || (GELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))
777c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		st_value = sym->st_value & ebl_func_addr_mask (ebl);
778c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard	      else
779c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		st_value = sym->st_value;
780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (GELF_ST_TYPE (sym->st_info) != STT_TLS)
781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
782c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  if (! ebl_check_special_symbol (ebl, ehdr, sym, name,
783c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper						  destshdr))
784c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    {
785c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		      if (st_value - sh_addr > destshdr->sh_size)
786ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			{
787ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			  /* GNU ld has severe bugs.  When it decides to remove
788ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			     empty sections it leaves symbols referencing them
7893bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			     behind.  These are symbols in .symtab or .dynsym
7903bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			     and for the named symbols have zero size.  See
7913bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			     sourceware PR13621.  */
792ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			  if (!gnuld
7933bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			      || (strcmp (section_name (ebl, idx), ".symtab")
7943bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			          && strcmp (section_name (ebl, idx),
7953bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard					     ".dynsym"))
7963bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			      || sym->st_size != 0
797ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			      || (strcmp (name, "__preinit_array_start") != 0
798ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__preinit_array_end") != 0
799ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__init_array_start") != 0
800ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__init_array_end") != 0
801ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__fini_array_start") != 0
8023bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard				  && strcmp (name, "__fini_array_end") != 0
8033bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard				  && strcmp (name, "__bss_start") != 0
804b94cceae503b56fb360cd597f154fa2b33552887Mark Wielaard				  && strcmp (name, "__bss_start__") != 0
805a95c4ad24cf83b2b0273fee73162bf476cebec8fMark Wielaard				  && strcmp (name, "__TMC_END__") != 0
80677e1739fc53c4021f6172955b73b2dce252d0709Mark Wielaard				  && strcmp (name, ".TOC.") != 0
80777e1739fc53c4021f6172955b73b2dce252d0709Mark Wielaard				  && strcmp (name, "_edata") != 0
80877e1739fc53c4021f6172955b73b2dce252d0709Mark Wielaard				  && strcmp (name, "__edata") != 0
80977e1739fc53c4021f6172955b73b2dce252d0709Mark Wielaard				  && strcmp (name, "_end") != 0
81077e1739fc53c4021f6172955b73b2dce252d0709Mark Wielaard				  && strcmp (name, "__end") != 0))
811ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			    ERROR (gettext ("\
812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds\n"),
813ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				   idx, section_name (ebl, idx), cnt);
814ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			}
815c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		      else if ((st_value - sh_addr
816c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper				+ sym->st_size) > destshdr->sh_size)
817c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
819c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx), cnt,
820c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (int) xndx, section_name (ebl, xndx));
821c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    }
822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if ((destshdr->sh_flags & SHF_TLS) == 0)
826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_TLS flag set\n"),
828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx), cnt,
829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   (int) xndx, section_name (ebl, xndx));
830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (ehdr->e_type == ET_REL)
832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      /* For object files the symbol value must fall
834c49d00afc4bda21181cd4237e67930f3f5228adfMark Wielaard			 into the section.  */
835c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		      if (st_value > destshdr->sh_size)
836b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
837b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       idx, section_name (ebl, idx), cnt,
839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       (int) xndx, section_name (ebl, xndx));
840c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		      else if (st_value + sym->st_size
841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       > destshdr->sh_size)
842b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
843b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
844b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       idx, section_name (ebl, idx), cnt,
845b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       (int) xndx, section_name (ebl, xndx));
846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
847b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  else
848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Phdr phdr_mem;
850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Phdr *phdr = NULL;
851bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath		      unsigned int pcnt;
852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
853bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath		      for (pcnt = 0; pcnt < phnum; ++pcnt)
854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
855b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
856b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (phdr != NULL && phdr->p_type == PT_TLS)
857b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    break;
858b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
860bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath		      if (pcnt == phnum)
861b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
862b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (no_pt_tls++ == 0)
863b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
864b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"),
865b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt);
866b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
86777be59bca4057b22af70b0b2d0197f9505577381Mark Wielaard		      else if (phdr == NULL)
86877be59bca4057b22af70b0b2d0197f9505577381Mark Wielaard			{
86977be59bca4057b22af70b0b2d0197f9505577381Mark Wielaard			    ERROR (gettext ("\
87077be59bca4057b22af70b0b2d0197f9505577381Mark Wielaardsection [%2d] '%s': symbol %zu: TLS symbol but couldn't get TLS program header entry\n"),
87177be59bca4057b22af70b0b2d0197f9505577381Mark Wielaard				   idx, section_name (ebl, idx), cnt);
87277be59bca4057b22af70b0b2d0197f9505577381Mark Wielaard			}
873a1e17a2551ddd1b2c4853e053dc1b254440211bdMark Wielaard		      else if (!is_debuginfo)
874b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
875c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard			  if (st_value
876b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      < destshdr->sh_offset - phdr->p_offset)
877b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
878b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"),
879b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
880b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
881c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard			  else if (st_value
882b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   > (destshdr->sh_offset - phdr->p_offset
883b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				      + destshdr->sh_size))
884b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
885b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
886b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
887b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
888c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard			  else if (st_value + sym->st_size
889b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   > (destshdr->sh_offset - phdr->p_offset
890b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				      + destshdr->sh_size))
891b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
892b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
893b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
894b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
895b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
896b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
897b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
898b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
899b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
900b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
901b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
902b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
903b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt >= shdr->sh_info)
904b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: local symbol outside range described in sh_info\n"),
906b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
907b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
908b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
909b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
910b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt < shdr->sh_info)
911b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
912b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: non-local symbol outside range described in sh_info\n"),
913b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
914b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
915b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
916b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
917b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: non-local section symbol\n"),
920b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
921b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
922b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (name != NULL)
923b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
924b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
925b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
926653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      /* Check that address and size match the global offset table.  */
927653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
928653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      GElf_Shdr destshdr_mem;
929653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx),
930653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						  &destshdr_mem);
931653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
932653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (destshdr == NULL && xndx == SHN_ABS)
933b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
934653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  /* In a DSO, we have to find the GOT section by name.  */
935653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  Elf_Scn *gotscn = NULL;
936c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  Elf_Scn *gscn = NULL;
937653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL)
938b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
939653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      destshdr = gelf_getshdr (gscn, &destshdr_mem);
940653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      assert (destshdr != NULL);
941653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      const char *sname = elf_strptr (ebl->elf,
942653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						      ehdr->e_shstrndx,
943653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						      destshdr->sh_name);
944653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      if (sname != NULL)
945b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
946c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  if (strcmp (sname, ".got.plt") == 0)
947653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    break;
948c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  if (strcmp (sname, ".got") == 0)
949653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    /* Do not stop looking.
950653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			       There might be a .got.plt section.  */
951653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    gotscn = gscn;
952b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
953653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
954653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      destshdr = NULL;
955b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
956653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
957653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  if (destshdr == NULL && gotscn != NULL)
958653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    destshdr = gelf_getshdr (gotscn, &destshdr_mem);
959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
960b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
961b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      const char *sname = ((destshdr == NULL || xndx == SHN_UNDEF)
962b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				   ? NULL
963653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath				   : elf_strptr (ebl->elf, ehdr->e_shstrndx,
964653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						 destshdr->sh_name));
965653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (sname == NULL)
966b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		{
967b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		  if (xndx != SHN_UNDEF || ehdr->e_type != ET_REL)
968b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		    ERROR (gettext ("\
969b597dfad924980dede10d7c19d87900b6172e599Ulrich Dreppersection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
970b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperbad section [%2d]\n"),
971b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			   idx, section_name (ebl, idx), xndx);
972b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		}
973653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      else if (strcmp (sname, ".got.plt") != 0
974653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		       && strcmp (sname, ".got") != 0)
975653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		ERROR (gettext ("\
976b597dfad924980dede10d7c19d87900b6172e599Ulrich Dreppersection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
977b597dfad924980dede10d7c19d87900b6172e599Ulrich Dreppersection [%2d] '%s'\n"),
978b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		       idx, section_name (ebl, idx), xndx, sname);
979653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
980653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (destshdr != NULL)
981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Found it.  */
983c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  if (!ebl_check_special_symbol (ebl, ehdr, sym, name,
984c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper						 destshdr))
985c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    {
986b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		      if (ehdr->e_type != ET_REL
987b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  && sym->st_value != destshdr->sh_addr)
988c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			/* This test is more strict than the psABIs which
989c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			   usually allow the symbol to be in the middle of
990c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			   the .got section, allowing negative offsets.  */
991c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
992653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match %s section address %#" PRIx64 "\n"),
993c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx),
994c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (uint64_t) sym->st_value,
995c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       sname, (uint64_t) destshdr->sh_addr);
996b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
997c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		      if (!gnuld && sym->st_size != destshdr->sh_size)
998c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
999653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match %s section size %" PRIu64 "\n"),
1000c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx),
1001c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (uint64_t) sym->st_size,
1002c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       sname, (uint64_t) destshdr->sh_size);
1003c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    }
1004b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1005b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
1006b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
1007b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"),
1008b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx));
1009b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1010b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (strcmp (name, "_DYNAMIC") == 0)
101141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    /* Check that address and size match the dynamic section.
101241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	       We locate the dynamic section via the program header
101341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	       entry.  */
1014bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	    for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt)
101541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      {
101641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Phdr phdr_mem;
101741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
1018b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
101941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
102041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  {
102141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    if (sym->st_value != phdr->p_vaddr)
102241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      ERROR (gettext ("\
1023b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"),
102441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     idx, section_name (ebl, idx),
102541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) sym->st_value,
102641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) phdr->p_vaddr);
1027b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
102841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    if (!gnuld && sym->st_size != phdr->p_memsz)
102941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      ERROR (gettext ("\
1030b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"),
103141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     idx, section_name (ebl, idx),
103241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) sym->st_size,
103341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) phdr->p_memsz);
1034b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
103541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    break;
103641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  }
1037b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1038b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1039c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper
1040c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper      if (GELF_ST_VISIBILITY (sym->st_other) != STV_DEFAULT
1041c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper	  && shdr->sh_type == SHT_DYNSYM)
1042c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper	ERROR (gettext ("\
1043c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Dreppersection [%2d] '%s': symbol %zu: symbol in dynamic symbol table with non-default visibility\n"),
1044c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1045a062b6bcadd1565d360acf640f9d4c159b2270eaMark Wielaard      if (! ebl_check_st_other_bits (ebl, sym->st_other))
1046c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper	ERROR (gettext ("\
1047c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Dreppersection [%2d] '%s': symbol %zu: unknown bit set in st_other\n"),
1048c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1049c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper
1050b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1052b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool
1055c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperis_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr,
105628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    bool is_rela)
1057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If this is no executable or DSO it cannot be a .rel.dyn section.  */
1059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1060b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return false;
1061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the section name.  Unfortunately necessary.  */
106328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (strcmp (section_name (ebl, idx), is_rela ? ".rela.dyn" : ".rel.dyn"))
1064b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return false;
1065b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1066b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section
1067b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     entry can be present as well.  */
1068b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn = NULL;
1069b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1071b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr rcshdr_mem;
1072b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem);
1073b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
107471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      if (rcshdr == NULL)
107571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	break;
107671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek
10770a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (rcshdr->sh_type == SHT_DYNAMIC && rcshdr->sh_entsize != 0)
1078b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Found the dynamic section.  Look through it.  */
1080b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  Elf_Data *d = elf_getdata (scn, NULL);
1081b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t cnt;
1082b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
10830a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  if (d == NULL)
10840a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    ERROR (gettext ("\
10850a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': cannot get section data.\n"),
10860a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		   idx, section_name (ebl, idx));
10870a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
1088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt)
1089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Dyn dyn_mem;
1091b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem);
109271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek
109371c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	      if (dyn == NULL)
109471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek		break;
1095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (dyn->d_tag == DT_RELCOUNT)
1097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
109828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  /* Found it.  Does the type match.  */
109928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if (is_rela)
1100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
110128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELCOUNT used for this RELA section\n"),
110228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx));
110328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  else
110428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    {
110528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Does the number specified number of relative
110628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations exceed the total number of
110728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations?  */
110871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek		      if (shdr->sh_entsize != 0
110971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek			  && dyn->d_un.d_val > (shdr->sh_size
111071c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek						/ shdr->sh_entsize))
111128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			ERROR (gettext ("\
1112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
111328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       idx, section_name (ebl, idx),
111428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       (int) dyn->d_un.d_val);
111528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
111628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Make sure the specified number of relocations are
111728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relative.  */
111828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
111928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper								   idx), NULL);
11200a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		      if (reldata != NULL && shdr->sh_entsize != 0)
112128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			for (size_t inner = 0;
112228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     inner < shdr->sh_size / shdr->sh_entsize;
112328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     ++inner)
112428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  {
112528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rel rel_mem;
112628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rel *rel = gelf_getrel (reldata, inner,
112728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							 &rel_mem);
112828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (rel == NULL)
112928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      /* The problem will be reported elsewhere.  */
113028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      break;
113128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
113228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (ebl_relative_reloc_p (ebl,
113328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						      GELF_R_TYPE (rel->r_info)))
113428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      {
113528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				if (inner >= dyn->d_un.d_val)
113628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				  ERROR (gettext ("\
113728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
113828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 idx, section_name (ebl, idx),
113928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 (int) dyn->d_un.d_val);
114028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      }
114128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    else if (inner < dyn->d_un.d_val)
114228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      ERROR (gettext ("\
114328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
114428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     idx, section_name (ebl, idx),
114528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     inner, (int) dyn->d_un.d_val);
114628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  }
114728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    }
114828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		}
114928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
115028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      if (dyn->d_tag == DT_RELACOUNT)
115128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		{
115228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  /* Found it.  Does the type match.  */
115328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if (!is_rela)
115428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    ERROR (gettext ("\
115528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELACOUNT used for this REL section\n"),
115628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx));
115728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  else
115828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    {
115928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Does the number specified number of relative
116028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations exceed the total number of
116128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations?  */
11620a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		      if (shdr->sh_entsize != 0
11630a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard			  && dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
116428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			ERROR (gettext ("\
116528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
116628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       idx, section_name (ebl, idx),
116728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       (int) dyn->d_un.d_val);
116828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
116928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Make sure the specified number of relocations are
117028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relative.  */
117128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
117228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper								   idx), NULL);
11730a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		      if (reldata != NULL && shdr->sh_entsize != 0)
117428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			for (size_t inner = 0;
117528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     inner < shdr->sh_size / shdr->sh_entsize;
117628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     ++inner)
117728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  {
117828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rela rela_mem;
117928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rela *rela = gelf_getrela (reldata, inner,
118028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							    &rela_mem);
118128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (rela == NULL)
118228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      /* The problem will be reported elsewhere.  */
118328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      break;
118428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
118528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (ebl_relative_reloc_p (ebl,
118628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						      GELF_R_TYPE (rela->r_info)))
118728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      {
118828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				if (inner >= dyn->d_un.d_val)
118928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				  ERROR (gettext ("\
119028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
119128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 idx, section_name (ebl, idx),
119228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 (int) dyn->d_un.d_val);
119328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      }
119428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    else if (inner < dyn->d_un.d_val)
119528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      ERROR (gettext ("\
119628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
119728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     idx, section_name (ebl, idx),
119828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     inner, (int) dyn->d_un.d_val);
119928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  }
120028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    }
1201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return true;
1209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
121241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstruct loaded_segment
121341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper{
121441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Addr from;
121541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Addr to;
121641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  bool read_only;
121741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *next;
121841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper};
121941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
122041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
122141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper/* Check whether binary has text relocation flag set.  */
122241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic bool textrel;
122341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
122441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper/* Keep track of whether text relocation flag is needed.  */
122541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic bool needed_textrel;
122641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
122741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1228c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic bool
1229c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr,
1230c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		  int idx, int reltype, GElf_Shdr **destshdrp,
123141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr *destshdr_memp, struct loaded_segment **loadedp)
1232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool reldyn = false;
1234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check whether the link to the section we relocate is reasonable.  */
1236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info >= shnum)
1237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"),
1238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1239c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  else if (shdr->sh_info != 0)
1240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1241c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      *destshdrp = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1242c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper				 destshdr_memp);
1243c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (*destshdrp != NULL)
1244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1245028d0ab0cc1cb5f96ee48feef966b7d8d56c6a8eMark Wielaard	  if(! ebl_check_reloc_target_type (ebl, (*destshdrp)->sh_type))
1246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true);
1248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (!reldyn)
1249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
1250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': invalid destination section type\n"),
1251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx));
1252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
1253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
1254c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		  /* There is no standard, but we require that .rel{,a}.dyn
1255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     sections have a sh_info value of zero.  */
1256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (shdr->sh_info != 0)
1257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
1258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': sh_info should be zero\n"),
1259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx));
1260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
126361c25a1c5b507629fa69b205a0e22d142092c6d1Mark Wielaard	  if ((((*destshdrp)->sh_flags & SHF_MERGE) != 0)
126461c25a1c5b507629fa69b205a0e22d142092c6d1Mark Wielaard	      && ((*destshdrp)->sh_flags & SHF_STRINGS) != 0)
1265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
126661c25a1c5b507629fa69b205a0e22d142092c6d1Mark Wielaardsection [%2d] '%s': no relocations for merge-able string sections possible\n"),
1267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
1268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
127171c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  size_t sh_entsize = gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT);
127271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  if (shdr->sh_entsize != sh_entsize)
1273c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext (reltype == ELF_T_RELA ? "\
1274c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Rela\n" : "\
1275c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Rel\n"),
1276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
127841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* In preparation of checking whether relocations are text
127941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     relocations or not we need to determine whether the file is
128041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     flagged to have text relocation and we need to determine a) what
128141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     the loaded segments are and b) which are read-only.  This will
128241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     also allow us to determine whether the same reloc section is
128341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     modifying loaded and not loaded segments.  */
1284bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  for (unsigned int i = 0; i < phnum; ++i)
128541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
128641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      GElf_Phdr phdr_mem;
128741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
128841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (phdr == NULL)
128941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	continue;
129041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
129141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (phdr->p_type == PT_LOAD)
129241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
129341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  struct loaded_segment *newp = xmalloc (sizeof (*newp));
129441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->from = phdr->p_vaddr;
129541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->to = phdr->p_vaddr + phdr->p_memsz;
129641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->read_only = (phdr->p_flags & PF_W) == 0;
129741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->next = *loadedp;
129841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  *loadedp = newp;
129941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
130041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      else if (phdr->p_type == PT_DYNAMIC)
130141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
130241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  Elf_Scn *dynscn = gelf_offscn (ebl->elf, phdr->p_offset);
130341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  GElf_Shdr dynshdr_mem;
130441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem);
130541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  Elf_Data *dyndata = elf_getdata (dynscn, NULL);
130641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC
13070a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      && dyndata != NULL && dynshdr->sh_entsize != 0)
130841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j)
130941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      {
131041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Dyn dyn_mem;
131141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Dyn *dyn = gelf_getdyn (dyndata, j, &dyn_mem);
131241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		if (dyn != NULL
131341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    && (dyn->d_tag == DT_TEXTREL
131441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			|| (dyn->d_tag == DT_FLAGS
131541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			    && (dyn->d_un.d_val & DF_TEXTREL) != 0)))
131641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  {
131741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    textrel = true;
131841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    break;
131941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  }
132041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      }
132141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
132241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
132341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
132441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* A quick test which can be easily done here (although it is a bit
132541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     out of place): the text relocation flag makes only sense if there
132641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     is a segment which is not writable.  */
132741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (textrel)
132841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
132941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *seg = *loadedp;
133041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      while (seg != NULL && !seg->read_only)
133141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	seg = seg->next;
133241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (seg == NULL)
133341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	ERROR (gettext ("\
133441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Dreppertext relocation flag set but there is no read-only segment\n"));
133541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
133641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1337c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  return reldyn;
1338c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper}
1339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
134141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperenum load_state
134241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  {
134341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_undecided,
134441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_loaded,
134541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_unloaded,
134641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_error
134741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  };
134841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
134941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1350c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic void
1351607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppercheck_one_reloc (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *relshdr, int idx,
1352607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		 size_t cnt, const GElf_Shdr *symshdr, Elf_Data *symdata,
1353607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		 GElf_Addr r_offset, GElf_Xword r_info,
135441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 const GElf_Shdr *destshdr, bool reldyn,
135541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 struct loaded_segment *loaded, enum load_state *statep)
1356c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper{
1357c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool known_broken = gnuld;
1358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1359c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (r_info)))
1360c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"),
1361c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1362607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper  else if (((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1363607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    /* The executable/DSO can contain relocation sections with
1364607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	       all the relocations the linker has applied.  Those sections
1365607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	       are marked non-loaded, though.  */
1366607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    || (relshdr->sh_flags & SHF_ALLOC) != 0)
1367607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	   && !ebl_reloc_valid_use (ebl, GELF_R_TYPE (r_info)))
1368c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("\
1369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
1370c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1372c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (symshdr != NULL
1373c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      && ((GELF_R_SYM (r_info) + 1)
1374c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
1375c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  > symshdr->sh_size))
1376c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("\
1377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: invalid symbol index\n"),
1378c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
13806ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper  /* No more tests if this is a no-op relocation.  */
13816ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper  if (ebl_none_reloc_p (ebl, GELF_R_TYPE (r_info)))
13826ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper    return;
13836ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper
1384c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (r_info)))
1385c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1386c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      const char *name;
1387c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      char buf[64];
1388c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Sym sym_mem;
1389c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
1390c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (sym != NULL
1391c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  /* Get the name for the symbol.  */
1392c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1393c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
1394c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	ERROR (gettext ("\
1395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
1396c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	       idx, section_name (ebl, idx), cnt,
1397c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	       ebl_reloc_type_name (ebl, GELF_R_SYM (r_info),
1398c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper				    buf, sizeof (buf)));
1399c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1401c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (reldyn)
1402c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1403c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      // XXX TODO Check .rel.dyn section addresses.
1404c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1405c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  else if (!known_broken)
1406c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1407c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (destshdr != NULL
1408c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && GELF_R_TYPE (r_info) != 0
1409b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  && (r_offset - (ehdr->e_type == ET_REL ? 0
1410b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  : destshdr->sh_addr)) >= destshdr->sh_size)
1411c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	ERROR (gettext ("\
1412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: offset out of bounds\n"),
1413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1414c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
141641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Sym sym_mem;
141741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
141841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
141941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info))
1420c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      /* Make sure the referenced symbol is an object or unspecified.  */
142141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && sym != NULL
142241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE
142341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
142441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
142541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      char buf[64];
142641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      ERROR (gettext ("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"),
142741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	     idx, section_name (ebl, idx), cnt,
142841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	     ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
142941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				   buf, sizeof (buf)));
143041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
143141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1432038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper  if ((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1433038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      || (relshdr->sh_flags & SHF_ALLOC) != 0)
143441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
1435038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      bool in_loaded_seg = false;
1436038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      while (loaded != NULL)
1437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1438038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  if (r_offset < loaded->to
1439038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      && r_offset + (sym == NULL ? 0 : sym->st_size) >= loaded->from)
144041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    {
1441038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      /* The symbol is in this segment.  */
1442038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      if  (loaded->read_only)
1443038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		{
1444038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		  if (textrel)
1445038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		    needed_textrel = true;
1446038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		  else
1447038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		    ERROR (gettext ("section [%2d] '%s': relocation %zu: read-only section modified but text relocation flag not set\n"),
1448038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper			   idx, section_name (ebl, idx), cnt);
1449038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		}
1450038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper
1451038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      in_loaded_seg = true;
145241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    }
145341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1454038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  loaded = loaded->next;
1455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
145641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1457038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      if (*statep == state_undecided)
1458038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	*statep = in_loaded_seg ? state_loaded : state_unloaded;
1459038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      else if ((*statep == state_unloaded && in_loaded_seg)
1460038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	       || (*statep == state_loaded && !in_loaded_seg))
1461038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	{
1462038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  ERROR (gettext ("\
146341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Dreppersection [%2d] '%s': relocations are against loaded and unloaded data\n"),
1464038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		 idx, section_name (ebl, idx));
1465038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  *statep = state_error;
1466038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	}
1467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1472c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1474c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
1476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
1479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
1480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1482c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  /* Check the fields of the section header.  */
1483c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr destshdr_mem;
1484c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *destshdr = NULL;
148541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *loaded = NULL;
1486c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELA, &destshdr,
148741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				  &destshdr_mem, &loaded);
1488c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1489c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1490c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr symshdr_mem;
1491c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1492c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
149341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  enum load_state state = state_undecided;
1494c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
149571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
149671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  for (size_t cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1498c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rela rela_mem;
1499c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem);
1500c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (rela == NULL)
1501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1502c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  ERROR (gettext ("\
1503c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': cannot get relocation %zu: %s\n"),
1504c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1505c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  continue;
1506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1507c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1508607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1509607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       rela->r_offset, rela->r_info, destshdr, reldyn, loaded,
1510607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       &state);
151141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
151241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
151341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  while (loaded != NULL)
151441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
151541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *old = loaded;
151641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      loaded = loaded->next;
151741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      free (old);
1518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1519c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper}
1520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1521c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1522c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic void
1523c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1524c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper{
1525c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1526c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (data == NULL)
1527c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1528c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1529c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	     idx, section_name (ebl, idx));
1530c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      return;
1531c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1532c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1533c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  /* Check the fields of the section header.  */
1534c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr destshdr_mem;
1535c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *destshdr = NULL;
153641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *loaded = NULL;
1537c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_REL, &destshdr,
153841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				  &destshdr_mem, &loaded);
1539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
1542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
154441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  enum load_state state = state_undecided;
1545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
154671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
154771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  for (size_t cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Rel rel_mem;
1550c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem);
1551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rel == NULL)
1552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get relocation %zu: %s\n"),
1555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
1557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1559607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1560607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       rel->r_offset, rel->r_info, destshdr, reldyn, loaded,
1561607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       &state);
156241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
156341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
156441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  while (loaded != NULL)
156541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
156641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *old = loaded;
156741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      loaded = loaded->next;
156841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      free (old);
1569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Number of dynamic sections.  */
1574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int ndynamic;
1575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1578607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppercheck_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *data;
1581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr strshdr_mem;
1582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *strshdr;
1583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cnt;
1584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool dependencies[DT_NUM][DT_NUM] =
1585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_NEEDED] = { [DT_STRTAB] = true },
1587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTRELSZ] = { [DT_JMPREL] = true },
1588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_HASH] = { [DT_SYMTAB] = true },
1589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRTAB] = { [DT_STRSZ] = true },
1590231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_SYMENT] = true },
1591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true },
1592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELASZ] = { [DT_RELA] = true },
1593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELAENT] = { [DT_RELA] = true },
1594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRSZ] = { [DT_STRTAB] = true },
1595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMENT] = { [DT_SYMTAB] = true },
1596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SONAME] = { [DT_STRTAB] = true },
1597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RPATH] = { [DT_STRTAB] = true },
1598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true },
1599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELSZ] = { [DT_REL] = true },
1600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELENT] = { [DT_REL] = true },
1601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true },
1602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RUNPATH] = { [DT_STRTAB] = true },
1603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTREL] = { [DT_JMPREL] = true },
1604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool has_dt[DT_NUM];
1606231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  bool has_val_dt[DT_VALNUM];
1607231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  bool has_addr_dt[DT_ADDRNUM];
1608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool level2[DT_NUM] =
1609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RPATH] = true,
1611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMBOLIC] = true,
1612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_TEXTREL] = true,
1613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_BIND_NOW] = true
1614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool mandatory[DT_NUM] =
1616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_NULL] = true,
1618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRTAB] = true,
1619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMTAB] = true,
1620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRSZ] = true,
1621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMENT] = true
1622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  memset (has_dt, '\0', sizeof (has_dt));
1625231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  memset (has_val_dt, '\0', sizeof (has_val_dt));
1626231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  memset (has_addr_dt, '\0', sizeof (has_addr_dt));
1627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (++ndynamic == 2)
1629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("more than one dynamic section present\n"));
1630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
163141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
1633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
1636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
1637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem);
1640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB)
1641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
1643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   shdr->sh_link, section_name (ebl, shdr->sh_link),
1644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
16450a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  else if (strshdr == NULL)
16460a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    {
16470a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      ERROR (gettext ("\
16480a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d]: referenced as string table for section [%2d] '%s' but section link value is invalid\n"),
16490a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	   shdr->sh_link, idx, section_name (ebl, idx));
16500a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      return;
16510a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    }
1652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
165371c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
165471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  if (shdr->sh_entsize != sh_entsize)
1655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Dyn\n"),
1657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info != 0)
1660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool non_null_warned = false;
166471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Dyn dyn_mem;
1667acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dyn_mem);
1668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn == NULL)
1669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get dynamic section entry %zu: %s\n"),
1672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
1674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned)
1677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"),
1680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx));
1681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  non_null_warned = true;
1682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (!ebl_dynamic_tag_check (ebl, dyn->d_tag))
1685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': entry %zu: unknown tag\n"),
1686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag >= 0 && dyn->d_tag < DT_NUM)
1689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (has_dt[dyn->d_tag]
1691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_NEEDED
1692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_NULL
1693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_POSFLAG_1)
1694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf[50];
1696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: more than one entry with tag %s\n"),
1698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt,
1699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   buf, sizeof (buf)));
1701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (be_strict && level2[dyn->d_tag])
1704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf[50];
1706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: level 2 tag %s used\n"),
1708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt,
1709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   buf, sizeof (buf)));
1711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  has_dt[dyn->d_tag] = true;
1714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
17150a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      else if (dyn->d_tag >= 0 && dyn->d_tag <= DT_VALRNGHI
1716231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       && DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
1717231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	has_val_dt[DT_VALTAGIDX (dyn->d_tag)] = true;
17180a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      else if (dyn->d_tag >= 0 && dyn->d_tag <= DT_ADDRRNGHI
1719231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       && DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
1720231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	has_addr_dt[DT_ADDRTAGIDX (dyn->d_tag)] = true;
1721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL
1723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && dyn->d_un.d_val != DT_RELA)
1724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
1725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"),
1726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1728607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      /* Check that addresses for entries are in loaded segments.  */
1729607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      switch (dyn->d_tag)
1730607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	{
1731607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  size_t n;
1732cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_STRTAB:
1733cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  /* We require the referenced section is the same as the one
1734cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	     specified in sh_link.  */
1735cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  if (strshdr->sh_addr != dyn->d_un.d_val)
1736cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    {
1737cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      ERROR (gettext ("\
1738cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Dreppersection [%2d] '%s': entry %zu: pointer does not match address of section [%2d] '%s' referenced by sh_link\n"),
1739cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1740cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1741cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      break;
1742cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    }
1743cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  goto check_addr;
1744cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper
1745607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	default:
1746607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (dyn->d_tag < DT_ADDRRNGLO || dyn->d_tag > DT_ADDRRNGHI)
1747607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    /* Value is no pointer.  */
1748607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    break;
1749607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* FALLTHROUGH */
1750607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
1751cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_AUXILIARY:
1752cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FILTER:
1753cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FINI:
1754cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FINI_ARRAY:
1755607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_HASH:
1756607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_INIT:
1757607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_INIT_ARRAY:
1758cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_JMPREL:
1759cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_PLTGOT:
1760cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_REL:
1761cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RELA:
1762cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SYMBOLIC:
1763cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SYMTAB:
1764607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_VERDEF:
1765607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_VERNEED:
1766cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_VERSYM:
1767cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	check_addr:
1768bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  for (n = 0; n < phnum; ++n)
1769607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
1770607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr phdr_mem;
1771607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, n, &phdr_mem);
1772607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      if (phdr != NULL && phdr->p_type == PT_LOAD
1773607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr <= dyn->d_un.d_ptr
1774607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr + phdr->p_memsz > dyn->d_un.d_ptr)
1775607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		break;
1776607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
1777bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  if (unlikely (n >= phnum))
1778607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
1779607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      char buf[50];
1780607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      ERROR (gettext ("\
1781607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppersection [%2d] '%s': entry %zu: %s value must point into loaded segment\n"),
1782607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1783607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1784607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper					   sizeof (buf)));
1785607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
1786cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  break;
1787cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper
1788cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_NEEDED:
1789cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RPATH:
1790cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RUNPATH:
1791cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SONAME:
1792cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  if (dyn->d_un.d_ptr >= strshdr->sh_size)
1793cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    {
1794cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      char buf[50];
1795cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      ERROR (gettext ("\
1796cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Dreppersection [%2d] '%s': entry %zu: %s value must be valid offset in section [%2d] '%s'\n"),
1797cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1798cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1799cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper					   sizeof (buf)),
1800cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1801cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    }
1802cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  break;
1803607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	}
1804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 1; cnt < DT_NUM; ++cnt)
1807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (has_dt[cnt])
1808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1809acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	for (int inner = 0; inner < DT_NUM; ++inner)
1810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (dependencies[cnt][inner] && ! has_dt[inner])
1811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf1[50];
1813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf2[50];
1814b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1815b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1816b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': contains %s entry but not %s\n"),
1817b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx),
1818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)),
1819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2)));
1820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    else
1823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (mandatory[cnt])
1825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
1826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    char buf[50];
1827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': mandatory tag %s not present\n"),
1829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx),
1830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf)));
1831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
1832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1834231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* Make sure we have an hash table.  */
1835231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (!has_dt[DT_HASH] && !has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)])
1836231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    ERROR (gettext ("\
1837231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': no hash section present\n"),
1838231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   idx, section_name (ebl, idx));
1839231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1840231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* The GNU-style hash table also needs a symbol table.  */
1841231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (!has_dt[DT_HASH] && has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)]
1842231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      && !has_dt[DT_SYMTAB])
1843231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    ERROR (gettext ("\
1844231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': contains %s entry but not %s\n"),
1845231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   idx, section_name (ebl, idx),
1846231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   "DT_GNU_HASH", "DT_SYMTAB");
1847231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the rel/rela tags.  At least one group must be available.  */
1849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT])
1850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT]))
1851b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': not all of %s, %s, and %s are present\n"),
1853b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
1854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   "DT_RELA", "DT_RELASZ", "DT_RELAENT");
1855b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1856b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT])
1857b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT]))
1858b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': not all of %s, %s, and %s are present\n"),
1860b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
1861b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   "DT_REL", "DT_RELSZ", "DT_RELENT");
1862231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1863231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* Check that all prelink sections are present if any of them is.  */
1864231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)]
1865231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1866231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    {
1867231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)])
1868231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1869231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1870231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_PRELINKED");
1871231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1872231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1873231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1874231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_CHECKSUM");
1875231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1876231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      /* Only DSOs can be marked like this.  */
1877231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (ehdr->e_type != ET_DYN)
1878231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1879231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': non-DSO file marked as dependency during prelink\n"),
1880231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx));
1881231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    }
1882231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1883231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)]
1884231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)]
1885231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)]
1886231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1887231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    {
1888231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)])
1889231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1890231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1891231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_CONFLICTSZ");
1892231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)])
1893231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1894231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1895231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_LIBLISTSZ");
1896231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)])
1897231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1898231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1899231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_CONFLICT");
1900231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1901231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1902231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1903231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_LIBLIST");
1904231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    }
1905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1906b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1907b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1908b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1909acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1910b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1911acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (ehdr->e_type != ET_REL)
1912acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
1913acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      ERROR (gettext ("\
1914acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': only relocatable files can have extended section index\n"),
1915acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	     idx, section_name (ebl, idx));
1916acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      return;
1917acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    }
1918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1919acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1920acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr symshdr_mem;
1921acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1922b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB)
1923b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1924b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended section index section not for symbol table\n"),
1925b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
19260a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  else if (symshdr == NULL)
19270a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    ERROR (gettext ("\
19280a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': sh_link extended section index [%2d] is invalid\n"),
19290a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	   idx, section_name (ebl, idx), shdr->sh_link);
1930acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
1931b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symdata == NULL)
1932b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("cannot get data for symbol section\n"));
1933b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1934b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_entsize != sizeof (Elf32_Word))
1935b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1936b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry size does not match Elf32_Word\n"),
1937b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1938b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1939b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL
19400a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      && shdr->sh_entsize != 0
19410a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      && symshdr->sh_entsize != 0
1942b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (shdr->sh_size / shdr->sh_entsize
1943b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  < symshdr->sh_size / symshdr->sh_entsize))
1944b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1945b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended index table too small for symbol table\n"),
1946b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1947b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1948b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info != 0)
1949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1950b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1951b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1952acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = idx + 1; cnt < shnum; ++cnt)
1953b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1954b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr rshdr_mem;
1955acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      GElf_Shdr *rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem);
1956b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX
1957b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && rshdr->sh_link == shdr->sh_link)
1958b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1960b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"),
1961b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx),
1962b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, section_name (ebl, cnt));
1963b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1964b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1965b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1966b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1967acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
19680a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || data->d_buf == NULL)
196971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    {
197071c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
197171c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	     idx, section_name (ebl, idx));
197271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      return;
197371c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    }
1974b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (*((Elf32_Word *) data->d_buf) != 0)
1976b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("symbol 0 should have zero extended section index\n"));
1977b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1978acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt];
1981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndx != 0)
1983b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Sym sym_data;
1985b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data);
1986b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym == NULL)
1987b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1988b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("cannot get data for symbol %zu\n"), cnt);
1989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
1990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1992b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym->st_shndx != SHN_XINDEX)
1993b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1994b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperextended section index is %" PRIu32 " but symbol index is not XINDEX\n"),
1995b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   (uint32_t) xndx);
1996b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1997b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1998b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1999b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2000b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2001b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
200228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
200328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		 GElf_Shdr *symshdr)
200428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
200528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
200628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
200728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
200828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
200928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    ERROR (gettext ("\
201028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
201128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
201228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
201328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
201428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t maxidx = nchain;
201528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
201671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  if (symshdr != NULL && symshdr->sh_entsize != 0)
201728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
201828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
201928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
202028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
202128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
202228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx));
202328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
202428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      maxidx = symsize;
202528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
202628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
202771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  Elf32_Word *buf = (Elf32_Word *) data->d_buf;
202871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  Elf32_Word *end = (Elf32_Word *) ((char *) data->d_buf + shdr->sh_size);
202928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
203028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
203171c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    {
203271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      if (buf + cnt >= end)
203371c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	break;
203471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      else if (buf[cnt] >= maxidx)
203528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
203628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash bucket reference %zu out of bounds\n"),
203728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2);
203871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    }
203928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
204028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (; cnt < 2 + nbucket + nchain; ++cnt)
204171c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    {
204271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      if (buf + cnt >= end)
204371c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	break;
204471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      else if (buf[cnt] >= maxidx)
204528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
204628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain reference %zu out of bounds\n"),
204728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2 - nbucket);
204871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    }
204928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
205028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
205128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
205228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
205328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
205428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		 GElf_Shdr *symshdr)
205528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
205628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
205728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
205828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
205928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
206028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    ERROR (gettext ("\
206128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
206228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
206328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
206428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
206528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t maxidx = nchain;
206628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
20670a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (symshdr != NULL && symshdr->sh_entsize != 0)
206828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
206928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
207028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
207128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
207228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
207328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx));
207428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
207528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      maxidx = symsize;
207628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
207728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
207871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  Elf64_Xword *buf = (Elf64_Xword *) data->d_buf;
207971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  Elf64_Xword *end = (Elf64_Xword *) ((char *) data->d_buf + shdr->sh_size);
208028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
208128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
208271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    {
208371c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      if (buf + cnt >= end)
208471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	break;
208571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      else if (buf[cnt] >= maxidx)
208628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
208728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash bucket reference %zu out of bounds\n"),
208828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2);
208971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    }
209028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
209128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (; cnt < 2 + nbucket + nchain; ++cnt)
209271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    {
209371c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      if (buf + cnt >= end)
209471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	break;
209571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      else if (buf[cnt] >= maxidx)
209628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
2097dcf6160602985e6eb70c96c6546ed9614a414d98Ulrich Dreppersection [%2d] '%s': hash chain reference %" PRIu64 " out of bounds\n"),
209871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	       idx, section_name (ebl, idx), (uint64_t) cnt - 2 - nbucket);
209971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    }
210028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
210128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
210228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
210328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
210428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
210528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		GElf_Shdr *symshdr)
210628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
2107281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard  if (data->d_size < 4 * sizeof (Elf32_Word))
2108281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard    {
2109281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard      ERROR (gettext ("\
2110281bb49c71665f306b23107cbf821636f59211e0Mark Wielaardsection [%2d] '%s': not enough data\n"),
2111281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard	     idx, section_name (ebl, idx));
2112281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard      return;
2113281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard    }
2114281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard
211528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0];
211628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
21178ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
211828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
2119281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard  if (bitmask_words == 0 || !powerof2 (bitmask_words))
2120281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard    {
2121281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard      ERROR (gettext ("\
2122281bb49c71665f306b23107cbf821636f59211e0Mark Wielaardsection [%2d] '%s': bitmask size zero or not power of 2: %u\n"),
2123281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard	     idx, section_name (ebl, idx), bitmask_words);
2124281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard      return;
2125281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard    }
21268ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
21278ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t bitmask_idxmask = bitmask_words - 1;
21288ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (gelf_getclass (ebl->elf) == ELFCLASS64)
21298ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    bitmask_words *= 2;
21308ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
21318ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
2132281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard  /* Is there still room for the sym chain?
2133281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard     Use uint64_t calculation to prevent 32bit overlow.  */
2134281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard  uint64_t used_buf = (4ULL + bitmask_words + nbuckets) * sizeof (Elf32_Word);
2135281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard  if (used_buf > data->d_size)
213628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
213728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
213871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelineksection [%2d] '%s': hash table section is too small (is %ld, expected at least %ld)\n"),
213928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), (long int) shdr->sh_size,
2140281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard	     (long int) used_buf);
214128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      return;
214228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
214328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
21448ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shift > 31)
214516e2ac344788f2bb08ae9dc0a20948f554ca560cMark Wielaard    {
214616e2ac344788f2bb08ae9dc0a20948f554ca560cMark Wielaard      ERROR (gettext ("\
21478ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': 2nd hash function shift too big: %u\n"),
214816e2ac344788f2bb08ae9dc0a20948f554ca560cMark Wielaard	     idx, section_name (ebl, idx), shift);
214916e2ac344788f2bb08ae9dc0a20948f554ca560cMark Wielaard      return;
215016e2ac344788f2bb08ae9dc0a20948f554ca560cMark Wielaard    }
21518ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
21528ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words
21538ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							 + nbuckets);
215428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
21550a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (symshdr != NULL && symshdr->sh_entsize != 0)
215628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    maxidx = MIN (maxidx, symshdr->sh_size / symshdr->sh_entsize);
215728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
215828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  /* We need the symbol section data.  */
215928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf_Data *symdata = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link), NULL);
216028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
21618ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  union
21628ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  {
21638ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    Elf32_Word *p32;
21648ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    Elf64_Xword *p64;
21658ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  } bitmask = { .p32 = &((Elf32_Word *) data->d_buf)[4] },
21668ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      collected = { .p32 = xcalloc (bitmask_words, sizeof (Elf32_Word)) };
21678ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
21688ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t classbits = gelf_getclass (ebl->elf) == ELFCLASS32 ? 32 : 64;
21698ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
217028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
21718ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  for (cnt = 4 + bitmask_words; cnt < 4 + bitmask_words + nbuckets; ++cnt)
217228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
21738ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      Elf32_Word symidx = ((Elf32_Word *) data->d_buf)[cnt];
217428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
217528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx == 0)
21768ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	continue;
217728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
217828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx < symbias)
217928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	{
218028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  ERROR (gettext ("\
218128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"),
21828ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		 idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
218328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  continue;
218428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	}
218528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
218628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      while (symidx - symbias < maxidx)
218728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	{
21888ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	  Elf32_Word chainhash = ((Elf32_Word *) data->d_buf)[4
21898ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							      + bitmask_words
21908ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							      + nbuckets
219128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							      + symidx
219228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							      - symbias];
219328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
219428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  if (symdata != NULL)
219528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    {
219628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      /* Check that the referenced symbol is not undefined.  */
219728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      GElf_Sym sym_mem;
219828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      GElf_Sym *sym = gelf_getsym (symdata, symidx, &sym_mem);
2199231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	      if (sym != NULL && sym->st_shndx == SHN_UNDEF
2200231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper		  && GELF_ST_TYPE (sym->st_info) != STT_FUNC)
220128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		ERROR (gettext ("\
220228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': symbol %u referenced in chain for bucket %zu is undefined\n"),
22035530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper		       idx, section_name (ebl, idx), symidx,
22045530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper		       cnt - (4 + bitmask_words));
220528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
22060a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      const char *symname = (sym != NULL
22070a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard				     ? elf_strptr (ebl->elf, symshdr->sh_link,
22080a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard						   sym->st_name)
22090a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard				     : NULL);
221028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      if (symname != NULL)
221128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		{
221228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  Elf32_Word hval = elf_gnu_hash (symname);
221328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if ((hval & ~1u) != (chainhash & ~1u))
221428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    ERROR (gettext ("\
221528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"),
22165530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper			   idx, section_name (ebl, idx), symidx,
22175530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper			   cnt - (4 + bitmask_words));
22188ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
22198ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  /* Set the bits in the bitmask.  */
22208ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  size_t maskidx = (hval / classbits) & bitmask_idxmask;
22210a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		  if (maskidx >= bitmask_words)
22220a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		    {
22230a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		      ERROR (gettext ("\
22240a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n"),
22250a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard			     idx, section_name (ebl, idx), symidx,
22260a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard			     cnt - (4 + bitmask_words));
22270a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		      return;
22280a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		    }
22298ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  if (classbits == 32)
22308ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    {
22318ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p32[maskidx]
22328ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT32_C (1) << (hval & (classbits - 1));
22338ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p32[maskidx]
22348ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT32_C (1) << ((hval >> shift) & (classbits - 1));
22358ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    }
22368ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  else
22378ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    {
22388ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p64[maskidx]
22398ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT64_C (1) << (hval & (classbits - 1));
22408ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p64[maskidx]
22418ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT64_C (1) << ((hval >> shift) & (classbits - 1));
22428ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    }
224328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		}
224428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    }
224528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
224628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  if ((chainhash & 1) != 0)
224728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    break;
224828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
224928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  ++symidx;
225028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	}
225128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
225228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx - symbias >= maxidx)
225328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("\
225428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain for bucket %zu out of bounds\n"),
22555530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper	       idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
22560a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      else if (symshdr != NULL && symshdr->sh_entsize != 0
225728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       && symidx > symshdr->sh_size / symshdr->sh_entsize)
225828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("\
225928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"),
22605530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper	       idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
226128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
22628ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
22638ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (memcmp (collected.p32, bitmask.p32, bitmask_words * sizeof (Elf32_Word)))
22648ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    ERROR (gettext ("\
22658ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': bitmask does not match names in the hash table\n"),
22668ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	   idx, section_name (ebl, idx));
22678ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
22688ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  free (collected.p32);
226928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
227028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
227128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
227228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
227328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_hash (int tag, Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2275acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (ehdr->e_type == ET_REL)
2276acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
2277acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      ERROR (gettext ("\
2278acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': relocatable files cannot have hash tables\n"),
2279acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	     idx, section_name (ebl, idx));
2280acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      return;
2281acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    }
2282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2283acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
22840a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || data->d_buf == NULL)
2285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2291acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr symshdr_mem;
2292acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2293acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &symshdr_mem);
2294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM)
2295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
2296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': hash table not for dynamic symbol table\n"),
2297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
22980a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  else if (symshdr == NULL)
22990a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    ERROR (gettext ("\
23000a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': invalid sh_link symbol table section index [%2d]\n"),
23010a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	   idx, section_name (ebl, idx), shdr->sh_link);
2302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
230328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_entsize != (tag == SHT_GNU_HASH
23048ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			   ? (gelf_getclass (ebl->elf) == ELFCLASS32
23058ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			      ? sizeof (Elf32_Word) : 0)
230628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   : (size_t) ebl_sysvhash_entrysize (ebl)))
2307b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
230828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table entry size incorrect\n"),
2309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((shdr->sh_flags & SHF_ALLOC) == 0)
2312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': not marked to be allocated\n"),
2313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
23158ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (shdr->sh_entsize ?: 4))
2316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
23188ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': hash table has not even room for initial administrative entries\n"),
2319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
232328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  switch (tag)
2324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
232528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    case SHT_HASH:
232628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
232728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	check_sysv_hash64 (ebl, shdr, data, idx, symshdr);
232828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      else
232928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	check_sysv_hash (ebl, shdr, data, idx, symshdr);
233028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      break;
2331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
233228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    case SHT_GNU_HASH:
233328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      check_gnu_hash (ebl, shdr, data, idx, symshdr);
233428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      break;
2335ee4b927bae351b21787355e00a3d28371bf78e8fUlrich Drepper
233628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    default:
23378ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      assert (! "should not happen");
2338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
23427c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper/* Compare content of both hash tables, it must be identical.  */
23437c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepperstatic void
23447c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppercompare_hash_gnu_hash (Ebl *ebl, GElf_Ehdr *ehdr, size_t hash_idx,
23457c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		       size_t gnu_hash_idx)
23467c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper{
23477c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *hash_scn = elf_getscn (ebl->elf, hash_idx);
23487c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *hash_data = elf_getdata (hash_scn, NULL);
23497c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr hash_shdr_mem;
23507c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *hash_shdr = gelf_getshdr (hash_scn, &hash_shdr_mem);
23517c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *gnu_hash_scn = elf_getscn (ebl->elf, gnu_hash_idx);
23527c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *gnu_hash_data = elf_getdata (gnu_hash_scn, NULL);
23537c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr gnu_hash_shdr_mem;
23547c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *gnu_hash_shdr = gelf_getshdr (gnu_hash_scn, &gnu_hash_shdr_mem);
23557c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23567c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr == NULL || gnu_hash_shdr == NULL
23570a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      || hash_data == NULL || hash_data->d_buf == NULL
23580a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      || gnu_hash_data == NULL || gnu_hash_data->d_buf == NULL)
23597c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    /* None of these pointers should be NULL since we used the
23607c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper       sections already.  We are careful nonetheless.  */
23617c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    return;
23627c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23637c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* The link must point to the same symbol table.  */
23647c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr->sh_link != gnu_hash_shdr->sh_link)
23657c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
23667c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      ERROR (gettext ("\
23677c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"),
23687c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
23697c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     gnu_hash_idx,
23707c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
23717c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      return;
23727c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
23737c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23747c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *sym_scn = elf_getscn (ebl->elf, hash_shdr->sh_link);
23757c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *sym_data = elf_getdata (sym_scn, NULL);
23767c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr sym_shdr_mem;
23777c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *sym_shdr = gelf_getshdr (sym_scn, &sym_shdr_mem);
23787c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23790a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (sym_data == NULL || sym_data->d_buf == NULL
23800a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      || sym_shdr == NULL || sym_shdr->sh_entsize == 0)
23817c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    return;
23827c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23830a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  const char *hash_name;
23840a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  const char *gnu_hash_name;
23850a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  hash_name  = elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name);
23860a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  gnu_hash_name  = elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name);
23870a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
23880a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (gnu_hash_data->d_size < 4 * sizeof (Elf32_Word))
23890a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    {
23900a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      ERROR (gettext ("\
23910a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' does not contain enough data\n"),
23920a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	     gnu_hash_idx, gnu_hash_name);
23930a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      return;
23940a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    }
23950a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
23960a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  uint32_t nentries = sym_shdr->sh_size / sym_shdr->sh_entsize;
23977c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  char *used = alloca (nentries);
23987c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  memset (used, '\0', nentries);
23997c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
24007c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* First go over the GNU_HASH table and mark the entries as used.  */
24017c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const Elf32_Word *gnu_hasharr = (Elf32_Word *) gnu_hash_data->d_buf;
24027c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf32_Word gnu_nbucket = gnu_hasharr[0];
24030a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  Elf32_Word gnu_symbias = gnu_hasharr[1];
24047c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const int bitmap_factor = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 1 : 2;
24057c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const Elf32_Word *gnu_bucket = (gnu_hasharr
24067c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper				  + (4 + gnu_hasharr[2] * bitmap_factor));
24070a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  const Elf32_Word *gnu_chain = gnu_bucket + gnu_hasharr[0];
24080a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
24090a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (gnu_hasharr[2] == 0)
24100a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    {
24110a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      ERROR (gettext ("\
24120a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' has zero bit mask words\n"),
24130a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	     gnu_hash_idx, gnu_hash_name);
24140a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      return;
24150a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    }
24160a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
24170a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  uint64_t used_buf = ((4ULL + gnu_hasharr[2] * bitmap_factor + gnu_nbucket)
24180a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		       * sizeof (Elf32_Word));
24190a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  uint32_t max_nsyms = (gnu_hash_data->d_size - used_buf) / sizeof (Elf32_Word);
24200a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (used_buf > gnu_hash_data->d_size)
24210a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    {
24220a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      ERROR (gettext ("\
24230a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' uses too much data\n"),
24240a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	     gnu_hash_idx, gnu_hash_name);
24250a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      return;
24260a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    }
24277c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
24287c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  for (Elf32_Word cnt = 0; cnt < gnu_nbucket; ++cnt)
24297c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
2430ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard      if (gnu_bucket[cnt] != STN_UNDEF)
2431ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	{
2432ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	  Elf32_Word symidx = gnu_bucket[cnt] - gnu_symbias;
2433ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	  do
2434ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	    {
2435ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	      if (symidx >= max_nsyms || symidx + gnu_symbias >= nentries)
2436ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard		{
2437ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard		  ERROR (gettext ("\
2438ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaardhash section [%2zu] '%s' invalid symbol index %" PRIu32 " (max_nsyms: %" PRIu32 ", nentries: %" PRIu32 "\n"),
2439ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard			 gnu_hash_idx, gnu_hash_name, symidx, max_nsyms, nentries);
2440ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard		  return;
2441ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard		}
2442ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	      used[symidx + gnu_symbias] |= 1;
2443ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	    }
2444ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	  while ((gnu_chain[symidx++] & 1u) == 0);
2445ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	}
24467c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
24477c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
24487c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* Now go over the old hash table and check that we cover the same
24497c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     entries.  */
24507c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr->sh_entsize == sizeof (Elf32_Word))
24517c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
24527c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *hasharr = (Elf32_Word *) hash_data->d_buf;
24530a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (hash_data->d_size < 2 * sizeof (Elf32_Word))
24540a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
24550a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
24560a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' does not contain enough data\n"),
24570a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		 hash_idx, hash_name);
24580a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  return;
24590a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
24600a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
24617c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      Elf32_Word nbucket = hasharr[0];
24620a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      Elf32_Word nchain = hasharr[1];
24630a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      uint64_t hash_used = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
24640a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (hash_used > hash_data->d_size)
24650a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
24660a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
24670a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' uses too much data\n"),
24680a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		 hash_idx, hash_name);
24690a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  return;
24700a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
24710a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
24727c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *bucket = &hasharr[2];
24737c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *chain = &hasharr[2 + nbucket];
24747c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
24757c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
24767c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	{
24777c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  Elf32_Word symidx = bucket[cnt];
24780a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  while (symidx != STN_UNDEF && symidx < nentries && symidx < nchain)
24797c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    {
24807c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      used[symidx] |= 2;
24817c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      symidx = chain[symidx];
24827c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    }
24837c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	}
24847c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
24850a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  else if (hash_shdr->sh_entsize == sizeof (Elf64_Word))
24867c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
24877c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *hasharr = (Elf64_Xword *) hash_data->d_buf;
24880a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (hash_data->d_size < 2 * sizeof (Elf32_Word))
24890a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
24900a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
24910a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' does not contain enough data\n"),
24920a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		 hash_idx, hash_name);
24930a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  return;
24940a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
24950a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
24967c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      Elf64_Xword nbucket = hasharr[0];
24970a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      Elf64_Xword nchain = hasharr[1];
24980a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      uint64_t maxwords = hash_data->d_size / sizeof (Elf64_Xword);
24990a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (maxwords < 2
25000a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  || maxwords - 2 < nbucket
25010a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  || maxwords - 2 - nbucket < nchain)
25020a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
25030a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
25040a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' uses too much data\n"),
25050a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		 hash_idx, hash_name);
25060a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  return;
25070a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
25080a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
25097c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *bucket = &hasharr[2];
25107c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *chain = &hasharr[2 + nbucket];
25117c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
25127c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
25137c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	{
25147c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  Elf64_Xword symidx = bucket[cnt];
25150a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  while (symidx != STN_UNDEF && symidx < nentries && symidx < nchain)
25167c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    {
25177c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      used[symidx] |= 2;
25187c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      symidx = chain[symidx];
25197c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    }
25207c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	}
25217c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
25220a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  else
25230a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    {
25240a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      ERROR (gettext ("\
25250a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' invalid sh_entsize\n"),
25260a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	     gnu_hash_idx, gnu_hash_name);
25270a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      return;
25280a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    }
25297c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
25307c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* Now see which entries are not set in one or both hash tables
25317c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     (unless the symbol is undefined in which case it can be omitted
25327c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     in the new table format).  */
25337c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if ((used[0] & 1) != 0)
25347c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"),
25357c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   gnu_hash_idx,
25367c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
25377c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if ((used[0] & 2) != 0)
25387c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"),
25397c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
25407c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
25410a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  for (uint32_t cnt = 1; cnt < nentries; ++cnt)
25427c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    if (used[cnt] != 0 && used[cnt] != 3)
25437c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      {
25447c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	if (used[cnt] == 1)
25457c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  ERROR (gettext ("\
25467c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersymbol %d referenced in new hash table in [%2zu] '%s' but not in old hash table in [%2zu] '%s'\n"),
25477c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 cnt, gnu_hash_idx,
25487c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name),
25497c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 hash_idx,
25507c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
25517c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	else
25527c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  {
25537c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    GElf_Sym sym_mem;
25547c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    GElf_Sym *sym = gelf_getsym (sym_data, cnt, &sym_mem);
25557c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
25567c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    if (sym != NULL && sym->st_shndx != STN_UNDEF)
25577c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      ERROR (gettext ("\
25587c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersymbol %d referenced in old hash table in [%2zu] '%s' but not in new hash table in [%2zu] '%s'\n"),
25597c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     cnt, hash_idx,
25607c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
25617c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     gnu_hash_idx,
25627c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
25637c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  }
25647c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      }
25657c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper}
25667c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
25677c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
2568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_null (Ebl *ebl, GElf_Shdr *shdr, int idx)
2570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define TEST(name, extra) \
2572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (extra && shdr->sh_##name != 0)					      \
2573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': nonzero sh_%s for NULL section\n"),  \
2574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), #name)
2575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (name, 1);
2577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (flags, 1);
2578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (addr, 1);
2579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (offset, 1);
2580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (size, idx != 0);
2581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (link, idx != 0);
2582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (info, 1);
2583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (addralign, 1);
2584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (entsize, 1);
2585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_REL)
2592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
2594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section groups only allowed in relocatable object files\n"),
2595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check that sh_link is an index of a symbol table.  */
26000e864dd86871c809668c557985ca19344dfff787Ulrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
26020e864dd86871c809668c557985ca19344dfff787Ulrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr == NULL)
2604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': cannot get symbol table: %s\n"),
2605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), elf_errmsg (-1));
2606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (symshdr->sh_type != SHT_SYMTAB)
2609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section reference in sh_link is no symbol table\n"),
2611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM,
2614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper							  1, EV_CURRENT))
2615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': invalid symbol index in sh_info\n"),
2617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags != 0)
2620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': sh_flags not zero\n"),
2621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
26230e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      GElf_Sym sym_data;
26240e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      GElf_Sym *sym = gelf_getsym (elf_getdata (symscn, NULL), shdr->sh_info,
26250e864dd86871c809668c557985ca19344dfff787Ulrich Drepper				   &sym_data);
26260e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      if (sym == NULL)
26270e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	ERROR (gettext ("\
26280e864dd86871c809668c557985ca19344dfff787Ulrich Dreppersection [%2d] '%s': cannot get symbol for signature\n"),
26290e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	       idx, section_name (ebl, idx));
26300a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      else if (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name) == NULL)
26310a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	ERROR (gettext ("\
26320a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': cannot get symbol name for signature\n"),
26330a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	       idx, section_name (ebl, idx));
26340e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      else if (strcmp (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name),
26350e864dd86871c809668c557985ca19344dfff787Ulrich Drepper		       "") == 0)
26360e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	ERROR (gettext ("\
26373b495d8e963eead963a37b5be5b063c96bb58c63Roland McGrathsection [%2d] '%s': signature symbol cannot be empty string\n"),
26380e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	       idx, section_name (ebl, idx));
26390e864dd86871c809668c557985ca19344dfff787Ulrich Drepper
2640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (be_strict
2641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT))
2642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': sh_flags not set correctly\n"),
2643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
26470a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || data->d_buf == NULL)
2648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': cannot get data: %s\n"),
2649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), elf_errmsg (-1));
2650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
2653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t cnt;
2654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf32_Word val;
2655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data->d_size % elsize != 0)
2657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"),
2659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data->d_size < elsize)
2662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group without flags word\n"),
2664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (be_strict)
2666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (data->d_size < 2 * elsize)
2668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group without member\n"),
2670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
2671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (data->d_size < 3 * elsize)
2672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group with only one member\n"),
2674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
2675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if ALLOW_UNALIGNED
2678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      val = *((Elf32_Word *) data->d_buf);
2679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#else
2680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      memcpy (&val, data->d_buf, elsize);
2681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
2682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((val & ~GRP_COMDAT) != 0)
2683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': unknown section group flags\n"),
2684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = elsize; cnt < data->d_size; cnt += elsize)
2687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if ALLOW_UNALIGNED
2689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  val = *((Elf32_Word *) ((char *) data->d_buf + cnt));
2690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#else
2691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  memcpy (&val, (char *) data->d_buf + cnt, elsize);
2692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
2693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (val > shnum)
2695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
26962ec957327cdfae6cee592a52958a9c937ea4b13cChih-Hung Hsiehsection [%2d] '%s': section index %zu out of range\n"),
2697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt / elsize);
2698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
2699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
2700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Shdr refshdr_mem;
2701acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	      GElf_Shdr *refshdr = gelf_getshdr (elf_getscn (ebl->elf, val),
2702acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper						 &refshdr_mem);
2703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (refshdr == NULL)
2704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
2705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get section header for element %zu: %s\n"),
2706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx), cnt / elsize,
2707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       elf_errmsg (-1));
2708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
2709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
2710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (refshdr->sh_type == SHT_GROUP)
2711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
2712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group contains another group [%2d] '%s'\n"),
2713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx),
2714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   val, section_name (ebl, val));
2715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if ((refshdr->sh_flags & SHF_GROUP) == 0)
2717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
27182ec957327cdfae6cee592a52958a9c937ea4b13cChih-Hung Hsiehsection [%2d] '%s': element %zu references section [%2d] '%s' without SHF_GROUP flag set\n"),
2719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx), cnt / elsize,
2720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   val, section_name (ebl, val));
2721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
2722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
27230a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      if (val < shnum && ++scnref[val] == 2)
2724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
2725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' is contained in more than one section group\n"),
2726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       val, section_name (ebl, val));
2727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
2728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2729b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2730b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2731b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *
2734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection_flags_string (GElf_Word flags, char *buf, size_t len)
2735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2736099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath  if (flags == 0)
2737099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath    return "none";
2738099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath
2739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const struct
2740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
2741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    GElf_Word flag;
2742b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    const char *name;
2743b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  } known_flags[] =
2744b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define NEWFLAG(name) { SHF_##name, #name }
2746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (WRITE),
2747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (ALLOC),
2748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (EXECINSTR),
2749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (MERGE),
2750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (STRINGS),
2751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (INFO_LINK),
2752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (LINK_ORDER),
2753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (OS_NONCONFORMING),
2754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (GROUP),
2755e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard      NEWFLAG (TLS),
2756e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard      NEWFLAG (COMPRESSED)
2757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
2758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#undef NEWFLAG
2759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
2760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *cp = buf;
2762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2763acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 0; cnt < nknown_flags; ++cnt)
2764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (flags & known_flags[cnt].flag)
2765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
2766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (cp != buf && len > 1)
2767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
2768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    *cp++ = '|';
2769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    --len;
2770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
2771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name));
2773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	cp = mempcpy (cp, known_flags[cnt].name, ncopy);
2774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	len -= ncopy;
2775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	flags ^= known_flags[cnt].flag;
2777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
2778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (flags != 0 || cp == buf)
2780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    snprintf (cp, len - 1, "%" PRIx64, (uint64_t) flags);
2781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *cp = '\0';
2783b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2784b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return buf;
2785b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2786b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2787b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2788dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2789dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperhas_copy_reloc (Ebl *ebl, unsigned int symscnndx, unsigned int symndx)
2790dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2791dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* First find the relocation section for the symbol table.  */
2792dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = NULL;
2793dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2794dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = NULL;
2795dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2796dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2797dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      shdr = gelf_getshdr (scn, &shdr_mem);
2798dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (shdr != NULL
2799dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
2800dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && shdr->sh_link == symscnndx)
2801dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	/* Found the section.  */
2802dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	break;
2803dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2804dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2805dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (scn == NULL)
2806dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 0;
2807dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2808dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
28090a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || shdr->sh_entsize == 0)
2810dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 0;
2811dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2812dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr->sh_type == SHT_REL)
2813dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2814dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2815dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rel rel_mem;
2816dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
2817dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (rel == NULL)
2818dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  continue;
2819dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2820dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (GELF_R_SYM (rel->r_info) == symndx
2821dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info)))
2822dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  return 1;
2823dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2824dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  else
2825dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2826dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2827dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rela rela_mem;
2828dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
2829dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (rela == NULL)
2830dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  continue;
2831dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2832dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (GELF_R_SYM (rela->r_info) == symndx
2833dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info)))
2834dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  return 1;
2835dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2836dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2837dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 0;
2838dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2839dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2840dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2841637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic int
2842637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperin_nobits_scn (Ebl *ebl, unsigned int shndx)
2843637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper{
2844637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Shdr shdr_mem;
2845637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, shndx), &shdr_mem);
2846637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  return shdr != NULL && shdr->sh_type == SHT_NOBITS;
2847637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper}
2848637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2849637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2850dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic struct version_namelist
2851dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2852dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  const char *objname;
2853dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  const char *name;
2854858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrath  GElf_Versym ndx;
2855dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  enum { ver_def, ver_need } type;
2856dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct version_namelist *next;
2857dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper} *version_namelist;
2858dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2859dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2860dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2861858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrathadd_version (const char *objname, const char *name, GElf_Versym ndx, int type)
2862dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2863dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Check that there are no duplications.  */
2864dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct version_namelist *nlp = version_namelist;
2865dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while (nlp != NULL)
2866dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2867dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (((nlp->objname == NULL && objname == NULL)
2868dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	   || (nlp->objname != NULL && objname != NULL
2869dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       && strcmp (nlp->objname, objname) == 0))
2870dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && strcmp (nlp->name, name) == 0)
2871dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	return nlp->type == ver_def ? 1 : -1;
2872dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      nlp = nlp->next;
2873dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2874dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2875dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp = xmalloc (sizeof (*nlp));
2876dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->objname = objname;
2877dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->name = name;
2878dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->ndx = ndx;
2879dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->type = type;
2880dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->next = version_namelist;
2881dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  version_namelist = nlp;
2882dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2883dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 0;
2884dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2885dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2886dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2887b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2888dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_versym (Ebl *ebl, int idx)
2889b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2890dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = elf_getscn (ebl->elf, idx);
2891dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2892dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2893dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr == NULL)
2894dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    /* The error has already been reported.  */
2895dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
2896dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2897dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
2898dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2899dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2900dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2901dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
2902dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
2903dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2904dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2905dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2906b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
2907dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2908b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr == NULL)
2909b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* The error has already been reported.  */
2910b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
2911b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2912b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr->sh_type != SHT_DYNSYM)
2913b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2914b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
2915b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"),
2916b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx),
2917b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     shdr->sh_link, section_name (ebl, shdr->sh_link));
2918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2920b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2921dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* The number of elements in the version symbol table must be the
2922dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     same as the number of symbols.  */
29230a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (shdr->sh_entsize != 0 && symshdr->sh_entsize != 0
292471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      && (shdr->sh_size / shdr->sh_entsize
292571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	  != symshdr->sh_size / symshdr->sh_entsize))
2926b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
2927b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"),
2928b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
2929b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   shdr->sh_link, section_name (ebl, shdr->sh_link));
2930b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2931dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
29320a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (symdata == NULL || shdr->sh_entsize == 0)
2933dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    /* The error has already been reported.  */
2934dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
2935dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2936dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (int cnt = 1; (size_t) cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2937dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2938dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Versym versym_mem;
2939dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Versym *versym = gelf_getversym (data, cnt, &versym_mem);
2940dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (versym == NULL)
2941dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2942dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2943dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: cannot read version data\n"),
2944dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
2945dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  break;
2946dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2947dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2948dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Sym sym_mem;
2949dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_mem);
2950dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (sym == NULL)
2951dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	/* Already reported elsewhere.  */
2952dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	continue;
2953dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
295461655e08ba36430de47381cefdf10d0c26aa8480Ulrich Drepper      if (*versym == VER_NDX_GLOBAL)
2955dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2956dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* Global symbol.  Make sure it is not defined as local.  */
2957dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2958dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2959dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: local symbol with global scope\n"),
2960dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
2961dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
296261655e08ba36430de47381cefdf10d0c26aa8480Ulrich Drepper      else if (*versym != VER_NDX_LOCAL)
2963dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2964c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	  /* Versioned symbol.  Make sure it is not defined as local.  */
2965c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	  if (!gnuld && GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2966c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	    ERROR (gettext ("\
2967c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Dreppersection [%2d] '%s': symbol %d: local symbol with version\n"),
2968c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
2969c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper
2970dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* Look through the list of defined versions and locate the
2971dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     index we need for this symbol.  */
2972dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *runp = version_namelist;
2973dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  while (runp != NULL)
2974858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrath	    if (runp->ndx == (*versym & (GElf_Versym) 0x7fff))
2975dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
2976dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    else
2977dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      runp = runp->next;
2978dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2979dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (runp == NULL)
2980dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2981dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: invalid version index %d\n"),
2982dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt, (int) *versym);
2983dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else if (sym->st_shndx == SHN_UNDEF
2984dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   && runp->type == ver_def)
2985dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2986dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: version index %d is for defined version\n"),
2987dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt, (int) *versym);
2988dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else if (sym->st_shndx != SHN_UNDEF
2989dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   && runp->type == ver_need)
2990dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2991dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      /* Unless this symbol has a copy relocation associated
2992dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 this must not happen.  */
2993637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper	      if (!has_copy_reloc (ebl, shdr->sh_link, cnt)
2994637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper		  && !in_nobits_scn (ebl, sym->st_shndx))
2995dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		ERROR (gettext ("\
2996dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: version index %d is for requested version\n"),
2997dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       idx, section_name (ebl, idx), cnt, (int) *versym);
2998dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2999dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3000dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3001dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
3002dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3003dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3004dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
3005bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrathunknown_dependency_p (Elf *elf, const char *fname)
3006dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
3007dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Phdr phdr_mem;
3008dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Phdr *phdr = NULL;
3009dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3010bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  unsigned int i;
3011bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  for (i = 0; i < phnum; ++i)
3012dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    if ((phdr = gelf_getphdr (elf, i, &phdr_mem)) != NULL
3013dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	&& phdr->p_type == PT_DYNAMIC)
3014dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      break;
3015dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3016bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  if (i == phnum)
3017dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 1;
3018dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  assert (phdr != NULL);
3019dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
3020dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
3021dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3022dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
30230a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC
30240a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      && data != NULL && shdr->sh_entsize != 0)
3025dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (size_t j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
3026dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
3027dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Dyn dyn_mem;
3028dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
3029dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (dyn != NULL && dyn->d_tag == DT_NEEDED)
3030dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  {
3031dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    const char *str = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
3032dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    if (str != NULL && strcmp (str, fname) == 0)
3033dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      /* Found it.  */
3034dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      return 0;
3035dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  }
3036dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
3037dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3038dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 1;
3039b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
3040b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3041b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3042acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic unsigned int nverneed;
3043acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3044b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
3045bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrathcheck_verneed (Ebl *ebl, GElf_Shdr *shdr, int idx)
3046b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
3047acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (++nverneed == 2)
3048acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("more than one version reference section present\n"));
3049acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3050acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr strshdr_mem;
3051acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
3052acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &strshdr_mem);
3053acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr == NULL)
3054acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    return;
3055acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
3056acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("\
3057acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': sh_link does not link to string table\n"),
3058acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	   idx, section_name (ebl, idx));
3059dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3060dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
3061dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
3062dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
3063dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
3064dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
3065dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
3066dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3067dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  unsigned int offset = 0;
30689d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard  for (Elf64_Word cnt = shdr->sh_info; cnt > 0; )
3069dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
30709d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard      cnt--;
30719d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard
3072dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Get the data at the next offset.  */
3073dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verneed needmem;
3074dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
3075dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need == NULL)
3076dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	break;
3077dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3078dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      unsigned int auxoffset = offset + need->vn_aux;
3079dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3080dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need->vn_version != EV_CURRENT)
3081dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3082dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong version %d\n"),
3083dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) need->vn_version);
3084dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3085dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need->vn_cnt > 0 && need->vn_aux < gelf_fsize (ebl->elf, ELF_T_VNEED,
3086dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper							 1, EV_CURRENT))
30870a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
30880a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
3089dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
30900a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
30910a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
30920a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
3093dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3094dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      const char *libname = elf_strptr (ebl->elf, shdr->sh_link,
3095dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					need->vn_file);
3096dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (libname == NULL)
3097dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3098dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
3099dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid file reference\n"),
3100dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
3101dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  goto next_need;
3102dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3103dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3104dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Check that there is a DT_NEEDED entry for the referenced library.  */
3105bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      if (unknown_dependency_p (ebl->elf, libname))
3106dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3107dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d references unknown dependency\n"),
3108dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
3109dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3110dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
3111dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3112dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  GElf_Vernaux auxmem;
3113dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
3114dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (aux == NULL)
3115dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    break;
3116dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3117dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vna_flags & ~VER_FLG_WEAK) != 0)
3118dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
3119dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"),
3120dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
3121dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3122dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  const char *verstr = elf_strptr (ebl->elf, shdr->sh_link,
3123dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					   aux->vna_name);
3124dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (verstr == NULL)
31250a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    {
31260a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      ERROR (gettext ("\
3127dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has invalid name reference\n"),
31280a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		     idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
31290a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      break;
31300a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    }
3131dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else
3132dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
3133dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      GElf_Word hashval = elf_hash (verstr);
3134dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (hashval != aux->vna_hash)
3135dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		ERROR (gettext ("\
3136dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: %#x, expected %#x\n"),
3137dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       idx, section_name (ebl, idx), need->vn_cnt - cnt2,
3138dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       cnt, (int) hashval, (int) aux->vna_hash);
3139dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3140dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      int res = add_version (libname, verstr, aux->vna_other,
3141dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper				     ver_need);
3142dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (unlikely (res !=0))
3143dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		{
3144dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  ERROR (gettext ("\
3145dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has duplicate version name '%s'\n"),
3146dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 idx, section_name (ebl, idx), need->vn_cnt - cnt2,
3147dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 cnt, verstr);
3148dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		}
3149dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
3150dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3151dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vna_next != 0 || cnt2 > 0)
3152dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && aux->vna_next < gelf_fsize (ebl->elf, ELF_T_VNAUX, 1,
3153dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					     EV_CURRENT))
3154dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
3155dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      ERROR (gettext ("\
3156dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"),
3157dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		     idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
3158dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
3159dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
3160dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3161dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  auxoffset += MAX (aux->vna_next,
3162dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			    gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, EV_CURRENT));
3163dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3164dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3165dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Find the next offset.  */
3166dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    next_need:
3167dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      offset += need->vn_next;
3168dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3169dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((need->vn_next != 0 || cnt > 0)
3170dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && offset < auxoffset)
31710a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
31720a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
3173dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid offset to next entry\n"),
31740a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
31750a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
31760a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
31770a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
31780a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (need->vn_next == 0 && cnt > 0)
31790a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
31800a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
31810a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': entry %d has zero offset to next entry, but sh_info says there are more entries\n"),
31820a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
31830a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
31840a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
3185dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3186acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper}
3187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3188acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3189acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic unsigned int nverdef;
3190acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3191acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic void
3192acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_verdef (Ebl *ebl, GElf_Shdr *shdr, int idx)
3193acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper{
3194acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (++nverdef == 2)
3195acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("more than one version definition section present\n"));
3196acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3197acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr strshdr_mem;
3198acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
3199acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &strshdr_mem);
3200acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr == NULL)
3201acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    return;
3202acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
3203acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("\
3204acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': sh_link does not link to string table\n"),
3205acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	   idx, section_name (ebl, idx));
3206dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3207dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
3208dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
3209dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
3210dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    no_data:
3211dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
3212dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
3213dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
3214dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3215dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3216dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Iterate over all version definition entries.  We check that there
3217dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     is a BASE entry and that each index is unique.  To do the later
3218dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     we collection the information in a list which is later
3219dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     examined.  */
3220dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct namelist
3221dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  {
3222dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    const char *name;
3223dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    struct namelist *next;
3224dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  } *namelist = NULL;
3225dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct namelist *refnamelist = NULL;
3226dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3227dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  bool has_base = false;
3228dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  unsigned int offset = 0;
32299d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard  for (Elf64_Word cnt = shdr->sh_info; cnt > 0; )
3230dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
32319d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard      cnt--;
32329d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard
3233dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Get the data at the next offset.  */
3234dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdef defmem;
3235dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
3236dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def == NULL)
3237dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	goto no_data;
3238dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3239dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_flags & VER_FLG_BASE) != 0)
3240dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3241dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (has_base)
3242dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
3243dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': more than one BASE definition\n"),
3244dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx));
3245dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (def->vd_ndx != VER_NDX_GLOBAL)
3246dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
3247dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"),
3248dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx));
3249dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  has_base = true;
3250dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3251dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_flags & ~(VER_FLG_BASE|VER_FLG_WEAK)) != 0)
3252dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3253dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has unknown flag\n"),
3254dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
3255dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3256dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_version != EV_CURRENT)
3257dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3258dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong version %d\n"),
3259dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) def->vd_version);
3260dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3261dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_cnt > 0 && def->vd_aux < gelf_fsize (ebl->elf, ELF_T_VDEF,
3262dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper						       1, EV_CURRENT))
32630a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
32640a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
3265dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
32660a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
32670a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
32680a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
3269dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3270dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      unsigned int auxoffset = offset + def->vd_aux;
3271dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdaux auxmem;
3272dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
3273dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (aux == NULL)
3274dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	goto no_data;
3275dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3276dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      const char *name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
3277dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (name == NULL)
3278dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3279dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
3280dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid name reference\n"),
3281dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
3282dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  goto next_def;
3283dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3284dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Word hashval = elf_hash (name);
3285dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_hash != hashval)
3286dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3287dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"),
3288dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) hashval,
3289dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       (int) def->vd_hash);
3290dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3291dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      int res = add_version (NULL, name, def->vd_ndx, ver_def);
3292dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (unlikely (res !=0))
3293dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3294dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
3295dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has duplicate version name '%s'\n"),
3296dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt, name);
3297dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3298dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3299dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      struct namelist *newname = alloca (sizeof (*newname));
33006247d634c33be4c9ee4bfc650bb8f06f5add41e5Ulrich Drepper      newname->name = name;
3301dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      newname->next = namelist;
3302dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      namelist = newname;
3303dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3304dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      auxoffset += aux->vda_next;
3305dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
3306dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3307dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
3308dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (aux == NULL)
3309dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    goto no_data;
3310dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3311c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
3312c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  if (name == NULL)
33130a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    {
33140a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      ERROR (gettext ("\
3315c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Dreppersection [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"),
33160a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		     idx, section_name (ebl, idx), cnt);
33170a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      break;
33180a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    }
3319c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  else
3320c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    {
3321c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname = alloca (sizeof (*newname));
3322c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname->name = name;
3323c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname->next = refnamelist;
3324c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      refnamelist = newname;
3325c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    }
3326dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3327dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vda_next != 0 || cnt2 + 1 < def->vd_cnt)
3328dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && aux->vda_next < gelf_fsize (ebl->elf, ELF_T_VDAUX, 1,
3329dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					     EV_CURRENT))
3330dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
3331dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      ERROR (gettext ("\
3332dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong next field in auxiliary data\n"),
3333dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		     idx, section_name (ebl, idx), cnt);
3334dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
3335dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
3336dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3337dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  auxoffset += MAX (aux->vda_next,
3338dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			    gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, EV_CURRENT));
3339dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3340dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3341dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Find the next offset.  */
3342dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    next_def:
3343dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      offset += def->vd_next;
3344dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3345dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_next != 0 || cnt > 0)
3346dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && offset < auxoffset)
33470a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
33480a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
3349dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid offset to next entry\n"),
33500a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
33510a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
33520a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
33530a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
33540a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (def->vd_next == 0 && cnt > 0)
33550a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
33560a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
33570a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': entry %d has zero offset to next entry, but sh_info says there are more entries\n"),
33580a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
33590a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
33600a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
3361dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3362dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3363dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (!has_base)
3364dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("section [%2d] '%s': no BASE definition\n"),
3365dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	   idx, section_name (ebl, idx));
3366dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3367dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Check whether the referenced names are available.  */
3368dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while (namelist != NULL)
3369dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
3370dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      struct version_namelist *runp = version_namelist;
3371dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      while (runp != NULL)
3372dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3373dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (runp->type == ver_def
3374dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && strcmp (runp->name, namelist->name) == 0)
3375dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    break;
3376dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  runp = runp->next;
3377dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3378dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3379dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (runp == NULL)
3380dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3381dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': unknown parent version '%s'\n"),
3382dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), namelist->name);
3383dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3384dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      namelist = namelist->next;
3385dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3386acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper}
3387acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3388059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathstatic void
3389059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathcheck_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
3390059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath{
3391059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (shdr->sh_size == 0)
3392059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3393059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ERROR (gettext ("section [%2d] '%s': empty object attributes section\n"),
3394059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	     idx, section_name (ebl, idx));
3395059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      return;
3396059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3397059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3398059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL);
33990a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || data->d_size == 0 || data->d_buf == NULL)
3400059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3401059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
3402059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	     idx, section_name (ebl, idx));
3403059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      return;
3404059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3405059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3406059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  inline size_t pos (const unsigned char *p)
3407059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  {
3408059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    return p - (const unsigned char *) data->d_buf;
3409059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  }
3410059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3411059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  const unsigned char *p = data->d_buf;
3412059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (*p++ != 'A')
3413059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3414059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ERROR (gettext ("section [%2d] '%s': unrecognized attribute format\n"),
3415059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	     idx, section_name (ebl, idx));
3416059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      return;
3417059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3418059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3419059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  inline size_t left (void)
3420059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  {
3421059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    return (const unsigned char *) data->d_buf + data->d_size - p;
3422059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  }
3423059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3424059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  while (left () >= 4)
3425059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3426059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      uint32_t len;
3427059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      memcpy (&len, p, sizeof len);
3428059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3429059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (len == 0)
3430059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	ERROR (gettext ("\
3431059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: zero length field in attribute section\n"),
3432059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	       idx, section_name (ebl, idx), pos (p));
3433059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3434059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3435059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	CONVERT (len);
3436059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3437059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (len > left ())
3438059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	{
3439059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  ERROR (gettext ("\
3440059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: invalid length in attribute section\n"),
3441059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		 idx, section_name (ebl, idx), pos (p));
3442059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  break;
3443059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	}
3444059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3445059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      const unsigned char *name = p + sizeof len;
3446059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      p += len;
3447059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3448059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      unsigned const char *q = memchr (name, '\0', len);
3449059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (q == NULL)
3450059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	{
3451059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  ERROR (gettext ("\
3452059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unterminated vendor name string\n"),
3453059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		 idx, section_name (ebl, idx), pos (p));
34545e80a1e8f57fbae3bd5687bb80a65e97f824f914Mark Wielaard	  break;
3455059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	}
3456059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ++q;
3457059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3458059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (q - name == sizeof "gnu" && !memcmp (name, "gnu", sizeof "gnu"))
3459059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	while (q < p)
3460059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  {
3461059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    unsigned const char *chunk = q;
3462059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3463059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    unsigned int subsection_tag;
34647a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	    get_uleb128 (subsection_tag, q, p);
3465059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3466059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (q >= p)
3467059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3468059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3469059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"),
3470059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (chunk));
3471059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		break;
3472059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3473059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3474059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    uint32_t subsection_len;
3475059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (p - q < (ptrdiff_t) sizeof subsection_len)
3476059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3477059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3478059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: truncated attribute section\n"),
3479059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (q));
3480059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		break;
3481059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3482059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3483059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    memcpy (&subsection_len, q, sizeof subsection_len);
3484059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (subsection_len == 0)
3485059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3486059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3487059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
3488059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (q));
3489059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3490059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		q += sizeof subsection_len;
3491059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		continue;
3492059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3493059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3494059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3495059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      CONVERT (subsection_len);
3496059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
34975e80a1e8f57fbae3bd5687bb80a65e97f824f914Mark Wielaard	    /* Don't overflow, ptrdiff_t might be 32bits, but signed.  */
34985e80a1e8f57fbae3bd5687bb80a65e97f824f914Mark Wielaard	    if (p - chunk < (ptrdiff_t) subsection_len
34995e80a1e8f57fbae3bd5687bb80a65e97f824f914Mark Wielaard	        || subsection_len >= (uint32_t) PTRDIFF_MAX)
3500059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3501059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3502059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
3503059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (q));
3504059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		break;
3505059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3506059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3507059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    const unsigned char *subsection_end = chunk + subsection_len;
3508059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    chunk = q;
3509059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    q = subsection_end;
3510059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3511059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (subsection_tag != 1) /* Tag_File */
3512059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      ERROR (gettext ("\
3513059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
3514059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		     idx, section_name (ebl, idx), pos (chunk), subsection_tag);
3515059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    else
3516059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3517059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		chunk += sizeof subsection_len;
3518059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		while (chunk < q)
3519059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		  {
3520059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    unsigned int tag;
35217a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard		    get_uleb128 (tag, chunk, q);
3522059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3523059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    uint64_t value = 0;
3524059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    const unsigned char *r = chunk;
3525059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    if (tag == 32 || (tag & 1) == 0)
3526059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      {
35277a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard			get_uleb128 (value, r, q);
3528059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			if (r > q)
3529059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  {
3530059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    ERROR (gettext ("\
3531059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"),
3532059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath				   idx, section_name (ebl, idx), pos (chunk));
3533059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    break;
3534059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  }
3535059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      }
3536059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    if (tag == 32 || (tag & 1) != 0)
3537059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      {
3538059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			r = memchr (r, '\0', q - r);
3539059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			if (r == NULL)
3540059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  {
3541059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    ERROR (gettext ("\
3542059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unterminated string in attribute\n"),
3543059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath				   idx, section_name (ebl, idx), pos (chunk));
3544059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    break;
3545059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  }
3546059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			++r;
3547059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      }
3548059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3549059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    const char *tag_name = NULL;
3550059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    const char *value_name = NULL;
3551059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    if (!ebl_check_object_attribute (ebl, (const char *) name,
3552059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath						     tag, value,
3553059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath						     &tag_name, &value_name))
3554059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      ERROR (gettext ("\
3555059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"),
3556059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			     idx, section_name (ebl, idx), pos (chunk), tag);
3557059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    else if ((tag & 1) == 0 && value_name == NULL)
3558059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      ERROR (gettext ("\
3559059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"),
3560059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			     idx, section_name (ebl, idx), pos (chunk),
3561059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			     tag_name, value);
3562059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3563059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    chunk = r;
3564059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		  }
3565059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3566059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  }
3567059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      else
3568059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	ERROR (gettext ("\
3569059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: vendor '%s' unknown\n"),
3570059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	       idx, section_name (ebl, idx), pos (p), name);
3571059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3572059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3573059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (left () != 0)
3574059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    ERROR (gettext ("\
3575059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: extra bytes after last attribute section\n"),
3576059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	   idx, section_name (ebl, idx), pos (p));
3577059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath}
3578acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3579637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic bool has_loadable_segment;
3580637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic bool has_interp_segment;
3581637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3582637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic const struct
3583637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper{
3584637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  const char *name;
3585637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  size_t namelen;
3586637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word type;
3587b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  enum { unused, exact, atleast, exact_or_gnuld } attrflag;
3588637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word attr;
3589637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word attr2;
3590637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper} special_sections[] =
3591637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  {
3592637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    /* See figure 4-14 in the gABI.  */
3593637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3594c49d00afc4bda21181cd4237e67930f3f5228adfMark Wielaard    { ".comment", 8, SHT_PROGBITS, atleast, 0, SHF_MERGE | SHF_STRINGS },
3595637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3596637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3597b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    { ".debug_str", 11, SHT_PROGBITS, exact_or_gnuld, SHF_MERGE | SHF_STRINGS, 0 },
3598b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    { ".debug", 6, SHT_PROGBITS, exact, 0, 0 },
3599637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE },
3600637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 },
3601637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 },
3602637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3603637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3604637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info?
3605637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 },
3606637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3607637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3608637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests?
3609637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".line", 6, SHT_PROGBITS, exact, 0, 0 },
3610099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath    { ".note", 6, SHT_NOTE, atleast, 0, SHF_ALLOC },
3611637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
3612637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3613738c18312e0db36dce5e1cd2cddaf66eb8947f1aRoland McGrath    { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests
3614738c18312e0db36dce5e1cd2cddaf66eb8947f1aRoland McGrath    { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests
3615637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3616637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3617637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 },
3618637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3619637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3620637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests
3621637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3622637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3623637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3624637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3625637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3626637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    /* The following are GNU extensions.  */
3627637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version", 13, SHT_GNU_versym, exact, SHF_ALLOC, 0 },
3628637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version_d", 15, SHT_GNU_verdef, exact, SHF_ALLOC, 0 },
3629059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 },
3630059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    { ".gnu.attributes", 16, SHT_GNU_ATTRIBUTES, exact, 0, 0 },
3631637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  };
3632637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper#define nspecial_sections \
3633637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  (sizeof (special_sections) / sizeof (special_sections[0]))
3634637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3635b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper#define IS_KNOWN_SPECIAL(idx, string, prefix)			      \
3636b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  (special_sections[idx].namelen == sizeof string - (prefix ? 1 : 0)  \
3637b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper   && !memcmp (special_sections[idx].name, string, \
3638b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	       sizeof string - (prefix ? 1 : 0)))
3639637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3640978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3641978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper/* Indeces of some sections we need later.  */
3642978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic size_t eh_frame_hdr_scnndx;
3643978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic size_t eh_frame_scnndx;
3644978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic size_t gcc_except_table_scnndx;
3645978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3646978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3647acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic void
3648acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_sections (Ebl *ebl, GElf_Ehdr *ehdr)
3649acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper{
3650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_shoff == 0)
3651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* No section header.  */
3652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
3653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Allocate array to count references in section groups.  */
3655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  scnref = (int *) xcalloc (shnum, sizeof (int));
3656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the zeroth section first.  It must not have any contents
3658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     and the section header must contain nonzero value at most in the
3659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     sh_size and sh_link fields.  */
3660acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr shdr_mem;
3661acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
3662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr == NULL)
3663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("cannot get section header of zeroth section\n"));
3664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
3665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_name != 0)
3667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero name\n"));
3668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type != 0)
3669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero type\n"));
3670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags != 0)
3671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero flags\n"));
3672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_addr != 0)
3673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero address\n"));
3674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_offset != 0)
3675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero offset\n"));
3676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_addralign != 0)
3677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero align value\n"));
3678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_entsize != 0)
3679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero entry size value\n"));
3680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_size != 0 && ehdr->e_shnum != 0)
3682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperzeroth section has nonzero size value while ELF header has nonzero shnum value\n"));
3684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX)
3686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperzeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n"));
3688bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath
3689bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      if (shdr->sh_info != 0 && ehdr->e_phnum != PN_XNUM)
3690bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	ERROR (gettext ("\
3691bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrathzeroth section has nonzero link value while ELF header does not signal overflow in phnum\n"));
3692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3694bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  int *segment_flags = xcalloc (phnum, sizeof segment_flags[0]);
369513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
3696acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  bool dot_interp_section = false;
3697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
36987c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  size_t hash_idx = 0;
36997c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  size_t gnu_hash_idx = 0;
37007c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
3701dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  size_t versym_scnndx = 0;
3702acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 1; cnt < shnum; ++cnt)
3703acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
3704e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard      Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
3705e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard      shdr = gelf_getshdr (scn, &shdr_mem);
3706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr == NULL)
3707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
3709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot get section header for section [%2zu] '%s': %s\n"),
3710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, section_name (ebl, cnt), elf_errmsg (-1));
3711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
3712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
3715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (scnname == NULL)
3717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2zu]: invalid name\n"), cnt);
3718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
3719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Check whether it is one of the special sections defined in
3721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     the gABI.  */
3722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t s;
3723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (s = 0; s < nspecial_sections; ++s)
3724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (strncmp (scnname, special_sections[s].name,
3725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 special_sections[s].namelen) == 0)
3726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
3727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf1[100];
3728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf2[100];
3729b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf3[100];
3730b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3731653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		GElf_Word good_type = special_sections[s].type;
3732b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		if (IS_KNOWN_SPECIAL (s, ".plt", false)
3733712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard		    && ebl_bss_plt_p (ebl))
3734653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  good_type = SHT_NOBITS;
3735653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
3736b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		/* In a debuginfo file, any normal section can be SHT_NOBITS.
3737b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		   This is only invalid for DWARF sections and .shstrtab.  */
3738653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		if (shdr->sh_type != good_type
3739b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		    && (shdr->sh_type != SHT_NOBITS
3740b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| !is_debuginfo
3741b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| IS_KNOWN_SPECIAL (s, ".debug_str", false)
3742b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| IS_KNOWN_SPECIAL (s, ".debug", true)
3743b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| IS_KNOWN_SPECIAL (s, ".shstrtab", false)))
3744b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  ERROR (gettext ("\
3745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' has wrong type: expected %s, is %s\n"),
3746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 (int) cnt, scnname,
3747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 ebl_section_type_name (ebl, special_sections[s].type,
3748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						stbuf1, sizeof (stbuf1)),
3749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 ebl_section_type_name (ebl, shdr->sh_type,
3750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						stbuf2, sizeof (stbuf2)));
3751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3752b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		if (special_sections[s].attrflag == exact
3753b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		    || special_sections[s].attrflag == exact_or_gnuld)
3754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3755e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard		    /* Except for the link order, group bit and
3756e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard		       compression flag all the other bits should
3757e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard		       match exactly.  */
3758e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard		    if ((shdr->sh_flags
3759e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard			 & ~(SHF_LINK_ORDER | SHF_GROUP | SHF_COMPRESSED))
3760b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			!= special_sections[s].attr
3761b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			&& (special_sections[s].attrflag == exact || !gnuld))
3762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has wrong flags: expected %s, is %s\n"),
3764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname,
3765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr,
3766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf1, sizeof (stbuf1)),
3767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (shdr->sh_flags
3768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   & ~SHF_LINK_ORDER,
3769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf2, sizeof (stbuf2)));
3770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else if (special_sections[s].attrflag == atleast)
3772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & special_sections[s].attr)
3774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			!= special_sections[s].attr
3775e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard			|| ((shdr->sh_flags
3776e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard			     & ~(SHF_LINK_ORDER | SHF_GROUP | SHF_COMPRESSED
3777e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard				 | special_sections[s].attr
3778e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard				 | special_sections[s].attr2))
3779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    != 0))
3780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"),
3782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname,
3783b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr,
3784b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf1, sizeof (stbuf1)),
3785b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr2,
3786b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf2, sizeof (stbuf2)),
3787b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (shdr->sh_flags
3788b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   & ~(SHF_LINK_ORDER
3789b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						       | SHF_GROUP),
3790b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf3, sizeof (stbuf3)));
3791b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (strcmp (scnname, ".interp") == 0)
3794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    dot_interp_section = true;
3796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (ehdr->e_type == ET_REL)
3798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' present in object file\n"),
3800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3802b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !has_loadable_segment)
3804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     && has_loadable_segment)
3809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
3814b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3815b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (strcmp (scnname, ".symtab_shndx") == 0
3816b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& ehdr->e_type != ET_REL)
3817b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' is extension section index table in non-object file\n"),
3819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* These sections must have the SHF_ALLOC flag set iff
3822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       a loadable segment is available.
3823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .relxxx
3825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .strtab
3826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .symtab
3827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .symtab_shndx
3828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       Check that if there is a reference from the
3830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       loaded section these sections also have the
3831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       ALLOC flag set.  */
3832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if 0
3833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    // XXX TODO
3834b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !has_loadable_segment)
3836b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3837b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3840b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     && has_loadable_segment)
3841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3842b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3843b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3844b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
3845b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3847b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		break;
3848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
3849978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3850978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  /* Remember a few special sections for later.  */
3851978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  if (strcmp (scnname, ".eh_frame_hdr") == 0)
3852978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	    eh_frame_hdr_scnndx = cnt;
3853978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  else if (strcmp (scnname, ".eh_frame") == 0)
3854978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	    eh_frame_scnndx = cnt;
3855978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  else if (strcmp (scnname, ".gcc_except_table") == 0)
3856978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	    gcc_except_table_scnndx = cnt;
3857b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3858b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize)
3860b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3861b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': size not multiple of entry size\n"),
3862b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3863b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3864b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL)
3865b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("cannot get section header\n"));
3866b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3867b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type >= SHT_NUM
3868059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  && shdr->sh_type != SHT_GNU_ATTRIBUTES
3869b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_LIBLIST
3870b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_CHECKSUM
3871b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_verdef
3872b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_verneed
387318e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && shdr->sh_type != SHT_GNU_versym
387418e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && ebl_section_type_name (ebl, shdr->sh_type, NULL, 0) == NULL)
387518e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	ERROR (gettext ("section [%2zu] '%s' has unsupported type %d\n"),
387618e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	       cnt, section_name (ebl, cnt),
387718e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	       (int) shdr->sh_type);
3878b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3879b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \
3880b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \
3881e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard		      | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS \
3882e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard		      | SHF_COMPRESSED)
3883aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper      if (shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS)
3884aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	{
3885aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS;
3886aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  if (sh_flags & SHF_MASKPROC)
3887aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    {
3888aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	      if (!ebl_machine_section_flag_check (ebl,
3889aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper						   sh_flags & SHF_MASKPROC))
3890aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		ERROR (gettext ("section [%2zu] '%s'"
3891aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper				" contains invalid processor-specific flag(s)"
3892aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper				" %#" PRIx64 "\n"),
3893aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		       cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
3894aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	      sh_flags &= ~(GElf_Xword) SHF_MASKPROC;
3895aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    }
3896aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  if (sh_flags != 0)
3897aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    ERROR (gettext ("section [%2zu] '%s' contains unknown flag(s)"
3898aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper			    " %#" PRIx64 "\n"),
3899aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		   cnt, section_name (ebl, cnt), sh_flags);
3900aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	}
3901aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper      if (shdr->sh_flags & SHF_TLS)
3902b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3903b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX Correct?
3904b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr->sh_addr != 0 && !gnuld)
3905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3906b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': thread-local data sections address not zero\n"),
3907b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, section_name (ebl, cnt));
3908b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3909b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX TODO more tests!?
3910b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3911b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3912e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard      if (shdr->sh_flags & SHF_COMPRESSED)
3913e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard	{
3914e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard	  if (shdr->sh_flags & SHF_ALLOC)
3915e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard	    ERROR (gettext ("\
3916e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaardsection [%2zu] '%s': allocated section cannot be compressed\n"),
3917e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard		   cnt, section_name (ebl, cnt));
3918e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard
3919e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard	  if (shdr->sh_type == SHT_NOBITS)
3920e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard	    ERROR (gettext ("\
3921e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaardsection [%2zu] '%s': nobits section cannot be compressed\n"),
3922e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard		   cnt, section_name (ebl, cnt));
3923e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard
3924e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard	  GElf_Chdr chdr;
3925e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard	  if (gelf_getchdr (scn, &chdr) == NULL)
3926e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard	    ERROR (gettext ("\
3927e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaardsection [%2zu] '%s': compressed section with no compression header: %s\n"),
3928e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard		   cnt, section_name (ebl, cnt), elf_errmsg (-1));
3929e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard	}
3930e5f976bcb1b3a27bd89d8d32c0cebb0c14c0e6d2Mark Wielaard
3931b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_link >= shnum)
3932b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3933b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': invalid section reference in link value\n"),
3934b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3935b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3936b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum)
3937b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3938b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': invalid section reference in info value\n"),
3939b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3940b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3941b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_flags & SHF_MERGE) == 0
3942b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && (shdr->sh_flags & SHF_STRINGS) != 0
3943b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && be_strict)
3944b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3945b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': strings flag set without merge flag\n"),
3946b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3947b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3948b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0)
3949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3950b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': merge flag set but entry size is zero\n"),
3951b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3952b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3953b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags & SHF_GROUP)
3954b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	check_scn_group (ebl, cnt);
3955b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
395613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath      if (shdr->sh_flags & SHF_EXECINSTR)
395713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	{
395813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	  switch (shdr->sh_type)
395913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    {
396013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    case SHT_PROGBITS:
396113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      break;
396213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
396313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    case SHT_NOBITS:
396413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      if (is_debuginfo)
396513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		break;
396613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    default:
396713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      ERROR (gettext ("\
396813b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' has unexpected type %d for an executable section\n"),
396913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		     cnt, section_name (ebl, cnt), shdr->sh_type);
397013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      break;
397113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    }
397213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
3973bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi	  if (shdr->sh_flags & SHF_WRITE)
3974bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi	    {
3975bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi	      if (is_debuginfo && shdr->sh_type != SHT_NOBITS)
3976bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi		ERROR (gettext ("\
3977bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesisection [%2zu] '%s' must be of type NOBITS in debuginfo files\n"),
3978bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi		       cnt, section_name (ebl, cnt));
3979bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi
3980bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi	      if (!is_debuginfo
3981bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi		  && !ebl_check_special_section (ebl, cnt, shdr,
3982bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi						 section_name (ebl, cnt)))
3983bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi		ERROR (gettext ("\
398413b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' is both executable and writable\n"),
3985bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi		       cnt, section_name (ebl, cnt));
3986bc119074c2fadf5288ab8e635a930aac496282d7Jose E. Marchesi	    }
398713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	}
398813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
3989a1e17a2551ddd1b2c4853e053dc1b254440211bdMark Wielaard      if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0
3990a1e17a2551ddd1b2c4853e053dc1b254440211bdMark Wielaard	  && !is_debuginfo)
3991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3992b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Make sure the section is contained in a loaded segment
3993b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     and that the initialization part matches NOBITS sections.  */
3994bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  unsigned int pcnt;
3995b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Phdr phdr_mem;
3996b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Phdr *phdr;
3997b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3998bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  for (pcnt = 0; pcnt < phnum; ++pcnt)
3999b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL
4000b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& ((phdr->p_type == PT_LOAD
4001b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     && (shdr->sh_flags & SHF_TLS) == 0)
4002b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    || (phdr->p_type == PT_TLS
4003b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& (shdr->sh_flags & SHF_TLS) != 0))
4004b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& phdr->p_offset <= shdr->sh_offset
400536aa5987df20c340fdfc584e04f4b3931a89abbdMark Wielaard		&& ((shdr->sh_offset - phdr->p_offset <= phdr->p_filesz
400636aa5987df20c340fdfc584e04f4b3931a89abbdMark Wielaard		     && (shdr->sh_offset - phdr->p_offset < phdr->p_filesz
400736aa5987df20c340fdfc584e04f4b3931a89abbdMark Wielaard			 || shdr->sh_size == 0))
400836aa5987df20c340fdfc584e04f4b3931a89abbdMark Wielaard		    || (shdr->sh_offset - phdr->p_offset < phdr->p_memsz
40099aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath			&& shdr->sh_type == SHT_NOBITS)))
4010b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
4011b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* Found the segment.  */
4012b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (phdr->p_offset + phdr->p_memsz
4013b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    < shdr->sh_offset + shdr->sh_size)
4014b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  ERROR (gettext ("\
4015b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' not fully contained in segment of program header entry %d\n"),
4016b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
4017b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4018b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (shdr->sh_type == SHT_NOBITS)
4019b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
4020b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz
4021b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !is_debuginfo)
40220292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard		      {
40230292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			if (!gnuld)
40240292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			  ERROR (gettext ("\
4025b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"),
40260292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard				 cnt, section_name (ebl, cnt), pcnt);
40270292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			else
40280292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			  {
40290292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    /* This is truly horrible. GNU ld might put a
40300292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       NOBITS section in the middle of a PT_LOAD
40310292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       segment, assuming the next gap in the file
40320292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       actually consists of zero bits...
40330292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       So it really is like a PROGBITS section
40340292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       where the data is all zeros.  Check those
40350292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       zero bytes are really there.  */
40360292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    bool bad;
40370292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    Elf_Data *databits;
40380292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    databits = elf_getdata_rawchunk (ebl->elf,
40390292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard							     shdr->sh_offset,
40400292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard							     shdr->sh_size,
40410292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard							     ELF_T_BYTE);
40420292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    bad = (databits == NULL
40430292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard				   || databits->d_size != shdr->sh_size);
40440292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    for (size_t idx = 0;
40450292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard				 idx < databits->d_size && ! bad;
40460292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard				 idx++)
40470292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			      bad = ((char *) databits->d_buf)[idx] != 0;
40480292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard
40490292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    if (bad)
40500292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			      ERROR (gettext ("\
40510292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaardsection [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d and file contents is non-zero\n"),
40520292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard				     cnt, section_name (ebl, cnt), pcnt);
40530292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			  }
40540292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard		      }
4055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
4056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
4057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
4058653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    const GElf_Off end = phdr->p_offset + phdr->p_filesz;
4059653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    if (shdr->sh_offset > end ||
4060653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			(shdr->sh_offset == end && shdr->sh_size != 0))
4061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
4062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"),
4063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
4064b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
4065b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
406613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		if (shdr->sh_type != SHT_NOBITS)
406713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		  {
406813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		    if ((shdr->sh_flags & SHF_EXECINSTR) != 0)
406913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      {
407013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			segment_flags[pcnt] |= PF_X;
407113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			if ((phdr->p_flags & PF_X) == 0)
407213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			  ERROR (gettext ("\
407313b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' is executable in nonexecutable segment %d\n"),
407413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath				 cnt, section_name (ebl, cnt), pcnt);
407513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      }
407613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
407713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		    if ((shdr->sh_flags & SHF_WRITE) != 0)
407813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      {
407913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			segment_flags[pcnt] |= PF_W;
408013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			if (0	/* XXX vdso images have this */
408113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			    && (phdr->p_flags & PF_W) == 0)
408213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			  ERROR (gettext ("\
408313b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' is writable in unwritable segment %d\n"),
408413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath				 cnt, section_name (ebl, cnt), pcnt);
408513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      }
408613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		  }
408713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
4088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		break;
4089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
4090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4091bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  if (pcnt == phnum)
4092b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
4093b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': alloc flag set but section not in any loaded segment\n"),
4094b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, section_name (ebl, cnt));
4095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB)
4098b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
4099b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"),
4100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
4101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      switch (shdr->sh_type)
4103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNSYM:
4105acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  if (ehdr->e_type == ET_REL)
4106acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    ERROR (gettext ("\
4107acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"),
4108acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper		   cnt, section_name (ebl, cnt));
4109acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  /* FALLTHROUGH */
4110acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_SYMTAB:
4111dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  check_symtab (ebl, ehdr, shdr, cnt);
4112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_RELA:
4115c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  check_rela (ebl, ehdr, shdr, cnt);
4116b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4117b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4118b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_REL:
4119c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  check_rel (ebl, ehdr, shdr, cnt);
4120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNAMIC:
4123607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  check_dynamic (ebl, ehdr, shdr, cnt);
4124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_SYMTAB_SHNDX:
4127acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  check_symtab_shndx (ebl, ehdr, shdr, cnt);
4128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_HASH:
41317c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
41327c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  hash_idx = cnt;
41337c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  break;
41347c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
413528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	case SHT_GNU_HASH:
413628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
41377c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  gnu_hash_idx = cnt;
4138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_NULL:
4141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  check_null (ebl, shdr, cnt);
4142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_GROUP:
4145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  check_group (ebl, ehdr, shdr, cnt);
4146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
414859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	case SHT_NOTE:
414959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  check_note_section (ebl, ehdr, shdr, cnt);
415059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  break;
415159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
4152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_GNU_versym:
4153dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* We cannot process this section now since we have no guarantee
4154dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     that the verneed and verdef sections have already been read.
4155dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     Just remember the section index.  */
4156dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (versym_scnndx != 0)
4157dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("more than one version symbol table present\n"));
4158dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  versym_scnndx = cnt;
4159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4161acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_GNU_verneed:
4162bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  check_verneed (ebl, shdr, cnt);
4163acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  break;
4164acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
4165acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_GNU_verdef:
4166acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  check_verdef (ebl, shdr, cnt);
4167acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  break;
4168acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
4169059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	case SHT_GNU_ATTRIBUTES:
4170059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  check_attributes (ebl, ehdr, shdr, cnt);
4171059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  break;
4172059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
4173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	default:
4174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Nothing.  */
4175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (has_interp_segment && !dot_interp_section)
4180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("INTERP program header entry but no .interp section\n"));
4181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
418213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath  if (!is_debuginfo)
4183bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt)
418413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath      {
418513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	GElf_Phdr phdr_mem;
418613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
418713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	if (phdr != NULL && (phdr->p_type == PT_LOAD || phdr->p_type == PT_TLS))
418813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	  {
418913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    if ((phdr->p_flags & PF_X) != 0
419013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		&& (segment_flags[pcnt] & PF_X) == 0)
419113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      ERROR (gettext ("\
419213b69609bcd5638e6194d940855fea3dd0519605Roland McGrathloadable segment [%u] is executable but contains no executable sections\n"),
419313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		     pcnt);
419413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
419513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    if ((phdr->p_flags & PF_W) != 0
419613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		&& (segment_flags[pcnt] & PF_W) == 0)
419713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      ERROR (gettext ("\
419813b69609bcd5638e6194d940855fea3dd0519605Roland McGrathloadable segment [%u] is writable but contains no writable sections\n"),
419913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		     pcnt);
420013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	  }
420113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath      }
420213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
420313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath  free (segment_flags);
420413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
4205dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (version_namelist != NULL)
4206dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
4207dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (versym_scnndx == 0)
4208dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("\
4209dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperno .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section exist\n"));
4210dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      else
4211dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	check_versym (ebl, versym_scnndx);
4212dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
4213dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Check for duplicate index numbers.  */
4214dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      do
4215dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
4216dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *runp = version_namelist->next;
4217dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  while (runp != NULL)
4218dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
4219dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (version_namelist->ndx == runp->ndx)
4220dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		{
4221dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  ERROR (gettext ("duplicate version index %d\n"),
4222dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 (int) version_namelist->ndx);
4223dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  break;
4224dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		}
4225dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      runp = runp->next;
4226dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
4227dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
4228dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *old = version_namelist;
4229dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  version_namelist = version_namelist->next;
4230dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  free (old);
4231dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
4232dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      while (version_namelist != NULL);
4233dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
4234dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  else if (versym_scnndx != 0)
4235dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("\
4236dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper.gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"));
4237dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
42387c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_idx != 0 && gnu_hash_idx != 0)
42397c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    compare_hash_gnu_hash (ebl, ehdr, hash_idx, gnu_hash_idx);
42407c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
4241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  free (scnref);
4242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
4243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
424559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic GElf_Off
424659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathcheck_note_data (Ebl *ebl, const GElf_Ehdr *ehdr,
424759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		 Elf_Data *data, int shndx, int phndx, GElf_Off start)
4248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
424959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t offset = 0;
425059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t last_offset = 0;
425159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  GElf_Nhdr nhdr;
425259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t name_offset;
425359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t desc_offset;
425459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  while (offset < data->d_size
425559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	 && (offset = gelf_getnote (data, offset,
425659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath				    &nhdr, &name_offset, &desc_offset)) > 0)
4257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
425859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      last_offset = offset;
4259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Make sure it is one of the note types we know about.  */
4261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type == ET_CORE)
426259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	switch (nhdr.n_type)
426359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  {
426459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRSTATUS:
426559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_FPREGSET:
426659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRPSINFO:
426759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_TASKSTRUCT:		/* NT_PRXREG on Solaris.  */
426859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PLATFORM:
426959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_AUXV:
427059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_GWINDOWS:
427159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_ASRS:
427259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PSTATUS:
427359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PSINFO:
427459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRCRED:
427559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_UTSNAME:
427659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_LWPSTATUS:
427759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_LWPSINFO:
427859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRFPXREG:
427959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    /* Known type.  */
428059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    break;
4281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
428259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  default:
428359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    if (shndx == 0)
4284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
428559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathphdr[%d]: unknown core file note type %" PRIu32 " at offset %" PRIu64 "\n"),
428659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     phndx, (uint32_t) nhdr.n_type, start + offset);
428759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    else
428859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	      ERROR (gettext ("\
428959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathsection [%2d] '%s': unknown core file note type %" PRIu32
42902ec957327cdfae6cee592a52958a9c937ea4b13cChih-Hung Hsieh			      " at offset %zu\n"),
429159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     shndx, section_name (ebl, shndx),
429259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     (uint32_t) nhdr.n_type, offset);
429359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  }
4294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
429559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	switch (nhdr.n_type)
4296d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  {
429759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_GNU_ABI_TAG:
4298d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  case NT_GNU_HWCAP:
4299d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  case NT_GNU_BUILD_ID:
4300bc1b92e9aff2595b078b7ffc354e5c2191a2c887Mark Wielaard	  case NT_GNU_GOLD_VERSION:
4301d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	    break;
4302d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath
4303099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath	  case 0:
4304099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath	    /* Linux vDSOs use a type 0 note for the kernel version word.  */
430559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    if (nhdr.n_namesz == sizeof "Linux"
430659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		&& !memcmp (data->d_buf + name_offset, "Linux", sizeof "Linux"))
4307099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath	      break;
4308099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath
4309d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  default:
431059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    if (shndx == 0)
431159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	      ERROR (gettext ("\
43122ec957327cdfae6cee592a52958a9c937ea4b13cChih-Hung Hsiehphdr[%d]: unknown object file note type %" PRIu32 " at offset %zu\n"),
431359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     phndx, (uint32_t) nhdr.n_type, offset);
431459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    else
431559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	      ERROR (gettext ("\
431659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathsection [%2d] '%s': unknown object file note type %" PRIu32
43172ec957327cdfae6cee592a52958a9c937ea4b13cChih-Hung Hsieh			      " at offset %zu\n"),
431859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     shndx, section_name (ebl, shndx),
431959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     (uint32_t) nhdr.n_type, offset);
4320d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  }
4321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
432359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  return last_offset;
432459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath}
432559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
4326978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
432759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic void
432859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathcheck_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt)
432959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath{
433059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
433159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
433259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("\
433359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathphdr[%d]: no note entries defined for the type of file\n"),
433459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   cnt);
433559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
433659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (is_debuginfo)
433759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    /* The p_offset values in a separate debug file are bogus.  */
433859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    return;
433959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
4340b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (phdr->p_filesz == 0)
4341b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    return;
4342b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
434359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  GElf_Off notes_size = 0;
434459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  Elf_Data *data = elf_getdata_rawchunk (ebl->elf,
434559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath					 phdr->p_offset, phdr->p_filesz,
434659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath					 ELF_T_NHDR);
43470a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data != NULL && data->d_buf != NULL)
434859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    notes_size = check_note_data (ebl, ehdr, data, 0, cnt, phdr->p_offset);
434959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
435059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (notes_size == 0)
435159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("phdr[%d]: cannot get content of note section: %s\n"),
435259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   cnt, elf_errmsg (-1));
435359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  else if (notes_size != phdr->p_filesz)
435459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("phdr[%d]: extra %" PRIu64 " bytes after last note\n"),
435559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   cnt, phdr->p_filesz - notes_size);
4356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
4357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4358978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
435959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic void
436059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathcheck_note_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
436159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath{
4362b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (shdr->sh_size == 0)
4363b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    return;
4364b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
436559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
43660a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || data->d_buf == NULL)
436759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    {
436859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
436959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	     idx, section_name (ebl, idx));
437059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      return;
437159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    }
437259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
437359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
437459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
437559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("\
437659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathsection [%2d] '%s': no note entries defined for the type of file\n"),
437759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	     idx, section_name (ebl, idx));
437859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
437959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  GElf_Off notes_size = check_note_data (ebl, ehdr, data, idx, 0, 0);
438059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
438159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (notes_size == 0)
438259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("section [%2d] '%s': cannot get content of note section\n"),
438359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   idx, section_name (ebl, idx));
438459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  else if (notes_size != shdr->sh_size)
438559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("section [%2d] '%s': extra %" PRIu64
438659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		    " bytes after last note\n"),
438759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   idx, section_name (ebl, idx), shdr->sh_size - notes_size);
438859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath}
4389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4390978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4391978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper/* Index of the PT_GNU_EH_FRAME program eader entry.  */
4392978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic int pt_gnu_eh_frame_pndx;
4393978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4394978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
4396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
4397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
4398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_phoff == 0)
4399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
4400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
4402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_CORE)
4403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
4404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperonly executables, shared objects, and core files can have program headers\n"));
4405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_interp = 0;
4407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_tls = 0;
4408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_relro = 0;
4409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4410bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  for (unsigned int cnt = 0; cnt < phnum; ++cnt)
4411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
4412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr phdr_mem;
4413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr *phdr;
4414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
4416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr == NULL)
4417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("cannot get program header entry %d: %s\n"),
4419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, elf_errmsg (-1));
4420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
4421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME
4424f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  && phdr->p_type != PT_GNU_STACK && phdr->p_type != PT_GNU_RELRO
4425f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  /* Check for a known machine-specific type.  */
4426f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  && ebl_segment_type_name (ebl, phdr->p_type, NULL, 0) == NULL)
4427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
4428f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrathprogram header entry %d: unknown program header entry type %#" PRIx64 "\n"),
4429f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	       cnt, (uint64_t) phdr->p_type);
4430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_type == PT_LOAD)
4432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	has_loadable_segment = true;
4433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_INTERP)
4434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_interp != 1)
4436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
4437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (num_pt_interp == 2)
4438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
4439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermore than one INTERP entry in program header\n"));
4440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
4441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  has_interp_segment = true;
4442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_TLS)
4444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_tls == 2)
4446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("more than one TLS entry in program header\n"));
4447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_NOTE)
4449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	check_note (ebl, ehdr, phdr, cnt);
445041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      else if (phdr->p_type == PT_DYNAMIC)
445141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
445241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  if (ehdr->e_type == ET_EXEC && ! has_interp_segment)
445341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    ERROR (gettext ("\
445441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic executable cannot have dynamic sections\n"));
445541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  else
445641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    {
445741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      /* Check that the .dynamic section, if it exists, has
445841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 the same address.  */
445941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      Elf_Scn *scn = NULL;
446041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
446141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		{
446241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr shdr_mem;
446341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
446441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
446541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    {
446641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      if (phdr->p_offset != shdr->sh_offset)
446741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			ERROR (gettext ("\
446841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperdynamic section reference in program header has wrong offset\n"));
446941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      if (phdr->p_memsz != shdr->sh_size)
447041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			ERROR (gettext ("\
447141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperdynamic section size mismatch in program and section header\n"));
447241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      break;
447341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    }
447441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		}
447541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    }
447641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
4477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_GNU_RELRO)
4478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_relro == 2)
4480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
4481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermore than one GNU_RELRO entry in program header\n"));
4482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
4483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
4484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Check that the region is in a writable segment.  */
4485bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	      unsigned int inner;
4486bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	      for (inner = 0; inner < phnum; ++inner)
4487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
4488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Phdr phdr2_mem;
4489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Phdr *phdr2;
4490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
4492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (phdr2 == NULL)
4493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    continue;
4494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (phdr2->p_type == PT_LOAD
4496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && phdr->p_vaddr >= phdr2->p_vaddr
4497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && (phdr->p_vaddr + phdr->p_memsz
4498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  <= phdr2->p_vaddr + phdr2->p_memsz))
4499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
4500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if ((phdr2->p_flags & PF_W) == 0)
4501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
4502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperloadable segment GNU_RELRO applies to is not writable\n"));
4503b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard		      /* Unless fully covered, relro flags could be a
4504b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			 subset of the phdrs2 flags.  For example the load
4505b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			 segment could also have PF_X set.  */
4506b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard		      if (phdr->p_vaddr == phdr2->p_vaddr
4507b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			  && (phdr->p_vaddr + phdr->p_memsz
4508b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			      == phdr2->p_vaddr + phdr2->p_memsz))
4509b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			{
4510b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			  if ((phdr2->p_flags & ~PF_W)
4511b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			      != (phdr->p_flags & ~PF_W))
4512b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			    ERROR (gettext ("\
4513d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrathloadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"),
4514b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard				   cnt, inner);
4515b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			}
4516b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard		      else
4517b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			{
4518b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			  if ((phdr->p_flags & ~phdr2->p_flags) != 0)
4519b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			    ERROR (gettext ("\
4520b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark WielaardGNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n"),
4521b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard				   inner, cnt);
4522b9be1434ff0a4ce9ebe80fcda5c6a9891904b26eMark Wielaard			}
4523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      break;
4524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
4525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
4526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4527bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	      if (inner >= phnum)
4528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
4529607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper%s segment not contained in a loaded segment\n"), "GNU_RELRO");
4530607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
4531607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	}
4532607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      else if (phdr->p_type == PT_PHDR)
4533607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	{
4534607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* Check that the region is in a writable segment.  */
4535bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  unsigned int inner;
4536bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  for (inner = 0; inner < phnum; ++inner)
4537607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
4538607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr phdr2_mem;
4539607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr *phdr2;
4540607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
4541607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
4542607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      if (phdr2 != NULL
4543607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr2->p_type == PT_LOAD
4544607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr >= phdr2->p_vaddr
4545607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && (phdr->p_vaddr + phdr->p_memsz
4546607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		      <= phdr2->p_vaddr + phdr2->p_memsz))
4547607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		break;
4548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
4549607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
4550bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  if (inner >= phnum)
4551607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    ERROR (gettext ("\
4552607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper%s segment not contained in a loaded segment\n"), "PHDR");
4553607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
4554607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* Check that offset in segment corresponds to offset in ELF
4555607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	     header.  */
4556607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (phdr->p_offset != ehdr->e_phoff)
4557607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    ERROR (gettext ("\
4558607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepperprogram header offset in ELF header and PHDR entry do not match"));
4559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
45603a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper      else if (phdr->p_type == PT_GNU_EH_FRAME)
45613a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	{
45623a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	  /* If there is an .eh_frame_hdr section it must be
45633a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	     referenced by this program header entry.  */
45643a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	  Elf_Scn *scn = NULL;
4565935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper	  GElf_Shdr shdr_mem;
4566935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper	  GElf_Shdr *shdr = NULL;
4567f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	  bool any = false;
45683a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
45693a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	    {
4570f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      any = true;
4571935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper	      shdr = gelf_getshdr (scn, &shdr_mem);
4572f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if (shdr != NULL
4573f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		  && shdr->sh_type == (is_debuginfo
4574f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper				       ? SHT_NOBITS : SHT_PROGBITS)
45750a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		  && elf_strptr (ebl->elf, shstrndx, shdr->sh_name) != NULL
45763a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		  && ! strcmp (".eh_frame_hdr",
45773a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper			       elf_strptr (ebl->elf, shstrndx, shdr->sh_name)))
45783a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		{
4579f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		  if (! is_debuginfo)
4580f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		    {
4581f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		      if (phdr->p_offset != shdr->sh_offset)
4582f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper			ERROR (gettext ("\
45833a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table reference in program header has wrong offset\n"));
4584f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		      if (phdr->p_memsz != shdr->sh_size)
4585f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper			ERROR (gettext ("\
45863a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table size mismatch in program and section header\n"));
4587f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		    }
45883a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		  break;
45893a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		}
45903a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	    }
45913a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper
4592f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	  if (scn == NULL)
4593f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    {
4594f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      /* If there is no section header table we don't
4595f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		 complain.  But if there is one there should be an
4596f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		 entry for .eh_frame_hdr.  */
4597f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if (any)
4598f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4599f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich DrepperPT_GNU_EH_FRAME present but no .eh_frame_hdr section\n"));
4600f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    }
4601f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	  else
4602f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    {
4603f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      /* The section must be allocated and not be writable and
4604f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		 executable.  */
4605f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if ((phdr->p_flags & PF_R) == 0)
4606f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
46073a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table must be allocated\n"));
4608f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      else if (shdr != NULL && (shdr->sh_flags & SHF_ALLOC) == 0)
4609f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4610935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppersection [%2zu] '%s' must be allocated\n"), elf_ndxscn (scn), ".eh_frame_hdr");
4611935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper
4612f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if ((phdr->p_flags & PF_W) != 0)
4613f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
46143a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table must not be writable\n"));
4615f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      else if (shdr != NULL && (shdr->sh_flags & SHF_WRITE) != 0)
4616f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4617935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppersection [%2zu] '%s' must not be writable\n"),
4618f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		       elf_ndxscn (scn), ".eh_frame_hdr");
4619935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper
4620f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if ((phdr->p_flags & PF_X) != 0)
4621f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
46223a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table must not be executable\n"));
4623f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      else if (shdr != NULL && (shdr->sh_flags & SHF_EXECINSTR) != 0)
4624f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4625935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppersection [%2zu] '%s' must not be executable\n"),
4626f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		       elf_ndxscn (scn), ".eh_frame_hdr");
4627f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    }
4628978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4629978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  /* Remember which entry this is.  */
4630978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  pt_gnu_eh_frame_pndx = cnt;
46313a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	}
4632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
46338190db6a86a37aec86c81626ab1b083c96aff891Roland McGrath      if (phdr->p_filesz > phdr->p_memsz
463456bc0b83ea81b7e959aaa4e1d01f8b36f2804a52Ulrich Drepper	  && (phdr->p_memsz != 0 || phdr->p_type != PT_NOTE))
4635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
4636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: file size greater than memory size\n"),
4637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt);
4638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_align > 1)
4640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (!powerof2 (phdr->p_align))
4642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
4643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: alignment not a power of 2\n"), cnt);
4644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0)
4645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
4646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: file offset and virtual address not module of alignment\n"), cnt);
4647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
4650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4652978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic void
4653935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppercheck_exception_data (Ebl *ebl __attribute__ ((unused)),
4654935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper		      GElf_Ehdr *ehdr __attribute__ ((unused)))
4655978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper{
4656daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper  if ((ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
4657daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper      && pt_gnu_eh_frame_pndx == 0 && eh_frame_hdr_scnndx != 0)
4658daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper    ERROR (gettext ("executable/DSO with .eh_frame_hdr section does not have "
4659daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper		    "a PT_GNU_EH_FRAME program header entry"));
4660978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper}
4661978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4662978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Process one file.  */
4664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
4665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprocess_elf_file (Elf *elf, const char *prefix, const char *suffix,
4666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  const char *fname, size_t size, bool only_one)
4667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
4668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Reset variables.  */
4669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ndynamic = 0;
4670acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  nverneed = 0;
4671acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  nverdef = 0;
467241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  textrel = false;
467341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  needed_textrel = false;
4674acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  has_loadable_segment = false;
4675acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  has_interp_segment = false;
4676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr ehdr_mem;
4678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
4679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Ebl *ebl;
4680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Print the file name.  */
4682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (!only_one)
4683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
4684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (prefix != NULL)
4685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	printf ("\n%s(%s)%s:\n", prefix, fname, suffix);
4686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
4687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	printf ("\n%s:\n", fname);
4688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr == NULL)
4691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
4692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("cannot read ELF header: %s\n"), elf_errmsg (-1));
4693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
4694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl = ebl_openbackend (elf);
4697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If there is no appropriate backend library we cannot test
4698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     architecture and OS specific features.  Any encountered extension
4699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     is an error.  */
4700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Go straight by the gABI, check all the parts in turn.  */
4702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_elf_header (ebl, ehdr, size);
4703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the program header.  */
4705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_program_header (ebl, ehdr);
4706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Next the section headers.  It is OK if there are no section
4708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     headers at all.  */
4709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_sections (ebl, ehdr);
4710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4711978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper  /* Check the exception handling data, if it exists.  */
4712978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper  if (pt_gnu_eh_frame_pndx != 0 || eh_frame_hdr_scnndx != 0
4713978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper      || eh_frame_scnndx != 0 || gcc_except_table_scnndx != 0)
4714978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper    check_exception_data (ebl, ehdr);
4715978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
471641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* Report if no relocation section needed the text relocation flag.  */
471741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (textrel && !needed_textrel)
471841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    ERROR (gettext ("text relocation flag set but not needed\n"));
471941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
4720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Free the resources.  */
4721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl_closebackend (ebl);
4722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
47233cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
47243cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
47253cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper#include "debugpred.h"
4726