elflint.c revision 2ec957327cdfae6cee592a52958a9c937ea4b13c
1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Pedantic checking of ELF files compliance with gABI/psABI spec.
271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek   Copyright (C) 2001-2014 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;
167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  struct stat64 st;
168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (fstat64 (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
38396d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper  /* We currently don't handle any OS ABIs other than Linux.  */
38496d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper  if (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE
38596d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper      && ehdr->e_ident[EI_OSABI] != ELFOSABI_LINUX)
386e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper    ERROR (gettext ("unsupported OS ABI e_ident[%d] == '%s'\n"),
387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_OSABI,
388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* No ABI versions other than zero supported either.  */
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_ABIVERSION] != 0)
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unsupport ABI version e_ident[%d] == %d\n"),
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_ABIVERSION, ehdr->e_ident[EI_ABIVERSION]);
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = EI_PAD; cnt < EI_NIDENT; ++cnt)
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (ehdr->e_ident[cnt] != 0)
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("e_ident[%zu] is not zero\n"), cnt);
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_type field.  */
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_REL && ehdr->e_type != ET_EXEC
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_DYN && ehdr->e_type != ET_CORE)
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown object file type %d\n"), ehdr->e_type);
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_machine field.  */
405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 0; cnt < nvalid_e_machine; ++cnt)
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (valid_e_machine[cnt] == ehdr->e_machine)
407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (cnt == nvalid_e_machine)
409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown machine type %d\n"), ehdr->e_machine);
410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_version field.  */
412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_version != EV_CURRENT)
413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown object file version\n"));
414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_phoff and e_phnum fields.  */
416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_phoff == 0)
417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phnum != 0)
419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header offset\n"));
420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperexecutables and DSOs cannot have zero program header offset\n"));
423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else if (ehdr->e_phnum == 0)
425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("invalid number of program header entries\n"));
426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_shoff field.  */
428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shnum = ehdr->e_shnum;
429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shstrndx = ehdr->e_shstrndx;
430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_shoff == 0)
431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shnum != 0)
433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header table offset\n"));
434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       && ehdr->e_type != ET_CORE)
436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section header table must be present\n"));
437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shnum == 0)
441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Get the header of the zeroth section.  The sh_size field
443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     might contain the section number.  */
444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
445acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr != NULL)
447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* The error will be reported later.  */
449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (shdr->sh_size == 0)
450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperinvalid number of section header table entries\n"));
452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		shnum = shdr->sh_size;
454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shstrndx == SHN_XINDEX)
458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Get the header of the zeroth section.  The sh_size field
460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     might contain the section number.  */
461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
462acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
463acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  if (shdr != NULL && shdr->sh_link < shnum)
464acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    shstrndx = shdr->sh_link;
465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (shstrndx >= shnum)
467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header index\n"));
468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
470bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  phnum = ehdr->e_phnum;
471bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  if (ehdr->e_phnum == PN_XNUM)
472bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    {
473bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      /* Get the header of the zeroth section.  The sh_info field
474bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	 might contain the phnum count.  */
475bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      GElf_Shdr shdr_mem;
476bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
477bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      if (shdr != NULL)
478bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	{
479bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  /* The error will be reported later.  */
480bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  if (shdr->sh_info < PN_XNUM)
481bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	    ERROR (gettext ("\
482bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrathinvalid number of program header table entries\n"));
483bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  else
484bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	    phnum = shdr->sh_info;
485bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	}
486bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    }
487bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath
488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_flags field.  */
489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (!ebl_machine_flag_check (ebl, ehdr->e_flags))
490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("invalid machine flags: %s\n"),
491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check e_ehsize, e_phentsize, and e_shentsize fields.  */
494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (gelf_getclass (ebl->elf) == ELFCLASS32)
495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf32_Ehdr))
497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr))
500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header size: %hd\n"),
501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_phentsize);
502bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size)
503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header position or size\n"));
504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr))
506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header size: %hd\n"),
507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_shentsize);
508bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      else if (ehdr->e_shoff + shnum * ehdr->e_shentsize > size)
509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header position or size\n"));
510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else if (gelf_getclass (ebl->elf) == ELFCLASS64)
512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf64_Ehdr))
514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr))
517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header size: %hd\n"),
518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_phentsize);
519bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size)
520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header position or size\n"));
521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr))
523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header size: %hd\n"),
524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_shentsize);
525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header position or size\n"));
527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Check that there is a section group section with index < IDX which
532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   contains section IDX and that there is exactly one.  */
533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_scn_group (Ebl *ebl, int idx)
535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (scnref[idx] == 0)
537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* No reference so far.  Search following sections, maybe the
539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 order is wrong.  */
540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t cnt;
541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = idx + 1; cnt < shnum; ++cnt)
543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
544acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
546acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr == NULL)
548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* We cannot get the section header so we cannot check it.
549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       The error to get the section header will be shown
550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       somewhere else.  */
551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr->sh_type != SHT_GROUP)
554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
556acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf_Data *data = elf_getdata (scn, NULL);
5570a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  if (data == NULL || data->d_buf == NULL
5580a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      || data->d_size < sizeof (Elf32_Word))
559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Cannot check the section.  */
560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
562acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf32_Word *grpdata = (Elf32_Word *) data->d_buf;
563acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  for (size_t inner = 1; inner < data->d_size / sizeof (Elf32_Word);
564acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	       ++inner)
565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (grpdata[inner] == (Elf32_Word) idx)
566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      goto out;
567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    out:
570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (cnt == shnum)
571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section with SHF_GROUP flag set not part of a section group\n"),
573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
5763b495d8e963eead963a37b5be5b063c96bb58c63Roland McGrathsection [%2d] '%s': section group [%2zu] '%s' does not precede group member\n"),
577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx),
578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
584dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_symtab (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool no_xndx_warned = false;
587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int no_pt_tls = 0;
588dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
596dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr strshdr_mem;
597dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
598dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper				     &strshdr_mem);
599dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (strshdr == NULL)
600dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
601dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
603521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath    {
604521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      ERROR (gettext ("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
605521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	     shdr->sh_link, section_name (ebl, shdr->sh_link),
606521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	     idx, section_name (ebl, idx));
607521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      strshdr = NULL;
608521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath    }
609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Search for an extended section index table section.  */
611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *xndxdata = NULL;
612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf32_Word xndxscnidx = 0;
613acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  bool found_xndx = false;
6143cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper  for (size_t cnt = 1; cnt < shnum; ++cnt)
615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (cnt != (size_t) idx)
616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf_Scn *xndxscn = elf_getscn (ebl->elf, cnt);
618acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	GElf_Shdr xndxshdr_mem;
619acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
620acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	if (xndxshdr == NULL)
621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    && xndxshdr->sh_link == (GElf_Word) idx)
625acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  {
626acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    if (found_xndx)
627acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	      ERROR (gettext ("\
628acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': symbol table cannot have more than one extended index section\n"),
629acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper		     idx, section_name (ebl, idx));
630acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
631acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    xndxdata = elf_getdata (xndxscn, NULL);
632acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    xndxscnidx = elf_ndxscn (xndxscn);
633acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    found_xndx = true;
634acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  }
635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
63771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT);
63871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  if (shdr->sh_entsize != sh_entsize)
639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
6403cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Dreppersection [%2u] '%s': entry size is does not match ElfXX_Sym\n"),
6413cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	   idx, section_name (ebl, idx));
642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Test the zeroth entry.  */
644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Sym sym_mem;
645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf32_Word xndx;
646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, 0, &sym_mem, &xndx);
647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (sym == NULL)
648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get symbol %d: %s\n"),
649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx), 0, elf_errmsg (-1));
650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_name != 0)
653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_name");
655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_value != 0)
656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_value");
658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_size != 0)
659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_size");
661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_info != 0)
662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_info");
664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_other != 0)
665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_other");
667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_shndx != 0)
668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_shndx");
670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndxdata != NULL && xndx != 0)
671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': XINDEX for zeroth entry not zero\n"),
673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       xndxscnidx, section_name (ebl, xndxscnidx));
674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
67671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  for (size_t cnt = 1; cnt < shdr->sh_size / sh_entsize; ++cnt)
677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx);
679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym == NULL)
680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("section [%2d] '%s': cannot get symbol %zu: %s\n"),
682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *name = NULL;
687521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      if (strshdr == NULL)
688521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	name = "";
689521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      else if (sym->st_name >= strshdr->sh_size)
690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: invalid name value\n"),
692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name);
6960a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  if (name == NULL)
6970a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    name = "";
698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_shndx == SHN_XINDEX)
701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (xndxdata == NULL)
703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
704fd992543185126eb0280c1ee0883e073020499b4Roland McGrath	      if (!no_xndx_warned)
705fd992543185126eb0280c1ee0883e073020499b4Roland McGrath		ERROR (gettext ("\
706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: too large section index but no extended section index section\n"),
707fd992543185126eb0280c1ee0883e073020499b4Roland McGrath		       idx, section_name (ebl, idx), cnt);
708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      no_xndx_warned = true;
709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (xndx < SHN_LORESERVE)
711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: XINDEX used for index which would fit in st_shndx (%" PRIu32 ")\n"),
713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   xndxscnidx, section_name (ebl, xndxscnidx), cnt,
714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   xndx);
715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if ((sym->st_shndx >= SHN_LORESERVE
717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		// && sym->st_shndx <= SHN_HIRESERVE    always true
718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& sym->st_shndx != SHN_ABS
719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& sym->st_shndx != SHN_COMMON)
720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       || (sym->st_shndx >= shnum
721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   && (sym->st_shndx < SHN_LORESERVE
722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       /* || sym->st_shndx > SHN_HIRESERVE  always false */)))
723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: invalid section index\n"),
725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	xndx = sym->st_shndx;
728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
72918e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath      if (GELF_ST_TYPE (sym->st_info) >= STT_NUM
73018e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && !ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), NULL, 0))
731b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': symbol %zu: unknown type\n"),
732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
73496d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper      if (GELF_ST_BIND (sym->st_info) >= STB_NUM
73596d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper	  && !ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info), NULL,
73696d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper				       0))
737b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
738b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: unknown symbol binding\n"),
739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
74096d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper      if (GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE
74196d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper	  && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
74296d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper	ERROR (gettext ("\
74396d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Dreppersection [%2d] '%s': symbol %zu: unique symbol not of object type\n"),
74496d950e3e28d89469b62b46d5a014ad1260e6a1aUlrich Drepper	       idx, section_name (ebl, idx), cnt);
745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndx == SHN_COMMON)
747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Common symbols can only appear in relocatable files.  */
749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (ehdr->e_type != ET_REL)
750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n"),
752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt < shdr->sh_info)
754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n"),
756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (GELF_R_TYPE (sym->st_info) == STT_FUNC)
758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"),
760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (xndx > 0 && xndx < shnum)
763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr destshdr_mem;
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr *destshdr;
766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), &destshdr_mem);
768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (destshdr != NULL)
769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
770b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      GElf_Addr sh_addr = (ehdr->e_type == ET_REL ? 0
771b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				   : destshdr->sh_addr);
772c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard	      GElf_Addr st_value;
773c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard	      if (GELF_ST_TYPE (sym->st_info) == STT_FUNC
774c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		  || (GELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))
775c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		st_value = sym->st_value & ebl_func_addr_mask (ebl);
776c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard	      else
777c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		st_value = sym->st_value;
778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (GELF_ST_TYPE (sym->st_info) != STT_TLS)
779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
780c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  if (! ebl_check_special_symbol (ebl, ehdr, sym, name,
781c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper						  destshdr))
782c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    {
783c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		      if (st_value - sh_addr > destshdr->sh_size)
784ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			{
785ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			  /* GNU ld has severe bugs.  When it decides to remove
786ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			     empty sections it leaves symbols referencing them
7873bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			     behind.  These are symbols in .symtab or .dynsym
7883bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			     and for the named symbols have zero size.  See
7893bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			     sourceware PR13621.  */
790ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			  if (!gnuld
7913bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			      || (strcmp (section_name (ebl, idx), ".symtab")
7923bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			          && strcmp (section_name (ebl, idx),
7933bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard					     ".dynsym"))
7943bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard			      || sym->st_size != 0
795ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			      || (strcmp (name, "__preinit_array_start") != 0
796ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__preinit_array_end") != 0
797ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__init_array_start") != 0
798ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__init_array_end") != 0
799ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__fini_array_start") != 0
8003bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard				  && strcmp (name, "__fini_array_end") != 0
8013bdc16ce98295463c071192eab2ec611a8edc508Mark Wielaard				  && strcmp (name, "__bss_start") != 0
802b94cceae503b56fb360cd597f154fa2b33552887Mark Wielaard				  && strcmp (name, "__bss_start__") != 0
803a95c4ad24cf83b2b0273fee73162bf476cebec8fMark Wielaard				  && strcmp (name, "__TMC_END__") != 0
804a95c4ad24cf83b2b0273fee73162bf476cebec8fMark Wielaard				  && strcmp (name, ".TOC.") != 0))
805ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			    ERROR (gettext ("\
806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds\n"),
807ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				   idx, section_name (ebl, idx), cnt);
808ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			}
809c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		      else if ((st_value - sh_addr
810c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper				+ sym->st_size) > destshdr->sh_size)
811c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
813c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx), cnt,
814c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (int) xndx, section_name (ebl, xndx));
815c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    }
816b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
817b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if ((destshdr->sh_flags & SHF_TLS) == 0)
820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_TLS flag set\n"),
822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx), cnt,
823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   (int) xndx, section_name (ebl, xndx));
824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (ehdr->e_type == ET_REL)
826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      /* For object files the symbol value must fall
828c49d00afc4bda21181cd4237e67930f3f5228adfMark Wielaard			 into the section.  */
829c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		      if (st_value > destshdr->sh_size)
830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       idx, section_name (ebl, idx), cnt,
833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       (int) xndx, section_name (ebl, xndx));
834c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard		      else if (st_value + sym->st_size
835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       > destshdr->sh_size)
836b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
837b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       idx, section_name (ebl, idx), cnt,
839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       (int) xndx, section_name (ebl, xndx));
840b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  else
842b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
843b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Phdr phdr_mem;
844b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Phdr *phdr = NULL;
845bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath		      unsigned int pcnt;
846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
847bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath		      for (pcnt = 0; pcnt < phnum; ++pcnt)
848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (phdr != NULL && phdr->p_type == PT_TLS)
851b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    break;
852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
853b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
854bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath		      if (pcnt == phnum)
855b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
856b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (no_pt_tls++ == 0)
857b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
858b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"),
859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt);
860b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
86177be59bca4057b22af70b0b2d0197f9505577381Mark Wielaard		      else if (phdr == NULL)
86277be59bca4057b22af70b0b2d0197f9505577381Mark Wielaard			{
86377be59bca4057b22af70b0b2d0197f9505577381Mark Wielaard			    ERROR (gettext ("\
86477be59bca4057b22af70b0b2d0197f9505577381Mark Wielaardsection [%2d] '%s': symbol %zu: TLS symbol but couldn't get TLS program header entry\n"),
86577be59bca4057b22af70b0b2d0197f9505577381Mark Wielaard				   idx, section_name (ebl, idx), cnt);
86677be59bca4057b22af70b0b2d0197f9505577381Mark Wielaard			}
867b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      else
868b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
869c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard			  if (st_value
870b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      < destshdr->sh_offset - phdr->p_offset)
871b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
872b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"),
873b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
874b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
875c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard			  else if (st_value
876b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   > (destshdr->sh_offset - phdr->p_offset
877b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				      + destshdr->sh_size))
878b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
879b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
880b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
881b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
882c1c1c06e30f0b3b4ae66fcfec6318a93b8f31569Mark Wielaard			  else if (st_value + sym->st_size
883b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   > (destshdr->sh_offset - phdr->p_offset
884b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				      + destshdr->sh_size))
885b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
886b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
887b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
888b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
889b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
890b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
891b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
892b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
893b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
894b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
895b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
896b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
897b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt >= shdr->sh_info)
898b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
899b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: local symbol outside range described in sh_info\n"),
900b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
901b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
902b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
903b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
904b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt < shdr->sh_info)
905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
906b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: non-local symbol outside range described in sh_info\n"),
907b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
908b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
909b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
910b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
911b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
912b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
913b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: non-local section symbol\n"),
914b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
915b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
916b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (name != NULL)
917b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
920653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      /* Check that address and size match the global offset table.  */
921653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
922653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      GElf_Shdr destshdr_mem;
923653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx),
924653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						  &destshdr_mem);
925653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
926653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (destshdr == NULL && xndx == SHN_ABS)
927b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
928653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  /* In a DSO, we have to find the GOT section by name.  */
929653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  Elf_Scn *gotscn = NULL;
930c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  Elf_Scn *gscn = NULL;
931653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL)
932b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
933653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      destshdr = gelf_getshdr (gscn, &destshdr_mem);
934653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      assert (destshdr != NULL);
935653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      const char *sname = elf_strptr (ebl->elf,
936653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						      ehdr->e_shstrndx,
937653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						      destshdr->sh_name);
938653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      if (sname != NULL)
939b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
940c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  if (strcmp (sname, ".got.plt") == 0)
941653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    break;
942c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  if (strcmp (sname, ".got") == 0)
943653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    /* Do not stop looking.
944653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			       There might be a .got.plt section.  */
945653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    gotscn = gscn;
946b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
947653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
948653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      destshdr = NULL;
949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
950653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
951653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  if (destshdr == NULL && gotscn != NULL)
952653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    destshdr = gelf_getshdr (gotscn, &destshdr_mem);
953b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
954b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
955b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      const char *sname = ((destshdr == NULL || xndx == SHN_UNDEF)
956b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				   ? NULL
957653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath				   : elf_strptr (ebl->elf, ehdr->e_shstrndx,
958653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						 destshdr->sh_name));
959653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (sname == NULL)
960b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		{
961b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		  if (xndx != SHN_UNDEF || ehdr->e_type != ET_REL)
962b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		    ERROR (gettext ("\
963b597dfad924980dede10d7c19d87900b6172e599Ulrich Dreppersection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
964b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperbad section [%2d]\n"),
965b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			   idx, section_name (ebl, idx), xndx);
966b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		}
967653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      else if (strcmp (sname, ".got.plt") != 0
968653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		       && strcmp (sname, ".got") != 0)
969653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		ERROR (gettext ("\
970b597dfad924980dede10d7c19d87900b6172e599Ulrich Dreppersection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
971b597dfad924980dede10d7c19d87900b6172e599Ulrich Dreppersection [%2d] '%s'\n"),
972b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		       idx, section_name (ebl, idx), xndx, sname);
973653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
974653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (destshdr != NULL)
975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
976b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Found it.  */
977c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  if (!ebl_check_special_symbol (ebl, ehdr, sym, name,
978c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper						 destshdr))
979c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    {
980b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		      if (ehdr->e_type != ET_REL
981b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  && sym->st_value != destshdr->sh_addr)
982c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			/* This test is more strict than the psABIs which
983c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			   usually allow the symbol to be in the middle of
984c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			   the .got section, allowing negative offsets.  */
985c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
986653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match %s section address %#" PRIx64 "\n"),
987c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx),
988c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (uint64_t) sym->st_value,
989c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       sname, (uint64_t) destshdr->sh_addr);
990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
991c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		      if (!gnuld && sym->st_size != destshdr->sh_size)
992c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
993653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match %s section size %" PRIu64 "\n"),
994c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx),
995c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (uint64_t) sym->st_size,
996c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       sname, (uint64_t) destshdr->sh_size);
997c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    }
998b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
999b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
1000b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
1001b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"),
1002b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx));
1003b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1004b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (strcmp (name, "_DYNAMIC") == 0)
100541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    /* Check that address and size match the dynamic section.
100641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	       We locate the dynamic section via the program header
100741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	       entry.  */
1008bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	    for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt)
100941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      {
101041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Phdr phdr_mem;
101141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
1012b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
101341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
101441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  {
101541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    if (sym->st_value != phdr->p_vaddr)
101641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      ERROR (gettext ("\
1017b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"),
101841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     idx, section_name (ebl, idx),
101941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) sym->st_value,
102041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) phdr->p_vaddr);
1021b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
102241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    if (!gnuld && sym->st_size != phdr->p_memsz)
102341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      ERROR (gettext ("\
1024b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"),
102541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     idx, section_name (ebl, idx),
102641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) sym->st_size,
102741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) phdr->p_memsz);
1028b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
102941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    break;
103041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  }
1031b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1032b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1033c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper
1034c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper      if (GELF_ST_VISIBILITY (sym->st_other) != STV_DEFAULT
1035c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper	  && shdr->sh_type == SHT_DYNSYM)
1036c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper	ERROR (gettext ("\
1037c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Dreppersection [%2d] '%s': symbol %zu: symbol in dynamic symbol table with non-default visibility\n"),
1038c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1039a062b6bcadd1565d360acf640f9d4c159b2270eaMark Wielaard      if (! ebl_check_st_other_bits (ebl, sym->st_other))
1040c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper	ERROR (gettext ("\
1041c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Dreppersection [%2d] '%s': symbol %zu: unknown bit set in st_other\n"),
1042c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1043c803fbe6c3fa15d08dee1c99948ec66326db1e9eUlrich Drepper
1044b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1045b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1046b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1047b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1048b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool
1049c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperis_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr,
105028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    bool is_rela)
1051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1052b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If this is no executable or DSO it cannot be a .rel.dyn section.  */
1053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return false;
1055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the section name.  Unfortunately necessary.  */
105728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (strcmp (section_name (ebl, idx), is_rela ? ".rela.dyn" : ".rel.dyn"))
1058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return false;
1059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1060b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section
1061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     entry can be present as well.  */
1062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn = NULL;
1063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1064b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1065b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr rcshdr_mem;
1066b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem);
1067b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
106871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      if (rcshdr == NULL)
106971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	break;
107071c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek
10710a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (rcshdr->sh_type == SHT_DYNAMIC && rcshdr->sh_entsize != 0)
1072b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1073b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Found the dynamic section.  Look through it.  */
1074b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  Elf_Data *d = elf_getdata (scn, NULL);
1075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t cnt;
1076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
10770a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  if (d == NULL)
10780a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    ERROR (gettext ("\
10790a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': cannot get section data.\n"),
10800a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		   idx, section_name (ebl, idx));
10810a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
1082b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt)
1083b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1084b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Dyn dyn_mem;
1085b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem);
108671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek
108771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	      if (dyn == NULL)
108871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek		break;
1089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (dyn->d_tag == DT_RELCOUNT)
1091b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
109228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  /* Found it.  Does the type match.  */
109328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if (is_rela)
1094b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
109528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELCOUNT used for this RELA section\n"),
109628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx));
109728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  else
109828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    {
109928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Does the number specified number of relative
110028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations exceed the total number of
110128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations?  */
110271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek		      if (shdr->sh_entsize != 0
110371c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek			  && dyn->d_un.d_val > (shdr->sh_size
110471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek						/ shdr->sh_entsize))
110528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			ERROR (gettext ("\
1106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
110728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       idx, section_name (ebl, idx),
110828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       (int) dyn->d_un.d_val);
110928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
111028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Make sure the specified number of relocations are
111128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relative.  */
111228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
111328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper								   idx), NULL);
11140a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		      if (reldata != NULL && shdr->sh_entsize != 0)
111528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			for (size_t inner = 0;
111628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     inner < shdr->sh_size / shdr->sh_entsize;
111728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     ++inner)
111828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  {
111928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rel rel_mem;
112028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rel *rel = gelf_getrel (reldata, inner,
112128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							 &rel_mem);
112228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (rel == NULL)
112328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      /* The problem will be reported elsewhere.  */
112428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      break;
112528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
112628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (ebl_relative_reloc_p (ebl,
112728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						      GELF_R_TYPE (rel->r_info)))
112828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      {
112928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				if (inner >= dyn->d_un.d_val)
113028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				  ERROR (gettext ("\
113128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
113228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 idx, section_name (ebl, idx),
113328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 (int) dyn->d_un.d_val);
113428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      }
113528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    else if (inner < dyn->d_un.d_val)
113628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      ERROR (gettext ("\
113728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
113828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     idx, section_name (ebl, idx),
113928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     inner, (int) dyn->d_un.d_val);
114028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  }
114128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    }
114228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		}
114328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
114428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      if (dyn->d_tag == DT_RELACOUNT)
114528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		{
114628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  /* Found it.  Does the type match.  */
114728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if (!is_rela)
114828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    ERROR (gettext ("\
114928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELACOUNT used for this REL section\n"),
115028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx));
115128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  else
115228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    {
115328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Does the number specified number of relative
115428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations exceed the total number of
115528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations?  */
11560a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		      if (shdr->sh_entsize != 0
11570a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard			  && dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
115828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			ERROR (gettext ("\
115928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
116028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       idx, section_name (ebl, idx),
116128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       (int) dyn->d_un.d_val);
116228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
116328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Make sure the specified number of relocations are
116428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relative.  */
116528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
116628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper								   idx), NULL);
11670a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		      if (reldata != NULL && shdr->sh_entsize != 0)
116828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			for (size_t inner = 0;
116928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     inner < shdr->sh_size / shdr->sh_entsize;
117028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     ++inner)
117128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  {
117228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rela rela_mem;
117328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rela *rela = gelf_getrela (reldata, inner,
117428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							    &rela_mem);
117528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (rela == NULL)
117628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      /* The problem will be reported elsewhere.  */
117728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      break;
117828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
117928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (ebl_relative_reloc_p (ebl,
118028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						      GELF_R_TYPE (rela->r_info)))
118128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      {
118228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				if (inner >= dyn->d_un.d_val)
118328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				  ERROR (gettext ("\
118428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
118528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 idx, section_name (ebl, idx),
118628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 (int) dyn->d_un.d_val);
118728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      }
118828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    else if (inner < dyn->d_un.d_val)
118928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      ERROR (gettext ("\
119028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
119128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     idx, section_name (ebl, idx),
119228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     inner, (int) dyn->d_un.d_val);
119328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  }
119428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    }
1195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return true;
1203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
120641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstruct loaded_segment
120741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper{
120841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Addr from;
120941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Addr to;
121041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  bool read_only;
121141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *next;
121241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper};
121341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
121441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
121541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper/* Check whether binary has text relocation flag set.  */
121641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic bool textrel;
121741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
121841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper/* Keep track of whether text relocation flag is needed.  */
121941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic bool needed_textrel;
122041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
122141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1222c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic bool
1223c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr,
1224c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		  int idx, int reltype, GElf_Shdr **destshdrp,
122541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr *destshdr_memp, struct loaded_segment **loadedp)
1226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool reldyn = false;
1228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check whether the link to the section we relocate is reasonable.  */
1230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info >= shnum)
1231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"),
1232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1233c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  else if (shdr->sh_info != 0)
1234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1235c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      *destshdrp = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1236c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper				 destshdr_memp);
1237c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (*destshdrp != NULL)
1238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1239028d0ab0cc1cb5f96ee48feef966b7d8d56c6a8eMark Wielaard	  if(! ebl_check_reloc_target_type (ebl, (*destshdrp)->sh_type))
1240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true);
1242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (!reldyn)
1243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
1244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': invalid destination section type\n"),
1245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx));
1246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
1247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
1248c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		  /* There is no standard, but we require that .rel{,a}.dyn
1249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     sections have a sh_info value of zero.  */
1250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (shdr->sh_info != 0)
1251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
1252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': sh_info should be zero\n"),
1253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx));
1254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1257c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  if (((*destshdrp)->sh_flags & (SHF_MERGE | SHF_STRINGS)) != 0)
1258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': no relocations for merge-able sections possible\n"),
1260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
1261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
126471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  size_t sh_entsize = gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT);
126571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  if (shdr->sh_entsize != sh_entsize)
1266c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext (reltype == ELF_T_RELA ? "\
1267c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Rela\n" : "\
1268c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Rel\n"),
1269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
127141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* In preparation of checking whether relocations are text
127241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     relocations or not we need to determine whether the file is
127341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     flagged to have text relocation and we need to determine a) what
127441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     the loaded segments are and b) which are read-only.  This will
127541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     also allow us to determine whether the same reloc section is
127641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     modifying loaded and not loaded segments.  */
1277bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  for (unsigned int i = 0; i < phnum; ++i)
127841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
127941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      GElf_Phdr phdr_mem;
128041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
128141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (phdr == NULL)
128241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	continue;
128341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
128441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (phdr->p_type == PT_LOAD)
128541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
128641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  struct loaded_segment *newp = xmalloc (sizeof (*newp));
128741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->from = phdr->p_vaddr;
128841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->to = phdr->p_vaddr + phdr->p_memsz;
128941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->read_only = (phdr->p_flags & PF_W) == 0;
129041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->next = *loadedp;
129141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  *loadedp = newp;
129241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
129341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      else if (phdr->p_type == PT_DYNAMIC)
129441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
129541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  Elf_Scn *dynscn = gelf_offscn (ebl->elf, phdr->p_offset);
129641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  GElf_Shdr dynshdr_mem;
129741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem);
129841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  Elf_Data *dyndata = elf_getdata (dynscn, NULL);
129941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC
13000a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      && dyndata != NULL && dynshdr->sh_entsize != 0)
130141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j)
130241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      {
130341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Dyn dyn_mem;
130441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Dyn *dyn = gelf_getdyn (dyndata, j, &dyn_mem);
130541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		if (dyn != NULL
130641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    && (dyn->d_tag == DT_TEXTREL
130741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			|| (dyn->d_tag == DT_FLAGS
130841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			    && (dyn->d_un.d_val & DF_TEXTREL) != 0)))
130941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  {
131041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    textrel = true;
131141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    break;
131241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  }
131341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      }
131441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
131541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
131641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
131741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* A quick test which can be easily done here (although it is a bit
131841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     out of place): the text relocation flag makes only sense if there
131941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     is a segment which is not writable.  */
132041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (textrel)
132141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
132241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *seg = *loadedp;
132341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      while (seg != NULL && !seg->read_only)
132441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	seg = seg->next;
132541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (seg == NULL)
132641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	ERROR (gettext ("\
132741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Dreppertext relocation flag set but there is no read-only segment\n"));
132841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
132941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1330c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  return reldyn;
1331c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper}
1332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
133441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperenum load_state
133541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  {
133641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_undecided,
133741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_loaded,
133841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_unloaded,
133941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_error
134041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  };
134141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
134241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1343c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic void
1344607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppercheck_one_reloc (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *relshdr, int idx,
1345607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		 size_t cnt, const GElf_Shdr *symshdr, Elf_Data *symdata,
1346607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		 GElf_Addr r_offset, GElf_Xword r_info,
134741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 const GElf_Shdr *destshdr, bool reldyn,
134841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 struct loaded_segment *loaded, enum load_state *statep)
1349c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper{
1350c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool known_broken = gnuld;
1351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1352c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (r_info)))
1353c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"),
1354c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1355607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper  else if (((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1356607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    /* The executable/DSO can contain relocation sections with
1357607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	       all the relocations the linker has applied.  Those sections
1358607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	       are marked non-loaded, though.  */
1359607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    || (relshdr->sh_flags & SHF_ALLOC) != 0)
1360607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	   && !ebl_reloc_valid_use (ebl, GELF_R_TYPE (r_info)))
1361c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("\
1362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
1363c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1365c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (symshdr != NULL
1366c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      && ((GELF_R_SYM (r_info) + 1)
1367c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
1368c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  > symshdr->sh_size))
1369c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("\
1370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: invalid symbol index\n"),
1371c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
13736ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper  /* No more tests if this is a no-op relocation.  */
13746ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper  if (ebl_none_reloc_p (ebl, GELF_R_TYPE (r_info)))
13756ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper    return;
13766ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper
1377c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (r_info)))
1378c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1379c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      const char *name;
1380c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      char buf[64];
1381c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Sym sym_mem;
1382c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
1383c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (sym != NULL
1384c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  /* Get the name for the symbol.  */
1385c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1386c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
1387c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	ERROR (gettext ("\
1388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
1389c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	       idx, section_name (ebl, idx), cnt,
1390c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	       ebl_reloc_type_name (ebl, GELF_R_SYM (r_info),
1391c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper				    buf, sizeof (buf)));
1392c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1394c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (reldyn)
1395c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1396c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      // XXX TODO Check .rel.dyn section addresses.
1397c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1398c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  else if (!known_broken)
1399c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1400c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (destshdr != NULL
1401c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && GELF_R_TYPE (r_info) != 0
1402b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  && (r_offset - (ehdr->e_type == ET_REL ? 0
1403b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  : destshdr->sh_addr)) >= destshdr->sh_size)
1404c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	ERROR (gettext ("\
1405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: offset out of bounds\n"),
1406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1407c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
140941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Sym sym_mem;
141041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
141141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
141241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info))
1413c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      /* Make sure the referenced symbol is an object or unspecified.  */
141441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && sym != NULL
141541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE
141641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
141741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
141841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      char buf[64];
141941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      ERROR (gettext ("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"),
142041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	     idx, section_name (ebl, idx), cnt,
142141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	     ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
142241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				   buf, sizeof (buf)));
142341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
142441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1425038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper  if ((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1426038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      || (relshdr->sh_flags & SHF_ALLOC) != 0)
142741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
1428038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      bool in_loaded_seg = false;
1429038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      while (loaded != NULL)
1430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1431038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  if (r_offset < loaded->to
1432038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      && r_offset + (sym == NULL ? 0 : sym->st_size) >= loaded->from)
143341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    {
1434038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      /* The symbol is in this segment.  */
1435038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      if  (loaded->read_only)
1436038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		{
1437038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		  if (textrel)
1438038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		    needed_textrel = true;
1439038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		  else
1440038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		    ERROR (gettext ("section [%2d] '%s': relocation %zu: read-only section modified but text relocation flag not set\n"),
1441038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper			   idx, section_name (ebl, idx), cnt);
1442038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		}
1443038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper
1444038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      in_loaded_seg = true;
144541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    }
144641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1447038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  loaded = loaded->next;
1448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
144941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1450038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      if (*statep == state_undecided)
1451038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	*statep = in_loaded_seg ? state_loaded : state_unloaded;
1452038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      else if ((*statep == state_unloaded && in_loaded_seg)
1453038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	       || (*statep == state_loaded && !in_loaded_seg))
1454038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	{
1455038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  ERROR (gettext ("\
145641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Dreppersection [%2d] '%s': relocations are against loaded and unloaded data\n"),
1457038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		 idx, section_name (ebl, idx));
1458038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  *statep = state_error;
1459038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	}
1460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1465c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1467c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
1469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
1472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
1473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1475c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  /* Check the fields of the section header.  */
1476c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr destshdr_mem;
1477c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *destshdr = NULL;
147841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *loaded = NULL;
1479c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELA, &destshdr,
148041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				  &destshdr_mem, &loaded);
1481c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1482c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1483c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr symshdr_mem;
1484c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1485c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
148641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  enum load_state state = state_undecided;
1487c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
148871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
148971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  for (size_t cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1491c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rela rela_mem;
1492c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem);
1493c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (rela == NULL)
1494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1495c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  ERROR (gettext ("\
1496c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': cannot get relocation %zu: %s\n"),
1497c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1498c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  continue;
1499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1500c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1501607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1502607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       rela->r_offset, rela->r_info, destshdr, reldyn, loaded,
1503607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       &state);
150441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
150541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
150641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  while (loaded != NULL)
150741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
150841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *old = loaded;
150941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      loaded = loaded->next;
151041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      free (old);
1511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1512c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper}
1513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1514c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1515c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic void
1516c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1517c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper{
1518c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1519c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (data == NULL)
1520c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1521c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1522c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	     idx, section_name (ebl, idx));
1523c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      return;
1524c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1525c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1526c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  /* Check the fields of the section header.  */
1527c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr destshdr_mem;
1528c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *destshdr = NULL;
152941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *loaded = NULL;
1530c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_REL, &destshdr,
153141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				  &destshdr_mem, &loaded);
1532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
1535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
153741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  enum load_state state = state_undecided;
1538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
153971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
154071c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  for (size_t cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Rel rel_mem;
1543c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem);
1544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rel == NULL)
1545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get relocation %zu: %s\n"),
1548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
1550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1552607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1553607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       rel->r_offset, rel->r_info, destshdr, reldyn, loaded,
1554607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       &state);
155541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
155641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
155741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  while (loaded != NULL)
155841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
155941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *old = loaded;
156041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      loaded = loaded->next;
156141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      free (old);
1562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Number of dynamic sections.  */
1567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int ndynamic;
1568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1571607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppercheck_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *data;
1574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr strshdr_mem;
1575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *strshdr;
1576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cnt;
1577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool dependencies[DT_NUM][DT_NUM] =
1578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_NEEDED] = { [DT_STRTAB] = true },
1580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTRELSZ] = { [DT_JMPREL] = true },
1581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_HASH] = { [DT_SYMTAB] = true },
1582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRTAB] = { [DT_STRSZ] = true },
1583231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_SYMENT] = true },
1584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true },
1585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELASZ] = { [DT_RELA] = true },
1586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELAENT] = { [DT_RELA] = true },
1587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRSZ] = { [DT_STRTAB] = true },
1588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMENT] = { [DT_SYMTAB] = true },
1589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SONAME] = { [DT_STRTAB] = true },
1590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RPATH] = { [DT_STRTAB] = true },
1591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true },
1592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELSZ] = { [DT_REL] = true },
1593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELENT] = { [DT_REL] = true },
1594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true },
1595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RUNPATH] = { [DT_STRTAB] = true },
1596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTREL] = { [DT_JMPREL] = true },
1597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool has_dt[DT_NUM];
1599231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  bool has_val_dt[DT_VALNUM];
1600231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  bool has_addr_dt[DT_ADDRNUM];
1601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool level2[DT_NUM] =
1602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RPATH] = true,
1604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMBOLIC] = true,
1605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_TEXTREL] = true,
1606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_BIND_NOW] = true
1607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool mandatory[DT_NUM] =
1609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_NULL] = true,
1611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRTAB] = true,
1612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMTAB] = true,
1613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRSZ] = true,
1614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMENT] = true
1615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  memset (has_dt, '\0', sizeof (has_dt));
1618231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  memset (has_val_dt, '\0', sizeof (has_val_dt));
1619231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  memset (has_addr_dt, '\0', sizeof (has_addr_dt));
1620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (++ndynamic == 2)
1622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("more than one dynamic section present\n"));
1623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
162441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
1626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
1629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
1630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem);
1633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB)
1634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
1636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   shdr->sh_link, section_name (ebl, shdr->sh_link),
1637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
16380a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  else if (strshdr == NULL)
16390a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    {
16400a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      ERROR (gettext ("\
16410a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d]: referenced as string table for section [%2d] '%s' but section link value is invalid\n"),
16420a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	   shdr->sh_link, idx, section_name (ebl, idx));
16430a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      return;
16440a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    }
1645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
164671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
164771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  if (shdr->sh_entsize != sh_entsize)
1648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Dyn\n"),
1650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info != 0)
1653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool non_null_warned = false;
165771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
1658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Dyn dyn_mem;
1660acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dyn_mem);
1661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn == NULL)
1662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get dynamic section entry %zu: %s\n"),
1665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
1667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned)
1670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"),
1673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx));
1674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  non_null_warned = true;
1675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (!ebl_dynamic_tag_check (ebl, dyn->d_tag))
1678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': entry %zu: unknown tag\n"),
1679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag >= 0 && dyn->d_tag < DT_NUM)
1682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (has_dt[dyn->d_tag]
1684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_NEEDED
1685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_NULL
1686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_POSFLAG_1)
1687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf[50];
1689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: more than one entry with tag %s\n"),
1691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt,
1692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   buf, sizeof (buf)));
1694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (be_strict && level2[dyn->d_tag])
1697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf[50];
1699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: level 2 tag %s used\n"),
1701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt,
1702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   buf, sizeof (buf)));
1704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  has_dt[dyn->d_tag] = true;
1707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
17080a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      else if (dyn->d_tag >= 0 && dyn->d_tag <= DT_VALRNGHI
1709231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       && DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
1710231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	has_val_dt[DT_VALTAGIDX (dyn->d_tag)] = true;
17110a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      else if (dyn->d_tag >= 0 && dyn->d_tag <= DT_ADDRRNGHI
1712231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       && DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
1713231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	has_addr_dt[DT_ADDRTAGIDX (dyn->d_tag)] = true;
1714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL
1716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && dyn->d_un.d_val != DT_RELA)
1717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
1718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"),
1719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1721607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      /* Check that addresses for entries are in loaded segments.  */
1722607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      switch (dyn->d_tag)
1723607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	{
1724607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  size_t n;
1725cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_STRTAB:
1726cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  /* We require the referenced section is the same as the one
1727cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	     specified in sh_link.  */
1728cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  if (strshdr->sh_addr != dyn->d_un.d_val)
1729cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    {
1730cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      ERROR (gettext ("\
1731cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Dreppersection [%2d] '%s': entry %zu: pointer does not match address of section [%2d] '%s' referenced by sh_link\n"),
1732cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1733cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1734cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      break;
1735cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    }
1736cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  goto check_addr;
1737cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper
1738607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	default:
1739607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (dyn->d_tag < DT_ADDRRNGLO || dyn->d_tag > DT_ADDRRNGHI)
1740607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    /* Value is no pointer.  */
1741607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    break;
1742607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* FALLTHROUGH */
1743607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
1744cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_AUXILIARY:
1745cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FILTER:
1746cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FINI:
1747cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FINI_ARRAY:
1748607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_HASH:
1749607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_INIT:
1750607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_INIT_ARRAY:
1751cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_JMPREL:
1752cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_PLTGOT:
1753cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_REL:
1754cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RELA:
1755cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SYMBOLIC:
1756cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SYMTAB:
1757607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_VERDEF:
1758607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_VERNEED:
1759cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_VERSYM:
1760cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	check_addr:
1761bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  for (n = 0; n < phnum; ++n)
1762607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
1763607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr phdr_mem;
1764607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, n, &phdr_mem);
1765607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      if (phdr != NULL && phdr->p_type == PT_LOAD
1766607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr <= dyn->d_un.d_ptr
1767607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr + phdr->p_memsz > dyn->d_un.d_ptr)
1768607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		break;
1769607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
1770bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  if (unlikely (n >= phnum))
1771607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
1772607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      char buf[50];
1773607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      ERROR (gettext ("\
1774607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppersection [%2d] '%s': entry %zu: %s value must point into loaded segment\n"),
1775607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1776607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1777607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper					   sizeof (buf)));
1778607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
1779cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  break;
1780cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper
1781cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_NEEDED:
1782cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RPATH:
1783cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RUNPATH:
1784cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SONAME:
1785cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  if (dyn->d_un.d_ptr >= strshdr->sh_size)
1786cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    {
1787cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      char buf[50];
1788cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      ERROR (gettext ("\
1789cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Dreppersection [%2d] '%s': entry %zu: %s value must be valid offset in section [%2d] '%s'\n"),
1790cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1791cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1792cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper					   sizeof (buf)),
1793cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1794cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    }
1795cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  break;
1796607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	}
1797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 1; cnt < DT_NUM; ++cnt)
1800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (has_dt[cnt])
1801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1802acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	for (int inner = 0; inner < DT_NUM; ++inner)
1803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (dependencies[cnt][inner] && ! has_dt[inner])
1804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf1[50];
1806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf2[50];
1807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': contains %s entry but not %s\n"),
1810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx),
1811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)),
1812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2)));
1813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1814b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1815b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    else
1816b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1817b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (mandatory[cnt])
1818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
1819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    char buf[50];
1820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': mandatory tag %s not present\n"),
1822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx),
1823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf)));
1824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
1825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1827231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* Make sure we have an hash table.  */
1828231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (!has_dt[DT_HASH] && !has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)])
1829231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    ERROR (gettext ("\
1830231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': no hash section present\n"),
1831231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   idx, section_name (ebl, idx));
1832231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1833231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* The GNU-style hash table also needs a symbol table.  */
1834231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (!has_dt[DT_HASH] && has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)]
1835231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      && !has_dt[DT_SYMTAB])
1836231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    ERROR (gettext ("\
1837231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': contains %s entry but not %s\n"),
1838231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   idx, section_name (ebl, idx),
1839231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   "DT_GNU_HASH", "DT_SYMTAB");
1840231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the rel/rela tags.  At least one group must be available.  */
1842b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT])
1843b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT]))
1844b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1845b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': not all of %s, %s, and %s are present\n"),
1846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
1847b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   "DT_RELA", "DT_RELASZ", "DT_RELAENT");
1848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT])
1850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT]))
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_REL", "DT_RELSZ", "DT_RELENT");
1855231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1856231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* Check that all prelink sections are present if any of them is.  */
1857231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)]
1858231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1859231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    {
1860231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)])
1861231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1862231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1863231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_PRELINKED");
1864231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1865231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1866231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1867231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_CHECKSUM");
1868231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1869231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      /* Only DSOs can be marked like this.  */
1870231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (ehdr->e_type != ET_DYN)
1871231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1872231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': non-DSO file marked as dependency during prelink\n"),
1873231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx));
1874231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    }
1875231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1876231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)]
1877231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)]
1878231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)]
1879231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1880231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    {
1881231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)])
1882231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1883231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1884231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_CONFLICTSZ");
1885231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)])
1886231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1887231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1888231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_LIBLISTSZ");
1889231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)])
1890231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1891231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1892231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_CONFLICT");
1893231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1894231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1895231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1896231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_LIBLIST");
1897231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    }
1898b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1899b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1900b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1901b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1902acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1903b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1904acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (ehdr->e_type != ET_REL)
1905acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
1906acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      ERROR (gettext ("\
1907acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': only relocatable files can have extended section index\n"),
1908acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	     idx, section_name (ebl, idx));
1909acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      return;
1910acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    }
1911b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1912acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1913acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr symshdr_mem;
1914acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1915b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB)
1916b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1917b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended section index section not for symbol table\n"),
1918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
19190a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  else if (symshdr == NULL)
19200a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    ERROR (gettext ("\
19210a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': sh_link extended section index [%2d] is invalid\n"),
19220a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	   idx, section_name (ebl, idx), shdr->sh_link);
1923acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
1924b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symdata == NULL)
1925b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("cannot get data for symbol section\n"));
1926b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1927b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_entsize != sizeof (Elf32_Word))
1928b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1929b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry size does not match Elf32_Word\n"),
1930b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1931b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1932b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL
19330a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      && shdr->sh_entsize != 0
19340a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      && symshdr->sh_entsize != 0
1935b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (shdr->sh_size / shdr->sh_entsize
1936b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  < symshdr->sh_size / symshdr->sh_entsize))
1937b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1938b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended index table too small for symbol table\n"),
1939b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1940b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1941b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info != 0)
1942b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1943b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1944b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1945acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = idx + 1; cnt < shnum; ++cnt)
1946b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1947b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr rshdr_mem;
1948acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      GElf_Shdr *rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem);
1949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX
1950b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && rshdr->sh_link == shdr->sh_link)
1951b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1952b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1953b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"),
1954b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx),
1955b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, section_name (ebl, cnt));
1956b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1957b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1958b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1960acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
19610a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || data->d_buf == NULL)
196271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    {
196371c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
196471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	     idx, section_name (ebl, idx));
196571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      return;
196671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    }
1967b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1968b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (*((Elf32_Word *) data->d_buf) != 0)
1969b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("symbol 0 should have zero extended section index\n"));
1970b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1971acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1972b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1973b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt];
1974b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndx != 0)
1976b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1977b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Sym sym_data;
1978b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data);
1979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym == NULL)
1980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("cannot get data for symbol %zu\n"), cnt);
1982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
1983b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1985b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym->st_shndx != SHN_XINDEX)
1986b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1987b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperextended section index is %" PRIu32 " but symbol index is not XINDEX\n"),
1988b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   (uint32_t) xndx);
1989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1992b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1993b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1994b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
199528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
199628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		 GElf_Shdr *symshdr)
199728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
199828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
199928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
200028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
200128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
200228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    ERROR (gettext ("\
200328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
200428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
200528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
200628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
200728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t maxidx = nchain;
200828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
200971c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  if (symshdr != NULL && symshdr->sh_entsize != 0)
201028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
201128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
201228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
201328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
201428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
201528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx));
201628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
201728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      maxidx = symsize;
201828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
201928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
202071c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  Elf32_Word *buf = (Elf32_Word *) data->d_buf;
202171c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  Elf32_Word *end = (Elf32_Word *) ((char *) data->d_buf + shdr->sh_size);
202228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
202328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
202471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    {
202571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      if (buf + cnt >= end)
202671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	break;
202771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      else if (buf[cnt] >= maxidx)
202828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
202928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash bucket reference %zu out of bounds\n"),
203028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2);
203171c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    }
203228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
203328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (; cnt < 2 + nbucket + nchain; ++cnt)
203471c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    {
203571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      if (buf + cnt >= end)
203671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	break;
203771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      else if (buf[cnt] >= maxidx)
203828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
203928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain reference %zu out of bounds\n"),
204028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2 - nbucket);
204171c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    }
204228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
204328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
204428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
204528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
204628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
204728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		 GElf_Shdr *symshdr)
204828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
204928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
205028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
205128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
205228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
205328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    ERROR (gettext ("\
205428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
205528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
205628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
205728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
205828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t maxidx = nchain;
205928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
20600a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (symshdr != NULL && symshdr->sh_entsize != 0)
206128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
206228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
206328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
206428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
206528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
206628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx));
206728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
206828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      maxidx = symsize;
206928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
207028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
207171c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  Elf64_Xword *buf = (Elf64_Xword *) data->d_buf;
207271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek  Elf64_Xword *end = (Elf64_Xword *) ((char *) data->d_buf + shdr->sh_size);
207328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
207428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
207571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    {
207671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      if (buf + cnt >= end)
207771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	break;
207871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      else if (buf[cnt] >= maxidx)
207928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
208028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash bucket reference %zu out of bounds\n"),
208128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2);
208271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    }
208328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
208428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (; cnt < 2 + nbucket + nchain; ++cnt)
208571c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    {
208671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      if (buf + cnt >= end)
208771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	break;
208871c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      else if (buf[cnt] >= maxidx)
208928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
2090dcf6160602985e6eb70c96c6546ed9614a414d98Ulrich Dreppersection [%2d] '%s': hash chain reference %" PRIu64 " out of bounds\n"),
209171c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	       idx, section_name (ebl, idx), (uint64_t) cnt - 2 - nbucket);
209271c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek    }
209328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
209428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
209528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
209628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
209728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
209828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		GElf_Shdr *symshdr)
209928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
2100281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard  if (data->d_size < 4 * sizeof (Elf32_Word))
2101281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard    {
2102281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard      ERROR (gettext ("\
2103281bb49c71665f306b23107cbf821636f59211e0Mark Wielaardsection [%2d] '%s': not enough data\n"),
2104281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard	     idx, section_name (ebl, idx));
2105281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard      return;
2106281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard    }
2107281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard
210828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0];
210928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
21108ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
211128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
2112281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard  if (bitmask_words == 0 || !powerof2 (bitmask_words))
2113281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard    {
2114281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard      ERROR (gettext ("\
2115281bb49c71665f306b23107cbf821636f59211e0Mark Wielaardsection [%2d] '%s': bitmask size zero or not power of 2: %u\n"),
2116281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard	     idx, section_name (ebl, idx), bitmask_words);
2117281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard      return;
2118281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard    }
21198ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
21208ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t bitmask_idxmask = bitmask_words - 1;
21218ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (gelf_getclass (ebl->elf) == ELFCLASS64)
21228ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    bitmask_words *= 2;
21238ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
21248ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
2125281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard  /* Is there still room for the sym chain?
2126281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard     Use uint64_t calculation to prevent 32bit overlow.  */
2127281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard  uint64_t used_buf = (4ULL + bitmask_words + nbuckets) * sizeof (Elf32_Word);
2128281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard  if (used_buf > data->d_size)
212928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
213028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
213171c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelineksection [%2d] '%s': hash table section is too small (is %ld, expected at least %ld)\n"),
213228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), (long int) shdr->sh_size,
2133281bb49c71665f306b23107cbf821636f59211e0Mark Wielaard	     (long int) used_buf);
213428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      return;
213528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
213628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
21378ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shift > 31)
213816e2ac344788f2bb08ae9dc0a20948f554ca560cMark Wielaard    {
213916e2ac344788f2bb08ae9dc0a20948f554ca560cMark Wielaard      ERROR (gettext ("\
21408ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': 2nd hash function shift too big: %u\n"),
214116e2ac344788f2bb08ae9dc0a20948f554ca560cMark Wielaard	     idx, section_name (ebl, idx), shift);
214216e2ac344788f2bb08ae9dc0a20948f554ca560cMark Wielaard      return;
214316e2ac344788f2bb08ae9dc0a20948f554ca560cMark Wielaard    }
21448ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
21458ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words
21468ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							 + nbuckets);
214728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
21480a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (symshdr != NULL && symshdr->sh_entsize != 0)
214928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    maxidx = MIN (maxidx, symshdr->sh_size / symshdr->sh_entsize);
215028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
215128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  /* We need the symbol section data.  */
215228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf_Data *symdata = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link), NULL);
215328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
21548ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  union
21558ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  {
21568ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    Elf32_Word *p32;
21578ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    Elf64_Xword *p64;
21588ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  } bitmask = { .p32 = &((Elf32_Word *) data->d_buf)[4] },
21598ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      collected = { .p32 = xcalloc (bitmask_words, sizeof (Elf32_Word)) };
21608ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
21618ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t classbits = gelf_getclass (ebl->elf) == ELFCLASS32 ? 32 : 64;
21628ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
216328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
21648ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  for (cnt = 4 + bitmask_words; cnt < 4 + bitmask_words + nbuckets; ++cnt)
216528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
21668ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      Elf32_Word symidx = ((Elf32_Word *) data->d_buf)[cnt];
216728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
216828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx == 0)
21698ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	continue;
217028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
217128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx < symbias)
217228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	{
217328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  ERROR (gettext ("\
217428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"),
21758ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		 idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
217628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  continue;
217728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	}
217828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
217928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      while (symidx - symbias < maxidx)
218028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	{
21818ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	  Elf32_Word chainhash = ((Elf32_Word *) data->d_buf)[4
21828ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							      + bitmask_words
21838ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							      + nbuckets
218428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							      + symidx
218528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							      - symbias];
218628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
218728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  if (symdata != NULL)
218828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    {
218928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      /* Check that the referenced symbol is not undefined.  */
219028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      GElf_Sym sym_mem;
219128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      GElf_Sym *sym = gelf_getsym (symdata, symidx, &sym_mem);
2192231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	      if (sym != NULL && sym->st_shndx == SHN_UNDEF
2193231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper		  && GELF_ST_TYPE (sym->st_info) != STT_FUNC)
219428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		ERROR (gettext ("\
219528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': symbol %u referenced in chain for bucket %zu is undefined\n"),
21965530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper		       idx, section_name (ebl, idx), symidx,
21975530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper		       cnt - (4 + bitmask_words));
219828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
21990a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      const char *symname = (sym != NULL
22000a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard				     ? elf_strptr (ebl->elf, symshdr->sh_link,
22010a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard						   sym->st_name)
22020a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard				     : NULL);
220328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      if (symname != NULL)
220428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		{
220528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  Elf32_Word hval = elf_gnu_hash (symname);
220628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if ((hval & ~1u) != (chainhash & ~1u))
220728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    ERROR (gettext ("\
220828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"),
22095530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper			   idx, section_name (ebl, idx), symidx,
22105530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper			   cnt - (4 + bitmask_words));
22118ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
22128ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  /* Set the bits in the bitmask.  */
22138ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  size_t maskidx = (hval / classbits) & bitmask_idxmask;
22140a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		  if (maskidx >= bitmask_words)
22150a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		    {
22160a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		      ERROR (gettext ("\
22170a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n"),
22180a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard			     idx, section_name (ebl, idx), symidx,
22190a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard			     cnt - (4 + bitmask_words));
22200a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		      return;
22210a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		    }
22228ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  if (classbits == 32)
22238ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    {
22248ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p32[maskidx]
22258ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT32_C (1) << (hval & (classbits - 1));
22268ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p32[maskidx]
22278ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT32_C (1) << ((hval >> shift) & (classbits - 1));
22288ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    }
22298ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  else
22308ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    {
22318ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p64[maskidx]
22328ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT64_C (1) << (hval & (classbits - 1));
22338ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p64[maskidx]
22348ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT64_C (1) << ((hval >> shift) & (classbits - 1));
22358ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    }
223628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		}
223728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    }
223828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
223928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  if ((chainhash & 1) != 0)
224028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    break;
224128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
224228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  ++symidx;
224328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	}
224428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
224528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx - symbias >= maxidx)
224628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("\
224728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain for bucket %zu out of bounds\n"),
22485530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper	       idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
22490a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      else if (symshdr != NULL && symshdr->sh_entsize != 0
225028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       && symidx > symshdr->sh_size / symshdr->sh_entsize)
225128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("\
225228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"),
22535530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper	       idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
225428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
22558ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
22568ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (memcmp (collected.p32, bitmask.p32, bitmask_words * sizeof (Elf32_Word)))
22578ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    ERROR (gettext ("\
22588ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': bitmask does not match names in the hash table\n"),
22598ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	   idx, section_name (ebl, idx));
22608ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
22618ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  free (collected.p32);
226228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
226328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
226428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
226528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
226628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_hash (int tag, Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2268acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (ehdr->e_type == ET_REL)
2269acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
2270acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      ERROR (gettext ("\
2271acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': relocatable files cannot have hash tables\n"),
2272acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	     idx, section_name (ebl, idx));
2273acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      return;
2274acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    }
2275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2276acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
22770a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || data->d_buf == NULL)
2278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2284acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr symshdr_mem;
2285acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2286acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &symshdr_mem);
2287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM)
2288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
2289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': hash table not for dynamic symbol table\n"),
2290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
22910a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  else if (symshdr == NULL)
22920a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    ERROR (gettext ("\
22930a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': invalid sh_link symbol table section index [%2d]\n"),
22940a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	   idx, section_name (ebl, idx), shdr->sh_link);
2295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
229628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_entsize != (tag == SHT_GNU_HASH
22978ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			   ? (gelf_getclass (ebl->elf) == ELFCLASS32
22988ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			      ? sizeof (Elf32_Word) : 0)
229928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   : (size_t) ebl_sysvhash_entrysize (ebl)))
2300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
230128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table entry size incorrect\n"),
2302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((shdr->sh_flags & SHF_ALLOC) == 0)
2305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': not marked to be allocated\n"),
2306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2307b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
23088ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (shdr->sh_entsize ?: 4))
2309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
23118ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': hash table has not even room for initial administrative entries\n"),
2312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
231628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  switch (tag)
2317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
231828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    case SHT_HASH:
231928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
232028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	check_sysv_hash64 (ebl, shdr, data, idx, symshdr);
232128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      else
232228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	check_sysv_hash (ebl, shdr, data, idx, symshdr);
232328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      break;
2324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
232528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    case SHT_GNU_HASH:
232628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      check_gnu_hash (ebl, shdr, data, idx, symshdr);
232728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      break;
2328ee4b927bae351b21787355e00a3d28371bf78e8fUlrich Drepper
232928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    default:
23308ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      assert (! "should not happen");
2331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
23357c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper/* Compare content of both hash tables, it must be identical.  */
23367c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepperstatic void
23377c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppercompare_hash_gnu_hash (Ebl *ebl, GElf_Ehdr *ehdr, size_t hash_idx,
23387c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		       size_t gnu_hash_idx)
23397c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper{
23407c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *hash_scn = elf_getscn (ebl->elf, hash_idx);
23417c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *hash_data = elf_getdata (hash_scn, NULL);
23427c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr hash_shdr_mem;
23437c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *hash_shdr = gelf_getshdr (hash_scn, &hash_shdr_mem);
23447c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *gnu_hash_scn = elf_getscn (ebl->elf, gnu_hash_idx);
23457c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *gnu_hash_data = elf_getdata (gnu_hash_scn, NULL);
23467c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr gnu_hash_shdr_mem;
23477c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *gnu_hash_shdr = gelf_getshdr (gnu_hash_scn, &gnu_hash_shdr_mem);
23487c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23497c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr == NULL || gnu_hash_shdr == NULL
23500a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      || hash_data == NULL || hash_data->d_buf == NULL
23510a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      || gnu_hash_data == NULL || gnu_hash_data->d_buf == NULL)
23527c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    /* None of these pointers should be NULL since we used the
23537c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper       sections already.  We are careful nonetheless.  */
23547c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    return;
23557c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23567c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* The link must point to the same symbol table.  */
23577c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr->sh_link != gnu_hash_shdr->sh_link)
23587c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
23597c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      ERROR (gettext ("\
23607c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"),
23617c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
23627c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     gnu_hash_idx,
23637c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
23647c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      return;
23657c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
23667c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23677c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *sym_scn = elf_getscn (ebl->elf, hash_shdr->sh_link);
23687c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *sym_data = elf_getdata (sym_scn, NULL);
23697c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr sym_shdr_mem;
23707c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *sym_shdr = gelf_getshdr (sym_scn, &sym_shdr_mem);
23717c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23720a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (sym_data == NULL || sym_data->d_buf == NULL
23730a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      || sym_shdr == NULL || sym_shdr->sh_entsize == 0)
23747c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    return;
23757c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23760a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  const char *hash_name;
23770a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  const char *gnu_hash_name;
23780a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  hash_name  = elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name);
23790a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  gnu_hash_name  = elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name);
23800a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
23810a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (gnu_hash_data->d_size < 4 * sizeof (Elf32_Word))
23820a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    {
23830a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      ERROR (gettext ("\
23840a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' does not contain enough data\n"),
23850a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	     gnu_hash_idx, gnu_hash_name);
23860a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      return;
23870a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    }
23880a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
23890a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  uint32_t nentries = sym_shdr->sh_size / sym_shdr->sh_entsize;
23907c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  char *used = alloca (nentries);
23917c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  memset (used, '\0', nentries);
23927c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23937c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* First go over the GNU_HASH table and mark the entries as used.  */
23947c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const Elf32_Word *gnu_hasharr = (Elf32_Word *) gnu_hash_data->d_buf;
23957c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf32_Word gnu_nbucket = gnu_hasharr[0];
23960a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  Elf32_Word gnu_symbias = gnu_hasharr[1];
23977c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const int bitmap_factor = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 1 : 2;
23987c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const Elf32_Word *gnu_bucket = (gnu_hasharr
23997c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper				  + (4 + gnu_hasharr[2] * bitmap_factor));
24000a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  const Elf32_Word *gnu_chain = gnu_bucket + gnu_hasharr[0];
24010a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
24020a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (gnu_hasharr[2] == 0)
24030a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    {
24040a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      ERROR (gettext ("\
24050a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' has zero bit mask words\n"),
24060a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	     gnu_hash_idx, gnu_hash_name);
24070a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      return;
24080a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    }
24090a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
24100a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  uint64_t used_buf = ((4ULL + gnu_hasharr[2] * bitmap_factor + gnu_nbucket)
24110a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		       * sizeof (Elf32_Word));
24120a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  uint32_t max_nsyms = (gnu_hash_data->d_size - used_buf) / sizeof (Elf32_Word);
24130a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (used_buf > gnu_hash_data->d_size)
24140a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    {
24150a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      ERROR (gettext ("\
24160a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' uses too much data\n"),
24170a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	     gnu_hash_idx, gnu_hash_name);
24180a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      return;
24190a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    }
24207c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
24217c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  for (Elf32_Word cnt = 0; cnt < gnu_nbucket; ++cnt)
24227c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
2423ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard      if (gnu_bucket[cnt] != STN_UNDEF)
2424ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	{
2425ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	  Elf32_Word symidx = gnu_bucket[cnt] - gnu_symbias;
2426ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	  do
2427ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	    {
2428ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	      if (symidx >= max_nsyms || symidx + gnu_symbias >= nentries)
2429ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard		{
2430ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard		  ERROR (gettext ("\
2431ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaardhash section [%2zu] '%s' invalid symbol index %" PRIu32 " (max_nsyms: %" PRIu32 ", nentries: %" PRIu32 "\n"),
2432ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard			 gnu_hash_idx, gnu_hash_name, symidx, max_nsyms, nentries);
2433ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard		  return;
2434ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard		}
2435ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	      used[symidx + gnu_symbias] |= 1;
2436ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	    }
2437ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	  while ((gnu_chain[symidx++] & 1u) == 0);
2438ae9aa3e4b2853d58598a6928eb1dbaacf6488496Mark Wielaard	}
24397c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
24407c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
24417c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* Now go over the old hash table and check that we cover the same
24427c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     entries.  */
24437c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr->sh_entsize == sizeof (Elf32_Word))
24447c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
24457c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *hasharr = (Elf32_Word *) hash_data->d_buf;
24460a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (hash_data->d_size < 2 * sizeof (Elf32_Word))
24470a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
24480a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
24490a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' does not contain enough data\n"),
24500a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		 hash_idx, hash_name);
24510a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  return;
24520a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
24530a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
24547c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      Elf32_Word nbucket = hasharr[0];
24550a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      Elf32_Word nchain = hasharr[1];
24560a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      uint64_t hash_used = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
24570a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (hash_used > hash_data->d_size)
24580a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
24590a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
24600a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' uses too much data\n"),
24610a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		 hash_idx, hash_name);
24620a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  return;
24630a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
24640a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
24657c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *bucket = &hasharr[2];
24667c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *chain = &hasharr[2 + nbucket];
24677c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
24687c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
24697c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	{
24707c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  Elf32_Word symidx = bucket[cnt];
24710a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  while (symidx != STN_UNDEF && symidx < nentries && symidx < nchain)
24727c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    {
24737c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      used[symidx] |= 2;
24747c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      symidx = chain[symidx];
24757c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    }
24767c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	}
24777c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
24780a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  else if (hash_shdr->sh_entsize == sizeof (Elf64_Word))
24797c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
24807c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *hasharr = (Elf64_Xword *) hash_data->d_buf;
24810a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (hash_data->d_size < 2 * sizeof (Elf32_Word))
24820a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
24830a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
24840a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' does not contain enough data\n"),
24850a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		 hash_idx, hash_name);
24860a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  return;
24870a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
24880a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
24897c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      Elf64_Xword nbucket = hasharr[0];
24900a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      Elf64_Xword nchain = hasharr[1];
24910a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      uint64_t maxwords = hash_data->d_size / sizeof (Elf64_Xword);
24920a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (maxwords < 2
24930a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  || maxwords - 2 < nbucket
24940a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  || maxwords - 2 - nbucket < nchain)
24950a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
24960a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
24970a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' uses too much data\n"),
24980a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		 hash_idx, hash_name);
24990a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  return;
25000a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
25010a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
25027c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *bucket = &hasharr[2];
25037c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *chain = &hasharr[2 + nbucket];
25047c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
25057c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
25067c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	{
25077c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  Elf64_Xword symidx = bucket[cnt];
25080a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  while (symidx != STN_UNDEF && symidx < nentries && symidx < nchain)
25097c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    {
25107c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      used[symidx] |= 2;
25117c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      symidx = chain[symidx];
25127c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    }
25137c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	}
25147c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
25150a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  else
25160a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    {
25170a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      ERROR (gettext ("\
25180a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardhash section [%2zu] '%s' invalid sh_entsize\n"),
25190a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	     gnu_hash_idx, gnu_hash_name);
25200a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      return;
25210a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard    }
25227c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
25237c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* Now see which entries are not set in one or both hash tables
25247c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     (unless the symbol is undefined in which case it can be omitted
25257c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     in the new table format).  */
25267c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if ((used[0] & 1) != 0)
25277c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"),
25287c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   gnu_hash_idx,
25297c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
25307c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if ((used[0] & 2) != 0)
25317c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"),
25327c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
25337c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
25340a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  for (uint32_t cnt = 1; cnt < nentries; ++cnt)
25357c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    if (used[cnt] != 0 && used[cnt] != 3)
25367c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      {
25377c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	if (used[cnt] == 1)
25387c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  ERROR (gettext ("\
25397c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersymbol %d referenced in new hash table in [%2zu] '%s' but not in old hash table in [%2zu] '%s'\n"),
25407c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 cnt, gnu_hash_idx,
25417c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name),
25427c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 hash_idx,
25437c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
25447c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	else
25457c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  {
25467c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    GElf_Sym sym_mem;
25477c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    GElf_Sym *sym = gelf_getsym (sym_data, cnt, &sym_mem);
25487c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
25497c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    if (sym != NULL && sym->st_shndx != STN_UNDEF)
25507c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      ERROR (gettext ("\
25517c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersymbol %d referenced in old hash table in [%2zu] '%s' but not in new hash table in [%2zu] '%s'\n"),
25527c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     cnt, hash_idx,
25537c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
25547c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     gnu_hash_idx,
25557c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
25567c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  }
25577c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      }
25587c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper}
25597c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
25607c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
2561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_null (Ebl *ebl, GElf_Shdr *shdr, int idx)
2563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define TEST(name, extra) \
2565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (extra && shdr->sh_##name != 0)					      \
2566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': nonzero sh_%s for NULL section\n"),  \
2567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), #name)
2568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (name, 1);
2570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (flags, 1);
2571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (addr, 1);
2572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (offset, 1);
2573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (size, idx != 0);
2574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (link, idx != 0);
2575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (info, 1);
2576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (addralign, 1);
2577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (entsize, 1);
2578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_REL)
2585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
2587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section groups only allowed in relocatable object files\n"),
2588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check that sh_link is an index of a symbol table.  */
25930e864dd86871c809668c557985ca19344dfff787Ulrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
25950e864dd86871c809668c557985ca19344dfff787Ulrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr == NULL)
2597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': cannot get symbol table: %s\n"),
2598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), elf_errmsg (-1));
2599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (symshdr->sh_type != SHT_SYMTAB)
2602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section reference in sh_link is no symbol table\n"),
2604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM,
2607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper							  1, EV_CURRENT))
2608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': invalid symbol index in sh_info\n"),
2610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags != 0)
2613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': sh_flags not zero\n"),
2614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
26160e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      GElf_Sym sym_data;
26170e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      GElf_Sym *sym = gelf_getsym (elf_getdata (symscn, NULL), shdr->sh_info,
26180e864dd86871c809668c557985ca19344dfff787Ulrich Drepper				   &sym_data);
26190e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      if (sym == NULL)
26200e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	ERROR (gettext ("\
26210e864dd86871c809668c557985ca19344dfff787Ulrich Dreppersection [%2d] '%s': cannot get symbol for signature\n"),
26220e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	       idx, section_name (ebl, idx));
26230a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      else if (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name) == NULL)
26240a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	ERROR (gettext ("\
26250a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': cannot get symbol name for signature\n"),
26260a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	       idx, section_name (ebl, idx));
26270e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      else if (strcmp (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name),
26280e864dd86871c809668c557985ca19344dfff787Ulrich Drepper		       "") == 0)
26290e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	ERROR (gettext ("\
26303b495d8e963eead963a37b5be5b063c96bb58c63Roland McGrathsection [%2d] '%s': signature symbol cannot be empty string\n"),
26310e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	       idx, section_name (ebl, idx));
26320e864dd86871c809668c557985ca19344dfff787Ulrich Drepper
2633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (be_strict
2634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT))
2635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': sh_flags not set correctly\n"),
2636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
26400a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || data->d_buf == NULL)
2641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': cannot get data: %s\n"),
2642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), elf_errmsg (-1));
2643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
2646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t cnt;
2647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf32_Word val;
2648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data->d_size % elsize != 0)
2650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"),
2652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data->d_size < elsize)
2655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group without flags word\n"),
2657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (be_strict)
2659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (data->d_size < 2 * elsize)
2661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group without member\n"),
2663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
2664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (data->d_size < 3 * elsize)
2665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group with only one member\n"),
2667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
2668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if ALLOW_UNALIGNED
2671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      val = *((Elf32_Word *) data->d_buf);
2672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#else
2673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      memcpy (&val, data->d_buf, elsize);
2674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
2675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((val & ~GRP_COMDAT) != 0)
2676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': unknown section group flags\n"),
2677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = elsize; cnt < data->d_size; cnt += elsize)
2680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if ALLOW_UNALIGNED
2682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  val = *((Elf32_Word *) ((char *) data->d_buf + cnt));
2683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#else
2684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  memcpy (&val, (char *) data->d_buf + cnt, elsize);
2685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
2686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (val > shnum)
2688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
26892ec957327cdfae6cee592a52958a9c937ea4b13cChih-Hung Hsiehsection [%2d] '%s': section index %zu out of range\n"),
2690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt / elsize);
2691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
2692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
2693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Shdr refshdr_mem;
2694acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	      GElf_Shdr *refshdr = gelf_getshdr (elf_getscn (ebl->elf, val),
2695acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper						 &refshdr_mem);
2696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (refshdr == NULL)
2697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
2698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get section header for element %zu: %s\n"),
2699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx), cnt / elsize,
2700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       elf_errmsg (-1));
2701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
2702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
2703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (refshdr->sh_type == SHT_GROUP)
2704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
2705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group contains another group [%2d] '%s'\n"),
2706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx),
2707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   val, section_name (ebl, val));
2708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if ((refshdr->sh_flags & SHF_GROUP) == 0)
2710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
27112ec957327cdfae6cee592a52958a9c937ea4b13cChih-Hung Hsiehsection [%2d] '%s': element %zu references section [%2d] '%s' without SHF_GROUP flag set\n"),
2712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx), cnt / elsize,
2713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   val, section_name (ebl, val));
2714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
2715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
27160a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      if (val < shnum && ++scnref[val] == 2)
2717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
2718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' is contained in more than one section group\n"),
2719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       val, section_name (ebl, val));
2720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
2721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *
2727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection_flags_string (GElf_Word flags, char *buf, size_t len)
2728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2729099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath  if (flags == 0)
2730099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath    return "none";
2731099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath
2732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const struct
2733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
2734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    GElf_Word flag;
2735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    const char *name;
2736b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  } known_flags[] =
2737b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2738b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define NEWFLAG(name) { SHF_##name, #name }
2739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (WRITE),
2740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (ALLOC),
2741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (EXECINSTR),
2742b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (MERGE),
2743b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (STRINGS),
2744b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (INFO_LINK),
2745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (LINK_ORDER),
2746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (OS_NONCONFORMING),
2747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (GROUP),
2748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (TLS)
2749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
2750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#undef NEWFLAG
2751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
2752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *cp = buf;
2754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2755acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 0; cnt < nknown_flags; ++cnt)
2756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (flags & known_flags[cnt].flag)
2757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
2758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (cp != buf && len > 1)
2759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
2760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    *cp++ = '|';
2761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    --len;
2762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
2763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name));
2765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	cp = mempcpy (cp, known_flags[cnt].name, ncopy);
2766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	len -= ncopy;
2767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	flags ^= known_flags[cnt].flag;
2769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
2770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (flags != 0 || cp == buf)
2772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    snprintf (cp, len - 1, "%" PRIx64, (uint64_t) flags);
2773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *cp = '\0';
2775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return buf;
2777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2780dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2781dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperhas_copy_reloc (Ebl *ebl, unsigned int symscnndx, unsigned int symndx)
2782dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2783dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* First find the relocation section for the symbol table.  */
2784dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = NULL;
2785dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2786dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = NULL;
2787dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2788dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2789dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      shdr = gelf_getshdr (scn, &shdr_mem);
2790dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (shdr != NULL
2791dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
2792dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && shdr->sh_link == symscnndx)
2793dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	/* Found the section.  */
2794dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	break;
2795dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2796dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2797dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (scn == NULL)
2798dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 0;
2799dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2800dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
28010a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || shdr->sh_entsize == 0)
2802dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 0;
2803dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2804dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr->sh_type == SHT_REL)
2805dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2806dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2807dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rel rel_mem;
2808dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
2809dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (rel == NULL)
2810dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  continue;
2811dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2812dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (GELF_R_SYM (rel->r_info) == symndx
2813dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info)))
2814dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  return 1;
2815dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2816dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  else
2817dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2818dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2819dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rela rela_mem;
2820dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
2821dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (rela == NULL)
2822dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  continue;
2823dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2824dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (GELF_R_SYM (rela->r_info) == symndx
2825dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info)))
2826dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  return 1;
2827dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2828dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2829dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 0;
2830dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2831dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2832dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2833637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic int
2834637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperin_nobits_scn (Ebl *ebl, unsigned int shndx)
2835637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper{
2836637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Shdr shdr_mem;
2837637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, shndx), &shdr_mem);
2838637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  return shdr != NULL && shdr->sh_type == SHT_NOBITS;
2839637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper}
2840637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2841637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2842dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic struct version_namelist
2843dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2844dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  const char *objname;
2845dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  const char *name;
2846858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrath  GElf_Versym ndx;
2847dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  enum { ver_def, ver_need } type;
2848dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct version_namelist *next;
2849dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper} *version_namelist;
2850dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2851dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2852dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2853858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrathadd_version (const char *objname, const char *name, GElf_Versym ndx, int type)
2854dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2855dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Check that there are no duplications.  */
2856dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct version_namelist *nlp = version_namelist;
2857dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while (nlp != NULL)
2858dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2859dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (((nlp->objname == NULL && objname == NULL)
2860dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	   || (nlp->objname != NULL && objname != NULL
2861dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       && strcmp (nlp->objname, objname) == 0))
2862dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && strcmp (nlp->name, name) == 0)
2863dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	return nlp->type == ver_def ? 1 : -1;
2864dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      nlp = nlp->next;
2865dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2866dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2867dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp = xmalloc (sizeof (*nlp));
2868dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->objname = objname;
2869dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->name = name;
2870dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->ndx = ndx;
2871dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->type = type;
2872dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->next = version_namelist;
2873dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  version_namelist = nlp;
2874dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2875dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 0;
2876dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2877dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2878dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2879b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2880dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_versym (Ebl *ebl, int idx)
2881b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2882dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = elf_getscn (ebl->elf, idx);
2883dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2884dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2885dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr == NULL)
2886dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    /* The error has already been reported.  */
2887dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
2888dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2889dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
2890dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2891dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2892dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2893dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
2894dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
2895dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2896dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2897dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2898b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
2899dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2900b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr == NULL)
2901b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* The error has already been reported.  */
2902b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
2903b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2904b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr->sh_type != SHT_DYNSYM)
2905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2906b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
2907b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"),
2908b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx),
2909b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     shdr->sh_link, section_name (ebl, shdr->sh_link));
2910b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2911b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2912b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2913dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* The number of elements in the version symbol table must be the
2914dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     same as the number of symbols.  */
29150a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (shdr->sh_entsize != 0 && symshdr->sh_entsize != 0
291671c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek      && (shdr->sh_size / shdr->sh_entsize
291771c1534c9c7a0652fb6c5f9295baa08f32b0b166Jakub Jelinek	  != symshdr->sh_size / symshdr->sh_entsize))
2918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
2919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"),
2920b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
2921b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   shdr->sh_link, section_name (ebl, shdr->sh_link));
2922b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2923dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
29240a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (symdata == NULL || shdr->sh_entsize == 0)
2925dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    /* The error has already been reported.  */
2926dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
2927dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2928dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (int cnt = 1; (size_t) cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2929dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2930dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Versym versym_mem;
2931dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Versym *versym = gelf_getversym (data, cnt, &versym_mem);
2932dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (versym == NULL)
2933dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2934dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2935dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: cannot read version data\n"),
2936dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
2937dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  break;
2938dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2939dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2940dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Sym sym_mem;
2941dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_mem);
2942dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (sym == NULL)
2943dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	/* Already reported elsewhere.  */
2944dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	continue;
2945dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
294661655e08ba36430de47381cefdf10d0c26aa8480Ulrich Drepper      if (*versym == VER_NDX_GLOBAL)
2947dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2948dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* Global symbol.  Make sure it is not defined as local.  */
2949dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2950dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2951dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: local symbol with global scope\n"),
2952dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
2953dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
295461655e08ba36430de47381cefdf10d0c26aa8480Ulrich Drepper      else if (*versym != VER_NDX_LOCAL)
2955dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2956c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	  /* Versioned symbol.  Make sure it is not defined as local.  */
2957c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	  if (!gnuld && GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2958c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	    ERROR (gettext ("\
2959c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Dreppersection [%2d] '%s': symbol %d: local symbol with version\n"),
2960c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
2961c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper
2962dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* Look through the list of defined versions and locate the
2963dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     index we need for this symbol.  */
2964dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *runp = version_namelist;
2965dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  while (runp != NULL)
2966858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrath	    if (runp->ndx == (*versym & (GElf_Versym) 0x7fff))
2967dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
2968dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    else
2969dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      runp = runp->next;
2970dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2971dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (runp == NULL)
2972dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2973dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: invalid version index %d\n"),
2974dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt, (int) *versym);
2975dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else if (sym->st_shndx == SHN_UNDEF
2976dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   && runp->type == ver_def)
2977dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2978dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: version index %d is for defined version\n"),
2979dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt, (int) *versym);
2980dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else if (sym->st_shndx != SHN_UNDEF
2981dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   && runp->type == ver_need)
2982dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2983dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      /* Unless this symbol has a copy relocation associated
2984dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 this must not happen.  */
2985637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper	      if (!has_copy_reloc (ebl, shdr->sh_link, cnt)
2986637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper		  && !in_nobits_scn (ebl, sym->st_shndx))
2987dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		ERROR (gettext ("\
2988dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: version index %d is for requested version\n"),
2989dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       idx, section_name (ebl, idx), cnt, (int) *versym);
2990dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2991dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2992dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2993dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2994dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2995dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2996dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2997bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrathunknown_dependency_p (Elf *elf, const char *fname)
2998dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2999dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Phdr phdr_mem;
3000dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Phdr *phdr = NULL;
3001dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3002bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  unsigned int i;
3003bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  for (i = 0; i < phnum; ++i)
3004dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    if ((phdr = gelf_getphdr (elf, i, &phdr_mem)) != NULL
3005dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	&& phdr->p_type == PT_DYNAMIC)
3006dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      break;
3007dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3008bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  if (i == phnum)
3009dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 1;
3010dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  assert (phdr != NULL);
3011dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
3012dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
3013dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3014dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
30150a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC
30160a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      && data != NULL && shdr->sh_entsize != 0)
3017dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (size_t j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
3018dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
3019dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Dyn dyn_mem;
3020dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
3021dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (dyn != NULL && dyn->d_tag == DT_NEEDED)
3022dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  {
3023dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    const char *str = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
3024dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    if (str != NULL && strcmp (str, fname) == 0)
3025dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      /* Found it.  */
3026dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      return 0;
3027dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  }
3028dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
3029dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3030dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 1;
3031b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
3032b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3033b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3034acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic unsigned int nverneed;
3035acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3036b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
3037bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrathcheck_verneed (Ebl *ebl, GElf_Shdr *shdr, int idx)
3038b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
3039acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (++nverneed == 2)
3040acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("more than one version reference section present\n"));
3041acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3042acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr strshdr_mem;
3043acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
3044acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &strshdr_mem);
3045acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr == NULL)
3046acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    return;
3047acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
3048acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("\
3049acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': sh_link does not link to string table\n"),
3050acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	   idx, section_name (ebl, idx));
3051dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3052dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
3053dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
3054dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
3055dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
3056dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
3057dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
3058dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3059dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  unsigned int offset = 0;
30609d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard  for (Elf64_Word cnt = shdr->sh_info; cnt > 0; )
3061dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
30629d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard      cnt--;
30639d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard
3064dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Get the data at the next offset.  */
3065dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verneed needmem;
3066dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
3067dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need == NULL)
3068dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	break;
3069dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3070dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      unsigned int auxoffset = offset + need->vn_aux;
3071dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3072dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need->vn_version != EV_CURRENT)
3073dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3074dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong version %d\n"),
3075dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) need->vn_version);
3076dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3077dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need->vn_cnt > 0 && need->vn_aux < gelf_fsize (ebl->elf, ELF_T_VNEED,
3078dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper							 1, EV_CURRENT))
30790a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
30800a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
3081dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
30820a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
30830a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
30840a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
3085dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3086dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      const char *libname = elf_strptr (ebl->elf, shdr->sh_link,
3087dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					need->vn_file);
3088dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (libname == NULL)
3089dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3090dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
3091dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid file reference\n"),
3092dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
3093dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  goto next_need;
3094dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3095dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3096dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Check that there is a DT_NEEDED entry for the referenced library.  */
3097bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      if (unknown_dependency_p (ebl->elf, libname))
3098dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3099dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d references unknown dependency\n"),
3100dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
3101dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3102dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
3103dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3104dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  GElf_Vernaux auxmem;
3105dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
3106dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (aux == NULL)
3107dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    break;
3108dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3109dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vna_flags & ~VER_FLG_WEAK) != 0)
3110dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
3111dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"),
3112dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
3113dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3114dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  const char *verstr = elf_strptr (ebl->elf, shdr->sh_link,
3115dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					   aux->vna_name);
3116dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (verstr == NULL)
31170a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    {
31180a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      ERROR (gettext ("\
3119dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has invalid name reference\n"),
31200a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		     idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
31210a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      break;
31220a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    }
3123dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else
3124dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
3125dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      GElf_Word hashval = elf_hash (verstr);
3126dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (hashval != aux->vna_hash)
3127dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		ERROR (gettext ("\
3128dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: %#x, expected %#x\n"),
3129dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       idx, section_name (ebl, idx), need->vn_cnt - cnt2,
3130dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       cnt, (int) hashval, (int) aux->vna_hash);
3131dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3132dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      int res = add_version (libname, verstr, aux->vna_other,
3133dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper				     ver_need);
3134dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (unlikely (res !=0))
3135dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		{
3136dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  ERROR (gettext ("\
3137dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has duplicate version name '%s'\n"),
3138dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 idx, section_name (ebl, idx), need->vn_cnt - cnt2,
3139dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 cnt, verstr);
3140dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		}
3141dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
3142dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3143dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vna_next != 0 || cnt2 > 0)
3144dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && aux->vna_next < gelf_fsize (ebl->elf, ELF_T_VNAUX, 1,
3145dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					     EV_CURRENT))
3146dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
3147dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      ERROR (gettext ("\
3148dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"),
3149dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		     idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
3150dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
3151dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
3152dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3153dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  auxoffset += MAX (aux->vna_next,
3154dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			    gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, EV_CURRENT));
3155dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3156dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3157dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Find the next offset.  */
3158dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    next_need:
3159dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      offset += need->vn_next;
3160dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3161dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((need->vn_next != 0 || cnt > 0)
3162dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && offset < auxoffset)
31630a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
31640a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
3165dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid offset to next entry\n"),
31660a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
31670a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
31680a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
31690a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
31700a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (need->vn_next == 0 && cnt > 0)
31710a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
31720a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
31730a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': entry %d has zero offset to next entry, but sh_info says there are more entries\n"),
31740a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
31750a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
31760a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
3177dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3178acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper}
3179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3180acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3181acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic unsigned int nverdef;
3182acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3183acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic void
3184acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_verdef (Ebl *ebl, GElf_Shdr *shdr, int idx)
3185acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper{
3186acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (++nverdef == 2)
3187acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("more than one version definition section present\n"));
3188acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3189acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr strshdr_mem;
3190acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
3191acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &strshdr_mem);
3192acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr == NULL)
3193acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    return;
3194acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
3195acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("\
3196acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': sh_link does not link to string table\n"),
3197acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	   idx, section_name (ebl, idx));
3198dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3199dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
3200dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
3201dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
3202dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    no_data:
3203dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
3204dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
3205dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
3206dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3207dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3208dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Iterate over all version definition entries.  We check that there
3209dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     is a BASE entry and that each index is unique.  To do the later
3210dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     we collection the information in a list which is later
3211dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     examined.  */
3212dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct namelist
3213dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  {
3214dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    const char *name;
3215dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    struct namelist *next;
3216dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  } *namelist = NULL;
3217dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct namelist *refnamelist = NULL;
3218dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3219dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  bool has_base = false;
3220dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  unsigned int offset = 0;
32219d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard  for (Elf64_Word cnt = shdr->sh_info; cnt > 0; )
3222dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
32239d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard      cnt--;
32249d0926538635fe9a2bda0684623516aaf4407ecbMark Wielaard
3225dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Get the data at the next offset.  */
3226dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdef defmem;
3227dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
3228dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def == NULL)
3229dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	goto no_data;
3230dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3231dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_flags & VER_FLG_BASE) != 0)
3232dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3233dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (has_base)
3234dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
3235dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': more than one BASE definition\n"),
3236dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx));
3237dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (def->vd_ndx != VER_NDX_GLOBAL)
3238dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
3239dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"),
3240dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx));
3241dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  has_base = true;
3242dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3243dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_flags & ~(VER_FLG_BASE|VER_FLG_WEAK)) != 0)
3244dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3245dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has unknown flag\n"),
3246dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
3247dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3248dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_version != EV_CURRENT)
3249dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3250dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong version %d\n"),
3251dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) def->vd_version);
3252dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3253dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_cnt > 0 && def->vd_aux < gelf_fsize (ebl->elf, ELF_T_VDEF,
3254dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper						       1, EV_CURRENT))
32550a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
32560a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
3257dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
32580a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
32590a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
32600a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
3261dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3262dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      unsigned int auxoffset = offset + def->vd_aux;
3263dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdaux auxmem;
3264dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
3265dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (aux == NULL)
3266dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	goto no_data;
3267dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3268dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      const char *name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
3269dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (name == NULL)
3270dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3271dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
3272dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid name reference\n"),
3273dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
3274dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  goto next_def;
3275dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3276dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Word hashval = elf_hash (name);
3277dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_hash != hashval)
3278dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3279dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"),
3280dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) hashval,
3281dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       (int) def->vd_hash);
3282dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3283dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      int res = add_version (NULL, name, def->vd_ndx, ver_def);
3284dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (unlikely (res !=0))
3285dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3286dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
3287dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has duplicate version name '%s'\n"),
3288dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt, name);
3289dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3290dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3291dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      struct namelist *newname = alloca (sizeof (*newname));
32926247d634c33be4c9ee4bfc650bb8f06f5add41e5Ulrich Drepper      newname->name = name;
3293dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      newname->next = namelist;
3294dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      namelist = newname;
3295dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3296dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      auxoffset += aux->vda_next;
3297dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
3298dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3299dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
3300dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (aux == NULL)
3301dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    goto no_data;
3302dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3303c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
3304c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  if (name == NULL)
33050a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    {
33060a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      ERROR (gettext ("\
3307c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Dreppersection [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"),
33080a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		     idx, section_name (ebl, idx), cnt);
33090a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	      break;
33100a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	    }
3311c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  else
3312c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    {
3313c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname = alloca (sizeof (*newname));
3314c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname->name = name;
3315c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname->next = refnamelist;
3316c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      refnamelist = newname;
3317c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    }
3318dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3319dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vda_next != 0 || cnt2 + 1 < def->vd_cnt)
3320dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && aux->vda_next < gelf_fsize (ebl->elf, ELF_T_VDAUX, 1,
3321dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					     EV_CURRENT))
3322dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
3323dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      ERROR (gettext ("\
3324dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong next field in auxiliary data\n"),
3325dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		     idx, section_name (ebl, idx), cnt);
3326dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
3327dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
3328dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3329dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  auxoffset += MAX (aux->vda_next,
3330dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			    gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, EV_CURRENT));
3331dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3332dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3333dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Find the next offset.  */
3334dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    next_def:
3335dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      offset += def->vd_next;
3336dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3337dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_next != 0 || cnt > 0)
3338dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && offset < auxoffset)
33390a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
33400a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
3341dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid offset to next entry\n"),
33420a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
33430a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
33440a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
33450a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard
33460a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard      if (def->vd_next == 0 && cnt > 0)
33470a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	{
33480a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  ERROR (gettext ("\
33490a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaardsection [%2d] '%s': entry %d has zero offset to next entry, but sh_info says there are more entries\n"),
33500a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	         idx, section_name (ebl, idx), cnt);
33510a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	  break;
33520a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard	}
3353dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3354dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3355dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (!has_base)
3356dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("section [%2d] '%s': no BASE definition\n"),
3357dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	   idx, section_name (ebl, idx));
3358dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3359dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Check whether the referenced names are available.  */
3360dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while (namelist != NULL)
3361dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
3362dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      struct version_namelist *runp = version_namelist;
3363dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      while (runp != NULL)
3364dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3365dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (runp->type == ver_def
3366dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && strcmp (runp->name, namelist->name) == 0)
3367dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    break;
3368dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  runp = runp->next;
3369dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3370dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3371dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (runp == NULL)
3372dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3373dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': unknown parent version '%s'\n"),
3374dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), namelist->name);
3375dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3376dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      namelist = namelist->next;
3377dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3378acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper}
3379acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3380059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathstatic void
3381059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathcheck_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
3382059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath{
3383059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (shdr->sh_size == 0)
3384059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3385059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ERROR (gettext ("section [%2d] '%s': empty object attributes section\n"),
3386059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	     idx, section_name (ebl, idx));
3387059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      return;
3388059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3389059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3390059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL);
33910a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || data->d_size == 0 || data->d_buf == NULL)
3392059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3393059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
3394059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	     idx, section_name (ebl, idx));
3395059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      return;
3396059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3397059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3398059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  inline size_t pos (const unsigned char *p)
3399059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  {
3400059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    return p - (const unsigned char *) data->d_buf;
3401059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  }
3402059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3403059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  const unsigned char *p = data->d_buf;
3404059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (*p++ != 'A')
3405059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3406059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ERROR (gettext ("section [%2d] '%s': unrecognized attribute format\n"),
3407059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	     idx, section_name (ebl, idx));
3408059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      return;
3409059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3410059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3411059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  inline size_t left (void)
3412059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  {
3413059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    return (const unsigned char *) data->d_buf + data->d_size - p;
3414059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  }
3415059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3416059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  while (left () >= 4)
3417059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3418059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      uint32_t len;
3419059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      memcpy (&len, p, sizeof len);
3420059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3421059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (len == 0)
3422059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	ERROR (gettext ("\
3423059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: zero length field in attribute section\n"),
3424059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	       idx, section_name (ebl, idx), pos (p));
3425059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3426059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3427059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	CONVERT (len);
3428059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3429059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (len > left ())
3430059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	{
3431059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  ERROR (gettext ("\
3432059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: invalid length in attribute section\n"),
3433059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		 idx, section_name (ebl, idx), pos (p));
3434059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  break;
3435059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	}
3436059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3437059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      const unsigned char *name = p + sizeof len;
3438059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      p += len;
3439059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3440059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      unsigned const char *q = memchr (name, '\0', len);
3441059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (q == NULL)
3442059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	{
3443059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  ERROR (gettext ("\
3444059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unterminated vendor name string\n"),
3445059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		 idx, section_name (ebl, idx), pos (p));
34465e80a1e8f57fbae3bd5687bb80a65e97f824f914Mark Wielaard	  break;
3447059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	}
3448059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ++q;
3449059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3450059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (q - name == sizeof "gnu" && !memcmp (name, "gnu", sizeof "gnu"))
3451059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	while (q < p)
3452059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  {
3453059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    unsigned const char *chunk = q;
3454059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3455059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    unsigned int subsection_tag;
34567a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	    get_uleb128 (subsection_tag, q, p);
3457059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3458059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (q >= p)
3459059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3460059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3461059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"),
3462059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (chunk));
3463059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		break;
3464059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3465059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3466059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    uint32_t subsection_len;
3467059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (p - q < (ptrdiff_t) sizeof subsection_len)
3468059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3469059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3470059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: truncated attribute section\n"),
3471059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (q));
3472059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		break;
3473059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3474059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3475059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    memcpy (&subsection_len, q, sizeof subsection_len);
3476059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (subsection_len == 0)
3477059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3478059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3479059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
3480059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (q));
3481059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3482059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		q += sizeof subsection_len;
3483059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		continue;
3484059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3485059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3486059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3487059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      CONVERT (subsection_len);
3488059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
34895e80a1e8f57fbae3bd5687bb80a65e97f824f914Mark Wielaard	    /* Don't overflow, ptrdiff_t might be 32bits, but signed.  */
34905e80a1e8f57fbae3bd5687bb80a65e97f824f914Mark Wielaard	    if (p - chunk < (ptrdiff_t) subsection_len
34915e80a1e8f57fbae3bd5687bb80a65e97f824f914Mark Wielaard	        || subsection_len >= (uint32_t) PTRDIFF_MAX)
3492059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3493059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3494059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
3495059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (q));
3496059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		break;
3497059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3498059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3499059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    const unsigned char *subsection_end = chunk + subsection_len;
3500059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    chunk = q;
3501059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    q = subsection_end;
3502059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3503059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (subsection_tag != 1) /* Tag_File */
3504059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      ERROR (gettext ("\
3505059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
3506059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		     idx, section_name (ebl, idx), pos (chunk), subsection_tag);
3507059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    else
3508059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3509059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		chunk += sizeof subsection_len;
3510059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		while (chunk < q)
3511059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		  {
3512059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    unsigned int tag;
35137a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard		    get_uleb128 (tag, chunk, q);
3514059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3515059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    uint64_t value = 0;
3516059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    const unsigned char *r = chunk;
3517059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    if (tag == 32 || (tag & 1) == 0)
3518059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      {
35197a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard			get_uleb128 (value, r, q);
3520059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			if (r > q)
3521059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  {
3522059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    ERROR (gettext ("\
3523059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"),
3524059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath				   idx, section_name (ebl, idx), pos (chunk));
3525059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    break;
3526059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  }
3527059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      }
3528059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    if (tag == 32 || (tag & 1) != 0)
3529059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      {
3530059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			r = memchr (r, '\0', q - r);
3531059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			if (r == NULL)
3532059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  {
3533059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    ERROR (gettext ("\
3534059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unterminated string in attribute\n"),
3535059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath				   idx, section_name (ebl, idx), pos (chunk));
3536059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    break;
3537059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  }
3538059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			++r;
3539059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      }
3540059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3541059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    const char *tag_name = NULL;
3542059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    const char *value_name = NULL;
3543059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    if (!ebl_check_object_attribute (ebl, (const char *) name,
3544059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath						     tag, value,
3545059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath						     &tag_name, &value_name))
3546059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      ERROR (gettext ("\
3547059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"),
3548059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			     idx, section_name (ebl, idx), pos (chunk), tag);
3549059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    else if ((tag & 1) == 0 && value_name == NULL)
3550059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      ERROR (gettext ("\
3551059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"),
3552059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			     idx, section_name (ebl, idx), pos (chunk),
3553059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			     tag_name, value);
3554059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3555059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    chunk = r;
3556059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		  }
3557059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3558059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  }
3559059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      else
3560059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	ERROR (gettext ("\
3561059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: vendor '%s' unknown\n"),
3562059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	       idx, section_name (ebl, idx), pos (p), name);
3563059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3564059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3565059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (left () != 0)
3566059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    ERROR (gettext ("\
3567059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: extra bytes after last attribute section\n"),
3568059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	   idx, section_name (ebl, idx), pos (p));
3569059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath}
3570acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3571637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic bool has_loadable_segment;
3572637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic bool has_interp_segment;
3573637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3574637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic const struct
3575637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper{
3576637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  const char *name;
3577637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  size_t namelen;
3578637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word type;
3579b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  enum { unused, exact, atleast, exact_or_gnuld } attrflag;
3580637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word attr;
3581637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word attr2;
3582637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper} special_sections[] =
3583637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  {
3584637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    /* See figure 4-14 in the gABI.  */
3585637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3586c49d00afc4bda21181cd4237e67930f3f5228adfMark Wielaard    { ".comment", 8, SHT_PROGBITS, atleast, 0, SHF_MERGE | SHF_STRINGS },
3587637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3588637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3589b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    { ".debug_str", 11, SHT_PROGBITS, exact_or_gnuld, SHF_MERGE | SHF_STRINGS, 0 },
3590b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    { ".debug", 6, SHT_PROGBITS, exact, 0, 0 },
3591637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE },
3592637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 },
3593637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 },
3594637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3595637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3596637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info?
3597637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 },
3598637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3599637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3600637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests?
3601637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".line", 6, SHT_PROGBITS, exact, 0, 0 },
3602099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath    { ".note", 6, SHT_NOTE, atleast, 0, SHF_ALLOC },
3603637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
3604637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3605738c18312e0db36dce5e1cd2cddaf66eb8947f1aRoland McGrath    { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests
3606738c18312e0db36dce5e1cd2cddaf66eb8947f1aRoland McGrath    { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests
3607637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3608637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3609637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 },
3610637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3611637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3612637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests
3613637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3614637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3615637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3616637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3617637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3618637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    /* The following are GNU extensions.  */
3619637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version", 13, SHT_GNU_versym, exact, SHF_ALLOC, 0 },
3620637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version_d", 15, SHT_GNU_verdef, exact, SHF_ALLOC, 0 },
3621059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 },
3622059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    { ".gnu.attributes", 16, SHT_GNU_ATTRIBUTES, exact, 0, 0 },
3623637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  };
3624637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper#define nspecial_sections \
3625637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  (sizeof (special_sections) / sizeof (special_sections[0]))
3626637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3627b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper#define IS_KNOWN_SPECIAL(idx, string, prefix)			      \
3628b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  (special_sections[idx].namelen == sizeof string - (prefix ? 1 : 0)  \
3629b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper   && !memcmp (special_sections[idx].name, string, \
3630b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	       sizeof string - (prefix ? 1 : 0)))
3631637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3632978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3633978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper/* Indeces of some sections we need later.  */
3634978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic size_t eh_frame_hdr_scnndx;
3635978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic size_t eh_frame_scnndx;
3636978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic size_t gcc_except_table_scnndx;
3637978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3638978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3639acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic void
3640acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_sections (Ebl *ebl, GElf_Ehdr *ehdr)
3641acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper{
3642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_shoff == 0)
3643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* No section header.  */
3644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
3645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Allocate array to count references in section groups.  */
3647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  scnref = (int *) xcalloc (shnum, sizeof (int));
3648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the zeroth section first.  It must not have any contents
3650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     and the section header must contain nonzero value at most in the
3651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     sh_size and sh_link fields.  */
3652acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr shdr_mem;
3653acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
3654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr == NULL)
3655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("cannot get section header of zeroth section\n"));
3656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
3657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_name != 0)
3659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero name\n"));
3660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type != 0)
3661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero type\n"));
3662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags != 0)
3663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero flags\n"));
3664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_addr != 0)
3665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero address\n"));
3666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_offset != 0)
3667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero offset\n"));
3668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_addralign != 0)
3669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero align value\n"));
3670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_entsize != 0)
3671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero entry size value\n"));
3672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_size != 0 && ehdr->e_shnum != 0)
3674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperzeroth section has nonzero size value while ELF header has nonzero shnum value\n"));
3676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX)
3678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperzeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n"));
3680bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath
3681bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      if (shdr->sh_info != 0 && ehdr->e_phnum != PN_XNUM)
3682bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	ERROR (gettext ("\
3683bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrathzeroth section has nonzero link value while ELF header does not signal overflow in phnum\n"));
3684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3686bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  int *segment_flags = xcalloc (phnum, sizeof segment_flags[0]);
368713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
3688acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  bool dot_interp_section = false;
3689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
36907c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  size_t hash_idx = 0;
36917c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  size_t gnu_hash_idx = 0;
36927c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
3693dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  size_t versym_scnndx = 0;
3694acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 1; cnt < shnum; ++cnt)
3695acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
3696acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      shdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &shdr_mem);
3697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr == NULL)
3698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
3700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot get section header for section [%2zu] '%s': %s\n"),
3701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, section_name (ebl, cnt), elf_errmsg (-1));
3702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
3703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
3706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (scnname == NULL)
3708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2zu]: invalid name\n"), cnt);
3709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
3710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Check whether it is one of the special sections defined in
3712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     the gABI.  */
3713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t s;
3714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (s = 0; s < nspecial_sections; ++s)
3715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (strncmp (scnname, special_sections[s].name,
3716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 special_sections[s].namelen) == 0)
3717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
3718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf1[100];
3719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf2[100];
3720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf3[100];
3721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3722653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		GElf_Word good_type = special_sections[s].type;
3723b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		if (IS_KNOWN_SPECIAL (s, ".plt", false)
3724712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard		    && ebl_bss_plt_p (ebl))
3725653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  good_type = SHT_NOBITS;
3726653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
3727b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		/* In a debuginfo file, any normal section can be SHT_NOBITS.
3728b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		   This is only invalid for DWARF sections and .shstrtab.  */
3729653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		if (shdr->sh_type != good_type
3730b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		    && (shdr->sh_type != SHT_NOBITS
3731b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| !is_debuginfo
3732b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| IS_KNOWN_SPECIAL (s, ".debug_str", false)
3733b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| IS_KNOWN_SPECIAL (s, ".debug", true)
3734b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| IS_KNOWN_SPECIAL (s, ".shstrtab", false)))
3735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  ERROR (gettext ("\
3736b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' has wrong type: expected %s, is %s\n"),
3737b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 (int) cnt, scnname,
3738b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 ebl_section_type_name (ebl, special_sections[s].type,
3739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						stbuf1, sizeof (stbuf1)),
3740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 ebl_section_type_name (ebl, shdr->sh_type,
3741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						stbuf2, sizeof (stbuf2)));
3742b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3743b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		if (special_sections[s].attrflag == exact
3744b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		    || special_sections[s].attrflag == exact_or_gnuld)
3745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* Except for the link order and group bit all the
3747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       other bits should match exactly.  */
3748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP))
3749b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			!= special_sections[s].attr
3750b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			&& (special_sections[s].attrflag == exact || !gnuld))
3751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has wrong flags: expected %s, is %s\n"),
3753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname,
3754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr,
3755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf1, sizeof (stbuf1)),
3756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (shdr->sh_flags
3757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   & ~SHF_LINK_ORDER,
3758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf2, sizeof (stbuf2)));
3759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else if (special_sections[s].attrflag == atleast)
3761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & special_sections[s].attr)
3763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			!= special_sections[s].attr
3764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			|| ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP
3765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						| special_sections[s].attr
3766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						| special_sections[s].attr2))
3767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    != 0))
3768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"),
3770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname,
3771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr,
3772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf1, sizeof (stbuf1)),
3773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr2,
3774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf2, sizeof (stbuf2)),
3775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (shdr->sh_flags
3776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   & ~(SHF_LINK_ORDER
3777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						       | SHF_GROUP),
3778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf3, sizeof (stbuf3)));
3779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (strcmp (scnname, ".interp") == 0)
3782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3783b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    dot_interp_section = true;
3784b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3785b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (ehdr->e_type == ET_REL)
3786b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3787b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' present in object file\n"),
3788b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3789b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3790b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3791b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !has_loadable_segment)
3792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     && has_loadable_segment)
3797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
3802b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (strcmp (scnname, ".symtab_shndx") == 0
3804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& ehdr->e_type != ET_REL)
3805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' is extension section index table in non-object file\n"),
3807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* These sections must have the SHF_ALLOC flag set iff
3810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       a loadable segment is available.
3811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .relxxx
3813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .strtab
3814b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .symtab
3815b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .symtab_shndx
3816b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3817b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       Check that if there is a reference from the
3818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       loaded section these sections also have the
3819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       ALLOC flag set.  */
3820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if 0
3821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    // XXX TODO
3822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !has_loadable_segment)
3824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     && has_loadable_segment)
3829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
3833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3834b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		break;
3836b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
3837978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3838978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  /* Remember a few special sections for later.  */
3839978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  if (strcmp (scnname, ".eh_frame_hdr") == 0)
3840978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	    eh_frame_hdr_scnndx = cnt;
3841978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  else if (strcmp (scnname, ".eh_frame") == 0)
3842978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	    eh_frame_scnndx = cnt;
3843978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  else if (strcmp (scnname, ".gcc_except_table") == 0)
3844978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	    gcc_except_table_scnndx = cnt;
3845b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3847b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize)
3848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': size not multiple of entry size\n"),
3850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3851b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL)
3853b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("cannot get section header\n"));
3854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3855b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type >= SHT_NUM
3856059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  && shdr->sh_type != SHT_GNU_ATTRIBUTES
3857b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_LIBLIST
3858b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_CHECKSUM
3859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_verdef
3860b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_verneed
386118e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && shdr->sh_type != SHT_GNU_versym
386218e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && ebl_section_type_name (ebl, shdr->sh_type, NULL, 0) == NULL)
386318e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	ERROR (gettext ("section [%2zu] '%s' has unsupported type %d\n"),
386418e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	       cnt, section_name (ebl, cnt),
386518e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	       (int) shdr->sh_type);
3866b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3867b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \
3868b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \
3869b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS)
3870aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper      if (shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS)
3871aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	{
3872aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS;
3873aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  if (sh_flags & SHF_MASKPROC)
3874aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    {
3875aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	      if (!ebl_machine_section_flag_check (ebl,
3876aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper						   sh_flags & SHF_MASKPROC))
3877aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		ERROR (gettext ("section [%2zu] '%s'"
3878aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper				" contains invalid processor-specific flag(s)"
3879aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper				" %#" PRIx64 "\n"),
3880aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		       cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
3881aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	      sh_flags &= ~(GElf_Xword) SHF_MASKPROC;
3882aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    }
3883aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  if (sh_flags != 0)
3884aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    ERROR (gettext ("section [%2zu] '%s' contains unknown flag(s)"
3885aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper			    " %#" PRIx64 "\n"),
3886aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		   cnt, section_name (ebl, cnt), sh_flags);
3887aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	}
3888aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper      if (shdr->sh_flags & SHF_TLS)
3889b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3890b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX Correct?
3891b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr->sh_addr != 0 && !gnuld)
3892b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3893b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': thread-local data sections address not zero\n"),
3894b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, section_name (ebl, cnt));
3895b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3896b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX TODO more tests!?
3897b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3898b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3899b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_link >= shnum)
3900b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3901b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': invalid section reference in link value\n"),
3902b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3903b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3904b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum)
3905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3906b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': invalid section reference in info value\n"),
3907b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3908b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3909b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_flags & SHF_MERGE) == 0
3910b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && (shdr->sh_flags & SHF_STRINGS) != 0
3911b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && be_strict)
3912b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3913b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': strings flag set without merge flag\n"),
3914b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3915b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3916b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0)
3917b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': merge flag set but entry size is zero\n"),
3919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3920b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3921b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags & SHF_GROUP)
3922b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	check_scn_group (ebl, cnt);
3923b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
392413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath      if (shdr->sh_flags & SHF_EXECINSTR)
392513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	{
392613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	  switch (shdr->sh_type)
392713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    {
392813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    case SHT_PROGBITS:
392913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      break;
393013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
393113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    case SHT_NOBITS:
393213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      if (is_debuginfo)
393313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		break;
393413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    default:
393513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      ERROR (gettext ("\
393613b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' has unexpected type %d for an executable section\n"),
393713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		     cnt, section_name (ebl, cnt), shdr->sh_type);
393813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      break;
393913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    }
394013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
394113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	  if ((shdr->sh_flags & SHF_WRITE)
394213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      && !ebl_check_special_section (ebl, cnt, shdr,
394313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath					     section_name (ebl, cnt)))
394413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    ERROR (gettext ("\
394513b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' is both executable and writable\n"),
394613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		   cnt, section_name (ebl, cnt));
394713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	}
394813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
3949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0)
3950b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3951b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Make sure the section is contained in a loaded segment
3952b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     and that the initialization part matches NOBITS sections.  */
3953bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  unsigned int pcnt;
3954b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Phdr phdr_mem;
3955b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Phdr *phdr;
3956b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3957bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  for (pcnt = 0; pcnt < phnum; ++pcnt)
3958b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL
3959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& ((phdr->p_type == PT_LOAD
3960b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     && (shdr->sh_flags & SHF_TLS) == 0)
3961b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    || (phdr->p_type == PT_TLS
3962b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& (shdr->sh_flags & SHF_TLS) != 0))
3963b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& phdr->p_offset <= shdr->sh_offset
396436aa5987df20c340fdfc584e04f4b3931a89abbdMark Wielaard		&& ((shdr->sh_offset - phdr->p_offset <= phdr->p_filesz
396536aa5987df20c340fdfc584e04f4b3931a89abbdMark Wielaard		     && (shdr->sh_offset - phdr->p_offset < phdr->p_filesz
396636aa5987df20c340fdfc584e04f4b3931a89abbdMark Wielaard			 || shdr->sh_size == 0))
396736aa5987df20c340fdfc584e04f4b3931a89abbdMark Wielaard		    || (shdr->sh_offset - phdr->p_offset < phdr->p_memsz
39689aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath			&& shdr->sh_type == SHT_NOBITS)))
3969b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
3970b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* Found the segment.  */
3971b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (phdr->p_offset + phdr->p_memsz
3972b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    < shdr->sh_offset + shdr->sh_size)
3973b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  ERROR (gettext ("\
3974b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' not fully contained in segment of program header entry %d\n"),
3975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
3976b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3977b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (shdr->sh_type == SHT_NOBITS)
3978b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz
3980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !is_debuginfo)
39810292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard		      {
39820292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			if (!gnuld)
39830292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			  ERROR (gettext ("\
3984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"),
39850292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard				 cnt, section_name (ebl, cnt), pcnt);
39860292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			else
39870292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			  {
39880292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    /* This is truly horrible. GNU ld might put a
39890292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       NOBITS section in the middle of a PT_LOAD
39900292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       segment, assuming the next gap in the file
39910292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       actually consists of zero bits...
39920292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       So it really is like a PROGBITS section
39930292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       where the data is all zeros.  Check those
39940292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			       zero bytes are really there.  */
39950292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    bool bad;
39960292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    Elf_Data *databits;
39970292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    databits = elf_getdata_rawchunk (ebl->elf,
39980292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard							     shdr->sh_offset,
39990292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard							     shdr->sh_size,
40000292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard							     ELF_T_BYTE);
40010292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    bad = (databits == NULL
40020292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard				   || databits->d_size != shdr->sh_size);
40030292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    for (size_t idx = 0;
40040292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard				 idx < databits->d_size && ! bad;
40050292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard				 idx++)
40060292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			      bad = ((char *) databits->d_buf)[idx] != 0;
40070292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard
40080292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			    if (bad)
40090292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			      ERROR (gettext ("\
40100292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark 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"),
40110292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard				     cnt, section_name (ebl, cnt), pcnt);
40120292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard			  }
40130292aefb4c813d41fb1b2dd2d3a3c857a5c6349dMark Wielaard		      }
4014b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
4015b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
4016b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
4017653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    const GElf_Off end = phdr->p_offset + phdr->p_filesz;
4018653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    if (shdr->sh_offset > end ||
4019653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			(shdr->sh_offset == end && shdr->sh_size != 0))
4020b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
4021b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"),
4022b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
4023b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
4024b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
402513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		if (shdr->sh_type != SHT_NOBITS)
402613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		  {
402713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		    if ((shdr->sh_flags & SHF_EXECINSTR) != 0)
402813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      {
402913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			segment_flags[pcnt] |= PF_X;
403013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			if ((phdr->p_flags & PF_X) == 0)
403113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			  ERROR (gettext ("\
403213b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' is executable in nonexecutable segment %d\n"),
403313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath				 cnt, section_name (ebl, cnt), pcnt);
403413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      }
403513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
403613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		    if ((shdr->sh_flags & SHF_WRITE) != 0)
403713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      {
403813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			segment_flags[pcnt] |= PF_W;
403913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			if (0	/* XXX vdso images have this */
404013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			    && (phdr->p_flags & PF_W) == 0)
404113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			  ERROR (gettext ("\
404213b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' is writable in unwritable segment %d\n"),
404313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath				 cnt, section_name (ebl, cnt), pcnt);
404413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      }
404513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		  }
404613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
4047b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		break;
4048b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
4049b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4050bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  if (pcnt == phnum)
4051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
4052b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': alloc flag set but section not in any loaded segment\n"),
4053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, section_name (ebl, cnt));
4054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB)
4057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
4058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"),
4059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
4060b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      switch (shdr->sh_type)
4062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNSYM:
4064acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  if (ehdr->e_type == ET_REL)
4065acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    ERROR (gettext ("\
4066acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"),
4067acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper		   cnt, section_name (ebl, cnt));
4068acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  /* FALLTHROUGH */
4069acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_SYMTAB:
4070dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  check_symtab (ebl, ehdr, shdr, cnt);
4071b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4072b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4073b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_RELA:
4074c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  check_rela (ebl, ehdr, shdr, cnt);
4075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4077b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_REL:
4078c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  check_rel (ebl, ehdr, shdr, cnt);
4079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4080b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4081b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNAMIC:
4082607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  check_dynamic (ebl, ehdr, shdr, cnt);
4083b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4084b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4085b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_SYMTAB_SHNDX:
4086acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  check_symtab_shndx (ebl, ehdr, shdr, cnt);
4087b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_HASH:
40907c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
40917c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  hash_idx = cnt;
40927c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  break;
40937c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
409428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	case SHT_GNU_HASH:
409528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
40967c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  gnu_hash_idx = cnt;
4097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4098b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4099b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_NULL:
4100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  check_null (ebl, shdr, cnt);
4101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_GROUP:
4104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  check_group (ebl, ehdr, shdr, cnt);
4105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
410759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	case SHT_NOTE:
410859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  check_note_section (ebl, ehdr, shdr, cnt);
410959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  break;
411059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
4111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_GNU_versym:
4112dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* We cannot process this section now since we have no guarantee
4113dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     that the verneed and verdef sections have already been read.
4114dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     Just remember the section index.  */
4115dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (versym_scnndx != 0)
4116dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("more than one version symbol table present\n"));
4117dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  versym_scnndx = cnt;
4118b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4120acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_GNU_verneed:
4121bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  check_verneed (ebl, shdr, cnt);
4122acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  break;
4123acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
4124acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_GNU_verdef:
4125acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  check_verdef (ebl, shdr, cnt);
4126acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  break;
4127acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
4128059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	case SHT_GNU_ATTRIBUTES:
4129059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  check_attributes (ebl, ehdr, shdr, cnt);
4130059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  break;
4131059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
4132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	default:
4133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Nothing.  */
4134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
4135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (has_interp_segment && !dot_interp_section)
4139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("INTERP program header entry but no .interp section\n"));
4140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
414113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath  if (!is_debuginfo)
4142bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt)
414313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath      {
414413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	GElf_Phdr phdr_mem;
414513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
414613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	if (phdr != NULL && (phdr->p_type == PT_LOAD || phdr->p_type == PT_TLS))
414713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	  {
414813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    if ((phdr->p_flags & PF_X) != 0
414913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		&& (segment_flags[pcnt] & PF_X) == 0)
415013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      ERROR (gettext ("\
415113b69609bcd5638e6194d940855fea3dd0519605Roland McGrathloadable segment [%u] is executable but contains no executable sections\n"),
415213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		     pcnt);
415313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
415413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    if ((phdr->p_flags & PF_W) != 0
415513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		&& (segment_flags[pcnt] & PF_W) == 0)
415613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      ERROR (gettext ("\
415713b69609bcd5638e6194d940855fea3dd0519605Roland McGrathloadable segment [%u] is writable but contains no writable sections\n"),
415813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		     pcnt);
415913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	  }
416013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath      }
416113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
416213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath  free (segment_flags);
416313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
4164dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (version_namelist != NULL)
4165dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
4166dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (versym_scnndx == 0)
4167dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("\
4168dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperno .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section exist\n"));
4169dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      else
4170dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	check_versym (ebl, versym_scnndx);
4171dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
4172dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Check for duplicate index numbers.  */
4173dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      do
4174dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
4175dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *runp = version_namelist->next;
4176dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  while (runp != NULL)
4177dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
4178dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (version_namelist->ndx == runp->ndx)
4179dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		{
4180dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  ERROR (gettext ("duplicate version index %d\n"),
4181dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 (int) version_namelist->ndx);
4182dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  break;
4183dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		}
4184dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      runp = runp->next;
4185dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
4186dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
4187dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *old = version_namelist;
4188dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  version_namelist = version_namelist->next;
4189dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  free (old);
4190dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
4191dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      while (version_namelist != NULL);
4192dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
4193dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  else if (versym_scnndx != 0)
4194dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("\
4195dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper.gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"));
4196dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
41977c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_idx != 0 && gnu_hash_idx != 0)
41987c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    compare_hash_gnu_hash (ebl, ehdr, hash_idx, gnu_hash_idx);
41997c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
4200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  free (scnref);
4201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
4202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
420459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic GElf_Off
420559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathcheck_note_data (Ebl *ebl, const GElf_Ehdr *ehdr,
420659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		 Elf_Data *data, int shndx, int phndx, GElf_Off start)
4207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
420859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t offset = 0;
420959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t last_offset = 0;
421059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  GElf_Nhdr nhdr;
421159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t name_offset;
421259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t desc_offset;
421359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  while (offset < data->d_size
421459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	 && (offset = gelf_getnote (data, offset,
421559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath				    &nhdr, &name_offset, &desc_offset)) > 0)
4216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
421759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      last_offset = offset;
4218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Make sure it is one of the note types we know about.  */
4220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type == ET_CORE)
422159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	switch (nhdr.n_type)
422259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  {
422359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRSTATUS:
422459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_FPREGSET:
422559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRPSINFO:
422659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_TASKSTRUCT:		/* NT_PRXREG on Solaris.  */
422759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PLATFORM:
422859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_AUXV:
422959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_GWINDOWS:
423059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_ASRS:
423159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PSTATUS:
423259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PSINFO:
423359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRCRED:
423459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_UTSNAME:
423559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_LWPSTATUS:
423659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_LWPSINFO:
423759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRFPXREG:
423859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    /* Known type.  */
423959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    break;
4240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
424159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  default:
424259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    if (shndx == 0)
4243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
424459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathphdr[%d]: unknown core file note type %" PRIu32 " at offset %" PRIu64 "\n"),
424559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     phndx, (uint32_t) nhdr.n_type, start + offset);
424659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    else
424759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	      ERROR (gettext ("\
424859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathsection [%2d] '%s': unknown core file note type %" PRIu32
42492ec957327cdfae6cee592a52958a9c937ea4b13cChih-Hung Hsieh			      " at offset %zu\n"),
425059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     shndx, section_name (ebl, shndx),
425159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     (uint32_t) nhdr.n_type, offset);
425259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  }
4253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
425459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	switch (nhdr.n_type)
4255d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  {
425659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_GNU_ABI_TAG:
4257d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  case NT_GNU_HWCAP:
4258d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  case NT_GNU_BUILD_ID:
4259bc1b92e9aff2595b078b7ffc354e5c2191a2c887Mark Wielaard	  case NT_GNU_GOLD_VERSION:
4260d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	    break;
4261d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath
4262099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath	  case 0:
4263099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath	    /* Linux vDSOs use a type 0 note for the kernel version word.  */
426459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    if (nhdr.n_namesz == sizeof "Linux"
426559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		&& !memcmp (data->d_buf + name_offset, "Linux", sizeof "Linux"))
4266099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath	      break;
4267099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath
4268d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  default:
426959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    if (shndx == 0)
427059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	      ERROR (gettext ("\
42712ec957327cdfae6cee592a52958a9c937ea4b13cChih-Hung Hsiehphdr[%d]: unknown object file note type %" PRIu32 " at offset %zu\n"),
427259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     phndx, (uint32_t) nhdr.n_type, offset);
427359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    else
427459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	      ERROR (gettext ("\
427559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathsection [%2d] '%s': unknown object file note type %" PRIu32
42762ec957327cdfae6cee592a52958a9c937ea4b13cChih-Hung Hsieh			      " at offset %zu\n"),
427759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     shndx, section_name (ebl, shndx),
427859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     (uint32_t) nhdr.n_type, offset);
4279d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  }
4280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
428259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  return last_offset;
428359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath}
428459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
4285978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
428659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic void
428759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathcheck_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt)
428859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath{
428959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
429059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
429159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("\
429259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathphdr[%d]: no note entries defined for the type of file\n"),
429359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   cnt);
429459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
429559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (is_debuginfo)
429659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    /* The p_offset values in a separate debug file are bogus.  */
429759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    return;
429859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
4299b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (phdr->p_filesz == 0)
4300b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    return;
4301b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
430259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  GElf_Off notes_size = 0;
430359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  Elf_Data *data = elf_getdata_rawchunk (ebl->elf,
430459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath					 phdr->p_offset, phdr->p_filesz,
430559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath					 ELF_T_NHDR);
43060a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data != NULL && data->d_buf != NULL)
430759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    notes_size = check_note_data (ebl, ehdr, data, 0, cnt, phdr->p_offset);
430859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
430959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (notes_size == 0)
431059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("phdr[%d]: cannot get content of note section: %s\n"),
431159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   cnt, elf_errmsg (-1));
431259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  else if (notes_size != phdr->p_filesz)
431359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("phdr[%d]: extra %" PRIu64 " bytes after last note\n"),
431459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   cnt, phdr->p_filesz - notes_size);
4315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
4316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4317978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
431859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic void
431959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathcheck_note_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
432059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath{
4321b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (shdr->sh_size == 0)
4322b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    return;
4323b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
432459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
43250a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard  if (data == NULL || data->d_buf == NULL)
432659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    {
432759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
432859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	     idx, section_name (ebl, idx));
432959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      return;
433059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    }
433159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
433259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
433359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
433459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("\
433559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathsection [%2d] '%s': no note entries defined for the type of file\n"),
433659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	     idx, section_name (ebl, idx));
433759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
433859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  GElf_Off notes_size = check_note_data (ebl, ehdr, data, idx, 0, 0);
433959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
434059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (notes_size == 0)
434159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("section [%2d] '%s': cannot get content of note section\n"),
434259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   idx, section_name (ebl, idx));
434359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  else if (notes_size != shdr->sh_size)
434459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("section [%2d] '%s': extra %" PRIu64
434559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		    " bytes after last note\n"),
434659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   idx, section_name (ebl, idx), shdr->sh_size - notes_size);
434759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath}
4348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4349978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4350978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper/* Index of the PT_GNU_EH_FRAME program eader entry.  */
4351978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic int pt_gnu_eh_frame_pndx;
4352978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4353978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
4355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
4356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
4357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_phoff == 0)
4358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
4359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
4361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_CORE)
4362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
4363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperonly executables, shared objects, and core files can have program headers\n"));
4364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_interp = 0;
4366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_tls = 0;
4367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_relro = 0;
4368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4369bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  for (unsigned int cnt = 0; cnt < phnum; ++cnt)
4370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
4371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr phdr_mem;
4372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr *phdr;
4373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
4375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr == NULL)
4376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("cannot get program header entry %d: %s\n"),
4378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, elf_errmsg (-1));
4379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
4380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME
4383f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  && phdr->p_type != PT_GNU_STACK && phdr->p_type != PT_GNU_RELRO
4384f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  /* Check for a known machine-specific type.  */
4385f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  && ebl_segment_type_name (ebl, phdr->p_type, NULL, 0) == NULL)
4386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
4387f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrathprogram header entry %d: unknown program header entry type %#" PRIx64 "\n"),
4388f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	       cnt, (uint64_t) phdr->p_type);
4389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_type == PT_LOAD)
4391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	has_loadable_segment = true;
4392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_INTERP)
4393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_interp != 1)
4395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
4396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (num_pt_interp == 2)
4397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
4398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermore than one INTERP entry in program header\n"));
4399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
4400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  has_interp_segment = true;
4401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_TLS)
4403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_tls == 2)
4405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("more than one TLS entry in program header\n"));
4406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_NOTE)
4408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	check_note (ebl, ehdr, phdr, cnt);
440941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      else if (phdr->p_type == PT_DYNAMIC)
441041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
441141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  if (ehdr->e_type == ET_EXEC && ! has_interp_segment)
441241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    ERROR (gettext ("\
441341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic executable cannot have dynamic sections\n"));
441441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  else
441541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    {
441641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      /* Check that the .dynamic section, if it exists, has
441741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 the same address.  */
441841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      Elf_Scn *scn = NULL;
441941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
442041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		{
442141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr shdr_mem;
442241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
442341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
442441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    {
442541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      if (phdr->p_offset != shdr->sh_offset)
442641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			ERROR (gettext ("\
442741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperdynamic section reference in program header has wrong offset\n"));
442841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      if (phdr->p_memsz != shdr->sh_size)
442941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			ERROR (gettext ("\
443041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperdynamic section size mismatch in program and section header\n"));
443141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      break;
443241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    }
443341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		}
443441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    }
443541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
4436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_GNU_RELRO)
4437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_relro == 2)
4439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
4440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermore than one GNU_RELRO entry in program header\n"));
4441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
4442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
4443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Check that the region is in a writable segment.  */
4444bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	      unsigned int inner;
4445bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	      for (inner = 0; inner < phnum; ++inner)
4446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
4447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Phdr phdr2_mem;
4448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Phdr *phdr2;
4449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
4451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (phdr2 == NULL)
4452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    continue;
4453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (phdr2->p_type == PT_LOAD
4455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && phdr->p_vaddr >= phdr2->p_vaddr
4456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && (phdr->p_vaddr + phdr->p_memsz
4457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  <= phdr2->p_vaddr + phdr2->p_memsz))
4458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
4459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if ((phdr2->p_flags & PF_W) == 0)
4460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
4461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperloadable segment GNU_RELRO applies to is not writable\n"));
44623a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		      if ((phdr2->p_flags & ~PF_W) != (phdr->p_flags & ~PF_W))
4463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
4464d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrathloadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"),
4465d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrath			       cnt, inner);
4466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      break;
4467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
4468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
4469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4470bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	      if (inner >= phnum)
4471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
4472607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper%s segment not contained in a loaded segment\n"), "GNU_RELRO");
4473607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
4474607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	}
4475607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      else if (phdr->p_type == PT_PHDR)
4476607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	{
4477607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* Check that the region is in a writable segment.  */
4478bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  unsigned int inner;
4479bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  for (inner = 0; inner < phnum; ++inner)
4480607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
4481607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr phdr2_mem;
4482607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr *phdr2;
4483607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
4484607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
4485607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      if (phdr2 != NULL
4486607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr2->p_type == PT_LOAD
4487607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr >= phdr2->p_vaddr
4488607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && (phdr->p_vaddr + phdr->p_memsz
4489607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		      <= phdr2->p_vaddr + phdr2->p_memsz))
4490607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		break;
4491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
4492607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
4493bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	  if (inner >= phnum)
4494607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    ERROR (gettext ("\
4495607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper%s segment not contained in a loaded segment\n"), "PHDR");
4496607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
4497607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* Check that offset in segment corresponds to offset in ELF
4498607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	     header.  */
4499607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (phdr->p_offset != ehdr->e_phoff)
4500607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    ERROR (gettext ("\
4501607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepperprogram header offset in ELF header and PHDR entry do not match"));
4502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
45033a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper      else if (phdr->p_type == PT_GNU_EH_FRAME)
45043a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	{
45053a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	  /* If there is an .eh_frame_hdr section it must be
45063a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	     referenced by this program header entry.  */
45073a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	  Elf_Scn *scn = NULL;
4508935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper	  GElf_Shdr shdr_mem;
4509935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper	  GElf_Shdr *shdr = NULL;
4510f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	  bool any = false;
45113a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
45123a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	    {
4513f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      any = true;
4514935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper	      shdr = gelf_getshdr (scn, &shdr_mem);
4515f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if (shdr != NULL
4516f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		  && shdr->sh_type == (is_debuginfo
4517f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper				       ? SHT_NOBITS : SHT_PROGBITS)
45180a545e678f2c0605ba050b4f72080572ac7c8470Mark Wielaard		  && elf_strptr (ebl->elf, shstrndx, shdr->sh_name) != NULL
45193a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		  && ! strcmp (".eh_frame_hdr",
45203a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper			       elf_strptr (ebl->elf, shstrndx, shdr->sh_name)))
45213a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		{
4522f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		  if (! is_debuginfo)
4523f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		    {
4524f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		      if (phdr->p_offset != shdr->sh_offset)
4525f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper			ERROR (gettext ("\
45263a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table reference in program header has wrong offset\n"));
4527f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		      if (phdr->p_memsz != shdr->sh_size)
4528f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper			ERROR (gettext ("\
45293a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table size mismatch in program and section header\n"));
4530f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		    }
45313a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		  break;
45323a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		}
45333a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	    }
45343a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper
4535f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	  if (scn == NULL)
4536f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    {
4537f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      /* If there is no section header table we don't
4538f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		 complain.  But if there is one there should be an
4539f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		 entry for .eh_frame_hdr.  */
4540f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if (any)
4541f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4542f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich DrepperPT_GNU_EH_FRAME present but no .eh_frame_hdr section\n"));
4543f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    }
4544f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	  else
4545f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    {
4546f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      /* The section must be allocated and not be writable and
4547f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		 executable.  */
4548f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if ((phdr->p_flags & PF_R) == 0)
4549f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
45503a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table must be allocated\n"));
4551f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      else if (shdr != NULL && (shdr->sh_flags & SHF_ALLOC) == 0)
4552f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4553935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppersection [%2zu] '%s' must be allocated\n"), elf_ndxscn (scn), ".eh_frame_hdr");
4554935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper
4555f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if ((phdr->p_flags & PF_W) != 0)
4556f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
45573a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table must not be writable\n"));
4558f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      else if (shdr != NULL && (shdr->sh_flags & SHF_WRITE) != 0)
4559f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4560935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppersection [%2zu] '%s' must not be writable\n"),
4561f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		       elf_ndxscn (scn), ".eh_frame_hdr");
4562935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper
4563f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if ((phdr->p_flags & PF_X) != 0)
4564f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
45653a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table must not be executable\n"));
4566f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      else if (shdr != NULL && (shdr->sh_flags & SHF_EXECINSTR) != 0)
4567f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4568935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppersection [%2zu] '%s' must not be executable\n"),
4569f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		       elf_ndxscn (scn), ".eh_frame_hdr");
4570f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    }
4571978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4572978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  /* Remember which entry this is.  */
4573978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  pt_gnu_eh_frame_pndx = cnt;
45743a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	}
4575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
45768190db6a86a37aec86c81626ab1b083c96aff891Roland McGrath      if (phdr->p_filesz > phdr->p_memsz
457756bc0b83ea81b7e959aaa4e1d01f8b36f2804a52Ulrich Drepper	  && (phdr->p_memsz != 0 || phdr->p_type != PT_NOTE))
4578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
4579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: file size greater than memory size\n"),
4580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt);
4581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_align > 1)
4583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (!powerof2 (phdr->p_align))
4585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
4586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: alignment not a power of 2\n"), cnt);
4587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0)
4588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
4589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: file offset and virtual address not module of alignment\n"), cnt);
4590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
4593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4595978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic void
4596935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppercheck_exception_data (Ebl *ebl __attribute__ ((unused)),
4597935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper		      GElf_Ehdr *ehdr __attribute__ ((unused)))
4598978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper{
4599daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper  if ((ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
4600daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper      && pt_gnu_eh_frame_pndx == 0 && eh_frame_hdr_scnndx != 0)
4601daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper    ERROR (gettext ("executable/DSO with .eh_frame_hdr section does not have "
4602daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper		    "a PT_GNU_EH_FRAME program header entry"));
4603978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper}
4604978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4605978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Process one file.  */
4607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
4608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprocess_elf_file (Elf *elf, const char *prefix, const char *suffix,
4609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  const char *fname, size_t size, bool only_one)
4610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
4611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Reset variables.  */
4612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ndynamic = 0;
4613acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  nverneed = 0;
4614acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  nverdef = 0;
461541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  textrel = false;
461641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  needed_textrel = false;
4617acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  has_loadable_segment = false;
4618acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  has_interp_segment = false;
4619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr ehdr_mem;
4621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
4622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Ebl *ebl;
4623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Print the file name.  */
4625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (!only_one)
4626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
4627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (prefix != NULL)
4628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	printf ("\n%s(%s)%s:\n", prefix, fname, suffix);
4629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
4630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	printf ("\n%s:\n", fname);
4631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr == NULL)
4634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
4635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("cannot read ELF header: %s\n"), elf_errmsg (-1));
4636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
4637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl = ebl_openbackend (elf);
4640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If there is no appropriate backend library we cannot test
4641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     architecture and OS specific features.  Any encountered extension
4642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     is an error.  */
4643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Go straight by the gABI, check all the parts in turn.  */
4645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_elf_header (ebl, ehdr, size);
4646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the program header.  */
4648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_program_header (ebl, ehdr);
4649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Next the section headers.  It is OK if there are no section
4651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     headers at all.  */
4652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_sections (ebl, ehdr);
4653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4654978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper  /* Check the exception handling data, if it exists.  */
4655978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper  if (pt_gnu_eh_frame_pndx != 0 || eh_frame_hdr_scnndx != 0
4656978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper      || eh_frame_scnndx != 0 || gcc_except_table_scnndx != 0)
4657978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper    check_exception_data (ebl, ehdr);
4658978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
465941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* Report if no relocation section needed the text relocation flag.  */
466041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (textrel && !needed_textrel)
466141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    ERROR (gettext ("text relocation flag set but not needed\n"));
466241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
4663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Free the resources.  */
4664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl_closebackend (ebl);
4665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
46663cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
46673cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
46683cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper#include "debugpred.h"
4669