elflint.c revision 8ae5814209558f51c93b583c9ae6fdd482f0cbb2
1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Pedantic checking of ELF files compliance with gABI/psABI spec.
282c345d92531e2577f16928efe62c14d19d5fc47Ulrich Drepper   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
3361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   This file is part of Red Hat elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Red Hat elfutils is free software; you can redistribute it and/or modify
7361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   it under the terms of the GNU General Public License as published by the
8361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Free Software Foundation; version 2 of the License.
9b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
10361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Red Hat elfutils is distributed in the hope that it will be useful, but
11361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
12361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   General Public License for more details.
14361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
15361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   You should have received a copy of the GNU General Public License along
16361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   with Red Hat elfutils; if not, write to the Free Software Foundation,
171e9ef50681e20ef14c2ba38aef37a71ff148be08Ulrich Drepper   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
19361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Red Hat elfutils is an included package of the Open Invention Network.
20361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   An included package of the Open Invention Network is a package for which
21361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Open Invention Network licensees cross-license their patents.  No patent
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   license is granted, either expressly or impliedly, by designation as an
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   included package.  Should you wish to participate in the Open Invention
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Network licensing program, please visit www.openinventionnetwork.com
25361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   <http://www.openinventionnetwork.com>.  */
26b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
27b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#ifdef HAVE_CONFIG_H
28b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper# include <config.h>
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <argp.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <assert.h>
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <byteswap.h>
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <endian.h>
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <error.h>
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <fcntl.h>
37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <gelf.h>
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <inttypes.h>
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libintl.h>
40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <locale.h>
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdbool.h>
42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdlib.h>
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <string.h>
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <unistd.h>
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/param.h>
46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <elf-knowledge.h>
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <system.h>
49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "../libebl/libeblP.h"
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
52b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Name and version of program.  */
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void print_version (FILE *stream, struct argp_state *state);
54b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppervoid (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Bug report address.  */
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperconst char *argp_program_bug_address = PACKAGE_BUGREPORT;
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ARGP_strict	300
60b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ARGP_gnuld	301
61b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Definitions of arguments for argp functions.  */
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const struct argp_option options[] =
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "strict", ARGP_strict, NULL, 0,
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Be extremely strict, flag level 2 features."), 0 },
68b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "quiet", 'q', NULL, 0, N_("Do not print anything if successful"), 0 },
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "debuginfo", 'd', NULL, 0, N_("Binary is a separate debuginfo file"), 0 },
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "gnu-ld", ARGP_gnuld, NULL, 0,
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Binary has been created with GNU ld and is therefore known to be \
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperbroken in certain ways"), 0 },
73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, NULL, 0 }
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
75b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Short description of program.  */
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char doc[] = N_("\
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperPedantic checking of ELF files compliance with gABI/psABI spec.");
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Strings for arguments in help texts.  */
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char args_doc[] = N_("FILE...");
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Prototype for option handler.  */
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Data structure to communicate with argp functions.  */
87b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic struct argp argp =
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  options, parse_opt, args_doc, doc, NULL, NULL, NULL
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Declarations of local functions.  */
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void process_file (int fd, Elf *elf, const char *prefix,
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  const char *suffix, const char *fname, size_t size,
96b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  bool only_one);
97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void process_elf_file (Elf *elf, const char *prefix, const char *suffix,
98b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      const char *fname, size_t size, bool only_one);
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
126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermain (int argc, char *argv[])
129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Set locale.  */
131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  setlocale (LC_ALL, "");
132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Initialize the message catalog.  */
134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  textdomain (PACKAGE);
135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Parse and process arguments.  */
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int remaining;
138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Before we start tell the ELF library which version we are using.  */
141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_version (EV_CURRENT);
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now process all the files given at the command line.  */
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool only_one = remaining + 1 == argc;
145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  do
146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Open the file.  */
148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      int fd = open (argv[remaining], O_RDONLY);
149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (fd == -1)
150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("cannot open input file"));
152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Create an `Elf' descriptor.  */
156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf == NULL)
158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("cannot generate Elf descriptor: %s\n"),
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       elf_errmsg (-1));
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  unsigned int prev_error_count = error_count;
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  struct stat64 st;
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (fstat64 (fd, &st) != 0)
166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      printf ("cannot stat '%s': %m\n", argv[remaining]);
168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      close (fd);
169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  process_file (fd, elf, NULL, NULL, argv[remaining], st.st_size,
173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			only_one);
174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Now we can close the descriptor.  */
176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (elf_end (elf) != 0)
177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("error while closing Elf descriptor: %s\n"),
178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   elf_errmsg (-1));
179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (prev_error_count == error_count && !be_quiet)
181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    puts (gettext ("No errors"));
182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      close (fd);
185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (++remaining < argc);
187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return error_count != 0;
189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle program arguments.  */
193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t
194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperparse_opt (int key, char *arg __attribute__ ((unused)),
195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   struct argp_state *state __attribute__ ((unused)))
196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (key)
198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ARGP_strict:
200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      be_strict = true;
201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'q':
204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      be_quiet = true;
205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'd':
208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      is_debuginfo = true;
209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ARGP_gnuld:
211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      gnuld = true;
212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ARGP_KEY_NO_ARGS:
215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      fputs (gettext ("Missing file name.\n"), stderr);
216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 program_invocation_short_name);
218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      exit (1);
219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ARGP_ERR_UNKNOWN;
222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print the version information.  */
228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, "elflint (%s) %s\n", PACKAGE_NAME, VERSION);
232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("\
233b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperCopyright (C) %s Red Hat, Inc.\n\
234b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperThis is free software; see the source for copying conditions.  There is NO\n\
235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
23682c345d92531e2577f16928efe62c14d19d5fc47Ulrich Drepper"), "2006");
237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Process one file.  */
242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprocess_file (int fd, Elf *elf, const char *prefix, const char *suffix,
244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      const char *fname, size_t size, bool only_one)
245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We can handle two types of files: ELF files and archives.  */
247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Kind kind = elf_kind (elf);
248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (kind)
250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_ELF:
252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Yes!  It's an ELF file.  */
253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      process_elf_file (elf, prefix, suffix, fname, size, only_one);
254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_AR:
257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf *subelf;
259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf_Cmd cmd = ELF_C_READ_MMAP;
260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size_t fname_len = strlen (fname) + 1;
262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char new_prefix[prefix_len + 1 + fname_len];
263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char new_suffix[(suffix == NULL ? 0 : strlen (suffix)) + 2];
264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char *cp = new_prefix;
265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Create the full name of the file.  */
267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (prefix != NULL)
268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    cp = mempcpy (cp, prefix, prefix_len);
270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    *cp++ = '(';
271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    strcpy (stpcpy (new_suffix, suffix), ")");
272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	else
274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  new_suffix[0] = '\0';
275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	memcpy (cp, fname, fname_len);
276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* It's an archive.  We process each file in it.  */
278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    kind = elf_kind (subelf);
281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Call this function recursively.  */
283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (kind == ELF_K_ELF || kind == ELF_K_AR)
284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		Elf_Arhdr *arhdr = elf_getarhdr (subelf);
286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		assert (arhdr != NULL);
287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		process_file (fd, subelf, new_prefix, new_suffix,
289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      arhdr->ar_name, arhdr->ar_size, false);
290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
291b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
292b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Get next archive element.  */
293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    cmd = elf_next (subelf);
294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (elf_end (subelf) != 0)
295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext (" error while freeing sub-ELF descriptor: %s\n"),
296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     elf_errmsg (-1));
297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
298b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We cannot do anything.  */
303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
30441de488a0ad6679e816dbab960351e5f62ab8eadUlrich DrepperNot an ELF file - it has the wrong magic bytes at the start\n"));
305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
307b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
308b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *
311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection_name (Ebl *ebl, int idx)
312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr shdr_mem;
314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *shdr;
315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr = gelf_getshdr (elf_getscn (ebl->elf, idx), &shdr_mem);
317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const int valid_e_machine[] =
323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_M32, EM_SPARC, EM_386, EM_68K, EM_88K, EM_860, EM_MIPS, EM_S370,
325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_MIPS_RS3_LE, EM_PARISC, EM_VPP500, EM_SPARC32PLUS, EM_960, EM_PPC,
326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_PPC64, EM_S390, EM_V800, EM_FR20, EM_RH32, EM_RCE, EM_ARM,
327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_FAKE_ALPHA, EM_SH, EM_SPARCV9, EM_TRICORE, EM_ARC, EM_H8_300,
328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_H8_300H, EM_H8S, EM_H8_500, EM_IA_64, EM_MIPS_X, EM_COLDFIRE,
329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_68HC12, EM_MMA, EM_PCP, EM_NCPU, EM_NDR1, EM_STARCORE, EM_ME16,
330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_ST100, EM_TINYJ, EM_X86_64, EM_PDSP, EM_FX66, EM_ST9PLUS, EM_ST7,
331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX,
332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM,
333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300,
334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  };
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define nvalid_e_machine \
337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (sizeof (valid_e_machine) / sizeof (valid_e_machine[0]))
338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Number of sections.  */
341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic unsigned int shnum;
342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size)
346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char buf[512];
348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cnt;
349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check e_ident field.  */
351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG0] != ELFMAG0)
352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG0, ELFMAG0);
353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG1] != ELFMAG1)
354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG1, ELFMAG1);
355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG2] != ELFMAG2)
356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG2, ELFMAG2);
357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG3] != ELFMAG3)
358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG3, ELFMAG3);
359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_CLASS] != ELFCLASS32
361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_ident[EI_CLASS] != ELFCLASS64)
362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("e_ident[%d] == %d is no known class\n"),
363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_CLASS, ehdr->e_ident[EI_CLASS]);
364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB
366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("e_ident[%d] == %d is no known data encoding\n"),
368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_DATA, ehdr->e_ident[EI_DATA]);
369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_VERSION] != EV_CURRENT)
371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown ELF header version number e_ident[%d] == %d\n"),
372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_VERSION, ehdr->e_ident[EI_VERSION]);
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We currently don't handle any OS ABIs.  */
375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE)
376e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper    ERROR (gettext ("unsupported OS ABI e_ident[%d] == '%s'\n"),
377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_OSABI,
378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* No ABI versions other than zero supported either.  */
381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_ABIVERSION] != 0)
382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unsupport ABI version e_ident[%d] == %d\n"),
383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_ABIVERSION, ehdr->e_ident[EI_ABIVERSION]);
384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = EI_PAD; cnt < EI_NIDENT; ++cnt)
386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (ehdr->e_ident[cnt] != 0)
387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("e_ident[%zu] is not zero\n"), cnt);
388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_type field.  */
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_REL && ehdr->e_type != ET_EXEC
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_DYN && ehdr->e_type != ET_CORE)
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown object file type %d\n"), ehdr->e_type);
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_machine field.  */
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 0; cnt < nvalid_e_machine; ++cnt)
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (valid_e_machine[cnt] == ehdr->e_machine)
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (cnt == nvalid_e_machine)
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown machine type %d\n"), ehdr->e_machine);
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_version field.  */
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_version != EV_CURRENT)
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown object file version\n"));
404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_phoff and e_phnum fields.  */
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_phoff == 0)
407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phnum != 0)
409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header offset\n"));
410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperexecutables and DSOs cannot have zero program header offset\n"));
413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else if (ehdr->e_phnum == 0)
415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("invalid number of program header entries\n"));
416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_shoff field.  */
418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shnum = ehdr->e_shnum;
419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shstrndx = ehdr->e_shstrndx;
420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_shoff == 0)
421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shnum != 0)
423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header table offset\n"));
424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       && ehdr->e_type != ET_CORE)
426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section header table must be present\n"));
427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shnum == 0)
431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Get the header of the zeroth section.  The sh_size field
433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     might contain the section number.  */
434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
435acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr != NULL)
437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* The error will be reported later.  */
439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (shdr->sh_size == 0)
440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperinvalid number of section header table entries\n"));
442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		shnum = shdr->sh_size;
444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shstrndx == SHN_XINDEX)
448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Get the header of the zeroth section.  The sh_size field
450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     might contain the section number.  */
451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
452acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
453acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  if (shdr != NULL && shdr->sh_link < shnum)
454acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    shstrndx = shdr->sh_link;
455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (shstrndx >= shnum)
457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header index\n"));
458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_flags field.  */
461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (!ebl_machine_flag_check (ebl, ehdr->e_flags))
462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("invalid machine flags: %s\n"),
463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check e_ehsize, e_phentsize, and e_shentsize fields.  */
466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (gelf_getclass (ebl->elf) == ELFCLASS32)
467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf32_Ehdr))
469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr))
472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header size: %hd\n"),
473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_phentsize);
474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header position or size\n"));
476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr))
478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header size: %hd\n"),
479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_shentsize);
480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header position or size\n"));
482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else if (gelf_getclass (ebl->elf) == ELFCLASS64)
484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf64_Ehdr))
486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr))
489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header size: %hd\n"),
490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_phentsize);
491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header position or size\n"));
493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr))
495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header size: %hd\n"),
496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_shentsize);
497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header position or size\n"));
499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Check that there is a section group section with index < IDX which
504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   contains section IDX and that there is exactly one.  */
505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_scn_group (Ebl *ebl, int idx)
507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (scnref[idx] == 0)
509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* No reference so far.  Search following sections, maybe the
511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 order is wrong.  */
512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t cnt;
513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = idx + 1; cnt < shnum; ++cnt)
515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
516acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
518acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr == NULL)
520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* We cannot get the section header so we cannot check it.
521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       The error to get the section header will be shown
522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       somewhere else.  */
523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr->sh_type != SHT_GROUP)
526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
528acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf_Data *data = elf_getdata (scn, NULL);
529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (data == NULL || data->d_size < sizeof (Elf32_Word))
530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Cannot check the section.  */
531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
533acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf32_Word *grpdata = (Elf32_Word *) data->d_buf;
534acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  for (size_t inner = 1; inner < data->d_size / sizeof (Elf32_Word);
535acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	       ++inner)
536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (grpdata[inner] == (Elf32_Word) idx)
537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      goto out;
538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    out:
541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (cnt == shnum)
542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section with SHF_GROUP flag set not part of a section group\n"),
544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group [%2zu] '%s' does not preceed group member\n"),
548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx),
549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
555dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_symtab (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool no_xndx_warned = false;
558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int no_pt_tls = 0;
559dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
567dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr strshdr_mem;
568dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
569dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper				     &strshdr_mem);
570dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (strshdr == NULL)
571dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
572dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   shdr->sh_link, section_name (ebl, shdr->sh_link),
576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Search for an extended section index table section.  */
579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cnt;
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *xndxdata = NULL;
581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf32_Word xndxscnidx = 0;
582acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  bool found_xndx = false;
583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 1; cnt < shnum; ++cnt)
584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (cnt != (size_t) idx)
585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf_Scn *xndxscn = elf_getscn (ebl->elf, cnt);
587acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	GElf_Shdr xndxshdr_mem;
588acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
589acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	if (xndxshdr == NULL)
590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    && xndxshdr->sh_link == (GElf_Word) idx)
594acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  {
595acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    if (found_xndx)
596acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	      ERROR (gettext ("\
597acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': symbol table cannot have more than one extended index section\n"),
598acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper		     idx, section_name (ebl, idx));
599acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
600acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    xndxdata = elf_getdata (xndxscn, NULL);
601acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    xndxscnidx = elf_ndxscn (xndxscn);
602acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    found_xndx = true;
603acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  }
604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT))
607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': entry size is does not match ElfXX_Sym\n"),
609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   cnt, section_name (ebl, cnt));
610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Test the zeroth entry.  */
612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Sym sym_mem;
613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf32_Word xndx;
614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, 0, &sym_mem, &xndx);
615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (sym == NULL)
616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get symbol %d: %s\n"),
617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx), 0, elf_errmsg (-1));
618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_name != 0)
621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_name");
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_value != 0)
624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_value");
626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_size != 0)
627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_size");
629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_info != 0)
630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_info");
632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_other != 0)
633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_other");
635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_shndx != 0)
636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_shndx");
638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndxdata != NULL && xndx != 0)
639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': XINDEX for zeroth entry not zero\n"),
641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       xndxscnidx, section_name (ebl, xndxscnidx));
642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 1; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx);
647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym == NULL)
648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("section [%2d] '%s': cannot get symbol %zu: %s\n"),
650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *name = NULL;
655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_name >= strshdr->sh_size)
656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: invalid name value\n"),
658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name);
662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  assert (name != NULL);
663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_shndx == SHN_XINDEX)
666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (xndxdata == NULL)
668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: too large section index but no extended section index section\n"),
671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt);
672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      no_xndx_warned = true;
673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (xndx < SHN_LORESERVE)
675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: XINDEX used for index which would fit in st_shndx (%" PRIu32 ")\n"),
677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   xndxscnidx, section_name (ebl, xndxscnidx), cnt,
678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   xndx);
679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if ((sym->st_shndx >= SHN_LORESERVE
681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		// && sym->st_shndx <= SHN_HIRESERVE    always true
682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& sym->st_shndx != SHN_ABS
683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& sym->st_shndx != SHN_COMMON)
684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       || (sym->st_shndx >= shnum
685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   && (sym->st_shndx < SHN_LORESERVE
686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       /* || sym->st_shndx > SHN_HIRESERVE  always false */)))
687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: invalid section index\n"),
689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	xndx = sym->st_shndx;
692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
69318e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath      if (GELF_ST_TYPE (sym->st_info) >= STT_NUM
69418e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && !ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), NULL, 0))
695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': symbol %zu: unknown type\n"),
696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_BIND (sym->st_info) >= STB_NUM)
699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: unknown symbol binding\n"),
701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndx == SHN_COMMON)
704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Common symbols can only appear in relocatable files.  */
706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (ehdr->e_type != ET_REL)
707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n"),
709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt < shdr->sh_info)
711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n"),
713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (GELF_R_TYPE (sym->st_info) == STT_FUNC)
715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"),
717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (xndx > 0 && xndx < shnum)
720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr destshdr_mem;
722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr *destshdr;
723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), &destshdr_mem);
725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (destshdr != NULL)
726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (GELF_ST_TYPE (sym->st_info) != STT_TLS)
728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
729c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  if (! ebl_check_special_symbol (ebl, ehdr, sym, name,
730c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper						  destshdr))
731c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    {
732c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		      if ((sym->st_value - destshdr->sh_addr)
733c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  > destshdr->sh_size)
734c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds\n"),
736c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx), cnt);
737c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		      else if ((sym->st_value - destshdr->sh_addr
738c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper				+ sym->st_size) > destshdr->sh_size)
739c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
741c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx), cnt,
742c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (int) xndx, section_name (ebl, xndx));
743c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    }
744b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if ((destshdr->sh_flags & SHF_TLS) == 0)
748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_TLS flag set\n"),
750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx), cnt,
751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   (int) xndx, section_name (ebl, xndx));
752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (ehdr->e_type == ET_REL)
754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      /* For object files the symbol value must fall
756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper                         into the section.  */
757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (sym->st_value > destshdr->sh_size)
758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       idx, section_name (ebl, idx), cnt,
761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       (int) xndx, section_name (ebl, xndx));
762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      else if (sym->st_value + sym->st_size
763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       > destshdr->sh_size)
764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       idx, section_name (ebl, idx), cnt,
767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       (int) xndx, section_name (ebl, xndx));
768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  else
770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Phdr phdr_mem;
772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Phdr *phdr = NULL;
773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      int pcnt;
774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (phdr != NULL && phdr->p_type == PT_TLS)
779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    break;
780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (pcnt == ehdr->e_phnum)
783b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
784b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (no_pt_tls++ == 0)
785b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
786b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"),
787b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt);
788b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
789b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      else
790b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
791b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (sym->st_value
792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      < destshdr->sh_offset - phdr->p_offset)
793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"),
795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  else if (sym->st_value
798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   > (destshdr->sh_offset - phdr->p_offset
799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				      + destshdr->sh_size))
800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
802b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  else if (sym->st_value + sym->st_size
805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   > (destshdr->sh_offset - phdr->p_offset
806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				      + destshdr->sh_size))
807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
814b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
815b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
816b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
817b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt >= shdr->sh_info)
820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: local symbol outside range described in sh_info\n"),
822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt < shdr->sh_info)
827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: non-local symbol outside range described in sh_info\n"),
829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
834b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: non-local section symbol\n"),
836b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
837b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (name != NULL)
839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
840b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
842653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      /* Check that address and size match the global offset table.  */
843653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
844653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      GElf_Shdr destshdr_mem;
845653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx),
846653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						  &destshdr_mem);
847653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
848653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (destshdr == NULL && xndx == SHN_ABS)
849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
850653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  /* In a DSO, we have to find the GOT section by name.  */
851653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  Elf_Scn *gotscn = NULL;
852c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  Elf_Scn *gscn = NULL;
853653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL)
854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
855653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      destshdr = gelf_getshdr (gscn, &destshdr_mem);
856653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      assert (destshdr != NULL);
857653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      const char *sname = elf_strptr (ebl->elf,
858653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						      ehdr->e_shstrndx,
859653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						      destshdr->sh_name);
860653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      if (sname != NULL)
861b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
862c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  if (strcmp (sname, ".got.plt") == 0)
863653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    break;
864c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  if (strcmp (sname, ".got") == 0)
865653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    /* Do not stop looking.
866653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			       There might be a .got.plt section.  */
867653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    gotscn = gscn;
868b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
869653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
870653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      destshdr = NULL;
871b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
872653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
873653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  if (destshdr == NULL && gotscn != NULL)
874653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    destshdr = gelf_getshdr (gotscn, &destshdr_mem);
875b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
876b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
877653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      const char *sname = (destshdr == NULL ? NULL
878653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath				   : elf_strptr (ebl->elf, ehdr->e_shstrndx,
879653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						 destshdr->sh_name));
880653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (sname == NULL)
881653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		ERROR (gettext ("\
882653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section\n"),
883653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		       idx, section_name (ebl, idx));
884653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      else if (strcmp (sname, ".got.plt") != 0
885653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		       && strcmp (sname, ".got") != 0)
886653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		ERROR (gettext ("\
887653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to '%s' section\n"),
888653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		       idx, section_name (ebl, idx), sname);
889653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
890653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (destshdr != NULL)
891b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
892b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Found it.  */
893c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  if (!ebl_check_special_symbol (ebl, ehdr, sym, name,
894c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper						 destshdr))
895c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    {
896c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		      if (sym->st_value != destshdr->sh_addr)
897c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			/* This test is more strict than the psABIs which
898c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			   usually allow the symbol to be in the middle of
899c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			   the .got section, allowing negative offsets.  */
900c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
901653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match %s section address %#" PRIx64 "\n"),
902c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx),
903c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (uint64_t) sym->st_value,
904c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       sname, (uint64_t) destshdr->sh_addr);
905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
906c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		      if (!gnuld && sym->st_size != destshdr->sh_size)
907c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
908653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match %s section size %" PRIu64 "\n"),
909c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx),
910c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (uint64_t) sym->st_size,
911c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       sname, (uint64_t) destshdr->sh_size);
912c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    }
913b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
914b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
915b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
916b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"),
917b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx));
918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (strcmp (name, "_DYNAMIC") == 0)
92041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    /* Check that address and size match the dynamic section.
92141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	       We locate the dynamic section via the program header
92241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	       entry.  */
92341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    for (int pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
92441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      {
92541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Phdr phdr_mem;
92641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
927b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
92841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
92941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  {
93041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    if (sym->st_value != phdr->p_vaddr)
93141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      ERROR (gettext ("\
932b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"),
93341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     idx, section_name (ebl, idx),
93441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) sym->st_value,
93541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) phdr->p_vaddr);
936b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
93741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    if (!gnuld && sym->st_size != phdr->p_memsz)
93841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      ERROR (gettext ("\
939b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"),
94041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     idx, section_name (ebl, idx),
94141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) sym->st_size,
94241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) phdr->p_memsz);
943b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
94441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    break;
94541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  }
946b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
947b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
948b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
950b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
951b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
952b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool
953c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperis_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr,
95428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    bool is_rela)
955b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
956b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If this is no executable or DSO it cannot be a .rel.dyn section.  */
957b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
958b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return false;
959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
960b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the section name.  Unfortunately necessary.  */
96128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (strcmp (section_name (ebl, idx), is_rela ? ".rela.dyn" : ".rel.dyn"))
962b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return false;
963b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
964b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section
965b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     entry can be present as well.  */
966b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn = NULL;
967b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
968b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
969b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr rcshdr_mem;
970b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem);
971b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      assert (rcshdr != NULL);
972b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
973b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rcshdr->sh_type == SHT_DYNAMIC)
974b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Found the dynamic section.  Look through it.  */
976b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  Elf_Data *d = elf_getdata (scn, NULL);
977b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t cnt;
978b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt)
980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Dyn dyn_mem;
982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem);
983b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      assert (dyn != NULL);
984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
985b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (dyn->d_tag == DT_RELCOUNT)
986b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
98728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  /* Found it.  Does the type match.  */
98828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if (is_rela)
989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
99028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELCOUNT used for this RELA section\n"),
99128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx));
99228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  else
99328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    {
99428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Does the number specified number of relative
99528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations exceed the total number of
99628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations?  */
99728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
99828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			ERROR (gettext ("\
999b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
100028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       idx, section_name (ebl, idx),
100128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       (int) dyn->d_un.d_val);
100228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
100328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Make sure the specified number of relocations are
100428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relative.  */
100528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
100628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper								   idx), NULL);
100728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (reldata != NULL)
100828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			for (size_t inner = 0;
100928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     inner < shdr->sh_size / shdr->sh_entsize;
101028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     ++inner)
101128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  {
101228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rel rel_mem;
101328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rel *rel = gelf_getrel (reldata, inner,
101428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							 &rel_mem);
101528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (rel == NULL)
101628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      /* The problem will be reported elsewhere.  */
101728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      break;
101828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
101928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (ebl_relative_reloc_p (ebl,
102028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						      GELF_R_TYPE (rel->r_info)))
102128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      {
102228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				if (inner >= dyn->d_un.d_val)
102328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				  ERROR (gettext ("\
102428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
102528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 idx, section_name (ebl, idx),
102628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 (int) dyn->d_un.d_val);
102728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      }
102828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    else if (inner < dyn->d_un.d_val)
102928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      ERROR (gettext ("\
103028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
103128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     idx, section_name (ebl, idx),
103228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     inner, (int) dyn->d_un.d_val);
103328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  }
103428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    }
103528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		}
103628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
103728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      if (dyn->d_tag == DT_RELACOUNT)
103828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		{
103928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  /* Found it.  Does the type match.  */
104028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if (!is_rela)
104128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    ERROR (gettext ("\
104228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELACOUNT used for this REL section\n"),
104328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx));
104428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  else
104528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    {
104628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Does the number specified number of relative
104728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations exceed the total number of
104828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations?  */
104928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
105028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			ERROR (gettext ("\
105128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
105228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       idx, section_name (ebl, idx),
105328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       (int) dyn->d_un.d_val);
105428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
105528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Make sure the specified number of relocations are
105628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relative.  */
105728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
105828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper								   idx), NULL);
105928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (reldata != NULL)
106028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			for (size_t inner = 0;
106128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     inner < shdr->sh_size / shdr->sh_entsize;
106228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     ++inner)
106328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  {
106428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rela rela_mem;
106528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rela *rela = gelf_getrela (reldata, inner,
106628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							    &rela_mem);
106728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (rela == NULL)
106828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      /* The problem will be reported elsewhere.  */
106928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      break;
107028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
107128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (ebl_relative_reloc_p (ebl,
107228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						      GELF_R_TYPE (rela->r_info)))
107328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      {
107428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				if (inner >= dyn->d_un.d_val)
107528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				  ERROR (gettext ("\
107628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
107728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 idx, section_name (ebl, idx),
107828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 (int) dyn->d_un.d_val);
107928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      }
108028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    else if (inner < dyn->d_un.d_val)
108128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      ERROR (gettext ("\
108228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
108328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     idx, section_name (ebl, idx),
108428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     inner, (int) dyn->d_un.d_val);
108528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  }
108628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    }
1087b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1091b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1092b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1093b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1094b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return true;
1095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
109841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstruct loaded_segment
109941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper{
110041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Addr from;
110141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Addr to;
110241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  bool read_only;
110341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *next;
110441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper};
110541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
110641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
110741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper/* Check whether binary has text relocation flag set.  */
110841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic bool textrel;
110941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
111041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper/* Keep track of whether text relocation flag is needed.  */
111141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic bool needed_textrel;
111241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
111341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1114c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic bool
1115c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr,
1116c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		  int idx, int reltype, GElf_Shdr **destshdrp,
111741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr *destshdr_memp, struct loaded_segment **loadedp)
1118b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool reldyn = false;
1120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check whether the link to the section we relocate is reasonable.  */
1122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info >= shnum)
1123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"),
1124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1125c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  else if (shdr->sh_info != 0)
1126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1127c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      *destshdrp = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1128c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper				 destshdr_memp);
1129c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (*destshdrp != NULL)
1130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1131c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  if((*destshdrp)->sh_type != SHT_PROGBITS
1132c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	     && (*destshdrp)->sh_type != SHT_NOBITS)
1133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true);
1135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (!reldyn)
1136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
1137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': invalid destination section type\n"),
1138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx));
1139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
1140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
1141c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		  /* There is no standard, but we require that .rel{,a}.dyn
1142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     sections have a sh_info value of zero.  */
1143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (shdr->sh_info != 0)
1144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
1145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': sh_info should be zero\n"),
1146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx));
1147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1150c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  if (((*destshdrp)->sh_flags & (SHF_MERGE | SHF_STRINGS)) != 0)
1151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': no relocations for merge-able sections possible\n"),
1153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
1154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1157c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (shdr->sh_entsize != gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT))
1158c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext (reltype == ELF_T_RELA ? "\
1159c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Rela\n" : "\
1160c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Rel\n"),
1161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
116341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* In preparation of checking whether relocations are text
116441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     relocations or not we need to determine whether the file is
116541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     flagged to have text relocation and we need to determine a) what
116641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     the loaded segments are and b) which are read-only.  This will
116741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     also allow us to determine whether the same reloc section is
116841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     modifying loaded and not loaded segments.  */
116941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  for (int i = 0; i < ehdr->e_phnum; ++i)
117041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
117141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      GElf_Phdr phdr_mem;
117241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
117341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (phdr == NULL)
117441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	continue;
117541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
117641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (phdr->p_type == PT_LOAD)
117741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
117841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  struct loaded_segment *newp = xmalloc (sizeof (*newp));
117941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->from = phdr->p_vaddr;
118041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->to = phdr->p_vaddr + phdr->p_memsz;
118141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->read_only = (phdr->p_flags & PF_W) == 0;
118241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->next = *loadedp;
118341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  *loadedp = newp;
118441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
118541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      else if (phdr->p_type == PT_DYNAMIC)
118641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
118741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  Elf_Scn *dynscn = gelf_offscn (ebl->elf, phdr->p_offset);
118841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  GElf_Shdr dynshdr_mem;
118941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem);
119041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  Elf_Data *dyndata = elf_getdata (dynscn, NULL);
119141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC
119241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      && dyndata != NULL)
119341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j)
119441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      {
119541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Dyn dyn_mem;
119641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Dyn *dyn = gelf_getdyn (dyndata, j, &dyn_mem);
119741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		if (dyn != NULL
119841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    && (dyn->d_tag == DT_TEXTREL
119941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			|| (dyn->d_tag == DT_FLAGS
120041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			    && (dyn->d_un.d_val & DF_TEXTREL) != 0)))
120141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  {
120241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    textrel = true;
120341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    break;
120441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  }
120541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      }
120641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
120741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
120841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
120941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* A quick test which can be easily done here (although it is a bit
121041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     out of place): the text relocation flag makes only sense if there
121141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     is a segment which is not writable.  */
121241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (textrel)
121341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
121441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *seg = *loadedp;
121541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      while (seg != NULL && !seg->read_only)
121641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	seg = seg->next;
121741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (seg == NULL)
121841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	ERROR (gettext ("\
121941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Dreppertext relocation flag set but there is no read-only segment\n"));
122041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
122141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1222c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  return reldyn;
1223c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper}
1224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
122641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperenum load_state
122741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  {
122841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_undecided,
122941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_loaded,
123041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_unloaded,
123141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_error
123241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  };
123341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
123441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1235c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic void
1236607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppercheck_one_reloc (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *relshdr, int idx,
1237607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		 size_t cnt, const GElf_Shdr *symshdr, Elf_Data *symdata,
1238607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		 GElf_Addr r_offset, GElf_Xword r_info,
123941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 const GElf_Shdr *destshdr, bool reldyn,
124041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 struct loaded_segment *loaded, enum load_state *statep)
1241c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper{
1242c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool known_broken = gnuld;
1243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1244c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (r_info)))
1245c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"),
1246c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1247607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper  else if (((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1248607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    /* The executable/DSO can contain relocation sections with
1249607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	       all the relocations the linker has applied.  Those sections
1250607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	       are marked non-loaded, though.  */
1251607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    || (relshdr->sh_flags & SHF_ALLOC) != 0)
1252607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	   && !ebl_reloc_valid_use (ebl, GELF_R_TYPE (r_info)))
1253c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("\
1254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
1255c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1257c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (symshdr != NULL
1258c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      && ((GELF_R_SYM (r_info) + 1)
1259c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
1260c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  > symshdr->sh_size))
1261c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("\
1262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: invalid symbol index\n"),
1263c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
12656ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper  /* No more tests if this is a no-op relocation.  */
12666ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper  if (ebl_none_reloc_p (ebl, GELF_R_TYPE (r_info)))
12676ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper    return;
12686ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper
1269c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (r_info)))
1270c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1271c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      const char *name;
1272c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      char buf[64];
1273c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Sym sym_mem;
1274c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
1275c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (sym != NULL
1276c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  /* Get the name for the symbol.  */
1277c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1278c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
1279c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	ERROR (gettext ("\
1280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
1281c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	       idx, section_name (ebl, idx), cnt,
1282c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	       ebl_reloc_type_name (ebl, GELF_R_SYM (r_info),
1283c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper				    buf, sizeof (buf)));
1284c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1286c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (reldyn)
1287c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1288c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      // XXX TODO Check .rel.dyn section addresses.
1289c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1290c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  else if (!known_broken)
1291c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1292c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (destshdr != NULL
1293c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && GELF_R_TYPE (r_info) != 0
1294c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && (r_offset - destshdr->sh_addr) >= destshdr->sh_size)
1295c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	ERROR (gettext ("\
1296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: offset out of bounds\n"),
1297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1298c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
130041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Sym sym_mem;
130141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
130241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
130341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info))
1304c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      /* Make sure the referenced symbol is an object or unspecified.  */
130541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && sym != NULL
130641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE
130741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
130841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
130941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      char buf[64];
131041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      ERROR (gettext ("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"),
131141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	     idx, section_name (ebl, idx), cnt,
131241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	     ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
131341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				   buf, sizeof (buf)));
131441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
131541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1316038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper  if ((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1317038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      || (relshdr->sh_flags & SHF_ALLOC) != 0)
131841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
1319038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      bool in_loaded_seg = false;
1320038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      while (loaded != NULL)
1321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1322038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  if (r_offset < loaded->to
1323038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      && r_offset + (sym == NULL ? 0 : sym->st_size) >= loaded->from)
132441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    {
1325038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      /* The symbol is in this segment.  */
1326038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      if  (loaded->read_only)
1327038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		{
1328038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		  if (textrel)
1329038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		    needed_textrel = true;
1330038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		  else
1331038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		    ERROR (gettext ("section [%2d] '%s': relocation %zu: read-only section modified but text relocation flag not set\n"),
1332038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper			   idx, section_name (ebl, idx), cnt);
1333038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		}
1334038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper
1335038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      in_loaded_seg = true;
133641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    }
133741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1338038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  loaded = loaded->next;
1339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
134041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1341038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      if (*statep == state_undecided)
1342038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	*statep = in_loaded_seg ? state_loaded : state_unloaded;
1343038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      else if ((*statep == state_unloaded && in_loaded_seg)
1344038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	       || (*statep == state_loaded && !in_loaded_seg))
1345038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	{
1346038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  ERROR (gettext ("\
134741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Dreppersection [%2d] '%s': relocations are against loaded and unloaded data\n"),
1348038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		 idx, section_name (ebl, idx));
1349038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  *statep = state_error;
1350038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	}
1351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1356c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1358c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
1360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
1363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
1364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1366c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  /* Check the fields of the section header.  */
1367c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr destshdr_mem;
1368c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *destshdr = NULL;
136941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *loaded = NULL;
1370c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELA, &destshdr,
137141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				  &destshdr_mem, &loaded);
1372c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1373c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1374c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr symshdr_mem;
1375c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1376c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
137741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  enum load_state state = state_undecided;
1378c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1379c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1381c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rela rela_mem;
1382c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem);
1383c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (rela == NULL)
1384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1385c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  ERROR (gettext ("\
1386c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': cannot get relocation %zu: %s\n"),
1387c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1388c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  continue;
1389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1390c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1391607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1392607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       rela->r_offset, rela->r_info, destshdr, reldyn, loaded,
1393607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       &state);
139441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
139541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
139641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  while (loaded != NULL)
139741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
139841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *old = loaded;
139941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      loaded = loaded->next;
140041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      free (old);
1401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1402c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper}
1403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1404c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1405c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic void
1406c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1407c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper{
1408c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1409c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (data == NULL)
1410c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1411c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1412c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	     idx, section_name (ebl, idx));
1413c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      return;
1414c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1415c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1416c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  /* Check the fields of the section header.  */
1417c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr destshdr_mem;
1418c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *destshdr = NULL;
141941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *loaded = NULL;
1420c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_REL, &destshdr,
142141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				  &destshdr_mem, &loaded);
1422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
1425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
142741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  enum load_state state = state_undecided;
1428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1429c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Rel rel_mem;
1432c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem);
1433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rel == NULL)
1434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get relocation %zu: %s\n"),
1437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
1439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1441607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1442607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       rel->r_offset, rel->r_info, destshdr, reldyn, loaded,
1443607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       &state);
144441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
144541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
144641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  while (loaded != NULL)
144741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
144841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *old = loaded;
144941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      loaded = loaded->next;
145041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      free (old);
1451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Number of dynamic sections.  */
1456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int ndynamic;
1457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1460607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppercheck_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *data;
1463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr strshdr_mem;
1464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *strshdr;
1465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cnt;
1466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool dependencies[DT_NUM][DT_NUM] =
1467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_NEEDED] = { [DT_STRTAB] = true },
1469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTRELSZ] = { [DT_JMPREL] = true },
1470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_HASH] = { [DT_SYMTAB] = true },
1471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRTAB] = { [DT_STRSZ] = true },
1472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_HASH] = true,
1473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      [DT_SYMENT] = true },
1474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true },
1475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELASZ] = { [DT_RELA] = true },
1476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELAENT] = { [DT_RELA] = true },
1477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRSZ] = { [DT_STRTAB] = true },
1478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMENT] = { [DT_SYMTAB] = true },
1479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SONAME] = { [DT_STRTAB] = true },
1480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RPATH] = { [DT_STRTAB] = true },
1481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true },
1482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELSZ] = { [DT_REL] = true },
1483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELENT] = { [DT_REL] = true },
1484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true },
1485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RUNPATH] = { [DT_STRTAB] = true },
1486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTREL] = { [DT_JMPREL] = true },
1487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTRELSZ] = { [DT_JMPREL] = true }
1488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool has_dt[DT_NUM];
1490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool level2[DT_NUM] =
1491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RPATH] = true,
1493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMBOLIC] = true,
1494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_TEXTREL] = true,
1495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_BIND_NOW] = true
1496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool mandatory[DT_NUM] =
1498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_NULL] = true,
1500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_HASH] = true,
1501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRTAB] = true,
1502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMTAB] = true,
1503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRSZ] = true,
1504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMENT] = true
1505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Addr reladdr = 0;
1507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Word relsz = 0;
1508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Addr pltreladdr = 0;
1509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Word pltrelsz = 0;
1510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  memset (has_dt, '\0', sizeof (has_dt));
1512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (++ndynamic == 2)
1514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("more than one dynamic section present\n"));
1515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
151641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
1518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
1521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
1522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem);
1525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB)
1526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
1528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   shdr->sh_link, section_name (ebl, shdr->sh_link),
1529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT))
1532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Dyn\n"),
1534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info != 0)
1537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool non_null_warned = false;
1541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Dyn dyn_mem;
1544acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dyn_mem);
1545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn == NULL)
1546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get dynamic section entry %zu: %s\n"),
1549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
1551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned)
1554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"),
1557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx));
1558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  non_null_warned = true;
1559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (!ebl_dynamic_tag_check (ebl, dyn->d_tag))
1562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': entry %zu: unknown tag\n"),
1563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag >= 0 && dyn->d_tag < DT_NUM)
1566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (has_dt[dyn->d_tag]
1568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_NEEDED
1569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_NULL
1570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_POSFLAG_1)
1571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf[50];
1573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: more than one entry with tag %s\n"),
1575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt,
1576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   buf, sizeof (buf)));
1578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (be_strict && level2[dyn->d_tag])
1581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf[50];
1583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: level 2 tag %s used\n"),
1585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt,
1586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   buf, sizeof (buf)));
1588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  has_dt[dyn->d_tag] = true;
1591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL
1594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && dyn->d_un.d_val != DT_RELA)
1595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
1596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"),
1597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_REL)
1600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	reladdr = dyn->d_un.d_ptr;
1601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_RELSZ)
1602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	relsz = dyn->d_un.d_val;
1603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_JMPREL)
1604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	pltreladdr = dyn->d_un.d_ptr;
1605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_PLTRELSZ)
1606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	pltrelsz = dyn->d_un.d_val;
1607607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
1608607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      /* Check that addresses for entries are in loaded segments.  */
1609607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      switch (dyn->d_tag)
1610607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	{
1611607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  size_t n;
1612cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_STRTAB:
1613cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  /* We require the referenced section is the same as the one
1614cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	     specified in sh_link.  */
1615cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  if (strshdr->sh_addr != dyn->d_un.d_val)
1616cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    {
1617cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      ERROR (gettext ("\
1618cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Dreppersection [%2d] '%s': entry %zu: pointer does not match address of section [%2d] '%s' referenced by sh_link\n"),
1619cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1620cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1621cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      break;
1622cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    }
1623cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  goto check_addr;
1624cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper
1625607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	default:
1626607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (dyn->d_tag < DT_ADDRRNGLO || dyn->d_tag > DT_ADDRRNGHI)
1627607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    /* Value is no pointer.  */
1628607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    break;
1629607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* FALLTHROUGH */
1630607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
1631cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_AUXILIARY:
1632cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FILTER:
1633cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FINI:
1634cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FINI_ARRAY:
1635607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_HASH:
1636607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_INIT:
1637607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_INIT_ARRAY:
1638cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_JMPREL:
1639cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_PLTGOT:
1640cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_REL:
1641cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RELA:
1642cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SYMBOLIC:
1643cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SYMTAB:
1644607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_VERDEF:
1645607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_VERNEED:
1646cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_VERSYM:
1647cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	check_addr:
1648607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  for (n = 0; n < ehdr->e_phnum; ++n)
1649607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
1650607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr phdr_mem;
1651607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, n, &phdr_mem);
1652607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      if (phdr != NULL && phdr->p_type == PT_LOAD
1653607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr <= dyn->d_un.d_ptr
1654607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr + phdr->p_memsz > dyn->d_un.d_ptr)
1655607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		break;
1656607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
1657607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (unlikely (n >= ehdr->e_phnum))
1658607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
1659607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      char buf[50];
1660607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      ERROR (gettext ("\
1661607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppersection [%2d] '%s': entry %zu: %s value must point into loaded segment\n"),
1662607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1663607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1664607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper					   sizeof (buf)));
1665607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
1666cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  break;
1667cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper
1668cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_NEEDED:
1669cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RPATH:
1670cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RUNPATH:
1671cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SONAME:
1672cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  if (dyn->d_un.d_ptr >= strshdr->sh_size)
1673cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    {
1674cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      char buf[50];
1675cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      ERROR (gettext ("\
1676cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Dreppersection [%2d] '%s': entry %zu: %s value must be valid offset in section [%2d] '%s'\n"),
1677cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1678cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1679cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper					   sizeof (buf)),
1680cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1681cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    }
1682cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  break;
1683607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	}
1684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 1; cnt < DT_NUM; ++cnt)
1687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (has_dt[cnt])
1688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1689acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	for (int inner = 0; inner < DT_NUM; ++inner)
1690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (dependencies[cnt][inner] && ! has_dt[inner])
1691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf1[50];
1693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf2[50];
1694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': contains %s entry but not %s\n"),
1697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx),
1698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)),
1699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2)));
1700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    else
1703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (mandatory[cnt])
1705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
1706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    char buf[50];
1707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': mandatory tag %s not present\n"),
1709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx),
1710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf)));
1711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
1712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the rel/rela tags.  At least one group must be available.  */
1715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT])
1716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT]))
1717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': not all of %s, %s, and %s are present\n"),
1719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
1720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   "DT_RELA", "DT_RELASZ", "DT_RELAENT");
1721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT])
1723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT]))
1724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': not all of %s, %s, and %s are present\n"),
1726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
1727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   "DT_REL", "DT_RELSZ", "DT_RELENT");
1728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1729b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1730b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1731b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1732acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1734acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (ehdr->e_type != ET_REL)
1735acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
1736acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      ERROR (gettext ("\
1737acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': only relocatable files can have extended section index\n"),
1738acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	     idx, section_name (ebl, idx));
1739acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      return;
1740acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    }
1741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1742acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1743acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr symshdr_mem;
1744acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB)
1746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended section index section not for symbol table\n"),
1748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1749acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
1750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symdata == NULL)
1751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("cannot get data for symbol section\n"));
1752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_entsize != sizeof (Elf32_Word))
1754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry size does not match Elf32_Word\n"),
1756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL
1759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (shdr->sh_size / shdr->sh_entsize
1760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  < symshdr->sh_size / symshdr->sh_entsize))
1761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended index table too small for symbol table\n"),
1763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info != 0)
1766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1769acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = idx + 1; cnt < shnum; ++cnt)
1770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr rshdr_mem;
1772acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      GElf_Shdr *rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem);
1773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX
1774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && rshdr->sh_link == shdr->sh_link)
1775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"),
1778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx),
1779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, section_name (ebl, cnt));
1780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1783b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1784acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1785b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1786b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (*((Elf32_Word *) data->d_buf) != 0)
1787b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("symbol 0 should have zero extended section index\n"));
1788b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1789acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1790b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1791b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt];
1792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndx != 0)
1794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Sym sym_data;
1796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data);
1797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym == NULL)
1798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("cannot get data for symbol %zu\n"), cnt);
1800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
1801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1802b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym->st_shndx != SHN_XINDEX)
1804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperextended section index is %" PRIu32 " but symbol index is not XINDEX\n"),
1806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   (uint32_t) xndx);
1807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
181328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
181428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		 GElf_Shdr *symshdr)
181528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
181628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
181728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
181828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
181928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
182028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    ERROR (gettext ("\
182128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
182228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
182328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
182428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
182528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t maxidx = nchain;
182628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
182728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (symshdr != NULL)
182828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
182928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
183028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
183128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
183228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
183328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx));
183428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
183528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      maxidx = symsize;
183628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
183728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
183828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
183928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
184028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx)
184128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
184228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash bucket reference %zu out of bounds\n"),
184328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2);
184428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
184528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (; cnt < 2 + nbucket + nchain; ++cnt)
184628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx)
184728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
184828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain reference %zu out of bounds\n"),
184928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2 - nbucket);
185028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
185128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
185228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
185328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
185428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
185528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		 GElf_Shdr *symshdr)
185628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
185728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
185828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
185928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
186028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
186128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    ERROR (gettext ("\
186228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
186328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
186428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
186528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
186628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t maxidx = nchain;
186728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
186828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (symshdr != NULL)
186928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
187028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
187128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
187228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
187328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
187428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx));
187528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
187628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      maxidx = symsize;
187728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
187828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
187928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
188028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
188128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx)
188228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
188328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash bucket reference %zu out of bounds\n"),
188428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2);
188528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
188628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (; cnt < 2 + nbucket + nchain; ++cnt)
188728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx)
188828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
188928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain reference %zu out of bounds\n"),
189028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2 - nbucket);
189128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
189228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
189328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
189428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
189528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
189628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		GElf_Shdr *symshdr)
189728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
189828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0];
189928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
19008ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
190128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
19028ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (!powerof2 (bitmask_words))
19038ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    ERROR (gettext ("\
19048ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': bitmask size not power of 2: %u\n"),
19058ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	   idx, section_name (ebl, idx), bitmask_words);
19068ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
19078ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t bitmask_idxmask = bitmask_words - 1;
19088ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (gelf_getclass (ebl->elf) == ELFCLASS64)
19098ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    bitmask_words *= 2;
19108ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
19118ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
19128ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shdr->sh_size < (4 + bitmask_words + nbuckets) * sizeof (Elf32_Word))
191328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
191428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
191528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected at least%ld)\n"),
191628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), (long int) shdr->sh_size,
19178ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	     (long int) ((4 + bitmask_words + nbuckets) * sizeof (Elf32_Word)));
191828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      return;
191928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
192028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
19218ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shift > 31)
19228ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    ERROR (gettext ("\
19238ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': 2nd hash function shift too big: %u\n"),
19248ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	   idx, section_name (ebl, idx), shift);
19258ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
19268ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words
19278ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							 + nbuckets);
192828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
192928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (symshdr != NULL)
193028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    maxidx = MIN (maxidx, symshdr->sh_size / symshdr->sh_entsize);
193128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
193228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  /* We need the symbol section data.  */
193328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf_Data *symdata = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link), NULL);
193428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
19358ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  union
19368ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  {
19378ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    Elf32_Word *p32;
19388ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    Elf64_Xword *p64;
19398ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  } bitmask = { .p32 = &((Elf32_Word *) data->d_buf)[4] },
19408ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      collected = { .p32 = xcalloc (bitmask_words, sizeof (Elf32_Word)) };
19418ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
19428ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t classbits = gelf_getclass (ebl->elf) == ELFCLASS32 ? 32 : 64;
19438ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
194428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
19458ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  for (cnt = 4 + bitmask_words; cnt < 4 + bitmask_words + nbuckets; ++cnt)
194628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
19478ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      Elf32_Word symidx = ((Elf32_Word *) data->d_buf)[cnt];
194828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
194928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx == 0)
19508ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	continue;
195128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
195228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx < symbias)
195328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	{
195428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  ERROR (gettext ("\
195528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"),
19568ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		 idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
195728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  continue;
195828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	}
195928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
196028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      while (symidx - symbias < maxidx)
196128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	{
19628ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	  Elf32_Word chainhash = ((Elf32_Word *) data->d_buf)[4
19638ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							      + bitmask_words
19648ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							      + nbuckets
196528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							      + symidx
196628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							      - symbias];
196728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
196828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  if (symdata != NULL)
196928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    {
197028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      /* Check that the referenced symbol is not undefined.  */
197128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      GElf_Sym sym_mem;
197228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      GElf_Sym *sym = gelf_getsym (symdata, symidx, &sym_mem);
197328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      if (sym != NULL && sym->st_shndx == SHN_UNDEF)
197428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		ERROR (gettext ("\
197528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': symbol %u referenced in chain for bucket %zu is undefined\n"),
197628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		       idx, section_name (ebl, idx), symidx, cnt / 2 - 1);
197728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
197828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      const char *symname = elf_strptr (ebl->elf, symshdr->sh_link,
197928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						sym->st_name);
198028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      if (symname != NULL)
198128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		{
198228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  Elf32_Word hval = elf_gnu_hash (symname);
198328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if ((hval & ~1u) != (chainhash & ~1u))
198428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    ERROR (gettext ("\
198528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"),
198628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx), symidx, cnt / 2 - 1);
19878ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
19888ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  /* Set the bits in the bitmask.  */
19898ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  size_t maskidx = (hval / classbits) & bitmask_idxmask;
19908ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  if (classbits == 32)
19918ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    {
19928ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p32[maskidx]
19938ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT32_C (1) << (hval & (classbits - 1));
19948ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p32[maskidx]
19958ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT32_C (1) << ((hval >> shift) & (classbits - 1));
19968ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    }
19978ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  else
19988ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    {
19998ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p64[maskidx]
20008ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT64_C (1) << (hval & (classbits - 1));
20018ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p64[maskidx]
20028ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT64_C (1) << ((hval >> shift) & (classbits - 1));
20038ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    }
200428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		}
200528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    }
200628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
200728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  if ((chainhash & 1) != 0)
200828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    break;
200928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
201028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  ++symidx;
201128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	}
201228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
201328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx - symbias >= maxidx)
201428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("\
201528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain for bucket %zu out of bounds\n"),
201628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx), cnt / 2 - 1);
201728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      else if (symshdr != NULL
201828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       && symidx > symshdr->sh_size / symshdr->sh_entsize)
201928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("\
202028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"),
202128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx), cnt / 2 - 1);
202228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
20238ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
20248ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (memcmp (collected.p32, bitmask.p32, bitmask_words * sizeof (Elf32_Word)))
20258ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    ERROR (gettext ("\
20268ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': bitmask does not match names in the hash table\n"),
20278ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	   idx, section_name (ebl, idx));
20288ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
20298ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  free (collected.p32);
203028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
203128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
203228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
203328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
203428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_hash (int tag, Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2035b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2036acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (ehdr->e_type == ET_REL)
2037acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
2038acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      ERROR (gettext ("\
2039acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': relocatable files cannot have hash tables\n"),
2040acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	     idx, section_name (ebl, idx));
2041acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      return;
2042acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    }
2043b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2044acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2045b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
2046b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2047b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2048b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2049b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2050b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2052acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr symshdr_mem;
2053acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2054acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &symshdr_mem);
2055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM)
2056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
2057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': hash table not for dynamic symbol table\n"),
2058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
206028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_entsize != (tag == SHT_GNU_HASH
20618ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			   ? (gelf_getclass (ebl->elf) == ELFCLASS32
20628ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			      ? sizeof (Elf32_Word) : 0)
206328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   : (size_t) ebl_sysvhash_entrysize (ebl)))
2064b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
206528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table entry size incorrect\n"),
2066b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2067b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2068b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((shdr->sh_flags & SHF_ALLOC) == 0)
2069b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': not marked to be allocated\n"),
2070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2071b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
20728ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (shdr->sh_entsize ?: 4))
2073b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2074b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
20758ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': hash table has not even room for initial administrative entries\n"),
2076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2077b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2078b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
208028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  switch (tag)
2081b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
208228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    case SHT_HASH:
208328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
208428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	check_sysv_hash64 (ebl, shdr, data, idx, symshdr);
208528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      else
208628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	check_sysv_hash (ebl, shdr, data, idx, symshdr);
208728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      break;
2088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
208928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    case SHT_GNU_HASH:
209028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      check_gnu_hash (ebl, shdr, data, idx, symshdr);
209128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      break;
2092ee4b927bae351b21787355e00a3d28371bf78e8fUlrich Drepper
209328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    default:
20948ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      assert (! "should not happen");
2095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2098b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2099b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_null (Ebl *ebl, GElf_Shdr *shdr, int idx)
2101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define TEST(name, extra) \
2103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (extra && shdr->sh_##name != 0)					      \
2104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': nonzero sh_%s for NULL section\n"),  \
2105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), #name)
2106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (name, 1);
2108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (flags, 1);
2109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (addr, 1);
2110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (offset, 1);
2111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (size, idx != 0);
2112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (link, idx != 0);
2113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (info, 1);
2114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (addralign, 1);
2115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (entsize, 1);
2116b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2117b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2118b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_REL)
2123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
2125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section groups only allowed in relocatable object files\n"),
2126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check that sh_link is an index of a symbol table.  */
2131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
2132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				     &symshdr_mem);
2134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr == NULL)
2135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': cannot get symbol table: %s\n"),
2136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), elf_errmsg (-1));
2137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (symshdr->sh_type != SHT_SYMTAB)
2140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section reference in sh_link is no symbol table\n"),
2142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM,
2145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper							  1, EV_CURRENT))
2146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': invalid symbol index in sh_info\n"),
2148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags != 0)
2151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': sh_flags not zero\n"),
2152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (be_strict
2155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT))
2156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': sh_flags not set correctly\n"),
2157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
2162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': cannot get data: %s\n"),
2163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), elf_errmsg (-1));
2164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
2167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t cnt;
2168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf32_Word val;
2169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data->d_size % elsize != 0)
2171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"),
2173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data->d_size < elsize)
2176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group without flags word\n"),
2178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (be_strict)
2180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (data->d_size < 2 * elsize)
2182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group without member\n"),
2184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
2185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (data->d_size < 3 * elsize)
2186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group with only one member\n"),
2188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
2189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if ALLOW_UNALIGNED
2192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      val = *((Elf32_Word *) data->d_buf);
2193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#else
2194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      memcpy (&val, data->d_buf, elsize);
2195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
2196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((val & ~GRP_COMDAT) != 0)
2197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': unknown section group flags\n"),
2198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = elsize; cnt < data->d_size; cnt += elsize)
2201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if ALLOW_UNALIGNED
2203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  val = *((Elf32_Word *) ((char *) data->d_buf + cnt));
2204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#else
2205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  memcpy (&val, (char *) data->d_buf + cnt, elsize);
2206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
2207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (val > shnum)
2209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section index %Zu out of range\n"),
2211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt / elsize);
2212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
2213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
2214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Shdr refshdr_mem;
2215acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	      GElf_Shdr *refshdr = gelf_getshdr (elf_getscn (ebl->elf, val),
2216acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper						 &refshdr_mem);
2217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (refshdr == NULL)
2218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
2219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get section header for element %zu: %s\n"),
2220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx), cnt / elsize,
2221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       elf_errmsg (-1));
2222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
2223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
2224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (refshdr->sh_type == SHT_GROUP)
2225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
2226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group contains another group [%2d] '%s'\n"),
2227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx),
2228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   val, section_name (ebl, val));
2229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if ((refshdr->sh_flags & SHF_GROUP) == 0)
2231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
2232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': element %Zu references section [%2d] '%s' without SHF_GROUP flag set\n"),
2233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx), cnt / elsize,
2234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   val, section_name (ebl, val));
2235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
2236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (++scnref[val] == 2)
2238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
2239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' is contained in more than one section group\n"),
2240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       val, section_name (ebl, val));
2241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
2242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *
2248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection_flags_string (GElf_Word flags, char *buf, size_t len)
2249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const struct
2251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
2252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    GElf_Word flag;
2253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    const char *name;
2254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  } known_flags[] =
2255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define NEWFLAG(name) { SHF_##name, #name }
2257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (WRITE),
2258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (ALLOC),
2259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (EXECINSTR),
2260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (MERGE),
2261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (STRINGS),
2262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (INFO_LINK),
2263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (LINK_ORDER),
2264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (OS_NONCONFORMING),
2265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (GROUP),
2266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (TLS)
2267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
2268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#undef NEWFLAG
2269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
2270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *cp = buf;
2272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2273acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 0; cnt < nknown_flags; ++cnt)
2274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (flags & known_flags[cnt].flag)
2275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
2276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (cp != buf && len > 1)
2277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
2278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    *cp++ = '|';
2279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    --len;
2280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
2281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name));
2283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	cp = mempcpy (cp, known_flags[cnt].name, ncopy);
2284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	len -= ncopy;
2285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	flags ^= known_flags[cnt].flag;
2287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
2288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (flags != 0 || cp == buf)
2290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    snprintf (cp, len - 1, "%" PRIx64, (uint64_t) flags);
2291b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2292b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *cp = '\0';
2293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return buf;
2295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2298dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2299dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperhas_copy_reloc (Ebl *ebl, unsigned int symscnndx, unsigned int symndx)
2300dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2301dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* First find the relocation section for the symbol table.  */
2302dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = NULL;
2303dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2304dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = NULL;
2305dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2306dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2307dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      shdr = gelf_getshdr (scn, &shdr_mem);
2308dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (shdr != NULL
2309dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
2310dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && shdr->sh_link == symscnndx)
2311dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	/* Found the section.  */
2312dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	break;
2313dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2314dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2315dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (scn == NULL)
2316dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 0;
2317dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2318dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
2319dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2320dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 0;
2321dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2322dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr->sh_type == SHT_REL)
2323dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2324dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2325dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rel rel_mem;
2326dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
2327dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (rel == NULL)
2328dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  continue;
2329dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2330dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (GELF_R_SYM (rel->r_info) == symndx
2331dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info)))
2332dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  return 1;
2333dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2334dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  else
2335dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2336dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2337dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rela rela_mem;
2338dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
2339dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (rela == NULL)
2340dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  continue;
2341dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2342dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (GELF_R_SYM (rela->r_info) == symndx
2343dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info)))
2344dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  return 1;
2345dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2346dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2347dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 0;
2348dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2349dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2350dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2351637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic int
2352637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperin_nobits_scn (Ebl *ebl, unsigned int shndx)
2353637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper{
2354637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Shdr shdr_mem;
2355637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, shndx), &shdr_mem);
2356637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  return shdr != NULL && shdr->sh_type == SHT_NOBITS;
2357637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper}
2358637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2359637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2360dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic struct version_namelist
2361dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2362dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  const char *objname;
2363dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  const char *name;
2364dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Word ndx;
2365dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  enum { ver_def, ver_need } type;
2366dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct version_namelist *next;
2367dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper} *version_namelist;
2368dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2369dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2370dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2371dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperadd_version (const char *objname, const char *name, GElf_Word ndx, int type)
2372dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2373dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Check that there are no duplications.  */
2374dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct version_namelist *nlp = version_namelist;
2375dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while (nlp != NULL)
2376dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2377dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (((nlp->objname == NULL && objname == NULL)
2378dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	   || (nlp->objname != NULL && objname != NULL
2379dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       && strcmp (nlp->objname, objname) == 0))
2380dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && strcmp (nlp->name, name) == 0)
2381dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	return nlp->type == ver_def ? 1 : -1;
2382dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      nlp = nlp->next;
2383dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2384dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2385dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp = xmalloc (sizeof (*nlp));
2386dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->objname = objname;
2387dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->name = name;
2388dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->ndx = ndx;
2389dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->type = type;
2390dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->next = version_namelist;
2391dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  version_namelist = nlp;
2392dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2393dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 0;
2394dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2395dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2396dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2398dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_versym (Ebl *ebl, int idx)
2399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2400dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = elf_getscn (ebl->elf, idx);
2401dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2402dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2403dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr == NULL)
2404dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    /* The error has already been reported.  */
2405dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
2406dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2407dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
2408dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2409dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2410dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2411dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
2412dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
2413dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2414dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2415dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
2417dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr == NULL)
2419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* The error has already been reported.  */
2420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
2421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr->sh_type != SHT_DYNSYM)
2423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
2425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"),
2426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx),
2427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     shdr->sh_link, section_name (ebl, shdr->sh_link));
2428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2431dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* The number of elements in the version symbol table must be the
2432dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     same as the number of symbols.  */
2433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_size / shdr->sh_entsize
2434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      != symshdr->sh_size / symshdr->sh_entsize)
2435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
2436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"),
2437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
2438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   shdr->sh_link, section_name (ebl, shdr->sh_link));
2439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2440dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
2441dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (symdata == NULL)
2442dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    /* The error has already been reported.  */
2443dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
2444dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2445dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (int cnt = 1; (size_t) cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2446dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2447dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Versym versym_mem;
2448dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Versym *versym = gelf_getversym (data, cnt, &versym_mem);
2449dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (versym == NULL)
2450dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2451dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2452dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: cannot read version data\n"),
2453dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
2454dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  break;
2455dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2456dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2457dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Sym sym_mem;
2458dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_mem);
2459dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (sym == NULL)
2460dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	/* Already reported elsewhere.  */
2461dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	continue;
2462dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
246361655e08ba36430de47381cefdf10d0c26aa8480Ulrich Drepper      if (*versym == VER_NDX_GLOBAL)
2464dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2465dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* Global symbol.  Make sure it is not defined as local.  */
2466dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2467dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2468dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: local symbol with global scope\n"),
2469dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
2470dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
247161655e08ba36430de47381cefdf10d0c26aa8480Ulrich Drepper      else if (*versym != VER_NDX_LOCAL)
2472dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2473c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	  /* Versioned symbol.  Make sure it is not defined as local.  */
2474c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	  if (!gnuld && GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2475c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	    ERROR (gettext ("\
2476c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Dreppersection [%2d] '%s': symbol %d: local symbol with version\n"),
2477c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
2478c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper
2479dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* Look through the list of defined versions and locate the
2480dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     index we need for this symbol.  */
2481dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *runp = version_namelist;
2482dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  while (runp != NULL)
248328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    if (runp->ndx == (*versym & 0x7fff))
2484dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
2485dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    else
2486dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      runp = runp->next;
2487dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2488dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (runp == NULL)
2489dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2490dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: invalid version index %d\n"),
2491dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt, (int) *versym);
2492dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else if (sym->st_shndx == SHN_UNDEF
2493dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   && runp->type == ver_def)
2494dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2495dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: version index %d is for defined version\n"),
2496dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt, (int) *versym);
2497dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else if (sym->st_shndx != SHN_UNDEF
2498dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   && runp->type == ver_need)
2499dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2500dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      /* Unless this symbol has a copy relocation associated
2501dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 this must not happen.  */
2502637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper	      if (!has_copy_reloc (ebl, shdr->sh_link, cnt)
2503637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper		  && !in_nobits_scn (ebl, sym->st_shndx))
2504dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		ERROR (gettext ("\
2505dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: version index %d is for requested version\n"),
2506dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       idx, section_name (ebl, idx), cnt, (int) *versym);
2507dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2508dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2509dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2510dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2511dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2512dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2513dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2514dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperunknown_dependency_p (Elf *elf, GElf_Ehdr *ehdr, const char *fname)
2515dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2516dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Phdr phdr_mem;
2517dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Phdr *phdr = NULL;
2518dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2519dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  int i;
2520dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (i = 0; i < ehdr->e_phnum; ++i)
2521dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    if ((phdr = gelf_getphdr (elf, i, &phdr_mem)) != NULL
2522dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	&& phdr->p_type == PT_DYNAMIC)
2523dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      break;
2524dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2525dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (i == ehdr->e_phnum)
2526dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 1;
2527dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  assert (phdr != NULL);
2528dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
2529dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2530dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2531dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
2532dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL)
2533dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (size_t j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
2534dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2535dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Dyn dyn_mem;
2536dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
2537dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (dyn != NULL && dyn->d_tag == DT_NEEDED)
2538dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  {
2539dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    const char *str = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
2540dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    if (str != NULL && strcmp (str, fname) == 0)
2541dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      /* Found it.  */
2542dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      return 0;
2543dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  }
2544dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2545dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2546dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 1;
2547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2550acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic unsigned int nverneed;
2551acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2553dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_verneed (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2555acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (++nverneed == 2)
2556acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("more than one version reference section present\n"));
2557acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2558acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr strshdr_mem;
2559acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2560acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &strshdr_mem);
2561acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr == NULL)
2562acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    return;
2563acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
2564acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("\
2565acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': sh_link does not link to string table\n"),
2566acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	   idx, section_name (ebl, idx));
2567dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2568dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2569dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2570dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2571dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2572dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
2573dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
2574dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2575dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  unsigned int offset = 0;
2576dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (int cnt = shdr->sh_info; --cnt >= 0; )
2577dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2578dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Get the data at the next offset.  */
2579dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verneed needmem;
2580dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
2581dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need == NULL)
2582dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	break;
2583dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2584dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      unsigned int auxoffset = offset + need->vn_aux;
2585dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2586dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need->vn_version != EV_CURRENT)
2587dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2588dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong version %d\n"),
2589dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) need->vn_version);
2590dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2591dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need->vn_cnt > 0 && need->vn_aux < gelf_fsize (ebl->elf, ELF_T_VNEED,
2592dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper							 1, EV_CURRENT))
2593dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2594dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
2595dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2596dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2597dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      const char *libname = elf_strptr (ebl->elf, shdr->sh_link,
2598dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					need->vn_file);
2599dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (libname == NULL)
2600dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2601dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2602dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid file reference\n"),
2603dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
2604dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  goto next_need;
2605dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2606dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2607dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Check that there is a DT_NEEDED entry for the referenced library.  */
2608dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (unknown_dependency_p (ebl->elf, ehdr, libname))
2609dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2610dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d references unknown dependency\n"),
2611dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2612dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2613dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2614dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2615dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  GElf_Vernaux auxmem;
2616dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2617dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (aux == NULL)
2618dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    break;
2619dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2620dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vna_flags & ~VER_FLG_WEAK) != 0)
2621dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2622dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"),
2623dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2624dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2625dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  const char *verstr = elf_strptr (ebl->elf, shdr->sh_link,
2626dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					   aux->vna_name);
2627dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (verstr == NULL)
2628dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2629dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has invalid name reference\n"),
2630dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2631dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else
2632dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2633dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      GElf_Word hashval = elf_hash (verstr);
2634dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (hashval != aux->vna_hash)
2635dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		ERROR (gettext ("\
2636dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: %#x, expected %#x\n"),
2637dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       idx, section_name (ebl, idx), need->vn_cnt - cnt2,
2638dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       cnt, (int) hashval, (int) aux->vna_hash);
2639dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2640dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      int res = add_version (libname, verstr, aux->vna_other,
2641dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper				     ver_need);
2642dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (unlikely (res !=0))
2643dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		{
2644dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  assert (res > 0);
2645dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  ERROR (gettext ("\
2646dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has duplicate version name '%s'\n"),
2647dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 idx, section_name (ebl, idx), need->vn_cnt - cnt2,
2648dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 cnt, verstr);
2649dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		}
2650dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2651dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2652dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vna_next != 0 || cnt2 > 0)
2653dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && aux->vna_next < gelf_fsize (ebl->elf, ELF_T_VNAUX, 1,
2654dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					     EV_CURRENT))
2655dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2656dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      ERROR (gettext ("\
2657dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"),
2658dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		     idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2659dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
2660dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2661dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2662dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  auxoffset += MAX (aux->vna_next,
2663dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			    gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, EV_CURRENT));
2664dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2665dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2666dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Find the next offset.  */
2667dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    next_need:
2668dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      offset += need->vn_next;
2669dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2670dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((need->vn_next != 0 || cnt > 0)
2671dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && offset < auxoffset)
2672dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2673dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid offset to next entry\n"),
2674dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2675dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2676acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper}
2677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2678acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2679acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic unsigned int nverdef;
2680acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2681acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic void
2682acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_verdef (Ebl *ebl, GElf_Shdr *shdr, int idx)
2683acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper{
2684acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (++nverdef == 2)
2685acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("more than one version definition section present\n"));
2686acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2687acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr strshdr_mem;
2688acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2689acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &strshdr_mem);
2690acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr == NULL)
2691acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    return;
2692acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
2693acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("\
2694acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': sh_link does not link to string table\n"),
2695acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	   idx, section_name (ebl, idx));
2696dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2697dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2698dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2699dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2700dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    no_data:
2701dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2702dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
2703dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
2704dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2705dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2706dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Iterate over all version definition entries.  We check that there
2707dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     is a BASE entry and that each index is unique.  To do the later
2708dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     we collection the information in a list which is later
2709dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     examined.  */
2710dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct namelist
2711dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  {
2712dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    const char *name;
2713dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    struct namelist *next;
2714dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  } *namelist = NULL;
2715dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct namelist *refnamelist = NULL;
2716dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2717dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  bool has_base = false;
2718dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  unsigned int offset = 0;
2719dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (int cnt = shdr->sh_info; --cnt >= 0; )
2720dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2721dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Get the data at the next offset.  */
2722dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdef defmem;
2723dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2724dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def == NULL)
2725dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	goto no_data;
2726dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2727dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_flags & VER_FLG_BASE) != 0)
2728dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2729dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (has_base)
2730dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2731dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': more than one BASE definition\n"),
2732dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx));
2733dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (def->vd_ndx != VER_NDX_GLOBAL)
2734dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2735dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"),
2736dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx));
2737dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  has_base = true;
2738dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2739dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_flags & ~(VER_FLG_BASE|VER_FLG_WEAK)) != 0)
2740dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2741dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has unknown flag\n"),
2742dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2743dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2744dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_version != EV_CURRENT)
2745dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2746dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong version %d\n"),
2747dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) def->vd_version);
2748dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2749dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_cnt > 0 && def->vd_aux < gelf_fsize (ebl->elf, ELF_T_VDEF,
2750dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper						       1, EV_CURRENT))
2751dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2752dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
2753dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2754dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2755dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      unsigned int auxoffset = offset + def->vd_aux;
2756dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdaux auxmem;
2757dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
2758dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (aux == NULL)
2759dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	goto no_data;
2760dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2761dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      const char *name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
2762dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (name == NULL)
2763dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2764dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2765dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid name reference\n"),
2766dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
2767dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  goto next_def;
2768dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2769dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Word hashval = elf_hash (name);
2770dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_hash != hashval)
2771dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2772dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"),
2773dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) hashval,
2774dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       (int) def->vd_hash);
2775dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2776dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      int res = add_version (NULL, name, def->vd_ndx, ver_def);
2777dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (unlikely (res !=0))
2778dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2779dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  assert (res > 0);
2780dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2781dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has duplicate version name '%s'\n"),
2782dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt, name);
2783dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2784dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2785dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      struct namelist *newname = alloca (sizeof (*newname));
27866247d634c33be4c9ee4bfc650bb8f06f5add41e5Ulrich Drepper      newname->name = name;
2787dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      newname->next = namelist;
2788dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      namelist = newname;
2789dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2790dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      auxoffset += aux->vda_next;
2791dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
2792dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2793dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
2794dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (aux == NULL)
2795dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    goto no_data;
2796dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2797c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
2798c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  if (name == NULL)
2799c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    ERROR (gettext ("\
2800c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Dreppersection [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"),
2801c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
2802c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  else
2803c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    {
2804c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname = alloca (sizeof (*newname));
2805c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname->name = name;
2806c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname->next = refnamelist;
2807c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      refnamelist = newname;
2808c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    }
2809dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2810dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vda_next != 0 || cnt2 + 1 < def->vd_cnt)
2811dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && aux->vda_next < gelf_fsize (ebl->elf, ELF_T_VDAUX, 1,
2812dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					     EV_CURRENT))
2813dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2814dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      ERROR (gettext ("\
2815dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong next field in auxiliary data\n"),
2816dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		     idx, section_name (ebl, idx), cnt);
2817dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
2818dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2819dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2820dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  auxoffset += MAX (aux->vda_next,
2821dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			    gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, EV_CURRENT));
2822dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2823dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2824dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Find the next offset.  */
2825dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    next_def:
2826dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      offset += def->vd_next;
2827dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2828dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_next != 0 || cnt > 0)
2829dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && offset < auxoffset)
2830dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2831dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid offset to next entry\n"),
2832dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2833dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2834dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2835dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (!has_base)
2836dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("section [%2d] '%s': no BASE definition\n"),
2837dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	   idx, section_name (ebl, idx));
2838dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2839dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Check whether the referenced names are available.  */
2840dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while (namelist != NULL)
2841dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2842dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      struct version_namelist *runp = version_namelist;
2843dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      while (runp != NULL)
2844dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2845dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (runp->type == ver_def
2846dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && strcmp (runp->name, namelist->name) == 0)
2847dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    break;
2848dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  runp = runp->next;
2849dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2850dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2851dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (runp == NULL)
2852dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2853dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': unknown parent version '%s'\n"),
2854dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), namelist->name);
2855dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2856dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      namelist = namelist->next;
2857dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2858acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper}
2859acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2860acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2861637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic bool has_loadable_segment;
2862637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic bool has_interp_segment;
2863637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2864637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic const struct
2865637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper{
2866637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  const char *name;
2867637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  size_t namelen;
2868637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word type;
2869637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  enum { unused, exact, atleast } attrflag;
2870637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word attr;
2871637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word attr2;
2872637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper} special_sections[] =
2873637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  {
2874637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    /* See figure 4-14 in the gABI.  */
2875637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
2876637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".comment", 8, SHT_PROGBITS, exact, 0, 0 },
2877637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
2878637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
2879637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".debug", 7, SHT_PROGBITS, exact, 0, 0 },
2880637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE },
2881637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 },
2882637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 },
2883637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
2884637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
2885637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info?
2886637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 },
2887637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
2888637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
2889637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests?
2890637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".line", 6, SHT_PROGBITS, exact, 0, 0 },
2891637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".note", 6, SHT_NOTE, exact, 0, 0 },
2892637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
2893637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
2894637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC }, // XXX more tests
2895637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC }, // XXX more tests
2896637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
2897637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
2898637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 },
2899637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
2900637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
2901637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests
2902637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
2903637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
2904637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
2905637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
2906637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2907637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    /* The following are GNU extensions.  */
2908637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version", 13, SHT_GNU_versym, exact, SHF_ALLOC, 0 },
2909637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version_d", 15, SHT_GNU_verdef, exact, SHF_ALLOC, 0 },
2910637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 }
2911637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  };
2912637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper#define nspecial_sections \
2913637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  (sizeof (special_sections) / sizeof (special_sections[0]))
2914637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2915637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2916acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic void
2917acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_sections (Ebl *ebl, GElf_Ehdr *ehdr)
2918acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper{
2919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_shoff == 0)
2920b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* No section header.  */
2921b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
2922b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2923b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Allocate array to count references in section groups.  */
2924b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  scnref = (int *) xcalloc (shnum, sizeof (int));
2925b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2926b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the zeroth section first.  It must not have any contents
2927b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     and the section header must contain nonzero value at most in the
2928b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     sh_size and sh_link fields.  */
2929acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr shdr_mem;
2930acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
2931b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr == NULL)
2932b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("cannot get section header of zeroth section\n"));
2933b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2934b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2935b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_name != 0)
2936b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero name\n"));
2937b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type != 0)
2938b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero type\n"));
2939b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags != 0)
2940b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero flags\n"));
2941b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_addr != 0)
2942b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero address\n"));
2943b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_offset != 0)
2944b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero offset\n"));
2945b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_info != 0)
2946b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero info field\n"));
2947b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_addralign != 0)
2948b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero align value\n"));
2949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_entsize != 0)
2950b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero entry size value\n"));
2951b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2952b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_size != 0 && ehdr->e_shnum != 0)
2953b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2954b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperzeroth section has nonzero size value while ELF header has nonzero shnum value\n"));
2955b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2956b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX)
2957b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2958b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperzeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n"));
2959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2960b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2961acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  bool dot_interp_section = false;
2962b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2963dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  size_t versym_scnndx = 0;
2964acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 1; cnt < shnum; ++cnt)
2965acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
2966acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      shdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &shdr_mem);
2967b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr == NULL)
2968b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2969b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
2970b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot get section header for section [%2zu] '%s': %s\n"),
2971b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, section_name (ebl, cnt), elf_errmsg (-1));
2972b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
2973b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2974b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
2976b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2977b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (scnname == NULL)
2978b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2zu]: invalid name\n"), cnt);
2979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
2980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Check whether it is one of the special sections defined in
2982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     the gABI.  */
2983b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t s;
2984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (s = 0; s < nspecial_sections; ++s)
2985b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (strncmp (scnname, special_sections[s].name,
2986b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 special_sections[s].namelen) == 0)
2987b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
2988b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf1[100];
2989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf2[100];
2990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf3[100];
2991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2992653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		GElf_Word good_type = special_sections[s].type;
2993653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		if (special_sections[s].namelen == sizeof ".plt" &&
2994653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    !memcmp (special_sections[s].name, ".plt", sizeof ".plt")
2995c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    && ebl_bss_plt_p (ebl, ehdr))
2996653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  good_type = SHT_NOBITS;
2997653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
2998653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		if (shdr->sh_type != good_type
2999b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    && !(is_debuginfo && shdr->sh_type == SHT_NOBITS))
3000b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  ERROR (gettext ("\
3001b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' has wrong type: expected %s, is %s\n"),
3002b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 (int) cnt, scnname,
3003b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 ebl_section_type_name (ebl, special_sections[s].type,
3004b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						stbuf1, sizeof (stbuf1)),
3005b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 ebl_section_type_name (ebl, shdr->sh_type,
3006b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						stbuf2, sizeof (stbuf2)));
3007b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3008b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (special_sections[s].attrflag == exact)
3009b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3010b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* Except for the link order and group bit all the
3011b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       other bits should match exactly.  */
3012b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP))
3013b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			!= special_sections[s].attr)
3014b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3015b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has wrong flags: expected %s, is %s\n"),
3016b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname,
3017b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr,
3018b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf1, sizeof (stbuf1)),
3019b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (shdr->sh_flags
3020b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   & ~SHF_LINK_ORDER,
3021b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf2, sizeof (stbuf2)));
3022b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3023b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else if (special_sections[s].attrflag == atleast)
3024b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3025b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & special_sections[s].attr)
3026b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			!= special_sections[s].attr
3027b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			|| ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP
3028b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						| special_sections[s].attr
3029b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						| special_sections[s].attr2))
3030b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    != 0))
3031b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3032b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"),
3033b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname,
3034b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr,
3035b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf1, sizeof (stbuf1)),
3036b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr2,
3037b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf2, sizeof (stbuf2)),
3038b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (shdr->sh_flags
3039b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   & ~(SHF_LINK_ORDER
3040b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						       | SHF_GROUP),
3041b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf3, sizeof (stbuf3)));
3042b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3043b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3044b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (strcmp (scnname, ".interp") == 0)
3045b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3046b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    dot_interp_section = true;
3047b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3048b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (ehdr->e_type == ET_REL)
3049b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3050b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' present in object file\n"),
3051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3052b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !has_loadable_segment)
3055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     && has_loadable_segment)
3060b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3064b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
3065b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3066b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (strcmp (scnname, ".symtab_shndx") == 0
3067b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& ehdr->e_type != ET_REL)
3068b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3069b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' is extension section index table in non-object file\n"),
3070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3071b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3072b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* These sections must have the SHF_ALLOC flag set iff
3073b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       a loadable segment is available.
3074b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .relxxx
3076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .strtab
3077b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .symtab
3078b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .symtab_shndx
3079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3080b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       Check that if there is a reference from the
3081b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       loaded section these sections also have the
3082b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       ALLOC flag set.  */
3083b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if 0
3084b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    // XXX TODO
3085b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3086b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !has_loadable_segment)
3087b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3091b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     && has_loadable_segment)
3092b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3093b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3094b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
3096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3098b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		break;
3099b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
3100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize)
3103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': size not multiple of entry size\n"),
3105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL)
3108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("cannot get section header\n"));
3109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type >= SHT_NUM
3111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_LIBLIST
3112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_CHECKSUM
3113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_verdef
3114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_verneed
311518e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && shdr->sh_type != SHT_GNU_versym
311618e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && ebl_section_type_name (ebl, shdr->sh_type, NULL, 0) == NULL)
311718e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	ERROR (gettext ("section [%2zu] '%s' has unsupported type %d\n"),
311818e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	       cnt, section_name (ebl, cnt),
311918e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	       (int) shdr->sh_type);
3120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \
3122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \
3123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS)
3124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags & ~ALL_SH_FLAGS)
312518e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	ERROR (gettext ("section [%2zu] '%s' contains unknown flag(s)"
312618e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath			" %#" PRIx64 "\n"),
3127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt),
312818e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	       (uint64_t) shdr->sh_flags & ~(uint64_t) ALL_SH_FLAGS);
3129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (shdr->sh_flags & SHF_TLS)
3130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX Correct?
3132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr->sh_addr != 0 && !gnuld)
3133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': thread-local data sections address not zero\n"),
3135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, section_name (ebl, cnt));
3136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX TODO more tests!?
3138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_link >= shnum)
3141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': invalid section reference in link value\n"),
3143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum)
3146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': invalid section reference in info value\n"),
3148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_flags & SHF_MERGE) == 0
3151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && (shdr->sh_flags & SHF_STRINGS) != 0
3152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && be_strict)
3153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': strings flag set without merge flag\n"),
3155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0)
3158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': merge flag set but entry size is zero\n"),
3160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags & SHF_GROUP)
3163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	check_scn_group (ebl, cnt);
3164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0)
3166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Make sure the section is contained in a loaded segment
3168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     and that the initialization part matches NOBITS sections.  */
3169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  int pcnt;
3170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Phdr phdr_mem;
3171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Phdr *phdr;
3172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
3174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL
3175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& ((phdr->p_type == PT_LOAD
3176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     && (shdr->sh_flags & SHF_TLS) == 0)
3177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    || (phdr->p_type == PT_TLS
3178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& (shdr->sh_flags & SHF_TLS) != 0))
3179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& phdr->p_offset <= shdr->sh_offset
3180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& phdr->p_offset + phdr->p_memsz > shdr->sh_offset)
3181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
3182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* Found the segment.  */
3183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (phdr->p_offset + phdr->p_memsz
3184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    < shdr->sh_offset + shdr->sh_size)
3185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  ERROR (gettext ("\
3186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' not fully contained in segment of program header entry %d\n"),
3187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
3188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (shdr->sh_type == SHT_NOBITS)
3190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz
3192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !is_debuginfo)
3193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"),
3195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
3196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
3198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3199653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    const GElf_Off end = phdr->p_offset + phdr->p_filesz;
3200653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    if (shdr->sh_offset > end ||
3201653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			(shdr->sh_offset == end && shdr->sh_size != 0))
3202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"),
3204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
3205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		break;
3208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
3209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (pcnt == ehdr->e_phnum)
3211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': alloc flag set but section not in any loaded segment\n"),
3213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, section_name (ebl, cnt));
3214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB)
3217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"),
3219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      switch (shdr->sh_type)
3222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNSYM:
3224acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  if (ehdr->e_type == ET_REL)
3225acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    ERROR (gettext ("\
3226acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"),
3227acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper		   cnt, section_name (ebl, cnt));
3228acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  /* FALLTHROUGH */
3229acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_SYMTAB:
3230dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  check_symtab (ebl, ehdr, shdr, cnt);
3231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_RELA:
3234c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  check_rela (ebl, ehdr, shdr, cnt);
3235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_REL:
3238c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  check_rel (ebl, ehdr, shdr, cnt);
3239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNAMIC:
3242607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  check_dynamic (ebl, ehdr, shdr, cnt);
3243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_SYMTAB_SHNDX:
3246acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  check_symtab_shndx (ebl, ehdr, shdr, cnt);
3247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_HASH:
325028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	case SHT_GNU_HASH:
325128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
3252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_NULL:
3255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  check_null (ebl, shdr, cnt);
3256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_GROUP:
3259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  check_group (ebl, ehdr, shdr, cnt);
3260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_GNU_versym:
3263dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* We cannot process this section now since we have no guarantee
3264dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     that the verneed and verdef sections have already been read.
3265dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     Just remember the section index.  */
3266dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (versym_scnndx != 0)
3267dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("more than one version symbol table present\n"));
3268dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  versym_scnndx = cnt;
3269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3271acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_GNU_verneed:
3272dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  check_verneed (ebl, ehdr, shdr, cnt);
3273acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  break;
3274acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3275acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_GNU_verdef:
3276acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  check_verdef (ebl, shdr, cnt);
3277acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  break;
3278acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	default:
3280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Nothing.  */
3281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (has_interp_segment && !dot_interp_section)
3286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("INTERP program header entry but no .interp section\n"));
3287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3288dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (version_namelist != NULL)
3289dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
3290dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (versym_scnndx == 0)
3291dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("\
3292dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperno .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section exist\n"));
3293dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      else
3294dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	check_versym (ebl, versym_scnndx);
3295dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3296dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Check for duplicate index numbers.  */
3297dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      do
3298dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3299dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *runp = version_namelist->next;
3300dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  while (runp != NULL)
3301dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
3302dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (version_namelist->ndx == runp->ndx)
3303dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		{
3304dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  ERROR (gettext ("duplicate version index %d\n"),
3305dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 (int) version_namelist->ndx);
3306dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  break;
3307dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		}
3308dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      runp = runp->next;
3309dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
3310dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3311dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *old = version_namelist;
3312dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  version_namelist = version_namelist->next;
3313dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  free (old);
3314dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3315dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      while (version_namelist != NULL);
3316dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3317dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  else if (versym_scnndx != 0)
3318dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("\
3319dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper.gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"));
3320dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  free (scnref);
3322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
3323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
3326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt)
3327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
3328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
3329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
3330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
3331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperphdr[%d]: no note entries defined for the type of file\n"),
3332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   cnt);
3333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (is_debuginfo)
3335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* The p_offset values in a separate debug file are bogus.  */
3336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
3337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *notemem = gelf_rawchunk (ebl->elf, phdr->p_offset, phdr->p_filesz);
3339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* ELF64 files often use note section entries in the 32-bit format.
3341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     The p_align field is set to 8 in case the 64-bit format is used.
3342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     In case the p_align value is 0 or 4 the 32-bit format is
3343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     used.  */
3344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Xword align = phdr->p_align == 0 || phdr->p_align == 4 ? 4 : 8;
3345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
3346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Xword idx = 0;
3348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (idx < phdr->p_filesz)
3349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      uint64_t namesz;
3351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      uint64_t descsz;
3352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      uint64_t type;
3353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      uint32_t namesz32;
3354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      uint32_t descsz32;
3355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (align == 4)
3357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  uint32_t *ptr = (uint32_t *) (notemem + idx);
3359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if ((__BYTE_ORDER == __LITTLE_ENDIAN
3361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
3362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      || (__BYTE_ORDER == __BIG_ENDIAN
3363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
3364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz32 = namesz = bswap_32 (*ptr);
3366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++ptr;
3367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz32 = descsz = bswap_32 (*ptr);
3368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++ptr;
3369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      type = bswap_32 (*ptr);
3370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
3372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz32 = namesz = *ptr++;
3374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz32 = descsz = *ptr++;
3375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      type = *ptr;
3376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
3379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  uint64_t *ptr = (uint64_t *) (notemem + idx);
3381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  uint32_t *ptr32 = (uint32_t *) (notemem + idx);
3382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if ((__BYTE_ORDER == __LITTLE_ENDIAN
3384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
3385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      || (__BYTE_ORDER == __BIG_ENDIAN
3386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
3387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz = bswap_64 (*ptr);
3389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++ptr;
3390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz = bswap_64 (*ptr);
3391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++ptr;
3392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      type = bswap_64 (*ptr);
3393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz32 = bswap_32 (*ptr32);
3395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++ptr32;
3396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz32 = bswap_32 (*ptr32);
3397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
3399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz = *ptr++;
3401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz = *ptr++;
3402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      type = *ptr;
3403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz32 = *ptr32++;
3405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz32 = *ptr32;
3406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (idx + 3 * align > phdr->p_filesz
3410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || (idx + 3 * align + ALIGNED_LEN (namesz) + ALIGNED_LEN (descsz)
3411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      > phdr->p_filesz))
3412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (ehdr->e_ident[EI_CLASS] == ELFCLASS64
3414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && idx + 3 * 4 <= phdr->p_filesz
3415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && (idx + 3 * 4 + ALIGNED_LEN (namesz32) + ALIGNED_LEN (descsz32)
3416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  <= phdr->p_filesz))
3417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperphdr[%d]: note entries probably in form of a 32-bit ELF file\n"), cnt);
3419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
3420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("phdr[%d]: extra %zu bytes after last note\n"),
3421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, (size_t) (phdr->p_filesz - idx));
3422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Make sure it is one of the note types we know about.  */
3426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type == ET_CORE)
3427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  switch (type)
3429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PRSTATUS:
3431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_FPREGSET:
3432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PRPSINFO:
3433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_TASKSTRUCT:		/* NT_PRXREG on Solaris.  */
3434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PLATFORM:
3435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_AUXV:
3436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_GWINDOWS:
3437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_ASRS:
3438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PSTATUS:
3439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PSINFO:
3440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PRCRED:
3441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_UTSNAME:
3442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_LWPSTATUS:
3443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_LWPSINFO:
3444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PRFPXREG:
3445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Known type.  */
3446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      break;
3447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    default:
3449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
3450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperphdr[%d]: unknown core file note type %" PRIu64 " at offset %" PRIu64 "\n"),
3451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     cnt, type, idx);
3452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
3455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (type != NT_VERSION)
3457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperphdr[%d]: unknown object file note type %" PRIu64 " at offset %" PRIu64 "\n"),
3459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, type, idx);
3460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Move to the next entry.  */
3463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      idx += 3 * align + ALIGNED_LEN (namesz) + ALIGNED_LEN (descsz);
3464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  gelf_freechunk (ebl->elf, notemem);
3468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
3469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
3472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
3473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
3474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_phoff == 0)
3475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
3476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
3478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_CORE)
3479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
3480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperonly executables, shared objects, and core files can have program headers\n"));
3481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_interp = 0;
3483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_tls = 0;
3484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_relro = 0;
3485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (int cnt = 0; cnt < ehdr->e_phnum; ++cnt)
3487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr phdr_mem;
3489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr *phdr;
3490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
3492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr == NULL)
3493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("cannot get program header entry %d: %s\n"),
3495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, elf_errmsg (-1));
3496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
3497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME
3500f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  && phdr->p_type != PT_GNU_STACK && phdr->p_type != PT_GNU_RELRO
3501f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  /* Check for a known machine-specific type.  */
3502f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  && ebl_segment_type_name (ebl, phdr->p_type, NULL, 0) == NULL)
3503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3504f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrathprogram header entry %d: unknown program header entry type %#" PRIx64 "\n"),
3505f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	       cnt, (uint64_t) phdr->p_type);
3506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_type == PT_LOAD)
3508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	has_loadable_segment = true;
3509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_INTERP)
3510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_interp != 1)
3512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (num_pt_interp == 2)
3514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
3515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermore than one INTERP entry in program header\n"));
3516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  has_interp_segment = true;
3518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_TLS)
3520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_tls == 2)
3522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("more than one TLS entry in program header\n"));
3523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_NOTE)
3525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	check_note (ebl, ehdr, phdr, cnt);
352641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      else if (phdr->p_type == PT_DYNAMIC)
352741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
352841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  if (ehdr->e_type == ET_EXEC && ! has_interp_segment)
352941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    ERROR (gettext ("\
353041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic executable cannot have dynamic sections\n"));
353141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  else
353241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    {
353341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      /* Check that the .dynamic section, if it exists, has
353441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 the same address.  */
353541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      Elf_Scn *scn = NULL;
353641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
353741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		{
353841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr shdr_mem;
353941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
354041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
354141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    {
354241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      if (phdr->p_offset != shdr->sh_offset)
354341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			ERROR (gettext ("\
354441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperdynamic section reference in program header has wrong offset\n"));
354541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      if (phdr->p_memsz != shdr->sh_size)
354641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			ERROR (gettext ("\
354741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperdynamic section size mismatch in program and section header\n"));
354841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      break;
354941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    }
355041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		}
355141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    }
355241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
3553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_GNU_RELRO)
3554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_relro == 2)
3556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermore than one GNU_RELRO entry in program header\n"));
3558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
3559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Check that the region is in a writable segment.  */
3561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      int inner;
3562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      for (inner = 0; inner < ehdr->e_phnum; ++inner)
3563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
3564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Phdr phdr2_mem;
3565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Phdr *phdr2;
3566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
3568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (phdr2 == NULL)
3569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    continue;
3570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (phdr2->p_type == PT_LOAD
3572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && phdr->p_vaddr >= phdr2->p_vaddr
3573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && (phdr->p_vaddr + phdr->p_memsz
3574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  <= phdr2->p_vaddr + phdr2->p_memsz))
3575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
3576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if ((phdr2->p_flags & PF_W) == 0)
3577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
3578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperloadable segment GNU_RELRO applies to is not writable\n"));
3579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if ((phdr2->p_flags & PF_X) != 0)
3580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
3581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperloadable segment GNU_RELRO applies to is executable\n"));
3582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      break;
3583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
3584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
3585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (inner >= ehdr->e_phnum)
3587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
3588607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper%s segment not contained in a loaded segment\n"), "GNU_RELRO");
3589607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
3590607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	}
3591607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      else if (phdr->p_type == PT_PHDR)
3592607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	{
3593607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* Check that the region is in a writable segment.  */
3594607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  int inner;
3595607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  for (inner = 0; inner < ehdr->e_phnum; ++inner)
3596607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
3597607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr phdr2_mem;
3598607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr *phdr2;
3599607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
3600607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
3601607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      if (phdr2 != NULL
3602607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr2->p_type == PT_LOAD
3603607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr >= phdr2->p_vaddr
3604607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && (phdr->p_vaddr + phdr->p_memsz
3605607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		      <= phdr2->p_vaddr + phdr2->p_memsz))
3606607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		break;
3607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3608607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
3609607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (inner >= ehdr->e_phnum)
3610607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    ERROR (gettext ("\
3611607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper%s segment not contained in a loaded segment\n"), "PHDR");
3612607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
3613607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* Check that offset in segment corresponds to offset in ELF
3614607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	     header.  */
3615607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (phdr->p_offset != ehdr->e_phoff)
3616607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    ERROR (gettext ("\
3617607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepperprogram header offset in ELF header and PHDR entry do not match"));
3618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_filesz > phdr->p_memsz)
3621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: file size greater than memory size\n"),
3623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt);
3624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_align > 1)
3626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (!powerof2 (phdr->p_align))
3628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: alignment not a power of 2\n"), cnt);
3630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0)
3631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: file offset and virtual address not module of alignment\n"), cnt);
3633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
3636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Process one file.  */
3639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
3640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprocess_elf_file (Elf *elf, const char *prefix, const char *suffix,
3641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  const char *fname, size_t size, bool only_one)
3642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
3643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Reset variables.  */
3644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ndynamic = 0;
3645acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  nverneed = 0;
3646acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  nverdef = 0;
364741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  textrel = false;
364841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  needed_textrel = false;
3649acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  has_loadable_segment = false;
3650acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  has_interp_segment = false;
3651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr ehdr_mem;
3653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
3654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Ebl *ebl;
3655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Print the file name.  */
3657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (!only_one)
3658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (prefix != NULL)
3660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	printf ("\n%s(%s)%s:\n", prefix, fname, suffix);
3661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
3662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	printf ("\n%s:\n", fname);
3663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr == NULL)
3666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("cannot read ELF header: %s\n"), elf_errmsg (-1));
3668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
3669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl = ebl_openbackend (elf);
3672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If there is no appropriate backend library we cannot test
3673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     architecture and OS specific features.  Any encountered extension
3674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     is an error.  */
3675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Go straight by the gABI, check all the parts in turn.  */
3677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_elf_header (ebl, ehdr, size);
3678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the program header.  */
3680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_program_header (ebl, ehdr);
3681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Next the section headers.  It is OK if there are no section
3683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     headers at all.  */
3684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_sections (ebl, ehdr);
3685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
368641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* Report if no relocation section needed the text relocation flag.  */
368741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (textrel && !needed_textrel)
368841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    ERROR (gettext ("text relocation flag set but not needed\n"));
368941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
3690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Free the resources.  */
3691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl_closebackend (ebl);
3692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
3693