elflint.c revision b0243863149acde9e42b25688c7c2959830e69a9
1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Pedantic checking of ELF files compliance with gABI/psABI spec.
2b770cf9d1045bde04a1d89c63f4d7eb261ff78daUlrich Drepper   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 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.  */
134b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  textdomain (PACKAGE_TARNAME);
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{
231b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  fprintf (stream, "elflint (%s) %s\n", PACKAGE_NAME, PACKAGE_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\
236b770cf9d1045bde04a1d89c63f4d7eb261ff78daUlrich Drepper"), "2007");
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,
334c373d850ec9ca342f4c71d5e287c8d8bf0723cd6Roland McGrath    EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA, EM_ALPHA
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)
734ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			{
735ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			  /* GNU ld has severe bugs.  When it decides to remove
736ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			     empty sections it leaves symbols referencing them
737ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			     behind.  These are symbols in .symtab.  */
738ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			  if (!gnuld
739ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			      || strcmp (section_name (ebl, idx), ".symtab")
740ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			      || (strcmp (name, "__preinit_array_start") != 0
741ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__preinit_array_end") != 0
742ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__init_array_start") != 0
743ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__init_array_end") != 0
744ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__fini_array_start") != 0
745ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__fini_array_end") != 0))
746ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			    ERROR (gettext ("\
747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds\n"),
748ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				   idx, section_name (ebl, idx), cnt);
749ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			}
750c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		      else if ((sym->st_value - destshdr->sh_addr
751c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper				+ sym->st_size) > destshdr->sh_size)
752c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
754c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx), cnt,
755c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (int) xndx, section_name (ebl, xndx));
756c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    }
757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if ((destshdr->sh_flags & SHF_TLS) == 0)
761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_TLS flag set\n"),
763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx), cnt,
764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   (int) xndx, section_name (ebl, xndx));
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (ehdr->e_type == ET_REL)
767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      /* For object files the symbol value must fall
769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper                         into the section.  */
770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (sym->st_value > destshdr->sh_size)
771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       idx, section_name (ebl, idx), cnt,
774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       (int) xndx, section_name (ebl, xndx));
775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      else if (sym->st_value + sym->st_size
776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       > destshdr->sh_size)
777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       idx, section_name (ebl, idx), cnt,
780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       (int) xndx, section_name (ebl, xndx));
781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  else
783b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
784b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Phdr phdr_mem;
785b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Phdr *phdr = NULL;
786b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      int pcnt;
787b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
788b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
789b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
790b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
791b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (phdr != NULL && phdr->p_type == PT_TLS)
792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    break;
793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (pcnt == ehdr->e_phnum)
796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (no_pt_tls++ == 0)
798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"),
800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt);
801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
802b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      else
803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (sym->st_value
805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      < destshdr->sh_offset - phdr->p_offset)
806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"),
808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  else if (sym->st_value
811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   > (destshdr->sh_offset - phdr->p_offset
812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				      + destshdr->sh_size))
813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
814b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
815b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
816b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
817b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  else if (sym->st_value + sym->st_size
818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   > (destshdr->sh_offset - phdr->p_offset
819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				      + destshdr->sh_size))
820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt >= shdr->sh_info)
833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
834b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: local symbol outside range described in sh_info\n"),
835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
836b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
837b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt < shdr->sh_info)
840b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: non-local symbol outside range described in sh_info\n"),
842b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
843b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
844b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
845b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
847b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: non-local section symbol\n"),
849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
851b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (name != NULL)
852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
853b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
855653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      /* Check that address and size match the global offset table.  */
856653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
857653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      GElf_Shdr destshdr_mem;
858653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx),
859653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						  &destshdr_mem);
860653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
861653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (destshdr == NULL && xndx == SHN_ABS)
862b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
863653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  /* In a DSO, we have to find the GOT section by name.  */
864653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  Elf_Scn *gotscn = NULL;
865c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  Elf_Scn *gscn = NULL;
866653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL)
867b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
868653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      destshdr = gelf_getshdr (gscn, &destshdr_mem);
869653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      assert (destshdr != NULL);
870653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      const char *sname = elf_strptr (ebl->elf,
871653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						      ehdr->e_shstrndx,
872653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						      destshdr->sh_name);
873653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      if (sname != NULL)
874b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
875c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  if (strcmp (sname, ".got.plt") == 0)
876653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    break;
877c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  if (strcmp (sname, ".got") == 0)
878653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    /* Do not stop looking.
879653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			       There might be a .got.plt section.  */
880653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    gotscn = gscn;
881b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
882653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
883653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      destshdr = NULL;
884b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
885653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
886653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  if (destshdr == NULL && gotscn != NULL)
887653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    destshdr = gelf_getshdr (gotscn, &destshdr_mem);
888b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
889b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
890653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      const char *sname = (destshdr == NULL ? NULL
891653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath				   : elf_strptr (ebl->elf, ehdr->e_shstrndx,
892653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						 destshdr->sh_name));
893653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (sname == NULL)
894653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		ERROR (gettext ("\
895653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section\n"),
896653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		       idx, section_name (ebl, idx));
897653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      else if (strcmp (sname, ".got.plt") != 0
898653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		       && strcmp (sname, ".got") != 0)
899653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		ERROR (gettext ("\
900653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to '%s' section\n"),
901653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		       idx, section_name (ebl, idx), sname);
902653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
903653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (destshdr != NULL)
904b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Found it.  */
906c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  if (!ebl_check_special_symbol (ebl, ehdr, sym, name,
907c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper						 destshdr))
908c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    {
909c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		      if (sym->st_value != destshdr->sh_addr)
910c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			/* This test is more strict than the psABIs which
911c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			   usually allow the symbol to be in the middle of
912c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			   the .got section, allowing negative offsets.  */
913c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
914653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match %s section address %#" PRIx64 "\n"),
915c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx),
916c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (uint64_t) sym->st_value,
917c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       sname, (uint64_t) destshdr->sh_addr);
918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
919c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		      if (!gnuld && sym->st_size != destshdr->sh_size)
920c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
921653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match %s section size %" PRIu64 "\n"),
922c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx),
923c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (uint64_t) sym->st_size,
924c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       sname, (uint64_t) destshdr->sh_size);
925c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    }
926b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
927b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
928b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
929b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"),
930b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx));
931b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
932b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (strcmp (name, "_DYNAMIC") == 0)
93341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    /* Check that address and size match the dynamic section.
93441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	       We locate the dynamic section via the program header
93541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	       entry.  */
93641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    for (int pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
93741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      {
93841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Phdr phdr_mem;
93941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
940b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
94141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
94241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  {
94341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    if (sym->st_value != phdr->p_vaddr)
94441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      ERROR (gettext ("\
945b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"),
94641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     idx, section_name (ebl, idx),
94741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) sym->st_value,
94841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) phdr->p_vaddr);
949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
95041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    if (!gnuld && sym->st_size != phdr->p_memsz)
95141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      ERROR (gettext ("\
952b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"),
95341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     idx, section_name (ebl, idx),
95441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) sym->st_size,
95541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) phdr->p_memsz);
956b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
95741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    break;
95841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  }
959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
960b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
961b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
962b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
963b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
964b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
965b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool
966c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperis_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr,
96728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    bool is_rela)
968b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
969b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If this is no executable or DSO it cannot be a .rel.dyn section.  */
970b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
971b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return false;
972b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
973b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the section name.  Unfortunately necessary.  */
97428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (strcmp (section_name (ebl, idx), is_rela ? ".rela.dyn" : ".rel.dyn"))
975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return false;
976b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
977b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section
978b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     entry can be present as well.  */
979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn = NULL;
980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr rcshdr_mem;
983b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem);
984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      assert (rcshdr != NULL);
985b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
986b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rcshdr->sh_type == SHT_DYNAMIC)
987b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
988b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Found the dynamic section.  Look through it.  */
989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  Elf_Data *d = elf_getdata (scn, NULL);
990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t cnt;
991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
992b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt)
993b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
994b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Dyn dyn_mem;
995b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem);
996b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      assert (dyn != NULL);
997b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
998b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (dyn->d_tag == DT_RELCOUNT)
999b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
100028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  /* Found it.  Does the type match.  */
100128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if (is_rela)
1002b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
100328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELCOUNT used for this RELA section\n"),
100428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx));
100528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  else
100628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    {
100728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Does the number specified number of relative
100828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations exceed the total number of
100928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations?  */
101028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
101128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			ERROR (gettext ("\
1012b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
101328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       idx, section_name (ebl, idx),
101428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       (int) dyn->d_un.d_val);
101528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
101628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Make sure the specified number of relocations are
101728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relative.  */
101828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
101928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper								   idx), NULL);
102028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (reldata != NULL)
102128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			for (size_t inner = 0;
102228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     inner < shdr->sh_size / shdr->sh_entsize;
102328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     ++inner)
102428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  {
102528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rel rel_mem;
102628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rel *rel = gelf_getrel (reldata, inner,
102728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							 &rel_mem);
102828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (rel == NULL)
102928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      /* The problem will be reported elsewhere.  */
103028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      break;
103128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
103228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (ebl_relative_reloc_p (ebl,
103328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						      GELF_R_TYPE (rel->r_info)))
103428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      {
103528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				if (inner >= dyn->d_un.d_val)
103628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				  ERROR (gettext ("\
103728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
103828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 idx, section_name (ebl, idx),
103928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 (int) dyn->d_un.d_val);
104028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      }
104128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    else if (inner < dyn->d_un.d_val)
104228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      ERROR (gettext ("\
104328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
104428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     idx, section_name (ebl, idx),
104528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     inner, (int) dyn->d_un.d_val);
104628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  }
104728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    }
104828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		}
104928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
105028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      if (dyn->d_tag == DT_RELACOUNT)
105128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		{
105228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  /* Found it.  Does the type match.  */
105328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if (!is_rela)
105428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    ERROR (gettext ("\
105528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELACOUNT used for this REL section\n"),
105628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx));
105728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  else
105828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    {
105928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Does the number specified number of relative
106028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations exceed the total number of
106128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations?  */
106228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
106328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			ERROR (gettext ("\
106428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
106528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       idx, section_name (ebl, idx),
106628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       (int) dyn->d_un.d_val);
106728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
106828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Make sure the specified number of relocations are
106928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relative.  */
107028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
107128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper								   idx), NULL);
107228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (reldata != NULL)
107328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			for (size_t inner = 0;
107428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     inner < shdr->sh_size / shdr->sh_entsize;
107528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     ++inner)
107628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  {
107728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rela rela_mem;
107828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rela *rela = gelf_getrela (reldata, inner,
107928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							    &rela_mem);
108028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (rela == NULL)
108128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      /* The problem will be reported elsewhere.  */
108228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      break;
108328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
108428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (ebl_relative_reloc_p (ebl,
108528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						      GELF_R_TYPE (rela->r_info)))
108628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      {
108728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				if (inner >= dyn->d_un.d_val)
108828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				  ERROR (gettext ("\
108928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
109028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 idx, section_name (ebl, idx),
109128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 (int) dyn->d_un.d_val);
109228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      }
109328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    else if (inner < dyn->d_un.d_val)
109428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      ERROR (gettext ("\
109528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
109628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     idx, section_name (ebl, idx),
109728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     inner, (int) dyn->d_un.d_val);
109828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  }
109928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    }
1100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return true;
1108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
111141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstruct loaded_segment
111241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper{
111341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Addr from;
111441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Addr to;
111541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  bool read_only;
111641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *next;
111741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper};
111841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
111941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
112041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper/* Check whether binary has text relocation flag set.  */
112141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic bool textrel;
112241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
112341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper/* Keep track of whether text relocation flag is needed.  */
112441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic bool needed_textrel;
112541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
112641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1127c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic bool
1128c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr,
1129c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		  int idx, int reltype, GElf_Shdr **destshdrp,
113041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr *destshdr_memp, struct loaded_segment **loadedp)
1131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool reldyn = false;
1133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check whether the link to the section we relocate is reasonable.  */
1135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info >= shnum)
1136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"),
1137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1138c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  else if (shdr->sh_info != 0)
1139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1140c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      *destshdrp = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1141c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper				 destshdr_memp);
1142c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (*destshdrp != NULL)
1143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1144c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  if((*destshdrp)->sh_type != SHT_PROGBITS
1145c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	     && (*destshdrp)->sh_type != SHT_NOBITS)
1146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true);
1148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (!reldyn)
1149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
1150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': invalid destination section type\n"),
1151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx));
1152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
1153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
1154c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		  /* There is no standard, but we require that .rel{,a}.dyn
1155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     sections have a sh_info value of zero.  */
1156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (shdr->sh_info != 0)
1157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
1158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': sh_info should be zero\n"),
1159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx));
1160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1163c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  if (((*destshdrp)->sh_flags & (SHF_MERGE | SHF_STRINGS)) != 0)
1164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': no relocations for merge-able sections possible\n"),
1166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
1167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1170c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (shdr->sh_entsize != gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT))
1171c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext (reltype == ELF_T_RELA ? "\
1172c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Rela\n" : "\
1173c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Rel\n"),
1174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
117641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* In preparation of checking whether relocations are text
117741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     relocations or not we need to determine whether the file is
117841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     flagged to have text relocation and we need to determine a) what
117941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     the loaded segments are and b) which are read-only.  This will
118041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     also allow us to determine whether the same reloc section is
118141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     modifying loaded and not loaded segments.  */
118241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  for (int i = 0; i < ehdr->e_phnum; ++i)
118341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
118441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      GElf_Phdr phdr_mem;
118541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
118641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (phdr == NULL)
118741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	continue;
118841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
118941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (phdr->p_type == PT_LOAD)
119041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
119141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  struct loaded_segment *newp = xmalloc (sizeof (*newp));
119241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->from = phdr->p_vaddr;
119341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->to = phdr->p_vaddr + phdr->p_memsz;
119441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->read_only = (phdr->p_flags & PF_W) == 0;
119541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->next = *loadedp;
119641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  *loadedp = newp;
119741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
119841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      else if (phdr->p_type == PT_DYNAMIC)
119941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
120041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  Elf_Scn *dynscn = gelf_offscn (ebl->elf, phdr->p_offset);
120141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  GElf_Shdr dynshdr_mem;
120241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem);
120341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  Elf_Data *dyndata = elf_getdata (dynscn, NULL);
120441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC
120541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      && dyndata != NULL)
120641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j)
120741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      {
120841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Dyn dyn_mem;
120941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Dyn *dyn = gelf_getdyn (dyndata, j, &dyn_mem);
121041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		if (dyn != NULL
121141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    && (dyn->d_tag == DT_TEXTREL
121241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			|| (dyn->d_tag == DT_FLAGS
121341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			    && (dyn->d_un.d_val & DF_TEXTREL) != 0)))
121441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  {
121541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    textrel = true;
121641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    break;
121741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  }
121841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      }
121941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
122041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
122141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
122241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* A quick test which can be easily done here (although it is a bit
122341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     out of place): the text relocation flag makes only sense if there
122441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     is a segment which is not writable.  */
122541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (textrel)
122641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
122741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *seg = *loadedp;
122841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      while (seg != NULL && !seg->read_only)
122941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	seg = seg->next;
123041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (seg == NULL)
123141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	ERROR (gettext ("\
123241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Dreppertext relocation flag set but there is no read-only segment\n"));
123341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
123441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1235c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  return reldyn;
1236c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper}
1237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
123941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperenum load_state
124041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  {
124141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_undecided,
124241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_loaded,
124341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_unloaded,
124441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_error
124541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  };
124641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
124741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1248c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic void
1249607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppercheck_one_reloc (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *relshdr, int idx,
1250607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		 size_t cnt, const GElf_Shdr *symshdr, Elf_Data *symdata,
1251607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		 GElf_Addr r_offset, GElf_Xword r_info,
125241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 const GElf_Shdr *destshdr, bool reldyn,
125341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 struct loaded_segment *loaded, enum load_state *statep)
1254c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper{
1255c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool known_broken = gnuld;
1256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1257c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (r_info)))
1258c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"),
1259c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1260607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper  else if (((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1261607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    /* The executable/DSO can contain relocation sections with
1262607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	       all the relocations the linker has applied.  Those sections
1263607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	       are marked non-loaded, though.  */
1264607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    || (relshdr->sh_flags & SHF_ALLOC) != 0)
1265607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	   && !ebl_reloc_valid_use (ebl, GELF_R_TYPE (r_info)))
1266c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("\
1267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
1268c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1270c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (symshdr != NULL
1271c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      && ((GELF_R_SYM (r_info) + 1)
1272c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
1273c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  > symshdr->sh_size))
1274c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("\
1275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: invalid symbol index\n"),
1276c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
12786ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper  /* No more tests if this is a no-op relocation.  */
12796ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper  if (ebl_none_reloc_p (ebl, GELF_R_TYPE (r_info)))
12806ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper    return;
12816ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper
1282c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (r_info)))
1283c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1284c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      const char *name;
1285c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      char buf[64];
1286c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Sym sym_mem;
1287c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
1288c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (sym != NULL
1289c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  /* Get the name for the symbol.  */
1290c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1291c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
1292c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	ERROR (gettext ("\
1293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
1294c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	       idx, section_name (ebl, idx), cnt,
1295c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	       ebl_reloc_type_name (ebl, GELF_R_SYM (r_info),
1296c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper				    buf, sizeof (buf)));
1297c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1298b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1299c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (reldyn)
1300c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1301c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      // XXX TODO Check .rel.dyn section addresses.
1302c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1303c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  else if (!known_broken)
1304c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1305c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (destshdr != NULL
1306c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && GELF_R_TYPE (r_info) != 0
1307c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && (r_offset - destshdr->sh_addr) >= destshdr->sh_size)
1308c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	ERROR (gettext ("\
1309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: offset out of bounds\n"),
1310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1311c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
131341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Sym sym_mem;
131441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
131541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
131641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info))
1317c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      /* Make sure the referenced symbol is an object or unspecified.  */
131841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && sym != NULL
131941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE
132041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
132141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
132241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      char buf[64];
132341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      ERROR (gettext ("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"),
132441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	     idx, section_name (ebl, idx), cnt,
132541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	     ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
132641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				   buf, sizeof (buf)));
132741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
132841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1329038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper  if ((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1330038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      || (relshdr->sh_flags & SHF_ALLOC) != 0)
133141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
1332038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      bool in_loaded_seg = false;
1333038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      while (loaded != NULL)
1334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1335038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  if (r_offset < loaded->to
1336038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      && r_offset + (sym == NULL ? 0 : sym->st_size) >= loaded->from)
133741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    {
1338038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      /* The symbol is in this segment.  */
1339038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      if  (loaded->read_only)
1340038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		{
1341038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		  if (textrel)
1342038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		    needed_textrel = true;
1343038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		  else
1344038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		    ERROR (gettext ("section [%2d] '%s': relocation %zu: read-only section modified but text relocation flag not set\n"),
1345038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper			   idx, section_name (ebl, idx), cnt);
1346038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		}
1347038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper
1348038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      in_loaded_seg = true;
134941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    }
135041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1351038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  loaded = loaded->next;
1352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
135341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1354038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      if (*statep == state_undecided)
1355038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	*statep = in_loaded_seg ? state_loaded : state_unloaded;
1356038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      else if ((*statep == state_unloaded && in_loaded_seg)
1357038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	       || (*statep == state_loaded && !in_loaded_seg))
1358038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	{
1359038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  ERROR (gettext ("\
136041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Dreppersection [%2d] '%s': relocations are against loaded and unloaded data\n"),
1361038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		 idx, section_name (ebl, idx));
1362038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  *statep = state_error;
1363038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	}
1364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1369c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1371c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
1373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
1376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
1377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1379c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  /* Check the fields of the section header.  */
1380c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr destshdr_mem;
1381c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *destshdr = NULL;
138241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *loaded = NULL;
1383c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELA, &destshdr,
138441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				  &destshdr_mem, &loaded);
1385c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1386c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1387c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr symshdr_mem;
1388c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1389c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
139041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  enum load_state state = state_undecided;
1391c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1392c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1394c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rela rela_mem;
1395c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem);
1396c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (rela == NULL)
1397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1398c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  ERROR (gettext ("\
1399c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': cannot get relocation %zu: %s\n"),
1400c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1401c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  continue;
1402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1403c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1404607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1405607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       rela->r_offset, rela->r_info, destshdr, reldyn, loaded,
1406607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       &state);
140741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
140841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
140941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  while (loaded != NULL)
141041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
141141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *old = loaded;
141241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      loaded = loaded->next;
141341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      free (old);
1414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1415c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper}
1416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1417c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1418c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic void
1419c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1420c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper{
1421c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1422c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (data == NULL)
1423c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1424c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1425c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	     idx, section_name (ebl, idx));
1426c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      return;
1427c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1428c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1429c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  /* Check the fields of the section header.  */
1430c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr destshdr_mem;
1431c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *destshdr = NULL;
143241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *loaded = NULL;
1433c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_REL, &destshdr,
143441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				  &destshdr_mem, &loaded);
1435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
1438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
144041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  enum load_state state = state_undecided;
1441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1442c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Rel rel_mem;
1445c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem);
1446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rel == NULL)
1447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get relocation %zu: %s\n"),
1450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
1452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1454607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1455607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       rel->r_offset, rel->r_info, destshdr, reldyn, loaded,
1456607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       &state);
145741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
145841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
145941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  while (loaded != NULL)
146041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
146141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *old = loaded;
146241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      loaded = loaded->next;
146341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      free (old);
1464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Number of dynamic sections.  */
1469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int ndynamic;
1470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1473607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppercheck_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *data;
1476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr strshdr_mem;
1477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *strshdr;
1478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cnt;
1479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool dependencies[DT_NUM][DT_NUM] =
1480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_NEEDED] = { [DT_STRTAB] = true },
1482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTRELSZ] = { [DT_JMPREL] = true },
1483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_HASH] = { [DT_SYMTAB] = true },
1484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRTAB] = { [DT_STRSZ] = true },
1485231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_SYMENT] = true },
1486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true },
1487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELASZ] = { [DT_RELA] = true },
1488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELAENT] = { [DT_RELA] = true },
1489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRSZ] = { [DT_STRTAB] = true },
1490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMENT] = { [DT_SYMTAB] = true },
1491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SONAME] = { [DT_STRTAB] = true },
1492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RPATH] = { [DT_STRTAB] = true },
1493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true },
1494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELSZ] = { [DT_REL] = true },
1495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELENT] = { [DT_REL] = true },
1496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true },
1497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RUNPATH] = { [DT_STRTAB] = true },
1498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTREL] = { [DT_JMPREL] = true },
1499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTRELSZ] = { [DT_JMPREL] = true }
1500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool has_dt[DT_NUM];
1502231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  bool has_val_dt[DT_VALNUM];
1503231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  bool has_addr_dt[DT_ADDRNUM];
1504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool level2[DT_NUM] =
1505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RPATH] = true,
1507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMBOLIC] = true,
1508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_TEXTREL] = true,
1509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_BIND_NOW] = true
1510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool mandatory[DT_NUM] =
1512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_NULL] = true,
1514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRTAB] = true,
1515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMTAB] = true,
1516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRSZ] = true,
1517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMENT] = true
1518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Addr reladdr = 0;
1520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Word relsz = 0;
1521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Addr pltreladdr = 0;
1522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Word pltrelsz = 0;
1523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  memset (has_dt, '\0', sizeof (has_dt));
1525231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  memset (has_val_dt, '\0', sizeof (has_val_dt));
1526231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  memset (has_addr_dt, '\0', sizeof (has_addr_dt));
1527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (++ndynamic == 2)
1529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("more than one dynamic section present\n"));
1530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
153141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
1533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
1536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
1537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem);
1540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB)
1541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
1543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   shdr->sh_link, section_name (ebl, shdr->sh_link),
1544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT))
1547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Dyn\n"),
1549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info != 0)
1552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool non_null_warned = false;
1556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Dyn dyn_mem;
1559acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dyn_mem);
1560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn == NULL)
1561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get dynamic section entry %zu: %s\n"),
1564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
1566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned)
1569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"),
1572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx));
1573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  non_null_warned = true;
1574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (!ebl_dynamic_tag_check (ebl, dyn->d_tag))
1577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': entry %zu: unknown tag\n"),
1578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag >= 0 && dyn->d_tag < DT_NUM)
1581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (has_dt[dyn->d_tag]
1583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_NEEDED
1584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_NULL
1585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_POSFLAG_1)
1586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf[50];
1588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: more than one entry with tag %s\n"),
1590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt,
1591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   buf, sizeof (buf)));
1593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (be_strict && level2[dyn->d_tag])
1596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf[50];
1598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: level 2 tag %s used\n"),
1600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt,
1601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   buf, sizeof (buf)));
1603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  has_dt[dyn->d_tag] = true;
1606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1607231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      else if (dyn->d_tag <= DT_VALRNGHI
1608231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       && DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
1609231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	has_val_dt[DT_VALTAGIDX (dyn->d_tag)] = true;
1610231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      else if (dyn->d_tag <= DT_ADDRRNGHI
1611231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       && DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
1612231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	has_addr_dt[DT_ADDRTAGIDX (dyn->d_tag)] = true;
1613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL
1615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && dyn->d_un.d_val != DT_RELA)
1616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
1617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"),
1618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_REL)
1621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	reladdr = dyn->d_un.d_ptr;
1622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_RELSZ)
1623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	relsz = dyn->d_un.d_val;
1624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_JMPREL)
1625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	pltreladdr = dyn->d_un.d_ptr;
1626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_PLTRELSZ)
1627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	pltrelsz = dyn->d_un.d_val;
1628607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
1629607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      /* Check that addresses for entries are in loaded segments.  */
1630607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      switch (dyn->d_tag)
1631607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	{
1632607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  size_t n;
1633cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_STRTAB:
1634cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  /* We require the referenced section is the same as the one
1635cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	     specified in sh_link.  */
1636cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  if (strshdr->sh_addr != dyn->d_un.d_val)
1637cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    {
1638cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      ERROR (gettext ("\
1639cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Dreppersection [%2d] '%s': entry %zu: pointer does not match address of section [%2d] '%s' referenced by sh_link\n"),
1640cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1641cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1642cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      break;
1643cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    }
1644cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  goto check_addr;
1645cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper
1646607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	default:
1647607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (dyn->d_tag < DT_ADDRRNGLO || dyn->d_tag > DT_ADDRRNGHI)
1648607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    /* Value is no pointer.  */
1649607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    break;
1650607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* FALLTHROUGH */
1651607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
1652cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_AUXILIARY:
1653cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FILTER:
1654cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FINI:
1655cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FINI_ARRAY:
1656607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_HASH:
1657607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_INIT:
1658607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_INIT_ARRAY:
1659cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_JMPREL:
1660cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_PLTGOT:
1661cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_REL:
1662cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RELA:
1663cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SYMBOLIC:
1664cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SYMTAB:
1665607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_VERDEF:
1666607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_VERNEED:
1667cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_VERSYM:
1668cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	check_addr:
1669607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  for (n = 0; n < ehdr->e_phnum; ++n)
1670607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
1671607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr phdr_mem;
1672607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, n, &phdr_mem);
1673607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      if (phdr != NULL && phdr->p_type == PT_LOAD
1674607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr <= dyn->d_un.d_ptr
1675607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr + phdr->p_memsz > dyn->d_un.d_ptr)
1676607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		break;
1677607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
1678607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (unlikely (n >= ehdr->e_phnum))
1679607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
1680607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      char buf[50];
1681607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      ERROR (gettext ("\
1682607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppersection [%2d] '%s': entry %zu: %s value must point into loaded segment\n"),
1683607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1684607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1685607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper					   sizeof (buf)));
1686607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
1687cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  break;
1688cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper
1689cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_NEEDED:
1690cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RPATH:
1691cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RUNPATH:
1692cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SONAME:
1693cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  if (dyn->d_un.d_ptr >= strshdr->sh_size)
1694cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    {
1695cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      char buf[50];
1696cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      ERROR (gettext ("\
1697cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Dreppersection [%2d] '%s': entry %zu: %s value must be valid offset in section [%2d] '%s'\n"),
1698cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1699cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1700cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper					   sizeof (buf)),
1701cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1702cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    }
1703cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  break;
1704607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	}
1705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 1; cnt < DT_NUM; ++cnt)
1708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (has_dt[cnt])
1709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1710acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	for (int inner = 0; inner < DT_NUM; ++inner)
1711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (dependencies[cnt][inner] && ! has_dt[inner])
1712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf1[50];
1714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf2[50];
1715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': contains %s entry but not %s\n"),
1718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx),
1719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)),
1720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2)));
1721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    else
1724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (mandatory[cnt])
1726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
1727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    char buf[50];
1728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1729b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': mandatory tag %s not present\n"),
1730b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx),
1731b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf)));
1732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
1733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1735231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* Make sure we have an hash table.  */
1736231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (!has_dt[DT_HASH] && !has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)])
1737231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    ERROR (gettext ("\
1738231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': no hash section present\n"),
1739231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   idx, section_name (ebl, idx));
1740231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1741231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* The GNU-style hash table also needs a symbol table.  */
1742231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (!has_dt[DT_HASH] && has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)]
1743231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      && !has_dt[DT_SYMTAB])
1744231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    ERROR (gettext ("\
1745231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': contains %s entry but not %s\n"),
1746231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   idx, section_name (ebl, idx),
1747231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   "DT_GNU_HASH", "DT_SYMTAB");
1748231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the rel/rela tags.  At least one group must be available.  */
1750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT])
1751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT]))
1752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': not all of %s, %s, and %s are present\n"),
1754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
1755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   "DT_RELA", "DT_RELASZ", "DT_RELAENT");
1756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT])
1758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT]))
1759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': not all of %s, %s, and %s are present\n"),
1761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
1762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   "DT_REL", "DT_RELSZ", "DT_RELENT");
1763231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1764231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* Check that all prelink sections are present if any of them is.  */
1765231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)]
1766231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1767231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    {
1768231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)])
1769231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1770231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1771231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_PRELINKED");
1772231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1773231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1774231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1775231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_CHECKSUM");
1776231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1777231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      /* Only DSOs can be marked like this.  */
1778231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (ehdr->e_type != ET_DYN)
1779231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1780231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': non-DSO file marked as dependency during prelink\n"),
1781231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx));
1782231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    }
1783231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1784231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)]
1785231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)]
1786231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)]
1787231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1788231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    {
1789231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)])
1790231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1791231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1792231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_CONFLICTSZ");
1793231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)])
1794231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1795231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1796231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_LIBLISTSZ");
1797231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)])
1798231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1799231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1800231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_CONFLICT");
1801231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1802231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1803231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1804231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_LIBLIST");
1805231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    }
1806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1810acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1812acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (ehdr->e_type != ET_REL)
1813acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
1814acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      ERROR (gettext ("\
1815acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': only relocatable files can have extended section index\n"),
1816acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	     idx, section_name (ebl, idx));
1817acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      return;
1818acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    }
1819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1820acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1821acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr symshdr_mem;
1822acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB)
1824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended section index section not for symbol table\n"),
1826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1827acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
1828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symdata == NULL)
1829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("cannot get data for symbol section\n"));
1830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_entsize != sizeof (Elf32_Word))
1832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry size does not match Elf32_Word\n"),
1834b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1836b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL
1837b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (shdr->sh_size / shdr->sh_entsize
1838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  < symshdr->sh_size / symshdr->sh_entsize))
1839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1840b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended index table too small for symbol table\n"),
1841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1842b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1843b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info != 0)
1844b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1845b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1847acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = idx + 1; cnt < shnum; ++cnt)
1848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr rshdr_mem;
1850acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      GElf_Shdr *rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem);
1851b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX
1852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && rshdr->sh_link == shdr->sh_link)
1853b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1855b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"),
1856b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx),
1857b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, section_name (ebl, cnt));
1858b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1860b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1861b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1862acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1863b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1864b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (*((Elf32_Word *) data->d_buf) != 0)
1865b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("symbol 0 should have zero extended section index\n"));
1866b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1867acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1868b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1869b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt];
1870b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1871b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndx != 0)
1872b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1873b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Sym sym_data;
1874b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data);
1875b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym == NULL)
1876b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1877b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("cannot get data for symbol %zu\n"), cnt);
1878b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
1879b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1880b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1881b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym->st_shndx != SHN_XINDEX)
1882b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1883b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperextended section index is %" PRIu32 " but symbol index is not XINDEX\n"),
1884b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   (uint32_t) xndx);
1885b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1886b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1887b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1888b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1889b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1890b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
189128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
189228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		 GElf_Shdr *symshdr)
189328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
189428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
189528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
189628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
189728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
189828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    ERROR (gettext ("\
189928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
190028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
190128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
190228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
190328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t maxidx = nchain;
190428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
190528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (symshdr != NULL)
190628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
190728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
190828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
190928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
191028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
191128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx));
191228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
191328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      maxidx = symsize;
191428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
191528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
191628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
191728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
191828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx)
191928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
192028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash bucket reference %zu out of bounds\n"),
192128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2);
192228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
192328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (; cnt < 2 + nbucket + nchain; ++cnt)
192428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx)
192528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
192628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain reference %zu out of bounds\n"),
192728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2 - nbucket);
192828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
192928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
193028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
193128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
193228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
193328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		 GElf_Shdr *symshdr)
193428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
193528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
193628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
193728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
193828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
193928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    ERROR (gettext ("\
194028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
194128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
194228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
194328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
194428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t maxidx = nchain;
194528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
194628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (symshdr != NULL)
194728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
194828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
194928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
195028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
195128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
195228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx));
195328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
195428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      maxidx = symsize;
195528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
195628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
195728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
195828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
195928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx)
196028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
196128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash bucket reference %zu out of bounds\n"),
196228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2);
196328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
196428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (; cnt < 2 + nbucket + nchain; ++cnt)
196528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx)
196628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
1967dcf6160602985e6eb70c96c6546ed9614a414d98Ulrich Dreppersection [%2d] '%s': hash chain reference %" PRIu64 " out of bounds\n"),
1968dcf6160602985e6eb70c96c6546ed9614a414d98Ulrich Drepper	     idx, section_name (ebl, idx), (uint64_t) (cnt - 2 - nbucket));
196928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
197028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
197128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
197228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
197328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
197428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		GElf_Shdr *symshdr)
197528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
197628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0];
197728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
19788ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
197928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
19808ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (!powerof2 (bitmask_words))
19818ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    ERROR (gettext ("\
19828ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': bitmask size not power of 2: %u\n"),
19838ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	   idx, section_name (ebl, idx), bitmask_words);
19848ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
19858ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t bitmask_idxmask = bitmask_words - 1;
19868ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (gelf_getclass (ebl->elf) == ELFCLASS64)
19878ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    bitmask_words *= 2;
19888ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
19898ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
19908ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shdr->sh_size < (4 + bitmask_words + nbuckets) * sizeof (Elf32_Word))
199128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
199228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
199328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected at least%ld)\n"),
199428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), (long int) shdr->sh_size,
19958ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	     (long int) ((4 + bitmask_words + nbuckets) * sizeof (Elf32_Word)));
199628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      return;
199728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
199828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
19998ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shift > 31)
20008ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    ERROR (gettext ("\
20018ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': 2nd hash function shift too big: %u\n"),
20028ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	   idx, section_name (ebl, idx), shift);
20038ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
20048ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words
20058ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							 + nbuckets);
200628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
200728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (symshdr != NULL)
200828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    maxidx = MIN (maxidx, symshdr->sh_size / symshdr->sh_entsize);
200928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
201028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  /* We need the symbol section data.  */
201128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf_Data *symdata = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link), NULL);
201228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
20138ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  union
20148ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  {
20158ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    Elf32_Word *p32;
20168ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    Elf64_Xword *p64;
20178ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  } bitmask = { .p32 = &((Elf32_Word *) data->d_buf)[4] },
20188ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      collected = { .p32 = xcalloc (bitmask_words, sizeof (Elf32_Word)) };
20198ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
20208ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t classbits = gelf_getclass (ebl->elf) == ELFCLASS32 ? 32 : 64;
20218ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
202228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
20238ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  for (cnt = 4 + bitmask_words; cnt < 4 + bitmask_words + nbuckets; ++cnt)
202428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
20258ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      Elf32_Word symidx = ((Elf32_Word *) data->d_buf)[cnt];
202628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
202728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx == 0)
20288ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	continue;
202928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
203028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx < symbias)
203128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	{
203228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  ERROR (gettext ("\
203328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"),
20348ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		 idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
203528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  continue;
203628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	}
203728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
203828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      while (symidx - symbias < maxidx)
203928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	{
20408ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	  Elf32_Word chainhash = ((Elf32_Word *) data->d_buf)[4
20418ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							      + bitmask_words
20428ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							      + nbuckets
204328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							      + symidx
204428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							      - symbias];
204528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
204628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  if (symdata != NULL)
204728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    {
204828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      /* Check that the referenced symbol is not undefined.  */
204928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      GElf_Sym sym_mem;
205028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      GElf_Sym *sym = gelf_getsym (symdata, symidx, &sym_mem);
2051231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	      if (sym != NULL && sym->st_shndx == SHN_UNDEF
2052231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper		  && GELF_ST_TYPE (sym->st_info) != STT_FUNC)
205328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		ERROR (gettext ("\
205428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': symbol %u referenced in chain for bucket %zu is undefined\n"),
205528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		       idx, section_name (ebl, idx), symidx, cnt / 2 - 1);
205628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
205728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      const char *symname = elf_strptr (ebl->elf, symshdr->sh_link,
205828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						sym->st_name);
205928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      if (symname != NULL)
206028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		{
206128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  Elf32_Word hval = elf_gnu_hash (symname);
206228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if ((hval & ~1u) != (chainhash & ~1u))
206328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    ERROR (gettext ("\
206428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"),
206528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx), symidx, cnt / 2 - 1);
20668ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
20678ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  /* Set the bits in the bitmask.  */
20688ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  size_t maskidx = (hval / classbits) & bitmask_idxmask;
20698ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  if (classbits == 32)
20708ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    {
20718ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p32[maskidx]
20728ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT32_C (1) << (hval & (classbits - 1));
20738ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p32[maskidx]
20748ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT32_C (1) << ((hval >> shift) & (classbits - 1));
20758ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    }
20768ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  else
20778ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    {
20788ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p64[maskidx]
20798ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT64_C (1) << (hval & (classbits - 1));
20808ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p64[maskidx]
20818ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT64_C (1) << ((hval >> shift) & (classbits - 1));
20828ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    }
208328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		}
208428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    }
208528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
208628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  if ((chainhash & 1) != 0)
208728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    break;
208828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
208928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  ++symidx;
209028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	}
209128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
209228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx - symbias >= maxidx)
209328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("\
209428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain for bucket %zu out of bounds\n"),
209528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx), cnt / 2 - 1);
209628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      else if (symshdr != NULL
209728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       && symidx > symshdr->sh_size / symshdr->sh_entsize)
209828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("\
209928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"),
210028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx), cnt / 2 - 1);
210128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
21028ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
21038ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (memcmp (collected.p32, bitmask.p32, bitmask_words * sizeof (Elf32_Word)))
21048ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    ERROR (gettext ("\
21058ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': bitmask does not match names in the hash table\n"),
21068ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	   idx, section_name (ebl, idx));
21078ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
21088ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  free (collected.p32);
210928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
211028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
211128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
211228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
211328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_hash (int tag, Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2115acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (ehdr->e_type == ET_REL)
2116acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
2117acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      ERROR (gettext ("\
2118acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': relocatable files cannot have hash tables\n"),
2119acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	     idx, section_name (ebl, idx));
2120acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      return;
2121acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    }
2122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2123acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
2125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2131acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr symshdr_mem;
2132acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2133acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &symshdr_mem);
2134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM)
2135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
2136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': hash table not for dynamic symbol table\n"),
2137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
213928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_entsize != (tag == SHT_GNU_HASH
21408ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			   ? (gelf_getclass (ebl->elf) == ELFCLASS32
21418ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			      ? sizeof (Elf32_Word) : 0)
214228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   : (size_t) ebl_sysvhash_entrysize (ebl)))
2143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
214428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table entry size incorrect\n"),
2145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((shdr->sh_flags & SHF_ALLOC) == 0)
2148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': not marked to be allocated\n"),
2149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
21518ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (shdr->sh_entsize ?: 4))
2152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
21548ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': hash table has not even room for initial administrative entries\n"),
2155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
215928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  switch (tag)
2160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
216128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    case SHT_HASH:
216228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
216328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	check_sysv_hash64 (ebl, shdr, data, idx, symshdr);
216428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      else
216528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	check_sysv_hash (ebl, shdr, data, idx, symshdr);
216628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      break;
2167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
216828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    case SHT_GNU_HASH:
216928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      check_gnu_hash (ebl, shdr, data, idx, symshdr);
217028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      break;
2171ee4b927bae351b21787355e00a3d28371bf78e8fUlrich Drepper
217228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    default:
21738ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      assert (! "should not happen");
2174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
21787c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper/* Compare content of both hash tables, it must be identical.  */
21797c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepperstatic void
21807c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppercompare_hash_gnu_hash (Ebl *ebl, GElf_Ehdr *ehdr, size_t hash_idx,
21817c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		       size_t gnu_hash_idx)
21827c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper{
21837c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *hash_scn = elf_getscn (ebl->elf, hash_idx);
21847c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *hash_data = elf_getdata (hash_scn, NULL);
21857c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr hash_shdr_mem;
21867c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *hash_shdr = gelf_getshdr (hash_scn, &hash_shdr_mem);
21877c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *gnu_hash_scn = elf_getscn (ebl->elf, gnu_hash_idx);
21887c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *gnu_hash_data = elf_getdata (gnu_hash_scn, NULL);
21897c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr gnu_hash_shdr_mem;
21907c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *gnu_hash_shdr = gelf_getshdr (gnu_hash_scn, &gnu_hash_shdr_mem);
21917c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
21927c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr == NULL || gnu_hash_shdr == NULL
21937c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      || hash_data == NULL || gnu_hash_data == NULL)
21947c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    /* None of these pointers should be NULL since we used the
21957c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper       sections already.  We are careful nonetheless.  */
21967c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    return;
21977c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
21987c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* The link must point to the same symbol table.  */
21997c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr->sh_link != gnu_hash_shdr->sh_link)
22007c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
22017c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      ERROR (gettext ("\
22027c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"),
22037c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
22047c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     gnu_hash_idx,
22057c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
22067c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      return;
22077c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
22087c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22097c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *sym_scn = elf_getscn (ebl->elf, hash_shdr->sh_link);
22107c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *sym_data = elf_getdata (sym_scn, NULL);
22117c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr sym_shdr_mem;
22127c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *sym_shdr = gelf_getshdr (sym_scn, &sym_shdr_mem);
22137c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22147c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (sym_data == NULL || sym_shdr == NULL)
22157c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    return;
22167c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22177c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  int nentries = sym_shdr->sh_size / sym_shdr->sh_entsize;
22187c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  char *used = alloca (nentries);
22197c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  memset (used, '\0', nentries);
22207c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22217c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* First go over the GNU_HASH table and mark the entries as used.  */
22227c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const Elf32_Word *gnu_hasharr = (Elf32_Word *) gnu_hash_data->d_buf;
22237c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf32_Word gnu_nbucket = gnu_hasharr[0];
22247c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const int bitmap_factor = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 1 : 2;
22257c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const Elf32_Word *gnu_bucket = (gnu_hasharr
22267c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper				  + (4 + gnu_hasharr[2] * bitmap_factor));
22277c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const Elf32_Word *gnu_chain = gnu_bucket + gnu_hasharr[0] - gnu_hasharr[1];
22287c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22297c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  for (Elf32_Word cnt = 0; cnt < gnu_nbucket; ++cnt)
22307c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
22317c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      Elf32_Word symidx = gnu_bucket[cnt];
22327c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      if (symidx != STN_UNDEF)
22337c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	do
22347c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  used[symidx] |= 1;
22357c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	while ((gnu_chain[symidx++] & 1u) == 0);
22367c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
22377c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22387c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* Now go over the old hash table and check that we cover the same
22397c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     entries.  */
22407c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr->sh_entsize == sizeof (Elf32_Word))
22417c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
22427c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *hasharr = (Elf32_Word *) hash_data->d_buf;
22437c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      Elf32_Word nbucket = hasharr[0];
22447c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *bucket = &hasharr[2];
22457c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *chain = &hasharr[2 + nbucket];
22467c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22477c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
22487c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	{
22497c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  Elf32_Word symidx = bucket[cnt];
22507c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  while (symidx != STN_UNDEF)
22517c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    {
22527c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      used[symidx] |= 2;
22537c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      symidx = chain[symidx];
22547c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    }
22557c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	}
22567c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
22577c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  else
22587c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
22597c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *hasharr = (Elf64_Xword *) hash_data->d_buf;
22607c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      Elf64_Xword nbucket = hasharr[0];
22617c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *bucket = &hasharr[2];
22627c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *chain = &hasharr[2 + nbucket];
22637c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22647c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
22657c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	{
22667c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  Elf64_Xword symidx = bucket[cnt];
22677c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  while (symidx != STN_UNDEF)
22687c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    {
22697c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      used[symidx] |= 2;
22707c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      symidx = chain[symidx];
22717c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    }
22727c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	}
22737c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
22747c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22757c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* Now see which entries are not set in one or both hash tables
22767c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     (unless the symbol is undefined in which case it can be omitted
22777c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     in the new table format).  */
22787c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if ((used[0] & 1) != 0)
22797c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"),
22807c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   gnu_hash_idx,
22817c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
22827c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if ((used[0] & 2) != 0)
22837c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"),
22847c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
22857c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22867c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  for (int cnt = 1; cnt < nentries; ++cnt)
22877c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    if (used[cnt] != 0 && used[cnt] != 3)
22887c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      {
22897c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	if (used[cnt] == 1)
22907c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  ERROR (gettext ("\
22917c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersymbol %d referenced in new hash table in [%2zu] '%s' but not in old hash table in [%2zu] '%s'\n"),
22927c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 cnt, gnu_hash_idx,
22937c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name),
22947c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 hash_idx,
22957c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
22967c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	else
22977c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  {
22987c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    GElf_Sym sym_mem;
22997c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    GElf_Sym *sym = gelf_getsym (sym_data, cnt, &sym_mem);
23007c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23017c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    if (sym != NULL && sym->st_shndx != STN_UNDEF)
23027c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      ERROR (gettext ("\
23037c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersymbol %d referenced in old hash table in [%2zu] '%s' but not in new hash table in [%2zu] '%s'\n"),
23047c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     cnt, hash_idx,
23057c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
23067c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     gnu_hash_idx,
23077c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
23087c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  }
23097c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      }
23107c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper}
23117c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23127c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
2313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_null (Ebl *ebl, GElf_Shdr *shdr, int idx)
2315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define TEST(name, extra) \
2317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (extra && shdr->sh_##name != 0)					      \
2318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': nonzero sh_%s for NULL section\n"),  \
2319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), #name)
2320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (name, 1);
2322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (flags, 1);
2323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (addr, 1);
2324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (offset, 1);
2325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (size, idx != 0);
2326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (link, idx != 0);
2327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (info, 1);
2328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (addralign, 1);
2329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (entsize, 1);
2330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_REL)
2337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
2339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section groups only allowed in relocatable object files\n"),
2340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check that sh_link is an index of a symbol table.  */
2345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
2346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				     &symshdr_mem);
2348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr == NULL)
2349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': cannot get symbol table: %s\n"),
2350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), elf_errmsg (-1));
2351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (symshdr->sh_type != SHT_SYMTAB)
2354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section reference in sh_link is no symbol table\n"),
2356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM,
2359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper							  1, EV_CURRENT))
2360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': invalid symbol index in sh_info\n"),
2362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags != 0)
2365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': sh_flags not zero\n"),
2366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (be_strict
2369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT))
2370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': sh_flags not set correctly\n"),
2371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
2376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': cannot get data: %s\n"),
2377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), elf_errmsg (-1));
2378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
2381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t cnt;
2382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf32_Word val;
2383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data->d_size % elsize != 0)
2385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"),
2387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data->d_size < elsize)
2390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group without flags word\n"),
2392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (be_strict)
2394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (data->d_size < 2 * elsize)
2396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group without member\n"),
2398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
2399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (data->d_size < 3 * elsize)
2400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group with only one member\n"),
2402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
2403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if ALLOW_UNALIGNED
2406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      val = *((Elf32_Word *) data->d_buf);
2407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#else
2408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      memcpy (&val, data->d_buf, elsize);
2409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
2410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((val & ~GRP_COMDAT) != 0)
2411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': unknown section group flags\n"),
2412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = elsize; cnt < data->d_size; cnt += elsize)
2415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if ALLOW_UNALIGNED
2417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  val = *((Elf32_Word *) ((char *) data->d_buf + cnt));
2418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#else
2419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  memcpy (&val, (char *) data->d_buf + cnt, elsize);
2420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
2421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (val > shnum)
2423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section index %Zu out of range\n"),
2425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt / elsize);
2426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
2427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
2428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Shdr refshdr_mem;
2429acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	      GElf_Shdr *refshdr = gelf_getshdr (elf_getscn (ebl->elf, val),
2430acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper						 &refshdr_mem);
2431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (refshdr == NULL)
2432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
2433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get section header for element %zu: %s\n"),
2434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx), cnt / elsize,
2435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       elf_errmsg (-1));
2436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
2437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
2438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (refshdr->sh_type == SHT_GROUP)
2439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
2440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group contains another group [%2d] '%s'\n"),
2441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx),
2442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   val, section_name (ebl, val));
2443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if ((refshdr->sh_flags & SHF_GROUP) == 0)
2445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
2446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': element %Zu references section [%2d] '%s' without SHF_GROUP flag set\n"),
2447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx), cnt / elsize,
2448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   val, section_name (ebl, val));
2449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
2450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (++scnref[val] == 2)
2452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
2453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' is contained in more than one section group\n"),
2454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       val, section_name (ebl, val));
2455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
2456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *
2462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection_flags_string (GElf_Word flags, char *buf, size_t len)
2463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const struct
2465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
2466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    GElf_Word flag;
2467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    const char *name;
2468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  } known_flags[] =
2469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define NEWFLAG(name) { SHF_##name, #name }
2471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (WRITE),
2472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (ALLOC),
2473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (EXECINSTR),
2474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (MERGE),
2475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (STRINGS),
2476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (INFO_LINK),
2477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (LINK_ORDER),
2478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (OS_NONCONFORMING),
2479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (GROUP),
2480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (TLS)
2481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
2482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#undef NEWFLAG
2483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
2484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *cp = buf;
2486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2487acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 0; cnt < nknown_flags; ++cnt)
2488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (flags & known_flags[cnt].flag)
2489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
2490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (cp != buf && len > 1)
2491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
2492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    *cp++ = '|';
2493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    --len;
2494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
2495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name));
2497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	cp = mempcpy (cp, known_flags[cnt].name, ncopy);
2498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	len -= ncopy;
2499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	flags ^= known_flags[cnt].flag;
2501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
2502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (flags != 0 || cp == buf)
2504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    snprintf (cp, len - 1, "%" PRIx64, (uint64_t) flags);
2505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *cp = '\0';
2507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return buf;
2509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2512dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2513dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperhas_copy_reloc (Ebl *ebl, unsigned int symscnndx, unsigned int symndx)
2514dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2515dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* First find the relocation section for the symbol table.  */
2516dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = NULL;
2517dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2518dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = NULL;
2519dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2520dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2521dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      shdr = gelf_getshdr (scn, &shdr_mem);
2522dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (shdr != NULL
2523dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
2524dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && shdr->sh_link == symscnndx)
2525dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	/* Found the section.  */
2526dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	break;
2527dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2528dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2529dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (scn == NULL)
2530dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 0;
2531dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2532dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
2533dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2534dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 0;
2535dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2536dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr->sh_type == SHT_REL)
2537dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2538dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2539dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rel rel_mem;
2540dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
2541dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (rel == NULL)
2542dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  continue;
2543dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2544dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (GELF_R_SYM (rel->r_info) == symndx
2545dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info)))
2546dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  return 1;
2547dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2548dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  else
2549dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2550dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2551dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rela rela_mem;
2552dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
2553dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (rela == NULL)
2554dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  continue;
2555dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2556dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (GELF_R_SYM (rela->r_info) == symndx
2557dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info)))
2558dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  return 1;
2559dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2560dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2561dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 0;
2562dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2563dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2564dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2565637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic int
2566637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperin_nobits_scn (Ebl *ebl, unsigned int shndx)
2567637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper{
2568637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Shdr shdr_mem;
2569637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, shndx), &shdr_mem);
2570637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  return shdr != NULL && shdr->sh_type == SHT_NOBITS;
2571637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper}
2572637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2573637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2574dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic struct version_namelist
2575dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2576dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  const char *objname;
2577dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  const char *name;
2578858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrath  GElf_Versym ndx;
2579dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  enum { ver_def, ver_need } type;
2580dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct version_namelist *next;
2581dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper} *version_namelist;
2582dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2583dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2584dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2585858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrathadd_version (const char *objname, const char *name, GElf_Versym ndx, int type)
2586dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2587dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Check that there are no duplications.  */
2588dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct version_namelist *nlp = version_namelist;
2589dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while (nlp != NULL)
2590dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2591dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (((nlp->objname == NULL && objname == NULL)
2592dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	   || (nlp->objname != NULL && objname != NULL
2593dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       && strcmp (nlp->objname, objname) == 0))
2594dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && strcmp (nlp->name, name) == 0)
2595dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	return nlp->type == ver_def ? 1 : -1;
2596dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      nlp = nlp->next;
2597dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2598dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2599dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp = xmalloc (sizeof (*nlp));
2600dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->objname = objname;
2601dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->name = name;
2602dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->ndx = ndx;
2603dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->type = type;
2604dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->next = version_namelist;
2605dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  version_namelist = nlp;
2606dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2607dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 0;
2608dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2609dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2610dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2612dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_versym (Ebl *ebl, int idx)
2613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2614dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = elf_getscn (ebl->elf, idx);
2615dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2616dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2617dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr == NULL)
2618dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    /* The error has already been reported.  */
2619dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
2620dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2621dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
2622dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2623dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2624dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2625dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
2626dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
2627dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2628dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2629dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
2631dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr == NULL)
2633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* The error has already been reported.  */
2634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
2635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr->sh_type != SHT_DYNSYM)
2637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
2639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"),
2640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx),
2641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     shdr->sh_link, section_name (ebl, shdr->sh_link));
2642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2645dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* The number of elements in the version symbol table must be the
2646dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     same as the number of symbols.  */
2647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_size / shdr->sh_entsize
2648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      != symshdr->sh_size / symshdr->sh_entsize)
2649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
2650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"),
2651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
2652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   shdr->sh_link, section_name (ebl, shdr->sh_link));
2653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2654dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
2655dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (symdata == NULL)
2656dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    /* The error has already been reported.  */
2657dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
2658dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2659dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (int cnt = 1; (size_t) cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2660dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2661dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Versym versym_mem;
2662dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Versym *versym = gelf_getversym (data, cnt, &versym_mem);
2663dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (versym == NULL)
2664dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2665dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2666dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: cannot read version data\n"),
2667dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
2668dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  break;
2669dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2670dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2671dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Sym sym_mem;
2672dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_mem);
2673dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (sym == NULL)
2674dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	/* Already reported elsewhere.  */
2675dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	continue;
2676dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
267761655e08ba36430de47381cefdf10d0c26aa8480Ulrich Drepper      if (*versym == VER_NDX_GLOBAL)
2678dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2679dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* Global symbol.  Make sure it is not defined as local.  */
2680dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2681dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2682dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: local symbol with global scope\n"),
2683dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
2684dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
268561655e08ba36430de47381cefdf10d0c26aa8480Ulrich Drepper      else if (*versym != VER_NDX_LOCAL)
2686dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2687c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	  /* Versioned symbol.  Make sure it is not defined as local.  */
2688c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	  if (!gnuld && GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2689c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	    ERROR (gettext ("\
2690c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Dreppersection [%2d] '%s': symbol %d: local symbol with version\n"),
2691c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
2692c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper
2693dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* Look through the list of defined versions and locate the
2694dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     index we need for this symbol.  */
2695dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *runp = version_namelist;
2696dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  while (runp != NULL)
2697858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrath	    if (runp->ndx == (*versym & (GElf_Versym) 0x7fff))
2698dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
2699dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    else
2700dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      runp = runp->next;
2701dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2702dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (runp == NULL)
2703dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2704dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: invalid version index %d\n"),
2705dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt, (int) *versym);
2706dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else if (sym->st_shndx == SHN_UNDEF
2707dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   && runp->type == ver_def)
2708dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2709dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: version index %d is for defined version\n"),
2710dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt, (int) *versym);
2711dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else if (sym->st_shndx != SHN_UNDEF
2712dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   && runp->type == ver_need)
2713dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2714dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      /* Unless this symbol has a copy relocation associated
2715dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 this must not happen.  */
2716637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper	      if (!has_copy_reloc (ebl, shdr->sh_link, cnt)
2717637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper		  && !in_nobits_scn (ebl, sym->st_shndx))
2718dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		ERROR (gettext ("\
2719dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: version index %d is for requested version\n"),
2720dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       idx, section_name (ebl, idx), cnt, (int) *versym);
2721dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2722dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2723dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2724dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2725dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2726dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2727dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2728dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperunknown_dependency_p (Elf *elf, GElf_Ehdr *ehdr, const char *fname)
2729dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2730dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Phdr phdr_mem;
2731dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Phdr *phdr = NULL;
2732dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2733dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  int i;
2734dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (i = 0; i < ehdr->e_phnum; ++i)
2735dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    if ((phdr = gelf_getphdr (elf, i, &phdr_mem)) != NULL
2736dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	&& phdr->p_type == PT_DYNAMIC)
2737dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      break;
2738dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2739dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (i == ehdr->e_phnum)
2740dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 1;
2741dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  assert (phdr != NULL);
2742dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
2743dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2744dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2745dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
2746dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL)
2747dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (size_t j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
2748dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2749dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Dyn dyn_mem;
2750dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
2751dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (dyn != NULL && dyn->d_tag == DT_NEEDED)
2752dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  {
2753dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    const char *str = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
2754dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    if (str != NULL && strcmp (str, fname) == 0)
2755dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      /* Found it.  */
2756dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      return 0;
2757dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  }
2758dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2759dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2760dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 1;
2761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2764acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic unsigned int nverneed;
2765acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2767dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_verneed (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2769acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (++nverneed == 2)
2770acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("more than one version reference section present\n"));
2771acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2772acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr strshdr_mem;
2773acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2774acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &strshdr_mem);
2775acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr == NULL)
2776acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    return;
2777acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
2778acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("\
2779acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': sh_link does not link to string table\n"),
2780acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	   idx, section_name (ebl, idx));
2781dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2782dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2783dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2784dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2785dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2786dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
2787dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
2788dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2789dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  unsigned int offset = 0;
2790dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (int cnt = shdr->sh_info; --cnt >= 0; )
2791dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2792dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Get the data at the next offset.  */
2793dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verneed needmem;
2794dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
2795dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need == NULL)
2796dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	break;
2797dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2798dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      unsigned int auxoffset = offset + need->vn_aux;
2799dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2800dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need->vn_version != EV_CURRENT)
2801dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2802dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong version %d\n"),
2803dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) need->vn_version);
2804dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2805dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need->vn_cnt > 0 && need->vn_aux < gelf_fsize (ebl->elf, ELF_T_VNEED,
2806dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper							 1, EV_CURRENT))
2807dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2808dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
2809dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2810dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2811dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      const char *libname = elf_strptr (ebl->elf, shdr->sh_link,
2812dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					need->vn_file);
2813dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (libname == NULL)
2814dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2815dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2816dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid file reference\n"),
2817dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
2818dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  goto next_need;
2819dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2820dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2821dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Check that there is a DT_NEEDED entry for the referenced library.  */
2822dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (unknown_dependency_p (ebl->elf, ehdr, libname))
2823dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2824dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d references unknown dependency\n"),
2825dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2826dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2827dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2828dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2829dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  GElf_Vernaux auxmem;
2830dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2831dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (aux == NULL)
2832dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    break;
2833dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2834dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vna_flags & ~VER_FLG_WEAK) != 0)
2835dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2836dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"),
2837dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2838dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2839dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  const char *verstr = elf_strptr (ebl->elf, shdr->sh_link,
2840dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					   aux->vna_name);
2841dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (verstr == NULL)
2842dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2843dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has invalid name reference\n"),
2844dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2845dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else
2846dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2847dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      GElf_Word hashval = elf_hash (verstr);
2848dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (hashval != aux->vna_hash)
2849dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		ERROR (gettext ("\
2850dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: %#x, expected %#x\n"),
2851dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       idx, section_name (ebl, idx), need->vn_cnt - cnt2,
2852dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       cnt, (int) hashval, (int) aux->vna_hash);
2853dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2854dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      int res = add_version (libname, verstr, aux->vna_other,
2855dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper				     ver_need);
2856dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (unlikely (res !=0))
2857dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		{
2858dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  assert (res > 0);
2859dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  ERROR (gettext ("\
2860dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has duplicate version name '%s'\n"),
2861dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 idx, section_name (ebl, idx), need->vn_cnt - cnt2,
2862dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 cnt, verstr);
2863dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		}
2864dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2865dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2866dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vna_next != 0 || cnt2 > 0)
2867dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && aux->vna_next < gelf_fsize (ebl->elf, ELF_T_VNAUX, 1,
2868dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					     EV_CURRENT))
2869dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2870dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      ERROR (gettext ("\
2871dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"),
2872dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		     idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2873dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
2874dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2875dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2876dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  auxoffset += MAX (aux->vna_next,
2877dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			    gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, EV_CURRENT));
2878dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2879dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2880dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Find the next offset.  */
2881dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    next_need:
2882dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      offset += need->vn_next;
2883dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2884dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((need->vn_next != 0 || cnt > 0)
2885dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && offset < auxoffset)
2886dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2887dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid offset to next entry\n"),
2888dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2889dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2890acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper}
2891b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2892acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2893acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic unsigned int nverdef;
2894acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2895acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic void
2896acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_verdef (Ebl *ebl, GElf_Shdr *shdr, int idx)
2897acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper{
2898acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (++nverdef == 2)
2899acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("more than one version definition section present\n"));
2900acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2901acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr strshdr_mem;
2902acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2903acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &strshdr_mem);
2904acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr == NULL)
2905acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    return;
2906acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
2907acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("\
2908acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': sh_link does not link to string table\n"),
2909acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	   idx, section_name (ebl, idx));
2910dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2911dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2912dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2913dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2914dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    no_data:
2915dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2916dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
2917dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
2918dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2919dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2920dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Iterate over all version definition entries.  We check that there
2921dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     is a BASE entry and that each index is unique.  To do the later
2922dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     we collection the information in a list which is later
2923dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     examined.  */
2924dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct namelist
2925dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  {
2926dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    const char *name;
2927dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    struct namelist *next;
2928dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  } *namelist = NULL;
2929dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct namelist *refnamelist = NULL;
2930dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2931dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  bool has_base = false;
2932dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  unsigned int offset = 0;
2933dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (int cnt = shdr->sh_info; --cnt >= 0; )
2934dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2935dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Get the data at the next offset.  */
2936dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdef defmem;
2937dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2938dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def == NULL)
2939dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	goto no_data;
2940dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2941dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_flags & VER_FLG_BASE) != 0)
2942dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2943dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (has_base)
2944dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2945dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': more than one BASE definition\n"),
2946dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx));
2947dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (def->vd_ndx != VER_NDX_GLOBAL)
2948dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2949dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"),
2950dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx));
2951dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  has_base = true;
2952dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2953dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_flags & ~(VER_FLG_BASE|VER_FLG_WEAK)) != 0)
2954dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2955dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has unknown flag\n"),
2956dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2957dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2958dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_version != EV_CURRENT)
2959dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2960dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong version %d\n"),
2961dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) def->vd_version);
2962dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2963dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_cnt > 0 && def->vd_aux < gelf_fsize (ebl->elf, ELF_T_VDEF,
2964dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper						       1, EV_CURRENT))
2965dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2966dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
2967dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2968dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2969dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      unsigned int auxoffset = offset + def->vd_aux;
2970dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdaux auxmem;
2971dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
2972dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (aux == NULL)
2973dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	goto no_data;
2974dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2975dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      const char *name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
2976dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (name == NULL)
2977dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2978dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2979dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid name reference\n"),
2980dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
2981dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  goto next_def;
2982dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2983dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Word hashval = elf_hash (name);
2984dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_hash != hashval)
2985dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2986dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"),
2987dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) hashval,
2988dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       (int) def->vd_hash);
2989dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2990dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      int res = add_version (NULL, name, def->vd_ndx, ver_def);
2991dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (unlikely (res !=0))
2992dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2993dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  assert (res > 0);
2994dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2995dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has duplicate version name '%s'\n"),
2996dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt, name);
2997dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2998dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2999dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      struct namelist *newname = alloca (sizeof (*newname));
30006247d634c33be4c9ee4bfc650bb8f06f5add41e5Ulrich Drepper      newname->name = name;
3001dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      newname->next = namelist;
3002dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      namelist = newname;
3003dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3004dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      auxoffset += aux->vda_next;
3005dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
3006dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3007dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
3008dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (aux == NULL)
3009dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    goto no_data;
3010dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3011c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
3012c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  if (name == NULL)
3013c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    ERROR (gettext ("\
3014c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Dreppersection [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"),
3015c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
3016c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  else
3017c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    {
3018c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname = alloca (sizeof (*newname));
3019c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname->name = name;
3020c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname->next = refnamelist;
3021c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      refnamelist = newname;
3022c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    }
3023dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3024dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vda_next != 0 || cnt2 + 1 < def->vd_cnt)
3025dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && aux->vda_next < gelf_fsize (ebl->elf, ELF_T_VDAUX, 1,
3026dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					     EV_CURRENT))
3027dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
3028dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      ERROR (gettext ("\
3029dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong next field in auxiliary data\n"),
3030dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		     idx, section_name (ebl, idx), cnt);
3031dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
3032dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
3033dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3034dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  auxoffset += MAX (aux->vda_next,
3035dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			    gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, EV_CURRENT));
3036dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3037dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3038dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Find the next offset.  */
3039dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    next_def:
3040dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      offset += def->vd_next;
3041dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3042dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_next != 0 || cnt > 0)
3043dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && offset < auxoffset)
3044dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3045dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid offset to next entry\n"),
3046dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
3047dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3048dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3049dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (!has_base)
3050dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("section [%2d] '%s': no BASE definition\n"),
3051dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	   idx, section_name (ebl, idx));
3052dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3053dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Check whether the referenced names are available.  */
3054dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while (namelist != NULL)
3055dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
3056dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      struct version_namelist *runp = version_namelist;
3057dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      while (runp != NULL)
3058dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3059dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (runp->type == ver_def
3060dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && strcmp (runp->name, namelist->name) == 0)
3061dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    break;
3062dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  runp = runp->next;
3063dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3064dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3065dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (runp == NULL)
3066dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3067dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': unknown parent version '%s'\n"),
3068dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), namelist->name);
3069dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3070dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      namelist = namelist->next;
3071dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3072acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper}
3073acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3074acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3075637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic bool has_loadable_segment;
3076637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic bool has_interp_segment;
3077637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3078637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic const struct
3079637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper{
3080637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  const char *name;
3081637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  size_t namelen;
3082637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word type;
3083637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  enum { unused, exact, atleast } attrflag;
3084637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word attr;
3085637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word attr2;
3086637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper} special_sections[] =
3087637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  {
3088637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    /* See figure 4-14 in the gABI.  */
3089637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3090637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".comment", 8, SHT_PROGBITS, exact, 0, 0 },
3091637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3092637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3093637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".debug", 7, SHT_PROGBITS, exact, 0, 0 },
3094637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE },
3095637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 },
3096637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 },
3097637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3098637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3099637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info?
3100637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 },
3101637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3102637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3103637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests?
3104637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".line", 6, SHT_PROGBITS, exact, 0, 0 },
3105637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".note", 6, SHT_NOTE, exact, 0, 0 },
3106637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
3107637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3108637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC }, // XXX more tests
3109637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC }, // XXX more tests
3110637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3111637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3112637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 },
3113637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3114637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3115637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests
3116637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3117637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3118637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3119637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3120637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3121637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    /* The following are GNU extensions.  */
3122637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version", 13, SHT_GNU_versym, exact, SHF_ALLOC, 0 },
3123637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version_d", 15, SHT_GNU_verdef, exact, SHF_ALLOC, 0 },
3124637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 }
3125637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  };
3126637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper#define nspecial_sections \
3127637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  (sizeof (special_sections) / sizeof (special_sections[0]))
3128637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3129637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3130acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic void
3131acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_sections (Ebl *ebl, GElf_Ehdr *ehdr)
3132acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper{
3133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_shoff == 0)
3134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* No section header.  */
3135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
3136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Allocate array to count references in section groups.  */
3138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  scnref = (int *) xcalloc (shnum, sizeof (int));
3139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the zeroth section first.  It must not have any contents
3141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     and the section header must contain nonzero value at most in the
3142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     sh_size and sh_link fields.  */
3143acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr shdr_mem;
3144acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
3145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr == NULL)
3146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("cannot get section header of zeroth section\n"));
3147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
3148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_name != 0)
3150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero name\n"));
3151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type != 0)
3152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero type\n"));
3153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags != 0)
3154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero flags\n"));
3155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_addr != 0)
3156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero address\n"));
3157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_offset != 0)
3158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero offset\n"));
3159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_info != 0)
3160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero info field\n"));
3161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_addralign != 0)
3162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero align value\n"));
3163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_entsize != 0)
3164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero entry size value\n"));
3165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_size != 0 && ehdr->e_shnum != 0)
3167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperzeroth section has nonzero size value while ELF header has nonzero shnum value\n"));
3169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX)
3171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperzeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n"));
3173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3175acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  bool dot_interp_section = false;
3176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
31777c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  size_t hash_idx = 0;
31787c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  size_t gnu_hash_idx = 0;
31797c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
3180dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  size_t versym_scnndx = 0;
3181acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 1; cnt < shnum; ++cnt)
3182acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
3183acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      shdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &shdr_mem);
3184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr == NULL)
3185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
3187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot get section header for section [%2zu] '%s': %s\n"),
3188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, section_name (ebl, cnt), elf_errmsg (-1));
3189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
3190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
3193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (scnname == NULL)
3195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2zu]: invalid name\n"), cnt);
3196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
3197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Check whether it is one of the special sections defined in
3199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     the gABI.  */
3200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t s;
3201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (s = 0; s < nspecial_sections; ++s)
3202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (strncmp (scnname, special_sections[s].name,
3203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 special_sections[s].namelen) == 0)
3204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
3205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf1[100];
3206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf2[100];
3207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf3[100];
3208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3209653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		GElf_Word good_type = special_sections[s].type;
3210653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		if (special_sections[s].namelen == sizeof ".plt" &&
3211653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    !memcmp (special_sections[s].name, ".plt", sizeof ".plt")
3212c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    && ebl_bss_plt_p (ebl, ehdr))
3213653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  good_type = SHT_NOBITS;
3214653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
3215653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		if (shdr->sh_type != good_type
3216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    && !(is_debuginfo && shdr->sh_type == SHT_NOBITS))
3217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  ERROR (gettext ("\
3218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' has wrong type: expected %s, is %s\n"),
3219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 (int) cnt, scnname,
3220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 ebl_section_type_name (ebl, special_sections[s].type,
3221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						stbuf1, sizeof (stbuf1)),
3222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 ebl_section_type_name (ebl, shdr->sh_type,
3223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						stbuf2, sizeof (stbuf2)));
3224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (special_sections[s].attrflag == exact)
3226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* Except for the link order and group bit all the
3228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       other bits should match exactly.  */
3229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP))
3230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			!= special_sections[s].attr)
3231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has wrong flags: expected %s, is %s\n"),
3233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname,
3234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr,
3235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf1, sizeof (stbuf1)),
3236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (shdr->sh_flags
3237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   & ~SHF_LINK_ORDER,
3238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf2, sizeof (stbuf2)));
3239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else if (special_sections[s].attrflag == atleast)
3241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & special_sections[s].attr)
3243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			!= special_sections[s].attr
3244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			|| ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP
3245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						| special_sections[s].attr
3246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						| special_sections[s].attr2))
3247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    != 0))
3248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"),
3250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname,
3251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr,
3252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf1, sizeof (stbuf1)),
3253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr2,
3254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf2, sizeof (stbuf2)),
3255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (shdr->sh_flags
3256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   & ~(SHF_LINK_ORDER
3257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						       | SHF_GROUP),
3258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf3, sizeof (stbuf3)));
3259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (strcmp (scnname, ".interp") == 0)
3262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    dot_interp_section = true;
3264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (ehdr->e_type == ET_REL)
3266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' present in object file\n"),
3268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !has_loadable_segment)
3272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     && has_loadable_segment)
3277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
3282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (strcmp (scnname, ".symtab_shndx") == 0
3284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& ehdr->e_type != ET_REL)
3285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' is extension section index table in non-object file\n"),
3287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* These sections must have the SHF_ALLOC flag set iff
3290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       a loadable segment is available.
3291b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3292b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .relxxx
3293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .strtab
3294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .symtab
3295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .symtab_shndx
3296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       Check that if there is a reference from the
3298b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       loaded section these sections also have the
3299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       ALLOC flag set.  */
3300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if 0
3301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    // XXX TODO
3302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !has_loadable_segment)
3304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3307b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3308b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     && has_loadable_segment)
3309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
3313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		break;
3316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
3317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize)
3320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': size not multiple of entry size\n"),
3322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL)
3325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("cannot get section header\n"));
3326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type >= SHT_NUM
3328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_LIBLIST
3329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_CHECKSUM
3330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_verdef
3331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_verneed
333218e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && shdr->sh_type != SHT_GNU_versym
333318e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && ebl_section_type_name (ebl, shdr->sh_type, NULL, 0) == NULL)
333418e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	ERROR (gettext ("section [%2zu] '%s' has unsupported type %d\n"),
333518e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	       cnt, section_name (ebl, cnt),
333618e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	       (int) shdr->sh_type);
3337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \
3339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \
3340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS)
3341aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper      if (shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS)
3342aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	{
3343aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS;
3344aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  if (sh_flags & SHF_MASKPROC)
3345aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    {
3346aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	      if (!ebl_machine_section_flag_check (ebl,
3347aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper						   sh_flags & SHF_MASKPROC))
3348aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		ERROR (gettext ("section [%2zu] '%s'"
3349aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper				" contains invalid processor-specific flag(s)"
3350aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper				" %#" PRIx64 "\n"),
3351aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		       cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
3352aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	      sh_flags &= ~(GElf_Xword) SHF_MASKPROC;
3353aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    }
3354aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  if (sh_flags != 0)
3355aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    ERROR (gettext ("section [%2zu] '%s' contains unknown flag(s)"
3356aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper			    " %#" PRIx64 "\n"),
3357aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		   cnt, section_name (ebl, cnt), sh_flags);
3358aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	}
3359aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper      if (shdr->sh_flags & SHF_TLS)
3360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX Correct?
3362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr->sh_addr != 0 && !gnuld)
3363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': thread-local data sections address not zero\n"),
3365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, section_name (ebl, cnt));
3366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX TODO more tests!?
3368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_link >= shnum)
3371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': invalid section reference in link value\n"),
3373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum)
3376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': invalid section reference in info value\n"),
3378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_flags & SHF_MERGE) == 0
3381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && (shdr->sh_flags & SHF_STRINGS) != 0
3382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && be_strict)
3383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': strings flag set without merge flag\n"),
3385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0)
3388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': merge flag set but entry size is zero\n"),
3390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags & SHF_GROUP)
3393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	check_scn_group (ebl, cnt);
3394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0)
3396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Make sure the section is contained in a loaded segment
3398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     and that the initialization part matches NOBITS sections.  */
3399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  int pcnt;
3400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Phdr phdr_mem;
3401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Phdr *phdr;
3402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
3404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL
3405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& ((phdr->p_type == PT_LOAD
3406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     && (shdr->sh_flags & SHF_TLS) == 0)
3407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    || (phdr->p_type == PT_TLS
3408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& (shdr->sh_flags & SHF_TLS) != 0))
3409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& phdr->p_offset <= shdr->sh_offset
34109aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath		&& (phdr->p_offset + phdr->p_filesz > shdr->sh_offset
34119aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath		    || (phdr->p_offset + phdr->p_memsz > shdr->sh_offset
34129aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath			&& shdr->sh_type == SHT_NOBITS)))
3413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
3414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* Found the segment.  */
3415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (phdr->p_offset + phdr->p_memsz
3416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    < shdr->sh_offset + shdr->sh_size)
3417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  ERROR (gettext ("\
3418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' not fully contained in segment of program header entry %d\n"),
3419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
3420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (shdr->sh_type == SHT_NOBITS)
3422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz
3424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !is_debuginfo)
3425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"),
3427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
3428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
3430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3431653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    const GElf_Off end = phdr->p_offset + phdr->p_filesz;
3432653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    if (shdr->sh_offset > end ||
3433653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			(shdr->sh_offset == end && shdr->sh_size != 0))
3434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"),
3436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
3437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		break;
3440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
3441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (pcnt == ehdr->e_phnum)
3443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': alloc flag set but section not in any loaded segment\n"),
3445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, section_name (ebl, cnt));
3446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB)
3449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"),
3451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      switch (shdr->sh_type)
3454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNSYM:
3456acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  if (ehdr->e_type == ET_REL)
3457acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    ERROR (gettext ("\
3458acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"),
3459acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper		   cnt, section_name (ebl, cnt));
3460acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  /* FALLTHROUGH */
3461acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_SYMTAB:
3462dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  check_symtab (ebl, ehdr, shdr, cnt);
3463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_RELA:
3466c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  check_rela (ebl, ehdr, shdr, cnt);
3467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_REL:
3470c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  check_rel (ebl, ehdr, shdr, cnt);
3471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNAMIC:
3474607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  check_dynamic (ebl, ehdr, shdr, cnt);
3475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_SYMTAB_SHNDX:
3478acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  check_symtab_shndx (ebl, ehdr, shdr, cnt);
3479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_HASH:
34827c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
34837c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  hash_idx = cnt;
34847c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  break;
34857c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
348628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	case SHT_GNU_HASH:
348728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
34887c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  gnu_hash_idx = cnt;
3489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_NULL:
3492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  check_null (ebl, shdr, cnt);
3493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_GROUP:
3496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  check_group (ebl, ehdr, shdr, cnt);
3497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_GNU_versym:
3500dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* We cannot process this section now since we have no guarantee
3501dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     that the verneed and verdef sections have already been read.
3502dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     Just remember the section index.  */
3503dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (versym_scnndx != 0)
3504dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("more than one version symbol table present\n"));
3505dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  versym_scnndx = cnt;
3506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3508acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_GNU_verneed:
3509dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  check_verneed (ebl, ehdr, shdr, cnt);
3510acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  break;
3511acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3512acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_GNU_verdef:
3513acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  check_verdef (ebl, shdr, cnt);
3514acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  break;
3515acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	default:
3517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Nothing.  */
3518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (has_interp_segment && !dot_interp_section)
3523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("INTERP program header entry but no .interp section\n"));
3524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3525dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (version_namelist != NULL)
3526dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
3527dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (versym_scnndx == 0)
3528dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("\
3529dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperno .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section exist\n"));
3530dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      else
3531dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	check_versym (ebl, versym_scnndx);
3532dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3533dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Check for duplicate index numbers.  */
3534dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      do
3535dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3536dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *runp = version_namelist->next;
3537dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  while (runp != NULL)
3538dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
3539dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (version_namelist->ndx == runp->ndx)
3540dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		{
3541dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  ERROR (gettext ("duplicate version index %d\n"),
3542dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 (int) version_namelist->ndx);
3543dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  break;
3544dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		}
3545dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      runp = runp->next;
3546dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
3547dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3548dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *old = version_namelist;
3549dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  version_namelist = version_namelist->next;
3550dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  free (old);
3551dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3552dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      while (version_namelist != NULL);
3553dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3554dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  else if (versym_scnndx != 0)
3555dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("\
3556dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper.gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"));
3557dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
35587c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_idx != 0 && gnu_hash_idx != 0)
35597c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    compare_hash_gnu_hash (ebl, ehdr, hash_idx, gnu_hash_idx);
35607c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
3561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  free (scnref);
3562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
3563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
3566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt)
3567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
3568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
3569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
3570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
3571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperphdr[%d]: no note entries defined for the type of file\n"),
3572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   cnt);
3573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (is_debuginfo)
3575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* The p_offset values in a separate debug file are bogus.  */
3576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
3577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *notemem = gelf_rawchunk (ebl->elf, phdr->p_offset, phdr->p_filesz);
3579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* ELF64 files often use note section entries in the 32-bit format.
3581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     The p_align field is set to 8 in case the 64-bit format is used.
3582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     In case the p_align value is 0 or 4 the 32-bit format is
3583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     used.  */
3584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Xword align = phdr->p_align == 0 || phdr->p_align == 4 ? 4 : 8;
3585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
3586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Xword idx = 0;
3588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (idx < phdr->p_filesz)
3589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      uint64_t namesz;
3591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      uint64_t descsz;
3592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      uint64_t type;
3593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      uint32_t namesz32;
3594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      uint32_t descsz32;
3595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (align == 4)
3597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  uint32_t *ptr = (uint32_t *) (notemem + idx);
3599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if ((__BYTE_ORDER == __LITTLE_ENDIAN
3601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
3602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      || (__BYTE_ORDER == __BIG_ENDIAN
3603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
3604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz32 = namesz = bswap_32 (*ptr);
3606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++ptr;
3607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz32 = descsz = bswap_32 (*ptr);
3608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++ptr;
3609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      type = bswap_32 (*ptr);
3610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
3612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz32 = namesz = *ptr++;
3614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz32 = descsz = *ptr++;
3615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      type = *ptr;
3616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
3619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  uint64_t *ptr = (uint64_t *) (notemem + idx);
3621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  uint32_t *ptr32 = (uint32_t *) (notemem + idx);
3622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if ((__BYTE_ORDER == __LITTLE_ENDIAN
3624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
3625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      || (__BYTE_ORDER == __BIG_ENDIAN
3626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
3627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz = bswap_64 (*ptr);
3629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++ptr;
3630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz = bswap_64 (*ptr);
3631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++ptr;
3632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      type = bswap_64 (*ptr);
3633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz32 = bswap_32 (*ptr32);
3635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++ptr32;
3636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz32 = bswap_32 (*ptr32);
3637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
3639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz = *ptr++;
3641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz = *ptr++;
3642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      type = *ptr;
3643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      namesz32 = *ptr32++;
3645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      descsz32 = *ptr32;
3646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (idx + 3 * align > phdr->p_filesz
3650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || (idx + 3 * align + ALIGNED_LEN (namesz) + ALIGNED_LEN (descsz)
3651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      > phdr->p_filesz))
3652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (ehdr->e_ident[EI_CLASS] == ELFCLASS64
3654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && idx + 3 * 4 <= phdr->p_filesz
3655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && (idx + 3 * 4 + ALIGNED_LEN (namesz32) + ALIGNED_LEN (descsz32)
3656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  <= phdr->p_filesz))
3657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperphdr[%d]: note entries probably in form of a 32-bit ELF file\n"), cnt);
3659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
3660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("phdr[%d]: extra %zu bytes after last note\n"),
3661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, (size_t) (phdr->p_filesz - idx));
3662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Make sure it is one of the note types we know about.  */
3666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type == ET_CORE)
3667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  switch (type)
3669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PRSTATUS:
3671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_FPREGSET:
3672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PRPSINFO:
3673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_TASKSTRUCT:		/* NT_PRXREG on Solaris.  */
3674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PLATFORM:
3675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_AUXV:
3676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_GWINDOWS:
3677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_ASRS:
3678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PSTATUS:
3679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PSINFO:
3680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PRCRED:
3681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_UTSNAME:
3682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_LWPSTATUS:
3683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_LWPSINFO:
3684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    case NT_PRFPXREG:
3685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Known type.  */
3686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      break;
3687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    default:
3689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
3690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperphdr[%d]: unknown core file note type %" PRIu64 " at offset %" PRIu64 "\n"),
3691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     cnt, type, idx);
3692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
3695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (type != NT_VERSION)
3697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperphdr[%d]: unknown object file note type %" PRIu64 " at offset %" PRIu64 "\n"),
3699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, type, idx);
3700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Move to the next entry.  */
3703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      idx += 3 * align + ALIGNED_LEN (namesz) + ALIGNED_LEN (descsz);
3704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  gelf_freechunk (ebl->elf, notemem);
3708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
3709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
3712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
3713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
3714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_phoff == 0)
3715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
3716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
3718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_CORE)
3719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
3720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperonly executables, shared objects, and core files can have program headers\n"));
3721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_interp = 0;
3723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_tls = 0;
3724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_relro = 0;
3725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (int cnt = 0; cnt < ehdr->e_phnum; ++cnt)
3727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr phdr_mem;
3729b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr *phdr;
3730b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3731b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
3732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr == NULL)
3733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("cannot get program header entry %d: %s\n"),
3735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, elf_errmsg (-1));
3736b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
3737b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3738b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME
3740f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  && phdr->p_type != PT_GNU_STACK && phdr->p_type != PT_GNU_RELRO
3741f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  /* Check for a known machine-specific type.  */
3742f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  && ebl_segment_type_name (ebl, phdr->p_type, NULL, 0) == NULL)
3743b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3744f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrathprogram header entry %d: unknown program header entry type %#" PRIx64 "\n"),
3745f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	       cnt, (uint64_t) phdr->p_type);
3746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_type == PT_LOAD)
3748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	has_loadable_segment = true;
3749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_INTERP)
3750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_interp != 1)
3752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (num_pt_interp == 2)
3754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
3755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermore than one INTERP entry in program header\n"));
3756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  has_interp_segment = true;
3758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_TLS)
3760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_tls == 2)
3762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("more than one TLS entry in program header\n"));
3763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_NOTE)
3765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	check_note (ebl, ehdr, phdr, cnt);
376641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      else if (phdr->p_type == PT_DYNAMIC)
376741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
376841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  if (ehdr->e_type == ET_EXEC && ! has_interp_segment)
376941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    ERROR (gettext ("\
377041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic executable cannot have dynamic sections\n"));
377141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  else
377241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    {
377341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      /* Check that the .dynamic section, if it exists, has
377441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 the same address.  */
377541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      Elf_Scn *scn = NULL;
377641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
377741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		{
377841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr shdr_mem;
377941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
378041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
378141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    {
378241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      if (phdr->p_offset != shdr->sh_offset)
378341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			ERROR (gettext ("\
378441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperdynamic section reference in program header has wrong offset\n"));
378541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      if (phdr->p_memsz != shdr->sh_size)
378641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			ERROR (gettext ("\
378741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperdynamic section size mismatch in program and section header\n"));
378841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      break;
378941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    }
379041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		}
379141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    }
379241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
3793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_GNU_RELRO)
3794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_relro == 2)
3796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermore than one GNU_RELRO entry in program header\n"));
3798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
3799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
3800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Check that the region is in a writable segment.  */
3801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      int inner;
3802b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      for (inner = 0; inner < ehdr->e_phnum; ++inner)
3803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
3804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Phdr phdr2_mem;
3805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Phdr *phdr2;
3806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
3808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (phdr2 == NULL)
3809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    continue;
3810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (phdr2->p_type == PT_LOAD
3812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && phdr->p_vaddr >= phdr2->p_vaddr
3813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && (phdr->p_vaddr + phdr->p_memsz
3814b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  <= phdr2->p_vaddr + phdr2->p_memsz))
3815b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
3816b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if ((phdr2->p_flags & PF_W) == 0)
3817b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
3818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperloadable segment GNU_RELRO applies to is not writable\n"));
3819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if ((phdr2->p_flags & PF_X) != 0)
3820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
3821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperloadable segment GNU_RELRO applies to is executable\n"));
3822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      break;
3823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
3824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
3825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (inner >= ehdr->e_phnum)
3827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
3828607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper%s segment not contained in a loaded segment\n"), "GNU_RELRO");
3829607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
3830607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	}
3831607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      else if (phdr->p_type == PT_PHDR)
3832607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	{
3833607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* Check that the region is in a writable segment.  */
3834607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  int inner;
3835607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  for (inner = 0; inner < ehdr->e_phnum; ++inner)
3836607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
3837607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr phdr2_mem;
3838607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr *phdr2;
3839607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
3840607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
3841607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      if (phdr2 != NULL
3842607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr2->p_type == PT_LOAD
3843607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr >= phdr2->p_vaddr
3844607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && (phdr->p_vaddr + phdr->p_memsz
3845607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		      <= phdr2->p_vaddr + phdr2->p_memsz))
3846607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		break;
3847b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
3848607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
3849607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (inner >= ehdr->e_phnum)
3850607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    ERROR (gettext ("\
3851607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper%s segment not contained in a loaded segment\n"), "PHDR");
3852607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
3853607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* Check that offset in segment corresponds to offset in ELF
3854607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	     header.  */
3855607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (phdr->p_offset != ehdr->e_phoff)
3856607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    ERROR (gettext ("\
3857607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepperprogram header offset in ELF header and PHDR entry do not match"));
3858b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
38608190db6a86a37aec86c81626ab1b083c96aff891Roland McGrath      if (phdr->p_filesz > phdr->p_memsz
386156bc0b83ea81b7e959aaa4e1d01f8b36f2804a52Ulrich Drepper	  && (phdr->p_memsz != 0 || phdr->p_type != PT_NOTE))
3862b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3863b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: file size greater than memory size\n"),
3864b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt);
3865b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3866b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_align > 1)
3867b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3868b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (!powerof2 (phdr->p_align))
3869b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3870b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: alignment not a power of 2\n"), cnt);
3871b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0)
3872b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3873b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: file offset and virtual address not module of alignment\n"), cnt);
3874b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3875b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3876b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
3877b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3878b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3879b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Process one file.  */
3880b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
3881b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprocess_elf_file (Elf *elf, const char *prefix, const char *suffix,
3882b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  const char *fname, size_t size, bool only_one)
3883b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
3884b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Reset variables.  */
3885b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ndynamic = 0;
3886acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  nverneed = 0;
3887acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  nverdef = 0;
388841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  textrel = false;
388941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  needed_textrel = false;
3890acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  has_loadable_segment = false;
3891acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  has_interp_segment = false;
3892b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3893b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr ehdr_mem;
3894b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
3895b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Ebl *ebl;
3896b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3897b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Print the file name.  */
3898b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (!only_one)
3899b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3900b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (prefix != NULL)
3901b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	printf ("\n%s(%s)%s:\n", prefix, fname, suffix);
3902b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
3903b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	printf ("\n%s:\n", fname);
3904b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3906b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr == NULL)
3907b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3908b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("cannot read ELF header: %s\n"), elf_errmsg (-1));
3909b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
3910b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3911b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3912b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl = ebl_openbackend (elf);
3913b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If there is no appropriate backend library we cannot test
3914b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     architecture and OS specific features.  Any encountered extension
3915b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     is an error.  */
3916b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3917b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Go straight by the gABI, check all the parts in turn.  */
3918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_elf_header (ebl, ehdr, size);
3919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3920b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the program header.  */
3921b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_program_header (ebl, ehdr);
3922b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3923b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Next the section headers.  It is OK if there are no section
3924b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     headers at all.  */
3925b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_sections (ebl, ehdr);
3926b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
392741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* Report if no relocation section needed the text relocation flag.  */
392841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (textrel && !needed_textrel)
392941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    ERROR (gettext ("text relocation flag set but not needed\n"));
393041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
3931b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Free the resources.  */
3932b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl_closebackend (ebl);
3933b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
3934