elflint.c revision f93ee8d7dcd0d58f7aab96773af084aca82d5798
1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Pedantic checking of ELF files compliance with gABI/psABI spec.
244173edad1dfd24c4d98fcf032308f7df28db652Ulrich Drepper   Copyright (C) 2001,2002,2003,2004,2005,2006,2007,2008,2009 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>
49059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#include "../libelf/libelfP.h"
50059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#include "../libelf/common.h"
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "../libebl/libeblP.h"
52059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#include "../libdw/libdwP.h"
53059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#include "../libdwfl/libdwflP.h"
54059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#include "../libdw/memory-access.h"
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Name and version of program.  */
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void print_version (FILE *stream, struct argp_state *state);
59fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
60b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
61b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Bug report address.  */
62fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ARGP_strict	300
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ARGP_gnuld	301
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Definitions of arguments for argp functions.  */
68b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const struct argp_option options[] =
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "strict", ARGP_strict, NULL, 0,
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Be extremely strict, flag level 2 features."), 0 },
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "quiet", 'q', NULL, 0, N_("Do not print anything if successful"), 0 },
73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "debuginfo", 'd', NULL, 0, N_("Binary is a separate debuginfo file"), 0 },
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "gnu-ld", ARGP_gnuld, NULL, 0,
75b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Binary has been created with GNU ld and is therefore known to be \
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperbroken in certain ways"), 0 },
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, NULL, 0 }
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Short description of program.  */
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char doc[] = N_("\
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperPedantic checking of ELF files compliance with gABI/psABI spec.");
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Strings for arguments in help texts.  */
85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char args_doc[] = N_("FILE...");
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
87b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Prototype for option handler.  */
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Data structure to communicate with argp functions.  */
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic struct argp argp =
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  options, parse_opt, args_doc, doc, NULL, NULL, NULL
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
96b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Declarations of local functions.  */
98b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void process_file (int fd, Elf *elf, const char *prefix,
99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  const char *suffix, const char *fname, size_t size,
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  bool only_one);
101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void process_elf_file (Elf *elf, const char *prefix, const char *suffix,
102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      const char *fname, size_t size, bool only_one);
10359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic void check_note_section (Ebl *ebl, GElf_Ehdr *ehdr,
10459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath				GElf_Shdr *shdr, int idx);
10559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Report an error.  */
108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ERROR(str, args...) \
109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  do {									      \
110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    printf (str, ##args);						      \
111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ++error_count;							      \
112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  } while (0)
113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic unsigned int error_count;
114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* True if we should perform very strict testing.  */
116b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool be_strict;
117b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
118b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* True if no message is to be printed if the run is succesful.  */
119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool be_quiet;
120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* True if binary is from strip -f, not a normal ELF file.  */
122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool is_debuginfo;
123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* True if binary is assumed to be generated with GNU ld.  */
125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool gnuld;
126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Index of section header string table.  */
128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic uint32_t shstrndx;
129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Array to count references in section groups.  */
131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int *scnref;
132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermain (int argc, char *argv[])
136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Set locale.  */
138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  setlocale (LC_ALL, "");
139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Initialize the message catalog.  */
141b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  textdomain (PACKAGE_TARNAME);
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Parse and process arguments.  */
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int remaining;
145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Before we start tell the ELF library which version we are using.  */
148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_version (EV_CURRENT);
149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now process all the files given at the command line.  */
151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool only_one = remaining + 1 == argc;
152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  do
153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Open the file.  */
155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      int fd = open (argv[remaining], O_RDONLY);
156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (fd == -1)
157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, errno, gettext ("cannot open input file"));
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Create an `Elf' descriptor.  */
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf == NULL)
165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("cannot generate Elf descriptor: %s\n"),
166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       elf_errmsg (-1));
167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  unsigned int prev_error_count = error_count;
170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  struct stat64 st;
171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (fstat64 (fd, &st) != 0)
173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      printf ("cannot stat '%s': %m\n", argv[remaining]);
175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      close (fd);
176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  process_file (fd, elf, NULL, NULL, argv[remaining], st.st_size,
180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			only_one);
181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Now we can close the descriptor.  */
183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (elf_end (elf) != 0)
184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("error while closing Elf descriptor: %s\n"),
185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   elf_errmsg (-1));
186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (prev_error_count == error_count && !be_quiet)
188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    puts (gettext ("No errors"));
189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      close (fd);
192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (++remaining < argc);
194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return error_count != 0;
196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle program arguments.  */
200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t
201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperparse_opt (int key, char *arg __attribute__ ((unused)),
202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   struct argp_state *state __attribute__ ((unused)))
203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (key)
205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ARGP_strict:
207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      be_strict = true;
208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'q':
211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      be_quiet = true;
212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'd':
215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      is_debuginfo = true;
216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ARGP_gnuld:
218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      gnuld = true;
219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ARGP_KEY_NO_ARGS:
222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      fputs (gettext ("Missing file name.\n"), stderr);
223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 program_invocation_short_name);
225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      exit (1);
226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ARGP_ERR_UNKNOWN;
229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print the version information.  */
235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
238b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  fprintf (stream, "elflint (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("\
240b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperCopyright (C) %s Red Hat, Inc.\n\
241b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperThis is free software; see the source for copying conditions.  There is NO\n\
242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
24344173edad1dfd24c4d98fcf032308f7df28db652Ulrich Drepper"), "2009");
244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Process one file.  */
249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprocess_file (int fd, Elf *elf, const char *prefix, const char *suffix,
251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      const char *fname, size_t size, bool only_one)
252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We can handle two types of files: ELF files and archives.  */
254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Kind kind = elf_kind (elf);
255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (kind)
257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_ELF:
259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Yes!  It's an ELF file.  */
260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      process_elf_file (elf, prefix, suffix, fname, size, only_one);
261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_AR:
264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf *subelf;
266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf_Cmd cmd = ELF_C_READ_MMAP;
267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size_t fname_len = strlen (fname) + 1;
269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char new_prefix[prefix_len + 1 + fname_len];
270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char new_suffix[(suffix == NULL ? 0 : strlen (suffix)) + 2];
271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char *cp = new_prefix;
272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Create the full name of the file.  */
274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (prefix != NULL)
275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    cp = mempcpy (cp, prefix, prefix_len);
277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    *cp++ = '(';
278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    strcpy (stpcpy (new_suffix, suffix), ")");
279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	else
281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  new_suffix[0] = '\0';
282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	memcpy (cp, fname, fname_len);
283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* It's an archive.  We process each file in it.  */
285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    kind = elf_kind (subelf);
288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Call this function recursively.  */
290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (kind == ELF_K_ELF || kind == ELF_K_AR)
291b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
292b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		Elf_Arhdr *arhdr = elf_getarhdr (subelf);
293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		assert (arhdr != NULL);
294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		process_file (fd, subelf, new_prefix, new_suffix,
296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      arhdr->ar_name, arhdr->ar_size, false);
297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
298b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Get next archive element.  */
300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    cmd = elf_next (subelf);
301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (elf_end (subelf) != 0)
302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext (" error while freeing sub-ELF descriptor: %s\n"),
303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     elf_errmsg (-1));
304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
307b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
308b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We cannot do anything.  */
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
31141de488a0ad6679e816dbab960351e5f62ab8eadUlrich DrepperNot an ELF file - it has the wrong magic bytes at the start\n"));
312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *
318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection_name (Ebl *ebl, int idx)
319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr shdr_mem;
321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *shdr;
322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shdr = gelf_getshdr (elf_getscn (ebl->elf, idx), &shdr_mem);
324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const int valid_e_machine[] =
330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_M32, EM_SPARC, EM_386, EM_68K, EM_88K, EM_860, EM_MIPS, EM_S370,
332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_MIPS_RS3_LE, EM_PARISC, EM_VPP500, EM_SPARC32PLUS, EM_960, EM_PPC,
333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_PPC64, EM_S390, EM_V800, EM_FR20, EM_RH32, EM_RCE, EM_ARM,
334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_FAKE_ALPHA, EM_SH, EM_SPARCV9, EM_TRICORE, EM_ARC, EM_H8_300,
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_H8_300H, EM_H8S, EM_H8_500, EM_IA_64, EM_MIPS_X, EM_COLDFIRE,
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_68HC12, EM_MMA, EM_PCP, EM_NCPU, EM_NDR1, EM_STARCORE, EM_ME16,
337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_ST100, EM_TINYJ, EM_X86_64, EM_PDSP, EM_FX66, EM_ST9PLUS, EM_ST7,
338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX,
339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM,
340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300,
341c373d850ec9ca342f4c71d5e287c8d8bf0723cd6Roland McGrath    EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA, EM_ALPHA
342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  };
343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define nvalid_e_machine \
344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (sizeof (valid_e_machine) / sizeof (valid_e_machine[0]))
345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Number of sections.  */
348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic unsigned int shnum;
349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size)
353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char buf[512];
355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cnt;
356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check e_ident field.  */
358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG0] != ELFMAG0)
359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG0, ELFMAG0);
360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG1] != ELFMAG1)
361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG1, ELFMAG1);
362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG2] != ELFMAG2)
363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG2, ELFMAG2);
364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_MAG3] != ELFMAG3)
365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR ("e_ident[%d] != '%c'\n", EI_MAG3, ELFMAG3);
366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_CLASS] != ELFCLASS32
368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_ident[EI_CLASS] != ELFCLASS64)
369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("e_ident[%d] == %d is no known class\n"),
370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_CLASS, ehdr->e_ident[EI_CLASS]);
371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("e_ident[%d] == %d is no known data encoding\n"),
375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_DATA, ehdr->e_ident[EI_DATA]);
376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_VERSION] != EV_CURRENT)
378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown ELF header version number e_ident[%d] == %d\n"),
379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_VERSION, ehdr->e_ident[EI_VERSION]);
380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We currently don't handle any OS ABIs.  */
382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE)
383e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper    ERROR (gettext ("unsupported OS ABI e_ident[%d] == '%s'\n"),
384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_OSABI,
385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* No ABI versions other than zero supported either.  */
388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_ident[EI_ABIVERSION] != 0)
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unsupport ABI version e_ident[%d] == %d\n"),
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   EI_ABIVERSION, ehdr->e_ident[EI_ABIVERSION]);
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = EI_PAD; cnt < EI_NIDENT; ++cnt)
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (ehdr->e_ident[cnt] != 0)
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("e_ident[%zu] is not zero\n"), cnt);
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_type field.  */
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_REL && ehdr->e_type != ET_EXEC
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_DYN && ehdr->e_type != ET_CORE)
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown object file type %d\n"), ehdr->e_type);
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_machine field.  */
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 0; cnt < nvalid_e_machine; ++cnt)
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (valid_e_machine[cnt] == ehdr->e_machine)
404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (cnt == nvalid_e_machine)
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown machine type %d\n"), ehdr->e_machine);
407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_version field.  */
409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_version != EV_CURRENT)
410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("unknown object file version\n"));
411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_phoff and e_phnum fields.  */
413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_phoff == 0)
414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phnum != 0)
416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header offset\n"));
417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperexecutables and DSOs cannot have zero program header offset\n"));
420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else if (ehdr->e_phnum == 0)
422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("invalid number of program header entries\n"));
423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_shoff field.  */
425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shnum = ehdr->e_shnum;
426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  shstrndx = ehdr->e_shstrndx;
427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_shoff == 0)
428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shnum != 0)
430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header table offset\n"));
431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       && ehdr->e_type != ET_CORE)
433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section header table must be present\n"));
434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shnum == 0)
438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Get the header of the zeroth section.  The sh_size field
440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     might contain the section number.  */
441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
442acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr != NULL)
444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* The error will be reported later.  */
446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (shdr->sh_size == 0)
447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperinvalid number of section header table entries\n"));
449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		shnum = shdr->sh_size;
451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shstrndx == SHN_XINDEX)
455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Get the header of the zeroth section.  The sh_size field
457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     might contain the section number.  */
458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
459acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
460acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  if (shdr != NULL && shdr->sh_link < shnum)
461acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    shstrndx = shdr->sh_link;
462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (shstrndx >= shnum)
464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header index\n"));
465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the e_flags field.  */
468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (!ebl_machine_flag_check (ebl, ehdr->e_flags))
469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("invalid machine flags: %s\n"),
470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check e_ehsize, e_phentsize, and e_shentsize fields.  */
473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (gelf_getclass (ebl->elf) == ELFCLASS32)
474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf32_Ehdr))
476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr))
479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header size: %hd\n"),
480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_phentsize);
481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header position or size\n"));
483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr))
485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header size: %hd\n"),
486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_shentsize);
487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header position or size\n"));
489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else if (gelf_getclass (ebl->elf) == ELFCLASS64)
491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf64_Ehdr))
493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr))
496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header size: %hd\n"),
497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_phentsize);
498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid program header position or size\n"));
500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr))
502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header size: %hd\n"),
503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ehdr->e_shentsize);
504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("invalid section header position or size\n"));
506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Check that there is a section group section with index < IDX which
511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   contains section IDX and that there is exactly one.  */
512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_scn_group (Ebl *ebl, int idx)
514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (scnref[idx] == 0)
516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* No reference so far.  Search following sections, maybe the
518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 order is wrong.  */
519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t cnt;
520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = idx + 1; cnt < shnum; ++cnt)
522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
523acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
525acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr == NULL)
527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* We cannot get the section header so we cannot check it.
528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       The error to get the section header will be shown
529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       somewhere else.  */
530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr->sh_type != SHT_GROUP)
533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
535acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf_Data *data = elf_getdata (scn, NULL);
536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (data == NULL || data->d_size < sizeof (Elf32_Word))
537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Cannot check the section.  */
538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
540acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  Elf32_Word *grpdata = (Elf32_Word *) data->d_buf;
541acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  for (size_t inner = 1; inner < data->d_size / sizeof (Elf32_Word);
542acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	       ++inner)
543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (grpdata[inner] == (Elf32_Word) idx)
544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      goto out;
545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    out:
548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (cnt == shnum)
549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section with SHF_GROUP flag set not part of a section group\n"),
551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group [%2zu] '%s' does not preceed group member\n"),
555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx),
556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
562dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_symtab (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool no_xndx_warned = false;
565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int no_pt_tls = 0;
566dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
574dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr strshdr_mem;
575dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
576dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper				     &strshdr_mem);
577dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (strshdr == NULL)
578dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
579dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
581521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath    {
582521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      ERROR (gettext ("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
583521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	     shdr->sh_link, section_name (ebl, shdr->sh_link),
584521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	     idx, section_name (ebl, idx));
585521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      strshdr = NULL;
586521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath    }
587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Search for an extended section index table section.  */
589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *xndxdata = NULL;
590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf32_Word xndxscnidx = 0;
591acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  bool found_xndx = false;
5923cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper  for (size_t cnt = 1; cnt < shnum; ++cnt)
593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (cnt != (size_t) idx)
594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Elf_Scn *xndxscn = elf_getscn (ebl->elf, cnt);
596acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	GElf_Shdr xndxshdr_mem;
597acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
598acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	if (xndxshdr == NULL)
599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    && xndxshdr->sh_link == (GElf_Word) idx)
603acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  {
604acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    if (found_xndx)
605acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	      ERROR (gettext ("\
606acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': symbol table cannot have more than one extended index section\n"),
607acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper		     idx, section_name (ebl, idx));
608acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
609acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    xndxdata = elf_getdata (xndxscn, NULL);
610acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    xndxscnidx = elf_ndxscn (xndxscn);
611acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    found_xndx = true;
612acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  }
613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT))
616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
6173cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Dreppersection [%2u] '%s': entry size is does not match ElfXX_Sym\n"),
6183cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	   idx, section_name (ebl, idx));
619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Test the zeroth entry.  */
621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Sym sym_mem;
622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf32_Word xndx;
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, 0, &sym_mem, &xndx);
624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (sym == NULL)
625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get symbol %d: %s\n"),
626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx), 0, elf_errmsg (-1));
627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_name != 0)
630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_name");
632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_value != 0)
633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_value");
635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_size != 0)
636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_size");
638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_info != 0)
639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_info");
641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_other != 0)
642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_other");
644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_shndx != 0)
645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), "st_shndx");
647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndxdata != NULL && xndx != 0)
648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': XINDEX for zeroth entry not zero\n"),
650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       xndxscnidx, section_name (ebl, xndxscnidx));
651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6533cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper  for (size_t cnt = 1; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx);
656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym == NULL)
657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("section [%2d] '%s': cannot get symbol %zu: %s\n"),
659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *name = NULL;
664521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      if (strshdr == NULL)
665521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath	name = "";
666521c47d2a216fc64098c024fc5ed53532b485f32Roland McGrath      else if (sym->st_name >= strshdr->sh_size)
667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: invalid name value\n"),
669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name);
673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  assert (name != NULL);
674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (sym->st_shndx == SHN_XINDEX)
677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (xndxdata == NULL)
679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: too large section index but no extended section index section\n"),
682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt);
683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      no_xndx_warned = true;
684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (xndx < SHN_LORESERVE)
686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: XINDEX used for index which would fit in st_shndx (%" PRIu32 ")\n"),
688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   xndxscnidx, section_name (ebl, xndxscnidx), cnt,
689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   xndx);
690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if ((sym->st_shndx >= SHN_LORESERVE
692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		// && sym->st_shndx <= SHN_HIRESERVE    always true
693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& sym->st_shndx != SHN_ABS
694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& sym->st_shndx != SHN_COMMON)
695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       || (sym->st_shndx >= shnum
696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   && (sym->st_shndx < SHN_LORESERVE
697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       /* || sym->st_shndx > SHN_HIRESERVE  always false */)))
698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: invalid section index\n"),
700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	xndx = sym->st_shndx;
703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
70418e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath      if (GELF_ST_TYPE (sym->st_info) >= STT_NUM
70518e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && !ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), NULL, 0))
706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': symbol %zu: unknown type\n"),
707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_BIND (sym->st_info) >= STB_NUM)
710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: unknown symbol binding\n"),
712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndx == SHN_COMMON)
715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Common symbols can only appear in relocatable files.  */
717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (ehdr->e_type != ET_REL)
718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n"),
720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt < shdr->sh_info)
722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n"),
724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (GELF_R_TYPE (sym->st_info) == STT_FUNC)
726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"),
728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
729b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
730b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (xndx > 0 && xndx < shnum)
731b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr destshdr_mem;
733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr *destshdr;
734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), &destshdr_mem);
736b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (destshdr != NULL)
737b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
738b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      GElf_Addr sh_addr = (ehdr->e_type == ET_REL ? 0
739b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				   : destshdr->sh_addr);
740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (GELF_ST_TYPE (sym->st_info) != STT_TLS)
741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
742c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  if (! ebl_check_special_symbol (ebl, ehdr, sym, name,
743c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper						  destshdr))
744c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    {
745b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		      if (sym->st_value - sh_addr > destshdr->sh_size)
746ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			{
747ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			  /* GNU ld has severe bugs.  When it decides to remove
748ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			     empty sections it leaves symbols referencing them
749ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			     behind.  These are symbols in .symtab.  */
750ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			  if (!gnuld
751ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			      || strcmp (section_name (ebl, idx), ".symtab")
752ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			      || (strcmp (name, "__preinit_array_start") != 0
753ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__preinit_array_end") != 0
754ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__init_array_start") != 0
755ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__init_array_end") != 0
756ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__fini_array_start") != 0
757ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				  && strcmp (name, "__fini_array_end") != 0))
758ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			    ERROR (gettext ("\
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds\n"),
760ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper				   idx, section_name (ebl, idx), cnt);
761ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			}
762b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		      else if ((sym->st_value - sh_addr
763c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper				+ sym->st_size) > destshdr->sh_size)
764c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
766c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx), cnt,
767c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (int) xndx, section_name (ebl, xndx));
768c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    }
769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if ((destshdr->sh_flags & SHF_TLS) == 0)
773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_TLS flag set\n"),
775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx), cnt,
776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   (int) xndx, section_name (ebl, xndx));
777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (ehdr->e_type == ET_REL)
779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      /* For object files the symbol value must fall
781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper                         into the section.  */
782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (sym->st_value > destshdr->sh_size)
783b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
784b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
785b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       idx, section_name (ebl, idx), cnt,
786b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       (int) xndx, section_name (ebl, xndx));
787b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      else if (sym->st_value + sym->st_size
788b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       > destshdr->sh_size)
789b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
790b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
791b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       idx, section_name (ebl, idx), cnt,
792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       (int) xndx, section_name (ebl, xndx));
793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  else
795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Phdr phdr_mem;
797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      GElf_Phdr *phdr = NULL;
798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      int pcnt;
799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
802b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (phdr != NULL && phdr->p_type == PT_TLS)
804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    break;
805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (pcnt == ehdr->e_phnum)
808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (no_pt_tls++ == 0)
810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"),
812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt);
813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
814b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      else
815b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
816b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  if (sym->st_value
817b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      < destshdr->sh_offset - phdr->p_offset)
818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"),
820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
822b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  else if (sym->st_value
823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   > (destshdr->sh_offset - phdr->p_offset
824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				      + destshdr->sh_size))
825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  else if (sym->st_value + sym->st_size
830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   > (destshdr->sh_offset - phdr->p_offset
831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				      + destshdr->sh_size))
832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    ERROR (gettext ("\
833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
834b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   idx, section_name (ebl, idx), cnt,
835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   (int) xndx, section_name (ebl, xndx));
836b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
837b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
840b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
842b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
843b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
844b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt >= shdr->sh_info)
845b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: local symbol outside range described in sh_info\n"),
847b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
851b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt < shdr->sh_info)
852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
853b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: non-local symbol outside range described in sh_info\n"),
854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt);
855b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
856b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
857b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
858b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
860b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': symbol %zu: non-local section symbol\n"),
861b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
862b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
863b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (name != NULL)
864b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
865b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
866b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
867653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      /* Check that address and size match the global offset table.  */
868653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
869653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      GElf_Shdr destshdr_mem;
870653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx),
871653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						  &destshdr_mem);
872653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
873653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (destshdr == NULL && xndx == SHN_ABS)
874b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
875653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  /* In a DSO, we have to find the GOT section by name.  */
876653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  Elf_Scn *gotscn = NULL;
877c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  Elf_Scn *gscn = NULL;
878653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL)
879b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
880653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      destshdr = gelf_getshdr (gscn, &destshdr_mem);
881653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      assert (destshdr != NULL);
882653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      const char *sname = elf_strptr (ebl->elf,
883653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						      ehdr->e_shstrndx,
884653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						      destshdr->sh_name);
885653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      if (sname != NULL)
886b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			{
887c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  if (strcmp (sname, ".got.plt") == 0)
888653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    break;
889c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  if (strcmp (sname, ".got") == 0)
890653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    /* Do not stop looking.
891653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			       There might be a .got.plt section.  */
892653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			    gotscn = gscn;
893b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
894653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
895653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		      destshdr = NULL;
896b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
897653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
898653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  if (destshdr == NULL && gotscn != NULL)
899653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    destshdr = gelf_getshdr (gotscn, &destshdr_mem);
900b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
901b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
902b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      const char *sname = ((destshdr == NULL || xndx == SHN_UNDEF)
903b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				   ? NULL
904653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath				   : elf_strptr (ebl->elf, ehdr->e_shstrndx,
905653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath						 destshdr->sh_name));
906653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (sname == NULL)
907b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		{
908b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		  if (xndx != SHN_UNDEF || ehdr->e_type != ET_REL)
909b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		    ERROR (gettext ("\
910b597dfad924980dede10d7c19d87900b6172e599Ulrich Dreppersection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
911b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperbad section [%2d]\n"),
912b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			   idx, section_name (ebl, idx), xndx);
913b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		}
914653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      else if (strcmp (sname, ".got.plt") != 0
915653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		       && strcmp (sname, ".got") != 0)
916653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		ERROR (gettext ("\
917b597dfad924980dede10d7c19d87900b6172e599Ulrich Dreppersection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
918b597dfad924980dede10d7c19d87900b6172e599Ulrich Dreppersection [%2d] '%s'\n"),
919b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		       idx, section_name (ebl, idx), xndx, sname);
920653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
921653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	      if (destshdr != NULL)
922b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
923b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Found it.  */
924c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		  if (!ebl_check_special_symbol (ebl, ehdr, sym, name,
925c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper						 destshdr))
926c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    {
927b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		      if (ehdr->e_type != ET_REL
928b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  && sym->st_value != destshdr->sh_addr)
929c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			/* This test is more strict than the psABIs which
930c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			   usually allow the symbol to be in the middle of
931c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			   the .got section, allowing negative offsets.  */
932c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
933653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match %s section address %#" PRIx64 "\n"),
934c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx),
935c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (uint64_t) sym->st_value,
936c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       sname, (uint64_t) destshdr->sh_addr);
937b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
938c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		      if (!gnuld && sym->st_size != destshdr->sh_size)
939c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			ERROR (gettext ("\
940653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match %s section size %" PRIu64 "\n"),
941c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       idx, section_name (ebl, idx),
942c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       (uint64_t) sym->st_size,
943c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			       sname, (uint64_t) destshdr->sh_size);
944c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    }
945b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
946b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
947b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
948b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"),
949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx));
950b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
951b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (strcmp (name, "_DYNAMIC") == 0)
95241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    /* Check that address and size match the dynamic section.
95341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	       We locate the dynamic section via the program header
95441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	       entry.  */
95541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    for (int pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
95641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      {
95741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Phdr phdr_mem;
95841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
96041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
96141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  {
96241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    if (sym->st_value != phdr->p_vaddr)
96341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      ERROR (gettext ("\
964b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"),
96541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     idx, section_name (ebl, idx),
96641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) sym->st_value,
96741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) phdr->p_vaddr);
968b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
96941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    if (!gnuld && sym->st_size != phdr->p_memsz)
97041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      ERROR (gettext ("\
971b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"),
97241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     idx, section_name (ebl, idx),
97341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) sym->st_size,
97441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			     (uint64_t) phdr->p_memsz);
975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
97641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    break;
97741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  }
978b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
983b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool
985c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperis_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr,
98628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    bool is_rela)
987b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
988b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If this is no executable or DSO it cannot be a .rel.dyn section.  */
989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return false;
991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
992b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the section name.  Unfortunately necessary.  */
99328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (strcmp (section_name (ebl, idx), is_rela ? ".rela.dyn" : ".rel.dyn"))
994b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return false;
995b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
996b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section
997b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     entry can be present as well.  */
998b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn = NULL;
999b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1000b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1001b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr rcshdr_mem;
1002b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem);
1003b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      assert (rcshdr != NULL);
1004b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1005b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rcshdr->sh_type == SHT_DYNAMIC)
1006b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1007b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Found the dynamic section.  Look through it.  */
1008b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  Elf_Data *d = elf_getdata (scn, NULL);
1009b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t cnt;
1010b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1011b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt)
1012b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1013b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Dyn dyn_mem;
1014b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem);
1015b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      assert (dyn != NULL);
1016b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1017b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (dyn->d_tag == DT_RELCOUNT)
1018b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
101928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  /* Found it.  Does the type match.  */
102028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if (is_rela)
1021b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
102228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELCOUNT used for this RELA section\n"),
102328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx));
102428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  else
102528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    {
102628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Does the number specified number of relative
102728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations exceed the total number of
102828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations?  */
102928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
103028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			ERROR (gettext ("\
1031b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
103228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       idx, section_name (ebl, idx),
103328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       (int) dyn->d_un.d_val);
103428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
103528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Make sure the specified number of relocations are
103628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relative.  */
103728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
103828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper								   idx), NULL);
103928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (reldata != NULL)
104028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			for (size_t inner = 0;
104128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     inner < shdr->sh_size / shdr->sh_entsize;
104228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     ++inner)
104328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  {
104428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rel rel_mem;
104528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rel *rel = gelf_getrel (reldata, inner,
104628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							 &rel_mem);
104728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (rel == NULL)
104828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      /* The problem will be reported elsewhere.  */
104928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      break;
105028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
105128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (ebl_relative_reloc_p (ebl,
105228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						      GELF_R_TYPE (rel->r_info)))
105328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      {
105428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				if (inner >= dyn->d_un.d_val)
105528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				  ERROR (gettext ("\
105628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
105728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 idx, section_name (ebl, idx),
105828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 (int) dyn->d_un.d_val);
105928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      }
106028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    else if (inner < dyn->d_un.d_val)
106128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      ERROR (gettext ("\
106228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
106328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     idx, section_name (ebl, idx),
106428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     inner, (int) dyn->d_un.d_val);
106528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  }
106628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    }
106728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		}
106828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
106928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      if (dyn->d_tag == DT_RELACOUNT)
107028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		{
107128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  /* Found it.  Does the type match.  */
107228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if (!is_rela)
107328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    ERROR (gettext ("\
107428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELACOUNT used for this REL section\n"),
107528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   idx, section_name (ebl, idx));
107628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  else
107728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    {
107828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Does the number specified number of relative
107928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations exceed the total number of
108028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relocations?  */
108128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
108228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			ERROR (gettext ("\
108328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
108428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       idx, section_name (ebl, idx),
108528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			       (int) dyn->d_un.d_val);
108628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
108728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      /* Make sure the specified number of relocations are
108828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			 relative.  */
108928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
109028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper								   idx), NULL);
109128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		      if (reldata != NULL)
109228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			for (size_t inner = 0;
109328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     inner < shdr->sh_size / shdr->sh_entsize;
109428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			     ++inner)
109528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  {
109628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rela rela_mem;
109728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    GElf_Rela *rela = gelf_getrela (reldata, inner,
109828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							    &rela_mem);
109928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (rela == NULL)
110028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      /* The problem will be reported elsewhere.  */
110128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      break;
110228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
110328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    if (ebl_relative_reloc_p (ebl,
110428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						      GELF_R_TYPE (rela->r_info)))
110528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      {
110628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				if (inner >= dyn->d_un.d_val)
110728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				  ERROR (gettext ("\
110828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
110928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 idx, section_name (ebl, idx),
111028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper					 (int) dyn->d_un.d_val);
111128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      }
111228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			    else if (inner < dyn->d_un.d_val)
111328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			      ERROR (gettext ("\
111428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
111528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     idx, section_name (ebl, idx),
111628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper				     inner, (int) dyn->d_un.d_val);
111728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			  }
111828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    }
1119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return true;
1127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
113041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstruct loaded_segment
113141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper{
113241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Addr from;
113341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Addr to;
113441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  bool read_only;
113541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *next;
113641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper};
113741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
113841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
113941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper/* Check whether binary has text relocation flag set.  */
114041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic bool textrel;
114141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
114241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper/* Keep track of whether text relocation flag is needed.  */
114341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic bool needed_textrel;
114441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
114541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1146c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic bool
1147c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr,
1148c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		  int idx, int reltype, GElf_Shdr **destshdrp,
114941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr *destshdr_memp, struct loaded_segment **loadedp)
1150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool reldyn = false;
1152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check whether the link to the section we relocate is reasonable.  */
1154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info >= shnum)
1155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"),
1156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1157c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  else if (shdr->sh_info != 0)
1158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1159c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      *destshdrp = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1160c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper				 destshdr_memp);
1161c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (*destshdrp != NULL)
1162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1163c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  if((*destshdrp)->sh_type != SHT_PROGBITS
1164c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	     && (*destshdrp)->sh_type != SHT_NOBITS)
1165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true);
1167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (!reldyn)
1168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
1169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': invalid destination section type\n"),
1170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx));
1171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
1172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
1173c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		  /* There is no standard, but we require that .rel{,a}.dyn
1174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     sections have a sh_info value of zero.  */
1175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (shdr->sh_info != 0)
1176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
1177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': sh_info should be zero\n"),
1178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx));
1179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
1180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1182c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  if (((*destshdrp)->sh_flags & (SHF_MERGE | SHF_STRINGS)) != 0)
1183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': no relocations for merge-able sections possible\n"),
1185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
1186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1189c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (shdr->sh_entsize != gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT))
1190c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext (reltype == ELF_T_RELA ? "\
1191c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Rela\n" : "\
1192c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Rel\n"),
1193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
119541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* In preparation of checking whether relocations are text
119641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     relocations or not we need to determine whether the file is
119741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     flagged to have text relocation and we need to determine a) what
119841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     the loaded segments are and b) which are read-only.  This will
119941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     also allow us to determine whether the same reloc section is
120041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     modifying loaded and not loaded segments.  */
120141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  for (int i = 0; i < ehdr->e_phnum; ++i)
120241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
120341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      GElf_Phdr phdr_mem;
120441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
120541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (phdr == NULL)
120641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	continue;
120741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
120841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (phdr->p_type == PT_LOAD)
120941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
121041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  struct loaded_segment *newp = xmalloc (sizeof (*newp));
121141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->from = phdr->p_vaddr;
121241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->to = phdr->p_vaddr + phdr->p_memsz;
121341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->read_only = (phdr->p_flags & PF_W) == 0;
121441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  newp->next = *loadedp;
121541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  *loadedp = newp;
121641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
121741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      else if (phdr->p_type == PT_DYNAMIC)
121841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
121941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  Elf_Scn *dynscn = gelf_offscn (ebl->elf, phdr->p_offset);
122041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  GElf_Shdr dynshdr_mem;
122141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem);
122241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  Elf_Data *dyndata = elf_getdata (dynscn, NULL);
122341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC
122441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      && dyndata != NULL)
122541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j)
122641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      {
122741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Dyn dyn_mem;
122841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		GElf_Dyn *dyn = gelf_getdyn (dyndata, j, &dyn_mem);
122941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		if (dyn != NULL
123041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    && (dyn->d_tag == DT_TEXTREL
123141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			|| (dyn->d_tag == DT_FLAGS
123241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			    && (dyn->d_un.d_val & DF_TEXTREL) != 0)))
123341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  {
123441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    textrel = true;
123541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    break;
123641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  }
123741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      }
123841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
123941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
124041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
124141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* A quick test which can be easily done here (although it is a bit
124241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     out of place): the text relocation flag makes only sense if there
124341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper     is a segment which is not writable.  */
124441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (textrel)
124541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
124641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *seg = *loadedp;
124741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      while (seg != NULL && !seg->read_only)
124841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	seg = seg->next;
124941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      if (seg == NULL)
125041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	ERROR (gettext ("\
125141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Dreppertext relocation flag set but there is no read-only segment\n"));
125241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
125341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1254c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  return reldyn;
1255c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper}
1256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
125841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperenum load_state
125941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  {
126041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_undecided,
126141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_loaded,
126241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_unloaded,
126341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    state_error
126441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  };
126541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
126641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1267c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic void
1268607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppercheck_one_reloc (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *relshdr, int idx,
1269607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		 size_t cnt, const GElf_Shdr *symshdr, Elf_Data *symdata,
1270607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		 GElf_Addr r_offset, GElf_Xword r_info,
127141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 const GElf_Shdr *destshdr, bool reldyn,
127241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 struct loaded_segment *loaded, enum load_state *statep)
1273c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper{
1274c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool known_broken = gnuld;
1275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1276c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (r_info)))
1277c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"),
1278c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1279607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper  else if (((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1280607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    /* The executable/DSO can contain relocation sections with
1281607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	       all the relocations the linker has applied.  Those sections
1282607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	       are marked non-loaded, though.  */
1283607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    || (relshdr->sh_flags & SHF_ALLOC) != 0)
1284607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	   && !ebl_reloc_valid_use (ebl, GELF_R_TYPE (r_info)))
1285c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("\
1286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
1287c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1289c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (symshdr != NULL
1290c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      && ((GELF_R_SYM (r_info) + 1)
1291c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
1292c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  > symshdr->sh_size))
1293c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    ERROR (gettext ("\
1294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: invalid symbol index\n"),
1295c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	   idx, section_name (ebl, idx), cnt);
1296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
12976ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper  /* No more tests if this is a no-op relocation.  */
12986ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper  if (ebl_none_reloc_p (ebl, GELF_R_TYPE (r_info)))
12996ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper    return;
13006ca4600fb59d1e1ae3dfb872b184ac91f10c473fUlrich Drepper
1301c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (r_info)))
1302c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1303c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      const char *name;
1304c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      char buf[64];
1305c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Sym sym_mem;
1306c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
1307c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (sym != NULL
1308c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  /* Get the name for the symbol.  */
1309c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1310c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
1311c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	ERROR (gettext ("\
1312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
1313c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	       idx, section_name (ebl, idx), cnt,
1314c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	       ebl_reloc_type_name (ebl, GELF_R_SYM (r_info),
1315c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper				    buf, sizeof (buf)));
1316c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1318c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (reldyn)
1319c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1320c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      // XXX TODO Check .rel.dyn section addresses.
1321c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1322c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  else if (!known_broken)
1323c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1324c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (destshdr != NULL
1325c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  && GELF_R_TYPE (r_info) != 0
1326b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  && (r_offset - (ehdr->e_type == ET_REL ? 0
1327b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  : destshdr->sh_addr)) >= destshdr->sh_size)
1328c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	ERROR (gettext ("\
1329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': relocation %zu: offset out of bounds\n"),
1330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1331c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
133341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Sym sym_mem;
133441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
133541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
133641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info))
1337c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      /* Make sure the referenced symbol is an object or unspecified.  */
133841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && sym != NULL
133941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE
134041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
134141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
134241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      char buf[64];
134341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      ERROR (gettext ("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"),
134441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	     idx, section_name (ebl, idx), cnt,
134541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	     ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
134641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				   buf, sizeof (buf)));
134741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
134841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1349038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper  if ((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1350038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      || (relshdr->sh_flags & SHF_ALLOC) != 0)
135141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
1352038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      bool in_loaded_seg = false;
1353038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      while (loaded != NULL)
1354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1355038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  if (r_offset < loaded->to
1356038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      && r_offset + (sym == NULL ? 0 : sym->st_size) >= loaded->from)
135741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    {
1358038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      /* The symbol is in this segment.  */
1359038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      if  (loaded->read_only)
1360038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		{
1361038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		  if (textrel)
1362038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		    needed_textrel = true;
1363038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		  else
1364038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		    ERROR (gettext ("section [%2d] '%s': relocation %zu: read-only section modified but text relocation flag not set\n"),
1365038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper			   idx, section_name (ebl, idx), cnt);
1366038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		}
1367038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper
1368038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	      in_loaded_seg = true;
136941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    }
137041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1371038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  loaded = loaded->next;
1372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
137341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
1374038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      if (*statep == state_undecided)
1375038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	*statep = in_loaded_seg ? state_loaded : state_unloaded;
1376038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper      else if ((*statep == state_unloaded && in_loaded_seg)
1377038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	       || (*statep == state_loaded && !in_loaded_seg))
1378038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	{
1379038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  ERROR (gettext ("\
138041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Dreppersection [%2d] '%s': relocations are against loaded and unloaded data\n"),
1381038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper		 idx, section_name (ebl, idx));
1382038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	  *statep = state_error;
1383038129b11ac71a13ccaf9029122be86d6c532990Ulrich Drepper	}
1384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1389c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1391c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
1393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
1396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
1397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1399c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  /* Check the fields of the section header.  */
1400c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr destshdr_mem;
1401c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *destshdr = NULL;
140241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *loaded = NULL;
1403c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELA, &destshdr,
140441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				  &destshdr_mem, &loaded);
1405c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1406c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1407c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr symshdr_mem;
1408c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1409c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
141041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  enum load_state state = state_undecided;
1411c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1412c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1414c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rela rela_mem;
1415c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem);
1416c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      if (rela == NULL)
1417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1418c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  ERROR (gettext ("\
1419c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppersection [%2d] '%s': cannot get relocation %zu: %s\n"),
1420c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1421c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  continue;
1422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1423c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1424607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1425607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       rela->r_offset, rela->r_info, destshdr, reldyn, loaded,
1426607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       &state);
142741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
142841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
142941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  while (loaded != NULL)
143041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
143141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *old = loaded;
143241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      loaded = loaded->next;
143341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      free (old);
1434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1435c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper}
1436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1437c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1438c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepperstatic void
1439c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Dreppercheck_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1440c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper{
1441c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1442c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  if (data == NULL)
1443c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    {
1444c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1445c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	     idx, section_name (ebl, idx));
1446c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      return;
1447c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper    }
1448c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper
1449c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  /* Check the fields of the section header.  */
1450c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr destshdr_mem;
1451c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  GElf_Shdr *destshdr = NULL;
145241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  struct loaded_segment *loaded = NULL;
1453c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_REL, &destshdr,
145441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper				  &destshdr_mem, &loaded);
1455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
1458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
146041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  enum load_state state = state_undecided;
1461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1462c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper  for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Rel rel_mem;
1465c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper      GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem);
1466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rel == NULL)
1467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get relocation %zu: %s\n"),
1470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
1472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1474607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1475607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       rel->r_offset, rel->r_info, destshdr, reldyn, loaded,
1476607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		       &state);
147741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    }
147841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
147941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  while (loaded != NULL)
148041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    {
148141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      struct loaded_segment *old = loaded;
148241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      loaded = loaded->next;
148341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      free (old);
1484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Number of dynamic sections.  */
1489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int ndynamic;
1490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1493607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppercheck_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *data;
1496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr strshdr_mem;
1497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr *strshdr;
1498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cnt;
1499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool dependencies[DT_NUM][DT_NUM] =
1500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_NEEDED] = { [DT_STRTAB] = true },
1502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTRELSZ] = { [DT_JMPREL] = true },
1503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_HASH] = { [DT_SYMTAB] = true },
1504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRTAB] = { [DT_STRSZ] = true },
1505231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_SYMENT] = true },
1506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true },
1507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELASZ] = { [DT_RELA] = true },
1508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELAENT] = { [DT_RELA] = true },
1509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRSZ] = { [DT_STRTAB] = true },
1510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMENT] = { [DT_SYMTAB] = true },
1511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SONAME] = { [DT_STRTAB] = true },
1512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RPATH] = { [DT_STRTAB] = true },
1513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true },
1514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELSZ] = { [DT_REL] = true },
1515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RELENT] = { [DT_REL] = true },
1516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true },
1517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RUNPATH] = { [DT_STRTAB] = true },
1518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_PLTREL] = { [DT_JMPREL] = true },
1519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool has_dt[DT_NUM];
1521231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  bool has_val_dt[DT_VALNUM];
1522231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  bool has_addr_dt[DT_ADDRNUM];
1523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool level2[DT_NUM] =
1524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_RPATH] = true,
1526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMBOLIC] = true,
1527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_TEXTREL] = true,
1528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_BIND_NOW] = true
1529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const bool mandatory[DT_NUM] =
1531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_NULL] = true,
1533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRTAB] = true,
1534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMTAB] = true,
1535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_STRSZ] = true,
1536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      [DT_SYMENT] = true
1537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
1538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Addr reladdr = 0;
1539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Word relsz = 0;
1540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Addr pltreladdr = 0;
1541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Word pltrelsz = 0;
1542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  memset (has_dt, '\0', sizeof (has_dt));
1544231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  memset (has_val_dt, '\0', sizeof (has_val_dt));
1545231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  memset (has_addr_dt, '\0', sizeof (has_addr_dt));
1546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (++ndynamic == 2)
1548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("more than one dynamic section present\n"));
1549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
155041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
1552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
1555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
1556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem);
1559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB)
1560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
1562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   shdr->sh_link, section_name (ebl, shdr->sh_link),
1563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT))
1566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section entry size does not match ElfXX_Dyn\n"),
1568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info != 0)
1571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool non_null_warned = false;
1575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Dyn dyn_mem;
1578acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dyn_mem);
1579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn == NULL)
1580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get dynamic section entry %zu: %s\n"),
1583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
1585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned)
1588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"),
1591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx));
1592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  non_null_warned = true;
1593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (!ebl_dynamic_tag_check (ebl, dyn->d_tag))
1596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': entry %zu: unknown tag\n"),
1597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag >= 0 && dyn->d_tag < DT_NUM)
1600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (has_dt[dyn->d_tag]
1602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_NEEDED
1603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_NULL
1604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && dyn->d_tag != DT_POSFLAG_1)
1605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf[50];
1607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: more than one entry with tag %s\n"),
1609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt,
1610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   buf, sizeof (buf)));
1612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (be_strict && level2[dyn->d_tag])
1615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf[50];
1617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: level 2 tag %s used\n"),
1619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx), cnt,
1620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   buf, sizeof (buf)));
1622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  has_dt[dyn->d_tag] = true;
1625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1626231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      else if (dyn->d_tag <= DT_VALRNGHI
1627231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       && DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
1628231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	has_val_dt[DT_VALTAGIDX (dyn->d_tag)] = true;
1629231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      else if (dyn->d_tag <= DT_ADDRRNGHI
1630231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       && DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
1631231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	has_addr_dt[DT_ADDRTAGIDX (dyn->d_tag)] = true;
1632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL
1634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && dyn->d_un.d_val != DT_RELA)
1635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
1636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"),
1637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx), cnt);
1638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_REL)
1640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	reladdr = dyn->d_un.d_ptr;
1641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_RELSZ)
1642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	relsz = dyn->d_un.d_val;
1643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_JMPREL)
1644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	pltreladdr = dyn->d_un.d_ptr;
1645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dyn->d_tag == DT_PLTRELSZ)
1646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	pltrelsz = dyn->d_un.d_val;
1647607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
1648607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      /* Check that addresses for entries are in loaded segments.  */
1649607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      switch (dyn->d_tag)
1650607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	{
1651607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  size_t n;
1652cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_STRTAB:
1653cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  /* We require the referenced section is the same as the one
1654cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	     specified in sh_link.  */
1655cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  if (strshdr->sh_addr != dyn->d_un.d_val)
1656cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    {
1657cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      ERROR (gettext ("\
1658cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Dreppersection [%2d] '%s': entry %zu: pointer does not match address of section [%2d] '%s' referenced by sh_link\n"),
1659cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1660cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1661cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      break;
1662cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    }
1663cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  goto check_addr;
1664cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper
1665607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	default:
1666607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (dyn->d_tag < DT_ADDRRNGLO || dyn->d_tag > DT_ADDRRNGHI)
1667607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    /* Value is no pointer.  */
1668607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    break;
1669607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* FALLTHROUGH */
1670607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
1671cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_AUXILIARY:
1672cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FILTER:
1673cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FINI:
1674cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_FINI_ARRAY:
1675607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_HASH:
1676607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_INIT:
1677607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_INIT_ARRAY:
1678cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_JMPREL:
1679cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_PLTGOT:
1680cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_REL:
1681cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RELA:
1682cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SYMBOLIC:
1683cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SYMTAB:
1684607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_VERDEF:
1685607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	case DT_VERNEED:
1686cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_VERSYM:
1687cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	check_addr:
1688607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  for (n = 0; n < ehdr->e_phnum; ++n)
1689607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
1690607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr phdr_mem;
1691607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, n, &phdr_mem);
1692607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      if (phdr != NULL && phdr->p_type == PT_LOAD
1693607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr <= dyn->d_un.d_ptr
1694607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr + phdr->p_memsz > dyn->d_un.d_ptr)
1695607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		break;
1696607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
1697607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (unlikely (n >= ehdr->e_phnum))
1698607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
1699607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      char buf[50];
1700607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      ERROR (gettext ("\
1701607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Dreppersection [%2d] '%s': entry %zu: %s value must point into loaded segment\n"),
1702607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1703607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1704607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper					   sizeof (buf)));
1705607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
1706cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  break;
1707cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper
1708cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_NEEDED:
1709cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RPATH:
1710cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_RUNPATH:
1711cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	case DT_SONAME:
1712cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  if (dyn->d_un.d_ptr >= strshdr->sh_size)
1713cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    {
1714cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      char buf[50];
1715cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	      ERROR (gettext ("\
1716cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Dreppersection [%2d] '%s': entry %zu: %s value must be valid offset in section [%2d] '%s'\n"),
1717cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     idx, section_name (ebl, idx), cnt,
1718cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1719cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper					   sizeof (buf)),
1720cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1721cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	    }
1722cbb51e5253e05d98af8bdaf2217fed00b2e489b9Ulrich Drepper	  break;
1723607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	}
1724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (cnt = 1; cnt < DT_NUM; ++cnt)
1727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (has_dt[cnt])
1728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1729acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	for (int inner = 0; inner < DT_NUM; ++inner)
1730b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (dependencies[cnt][inner] && ! has_dt[inner])
1731b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf1[50];
1733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      char buf2[50];
1734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
1736b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': contains %s entry but not %s\n"),
1737b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     idx, section_name (ebl, idx),
1738b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)),
1739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2)));
1740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1742b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    else
1743b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
1744b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (mandatory[cnt])
1745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
1746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    char buf[50];
1747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': mandatory tag %s not present\n"),
1749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx),
1750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf)));
1751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
1752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
1753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1754231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* Make sure we have an hash table.  */
1755231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (!has_dt[DT_HASH] && !has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)])
1756231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    ERROR (gettext ("\
1757231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': no hash section present\n"),
1758231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   idx, section_name (ebl, idx));
1759231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1760231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* The GNU-style hash table also needs a symbol table.  */
1761231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (!has_dt[DT_HASH] && has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)]
1762231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      && !has_dt[DT_SYMTAB])
1763231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    ERROR (gettext ("\
1764231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': contains %s entry but not %s\n"),
1765231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   idx, section_name (ebl, idx),
1766231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	   "DT_GNU_HASH", "DT_SYMTAB");
1767231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the rel/rela tags.  At least one group must be available.  */
1769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT])
1770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT]))
1771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': not all of %s, %s, and %s are present\n"),
1773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
1774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   "DT_RELA", "DT_RELASZ", "DT_RELAENT");
1775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT])
1777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT]))
1778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': not all of %s, %s, and %s are present\n"),
1780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
1781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   "DT_REL", "DT_RELSZ", "DT_RELENT");
1782231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1783231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  /* Check that all prelink sections are present if any of them is.  */
1784231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)]
1785231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1786231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    {
1787231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)])
1788231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1789231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1790231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_PRELINKED");
1791231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1792231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1793231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1794231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_CHECKSUM");
1795231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1796231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      /* Only DSOs can be marked like this.  */
1797231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (ehdr->e_type != ET_DYN)
1798231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1799231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': non-DSO file marked as dependency during prelink\n"),
1800231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx));
1801231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    }
1802231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper
1803231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper  if (has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)]
1804231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)]
1805231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)]
1806231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1807231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    {
1808231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)])
1809231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1810231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1811231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_CONFLICTSZ");
1812231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)])
1813231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1814231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1815231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_LIBLISTSZ");
1816231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)])
1817231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1818231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1819231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_CONFLICT");
1820231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1821231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	ERROR (gettext ("\
1822231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Dreppersection [%2d] '%s': %s tag missing in prelinked executable\n"),
1823231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	       idx, section_name (ebl, idx), "DT_GNU_LIBLIST");
1824231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper    }
1825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
1829acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1831acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (ehdr->e_type != ET_REL)
1832acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
1833acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      ERROR (gettext ("\
1834acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': only relocatable files can have extended section index\n"),
1835acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	     idx, section_name (ebl, idx));
1836acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      return;
1837acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    }
1838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1839acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1840acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr symshdr_mem;
1841acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1842b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB)
1843b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1844b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended section index section not for symbol table\n"),
1845b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1846acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
1847b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symdata == NULL)
1848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("cannot get data for symbol section\n"));
1849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_entsize != sizeof (Elf32_Word))
1851b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': entry size does not match Elf32_Word\n"),
1853b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1855b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL
1856b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && (shdr->sh_size / shdr->sh_entsize
1857b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  < symshdr->sh_size / symshdr->sh_entsize))
1858b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
1859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended index table too small for symbol table\n"),
1860b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1861b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1862b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_info != 0)
1863b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1864b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
1865b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1866acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = idx + 1; cnt < shnum; ++cnt)
1867b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1868b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr rshdr_mem;
1869acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      GElf_Shdr *rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem);
1870b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX
1871b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && rshdr->sh_link == shdr->sh_link)
1872b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1873b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
1874b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"),
1875b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 idx, section_name (ebl, idx),
1876b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, section_name (ebl, cnt));
1877b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1878b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1879b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1880b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1881acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1882b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1883b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (*((Elf32_Word *) data->d_buf) != 0)
1884b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("symbol 0 should have zero extended section index\n"));
1885b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1886acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1887b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1888b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt];
1889b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1890b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (xndx != 0)
1891b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1892b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Sym sym_data;
1893b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data);
1894b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym == NULL)
1895b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1896b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("cannot get data for symbol %zu\n"), cnt);
1897b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
1898b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1899b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1900b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (sym->st_shndx != SHN_XINDEX)
1901b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
1902b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperextended section index is %" PRIu32 " but symbol index is not XINDEX\n"),
1903b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   (uint32_t) xndx);
1904b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1906b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1907b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1908b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1909b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
191028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
191128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		 GElf_Shdr *symshdr)
191228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
191328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
191428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
191528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
191628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
191728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    ERROR (gettext ("\
191828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
191928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
192028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
192128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
192228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t maxidx = nchain;
192328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
192428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (symshdr != NULL)
192528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
192628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
192728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
192828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
192928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
193028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx));
193128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
193228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      maxidx = symsize;
193328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
193428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
193528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
193628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
193728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx)
193828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
193928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash bucket reference %zu out of bounds\n"),
194028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2);
194128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
194228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (; cnt < 2 + nbucket + nchain; ++cnt)
194328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx)
194428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
194528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain reference %zu out of bounds\n"),
194628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2 - nbucket);
194728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
194828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
194928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
195028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
195128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
195228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		 GElf_Shdr *symshdr)
195328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
195428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
195528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
195628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
195728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
195828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    ERROR (gettext ("\
195928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
196028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
196128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
196228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
196328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t maxidx = nchain;
196428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
196528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (symshdr != NULL)
196628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
196728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
196828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
196928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
197028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
197128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       idx, section_name (ebl, idx));
197228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
197328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      maxidx = symsize;
197428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
197528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
197628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
197728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
197828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx)
197928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
198028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash bucket reference %zu out of bounds\n"),
198128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), cnt - 2);
198228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
198328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  for (; cnt < 2 + nbucket + nchain; ++cnt)
198428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx)
198528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
1986dcf6160602985e6eb70c96c6546ed9614a414d98Ulrich Dreppersection [%2d] '%s': hash chain reference %" PRIu64 " out of bounds\n"),
1987dcf6160602985e6eb70c96c6546ed9614a414d98Ulrich Drepper	     idx, section_name (ebl, idx), (uint64_t) (cnt - 2 - nbucket));
198828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
198928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
199028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
199128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
199228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
199328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		GElf_Shdr *symshdr)
199428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper{
199528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0];
199628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
19978ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
199828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
19998ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (!powerof2 (bitmask_words))
20008ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    ERROR (gettext ("\
20018ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': bitmask size not power of 2: %u\n"),
20028ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	   idx, section_name (ebl, idx), bitmask_words);
20038ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
20048ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t bitmask_idxmask = bitmask_words - 1;
20058ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (gelf_getclass (ebl->elf) == ELFCLASS64)
20068ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    bitmask_words *= 2;
20078ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
20088ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
20098ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shdr->sh_size < (4 + bitmask_words + nbuckets) * sizeof (Elf32_Word))
201028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
201128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      ERROR (gettext ("\
201228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table section is too small (is %ld, expected at least%ld)\n"),
201328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	     idx, section_name (ebl, idx), (long int) shdr->sh_size,
20148ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	     (long int) ((4 + bitmask_words + nbuckets) * sizeof (Elf32_Word)));
201528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      return;
201628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
201728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
20188ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shift > 31)
20198ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    ERROR (gettext ("\
20208ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': 2nd hash function shift too big: %u\n"),
20218ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	   idx, section_name (ebl, idx), shift);
20228ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
20238ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words
20248ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							 + nbuckets);
202528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
202628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (symshdr != NULL)
202728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    maxidx = MIN (maxidx, symshdr->sh_size / symshdr->sh_entsize);
202828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
202928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  /* We need the symbol section data.  */
203028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  Elf_Data *symdata = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link), NULL);
203128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
20328ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  union
20338ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  {
20348ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    Elf32_Word *p32;
20358ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    Elf64_Xword *p64;
20368ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  } bitmask = { .p32 = &((Elf32_Word *) data->d_buf)[4] },
20378ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      collected = { .p32 = xcalloc (bitmask_words, sizeof (Elf32_Word)) };
20388ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
20398ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  size_t classbits = gelf_getclass (ebl->elf) == ELFCLASS32 ? 32 : 64;
20408ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
204128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  size_t cnt;
20428ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  for (cnt = 4 + bitmask_words; cnt < 4 + bitmask_words + nbuckets; ++cnt)
204328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    {
20448ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      Elf32_Word symidx = ((Elf32_Word *) data->d_buf)[cnt];
204528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
204628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx == 0)
20478ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	continue;
204828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
204928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx < symbias)
205028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	{
205128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  ERROR (gettext ("\
205228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"),
20538ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		 idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
205428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  continue;
205528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	}
205628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
205728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      while (symidx - symbias < maxidx)
205828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	{
20598ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	  Elf32_Word chainhash = ((Elf32_Word *) data->d_buf)[4
20608ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							      + bitmask_words
20618ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper							      + nbuckets
206228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							      + symidx
206328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper							      - symbias];
206428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
206528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  if (symdata != NULL)
206628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    {
206728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      /* Check that the referenced symbol is not undefined.  */
206828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      GElf_Sym sym_mem;
206928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      GElf_Sym *sym = gelf_getsym (symdata, symidx, &sym_mem);
2070231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper	      if (sym != NULL && sym->st_shndx == SHN_UNDEF
2071231c590fbe9d6f3a8e22796ded9c6a378628eb09Ulrich Drepper		  && GELF_ST_TYPE (sym->st_info) != STT_FUNC)
207228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		ERROR (gettext ("\
207328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': symbol %u referenced in chain for bucket %zu is undefined\n"),
20745530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper		       idx, section_name (ebl, idx), symidx,
20755530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper		       cnt - (4 + bitmask_words));
207628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
207728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      const char *symname = elf_strptr (ebl->elf, symshdr->sh_link,
207828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper						sym->st_name);
207928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	      if (symname != NULL)
208028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		{
208128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  Elf32_Word hval = elf_gnu_hash (symname);
208228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		  if ((hval & ~1u) != (chainhash & ~1u))
208328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		    ERROR (gettext ("\
208428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"),
20855530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper			   idx, section_name (ebl, idx), symidx,
20865530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper			   cnt - (4 + bitmask_words));
20878ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
20888ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  /* Set the bits in the bitmask.  */
20898ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  size_t maskidx = (hval / classbits) & bitmask_idxmask;
20908ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  if (classbits == 32)
20918ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    {
20928ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p32[maskidx]
20938ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT32_C (1) << (hval & (classbits - 1));
20948ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p32[maskidx]
20958ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT32_C (1) << ((hval >> shift) & (classbits - 1));
20968ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    }
20978ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		  else
20988ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    {
20998ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p64[maskidx]
21008ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT64_C (1) << (hval & (classbits - 1));
21018ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		      collected.p64[maskidx]
21028ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			|= UINT64_C (1) << ((hval >> shift) & (classbits - 1));
21038ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper		    }
210428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper		}
210528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    }
210628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
210728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  if ((chainhash & 1) != 0)
210828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	    break;
210928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
211028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  ++symidx;
211128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	}
211228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
211328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (symidx - symbias >= maxidx)
211428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("\
211528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash chain for bucket %zu out of bounds\n"),
21165530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper	       idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
211728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      else if (symshdr != NULL
211828ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	       && symidx > symshdr->sh_size / symshdr->sh_entsize)
211928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	ERROR (gettext ("\
212028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"),
21215530ec5bbb95d2041ba9ece15ba10fe2b1d86eabUlrich Drepper	       idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
212228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    }
21238ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
21248ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (memcmp (collected.p32, bitmask.p32, bitmask_words * sizeof (Elf32_Word)))
21258ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper    ERROR (gettext ("\
21268ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': bitmask does not match names in the hash table\n"),
21278ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper	   idx, section_name (ebl, idx));
21288ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper
21298ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  free (collected.p32);
213028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper}
213128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
213228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper
213328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepperstatic void
213428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppercheck_hash (int tag, Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2136acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (ehdr->e_type == ET_REL)
2137acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
2138acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      ERROR (gettext ("\
2139acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': relocatable files cannot have hash tables\n"),
2140acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	     idx, section_name (ebl, idx));
2141acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      return;
2142acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    }
2143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2144acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
2146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2152acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr symshdr_mem;
2153acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2154acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &symshdr_mem);
2155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM)
2156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
2157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': hash table not for dynamic symbol table\n"),
2158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
216028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  if (shdr->sh_entsize != (tag == SHT_GNU_HASH
21618ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			   ? (gelf_getclass (ebl->elf) == ELFCLASS32
21628ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper			      ? sizeof (Elf32_Word) : 0)
216328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper			   : (size_t) ebl_sysvhash_entrysize (ebl)))
2164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
216528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Dreppersection [%2d] '%s': hash table entry size incorrect\n"),
2166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((shdr->sh_flags & SHF_ALLOC) == 0)
2169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': not marked to be allocated\n"),
2170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx));
2171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
21728ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper  if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (shdr->sh_entsize ?: 4))
2173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
21758ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Dreppersection [%2d] '%s': hash table has not even room for initial administrative entries\n"),
2176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
218028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper  switch (tag)
2181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
218228ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    case SHT_HASH:
218328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
218428ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	check_sysv_hash64 (ebl, shdr, data, idx, symshdr);
218528ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      else
218628ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	check_sysv_hash (ebl, shdr, data, idx, symshdr);
218728ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      break;
2188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
218928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    case SHT_GNU_HASH:
219028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      check_gnu_hash (ebl, shdr, data, idx, symshdr);
219128ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper      break;
2192ee4b927bae351b21787355e00a3d28371bf78e8fUlrich Drepper
219328ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper    default:
21948ae5814209558f51c93b583c9ae6fdd482f0cbb2Ulrich Drepper      assert (! "should not happen");
2195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
21997c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper/* Compare content of both hash tables, it must be identical.  */
22007c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepperstatic void
22017c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppercompare_hash_gnu_hash (Ebl *ebl, GElf_Ehdr *ehdr, size_t hash_idx,
22027c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		       size_t gnu_hash_idx)
22037c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper{
22047c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *hash_scn = elf_getscn (ebl->elf, hash_idx);
22057c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *hash_data = elf_getdata (hash_scn, NULL);
22067c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr hash_shdr_mem;
22077c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *hash_shdr = gelf_getshdr (hash_scn, &hash_shdr_mem);
22087c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *gnu_hash_scn = elf_getscn (ebl->elf, gnu_hash_idx);
22097c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *gnu_hash_data = elf_getdata (gnu_hash_scn, NULL);
22107c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr gnu_hash_shdr_mem;
22117c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *gnu_hash_shdr = gelf_getshdr (gnu_hash_scn, &gnu_hash_shdr_mem);
22127c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22137c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr == NULL || gnu_hash_shdr == NULL
22147c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      || hash_data == NULL || gnu_hash_data == NULL)
22157c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    /* None of these pointers should be NULL since we used the
22167c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper       sections already.  We are careful nonetheless.  */
22177c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    return;
22187c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22197c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* The link must point to the same symbol table.  */
22207c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr->sh_link != gnu_hash_shdr->sh_link)
22217c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
22227c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      ERROR (gettext ("\
22237c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"),
22247c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
22257c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     gnu_hash_idx,
22267c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
22277c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      return;
22287c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
22297c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22307c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Scn *sym_scn = elf_getscn (ebl->elf, hash_shdr->sh_link);
22317c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf_Data *sym_data = elf_getdata (sym_scn, NULL);
22327c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr sym_shdr_mem;
22337c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  GElf_Shdr *sym_shdr = gelf_getshdr (sym_scn, &sym_shdr_mem);
22347c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22357c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (sym_data == NULL || sym_shdr == NULL)
22367c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    return;
22377c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22387c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  int nentries = sym_shdr->sh_size / sym_shdr->sh_entsize;
22397c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  char *used = alloca (nentries);
22407c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  memset (used, '\0', nentries);
22417c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22427c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* First go over the GNU_HASH table and mark the entries as used.  */
22437c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const Elf32_Word *gnu_hasharr = (Elf32_Word *) gnu_hash_data->d_buf;
22447c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  Elf32_Word gnu_nbucket = gnu_hasharr[0];
22457c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const int bitmap_factor = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 1 : 2;
22467c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const Elf32_Word *gnu_bucket = (gnu_hasharr
22477c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper				  + (4 + gnu_hasharr[2] * bitmap_factor));
22487c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  const Elf32_Word *gnu_chain = gnu_bucket + gnu_hasharr[0] - gnu_hasharr[1];
22497c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22507c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  for (Elf32_Word cnt = 0; cnt < gnu_nbucket; ++cnt)
22517c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
22527c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      Elf32_Word symidx = gnu_bucket[cnt];
22537c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      if (symidx != STN_UNDEF)
22547c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	do
22557c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  used[symidx] |= 1;
22567c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	while ((gnu_chain[symidx++] & 1u) == 0);
22577c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
22587c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22597c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* Now go over the old hash table and check that we cover the same
22607c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     entries.  */
22617c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_shdr->sh_entsize == sizeof (Elf32_Word))
22627c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
22637c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *hasharr = (Elf32_Word *) hash_data->d_buf;
22647c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      Elf32_Word nbucket = hasharr[0];
22657c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *bucket = &hasharr[2];
22667c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf32_Word *chain = &hasharr[2 + nbucket];
22677c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22687c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
22697c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	{
22707c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  Elf32_Word symidx = bucket[cnt];
22717c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  while (symidx != STN_UNDEF)
22727c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    {
22737c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      used[symidx] |= 2;
22747c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      symidx = chain[symidx];
22757c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    }
22767c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	}
22777c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
22787c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  else
22797c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    {
22807c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *hasharr = (Elf64_Xword *) hash_data->d_buf;
22817c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      Elf64_Xword nbucket = hasharr[0];
22827c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *bucket = &hasharr[2];
22837c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      const Elf64_Xword *chain = &hasharr[2 + nbucket];
22847c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22857c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
22867c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	{
22877c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  Elf64_Xword symidx = bucket[cnt];
22887c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  while (symidx != STN_UNDEF)
22897c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    {
22907c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      used[symidx] |= 2;
22917c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      symidx = chain[symidx];
22927c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    }
22937c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	}
22947c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    }
22957c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
22967c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  /* Now see which entries are not set in one or both hash tables
22977c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     (unless the symbol is undefined in which case it can be omitted
22987c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper     in the new table format).  */
22997c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if ((used[0] & 1) != 0)
23007c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"),
23017c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   gnu_hash_idx,
23027c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
23037c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if ((used[0] & 2) != 0)
23047c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"),
23057c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	   hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
23067c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23077c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  for (int cnt = 1; cnt < nentries; ++cnt)
23087c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    if (used[cnt] != 0 && used[cnt] != 3)
23097c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      {
23107c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	if (used[cnt] == 1)
23117c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  ERROR (gettext ("\
23127c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersymbol %d referenced in new hash table in [%2zu] '%s' but not in old hash table in [%2zu] '%s'\n"),
23137c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 cnt, gnu_hash_idx,
23147c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name),
23157c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 hash_idx,
23167c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		 elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
23177c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	else
23187c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  {
23197c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    GElf_Sym sym_mem;
23207c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    GElf_Sym *sym = gelf_getsym (sym_data, cnt, &sym_mem);
23217c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23227c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	    if (sym != NULL && sym->st_shndx != STN_UNDEF)
23237c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	      ERROR (gettext ("\
23247c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Dreppersymbol %d referenced in old hash table in [%2zu] '%s' but not in new hash table in [%2zu] '%s'\n"),
23257c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     cnt, hash_idx,
23267c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
23277c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     gnu_hash_idx,
23287c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper		     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
23297c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  }
23307c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper      }
23317c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper}
23327c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
23337c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
2334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_null (Ebl *ebl, GElf_Shdr *shdr, int idx)
2336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define TEST(name, extra) \
2338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (extra && shdr->sh_##name != 0)					      \
2339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': nonzero sh_%s for NULL section\n"),  \
2340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), #name)
2341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (name, 1);
2343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (flags, 1);
2344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (addr, 1);
2345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (offset, 1);
2346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (size, idx != 0);
2347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (link, idx != 0);
2348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (info, 1);
2349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (addralign, 1);
2350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  TEST (entsize, 1);
2351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_REL)
2358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
2360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section groups only allowed in relocatable object files\n"),
2361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx));
2362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check that sh_link is an index of a symbol table.  */
23660e864dd86871c809668c557985ca19344dfff787Ulrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
23680e864dd86871c809668c557985ca19344dfff787Ulrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr == NULL)
2370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': cannot get symbol table: %s\n"),
2371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), elf_errmsg (-1));
2372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (symshdr->sh_type != SHT_SYMTAB)
2375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section reference in sh_link is no symbol table\n"),
2377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM,
2380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper							  1, EV_CURRENT))
2381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': invalid symbol index in sh_info\n"),
2383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags != 0)
2386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': sh_flags not zero\n"),
2387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
23890e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      GElf_Sym sym_data;
23900e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      GElf_Sym *sym = gelf_getsym (elf_getdata (symscn, NULL), shdr->sh_info,
23910e864dd86871c809668c557985ca19344dfff787Ulrich Drepper				   &sym_data);
23920e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      if (sym == NULL)
23930e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	ERROR (gettext ("\
23940e864dd86871c809668c557985ca19344dfff787Ulrich Dreppersection [%2d] '%s': cannot get symbol for signature\n"),
23950e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	       idx, section_name (ebl, idx));
23960e864dd86871c809668c557985ca19344dfff787Ulrich Drepper      else if (strcmp (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name),
23970e864dd86871c809668c557985ca19344dfff787Ulrich Drepper		       "") == 0)
23980e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	ERROR (gettext ("\
23990e864dd86871c809668c557985ca19344dfff787Ulrich Dreppersection [%2d] '%s': signature symbol canot be empty string\n"),
24000e864dd86871c809668c557985ca19344dfff787Ulrich Drepper	       idx, section_name (ebl, idx));
24010e864dd86871c809668c557985ca19344dfff787Ulrich Drepper
2402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (be_strict
2403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT))
2404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': sh_flags not set correctly\n"),
2405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (data == NULL)
2410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("section [%2d] '%s': cannot get data: %s\n"),
2411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx), elf_errmsg (-1));
2412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
2413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
2415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      size_t cnt;
2416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf32_Word val;
2417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data->d_size % elsize != 0)
2419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"),
2421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data->d_size < elsize)
2424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
2425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group without flags word\n"),
2426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (be_strict)
2428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (data->d_size < 2 * elsize)
2430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group without member\n"),
2432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
2433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (data->d_size < 3 * elsize)
2434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group with only one member\n"),
2436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx));
2437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if ALLOW_UNALIGNED
2440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      val = *((Elf32_Word *) data->d_buf);
2441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#else
2442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      memcpy (&val, data->d_buf, elsize);
2443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
2444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((val & ~GRP_COMDAT) != 0)
2445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2d] '%s': unknown section group flags\n"),
2446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       idx, section_name (ebl, idx));
2447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (cnt = elsize; cnt < data->d_size; cnt += elsize)
2449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if ALLOW_UNALIGNED
2451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  val = *((Elf32_Word *) ((char *) data->d_buf + cnt));
2452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#else
2453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  memcpy (&val, (char *) data->d_buf + cnt, elsize);
2454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
2455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (val > shnum)
2457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
2458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section index %Zu out of range\n"),
2459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   idx, section_name (ebl, idx), cnt / elsize);
2460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
2461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
2462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Shdr refshdr_mem;
2463acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	      GElf_Shdr *refshdr = gelf_getshdr (elf_getscn (ebl->elf, val),
2464acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper						 &refshdr_mem);
2465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (refshdr == NULL)
2466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
2467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': cannot get section header for element %zu: %s\n"),
2468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       idx, section_name (ebl, idx), cnt / elsize,
2469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       elf_errmsg (-1));
2470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      else
2471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
2472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (refshdr->sh_type == SHT_GROUP)
2473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
2474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': section group contains another group [%2d] '%s'\n"),
2475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx),
2476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   val, section_name (ebl, val));
2477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if ((refshdr->sh_flags & SHF_GROUP) == 0)
2479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    ERROR (gettext ("\
2480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s': element %Zu references section [%2d] '%s' without SHF_GROUP flag set\n"),
2481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   idx, section_name (ebl, idx), cnt / elsize,
2482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   val, section_name (ebl, val));
2483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
2484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (++scnref[val] == 2)
2486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
2487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' is contained in more than one section group\n"),
2488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       val, section_name (ebl, val));
2489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
2490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *
2496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection_flags_string (GElf_Word flags, char *buf, size_t len)
2497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2498099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath  if (flags == 0)
2499099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath    return "none";
2500099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath
2501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  static const struct
2502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
2503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    GElf_Word flag;
2504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    const char *name;
2505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  } known_flags[] =
2506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define NEWFLAG(name) { SHF_##name, #name }
2508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (WRITE),
2509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (ALLOC),
2510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (EXECINSTR),
2511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (MERGE),
2512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (STRINGS),
2513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (INFO_LINK),
2514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (LINK_ORDER),
2515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (OS_NONCONFORMING),
2516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (GROUP),
2517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      NEWFLAG (TLS)
2518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    };
2519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#undef NEWFLAG
2520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
2521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *cp = buf;
2523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2524acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 0; cnt < nknown_flags; ++cnt)
2525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (flags & known_flags[cnt].flag)
2526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
2527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (cp != buf && len > 1)
2528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
2529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    *cp++ = '|';
2530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    --len;
2531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
2532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name));
2534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	cp = mempcpy (cp, known_flags[cnt].name, ncopy);
2535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	len -= ncopy;
2536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	flags ^= known_flags[cnt].flag;
2538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
2539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (flags != 0 || cp == buf)
2541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    snprintf (cp, len - 1, "%" PRIx64, (uint64_t) flags);
2542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *cp = '\0';
2544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return buf;
2546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2549dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2550dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperhas_copy_reloc (Ebl *ebl, unsigned int symscnndx, unsigned int symndx)
2551dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2552dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* First find the relocation section for the symbol table.  */
2553dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = NULL;
2554dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2555dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = NULL;
2556dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2557dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2558dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      shdr = gelf_getshdr (scn, &shdr_mem);
2559dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (shdr != NULL
2560dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
2561dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && shdr->sh_link == symscnndx)
2562dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	/* Found the section.  */
2563dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	break;
2564dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2565dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2566dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (scn == NULL)
2567dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 0;
2568dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2569dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
2570dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2571dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 0;
2572dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2573dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr->sh_type == SHT_REL)
2574dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2575dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2576dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rel rel_mem;
2577dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
2578dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (rel == NULL)
2579dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  continue;
2580dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2581dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (GELF_R_SYM (rel->r_info) == symndx
2582dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info)))
2583dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  return 1;
2584dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2585dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  else
2586dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2587dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2588dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rela rela_mem;
2589dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
2590dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (rela == NULL)
2591dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  continue;
2592dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2593dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (GELF_R_SYM (rela->r_info) == symndx
2594dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info)))
2595dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  return 1;
2596dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2597dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2598dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 0;
2599dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2600dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2601dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2602637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic int
2603637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperin_nobits_scn (Ebl *ebl, unsigned int shndx)
2604637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper{
2605637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Shdr shdr_mem;
2606637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, shndx), &shdr_mem);
2607637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  return shdr != NULL && shdr->sh_type == SHT_NOBITS;
2608637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper}
2609637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2610637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
2611dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic struct version_namelist
2612dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2613dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  const char *objname;
2614dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  const char *name;
2615858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrath  GElf_Versym ndx;
2616dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  enum { ver_def, ver_need } type;
2617dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct version_namelist *next;
2618dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper} *version_namelist;
2619dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2620dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2621dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2622858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrathadd_version (const char *objname, const char *name, GElf_Versym ndx, int type)
2623dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2624dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Check that there are no duplications.  */
2625dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct version_namelist *nlp = version_namelist;
2626dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while (nlp != NULL)
2627dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2628dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (((nlp->objname == NULL && objname == NULL)
2629dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	   || (nlp->objname != NULL && objname != NULL
2630dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       && strcmp (nlp->objname, objname) == 0))
2631dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && strcmp (nlp->name, name) == 0)
2632dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	return nlp->type == ver_def ? 1 : -1;
2633dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      nlp = nlp->next;
2634dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2635dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2636dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp = xmalloc (sizeof (*nlp));
2637dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->objname = objname;
2638dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->name = name;
2639dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->ndx = ndx;
2640dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->type = type;
2641dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  nlp->next = version_namelist;
2642dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  version_namelist = nlp;
2643dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2644dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 0;
2645dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2646dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2647dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2649dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_versym (Ebl *ebl, int idx)
2650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2651dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = elf_getscn (ebl->elf, idx);
2652dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2653dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2654dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr == NULL)
2655dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    /* The error has already been reported.  */
2656dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
2657dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2658dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
2659dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2660dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2661dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2662dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
2663dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
2664dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2665dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2666dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Shdr symshdr_mem;
2668dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr == NULL)
2670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* The error has already been reported.  */
2671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
2672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (symshdr->sh_type != SHT_DYNSYM)
2674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("\
2676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"),
2677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     idx, section_name (ebl, idx),
2678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     shdr->sh_link, section_name (ebl, shdr->sh_link));
2679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
2680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
2681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2682dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* The number of elements in the version symbol table must be the
2683dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     same as the number of symbols.  */
2684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr->sh_size / shdr->sh_entsize
2685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      != symshdr->sh_size / symshdr->sh_entsize)
2686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
2687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"),
2688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   idx, section_name (ebl, idx),
2689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   shdr->sh_link, section_name (ebl, shdr->sh_link));
2690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2691dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *symdata = elf_getdata (symscn, NULL);
2692dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (symdata == NULL)
2693dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    /* The error has already been reported.  */
2694dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return;
2695dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2696dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (int cnt = 1; (size_t) cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2697dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2698dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Versym versym_mem;
2699dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Versym *versym = gelf_getversym (data, cnt, &versym_mem);
2700dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (versym == NULL)
2701dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2702dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2703dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: cannot read version data\n"),
2704dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
2705dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  break;
2706dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2707dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2708dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Sym sym_mem;
2709dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_mem);
2710dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (sym == NULL)
2711dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	/* Already reported elsewhere.  */
2712dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	continue;
2713dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
271461655e08ba36430de47381cefdf10d0c26aa8480Ulrich Drepper      if (*versym == VER_NDX_GLOBAL)
2715dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2716dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* Global symbol.  Make sure it is not defined as local.  */
2717dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2718dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2719dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: local symbol with global scope\n"),
2720dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
2721dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
272261655e08ba36430de47381cefdf10d0c26aa8480Ulrich Drepper      else if (*versym != VER_NDX_LOCAL)
2723dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2724c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	  /* Versioned symbol.  Make sure it is not defined as local.  */
2725c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	  if (!gnuld && GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2726c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper	    ERROR (gettext ("\
2727c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Dreppersection [%2d] '%s': symbol %d: local symbol with version\n"),
2728c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
2729c5a06cd2a5f48351b273872ed3e4a2d63d29e459Ulrich Drepper
2730dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* Look through the list of defined versions and locate the
2731dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     index we need for this symbol.  */
2732dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *runp = version_namelist;
2733dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  while (runp != NULL)
2734858b189f82ecc32ca7042e74ccb022f794a9f83bRoland McGrath	    if (runp->ndx == (*versym & (GElf_Versym) 0x7fff))
2735dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
2736dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    else
2737dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      runp = runp->next;
2738dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2739dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (runp == NULL)
2740dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2741dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: invalid version index %d\n"),
2742dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt, (int) *versym);
2743dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else if (sym->st_shndx == SHN_UNDEF
2744dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   && runp->type == ver_def)
2745dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2746dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: version index %d is for defined version\n"),
2747dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), cnt, (int) *versym);
2748dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else if (sym->st_shndx != SHN_UNDEF
2749dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   && runp->type == ver_need)
2750dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2751dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      /* Unless this symbol has a copy relocation associated
2752dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 this must not happen.  */
2753637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper	      if (!has_copy_reloc (ebl, shdr->sh_link, cnt)
2754637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper		  && !in_nobits_scn (ebl, sym->st_shndx))
2755dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		ERROR (gettext ("\
2756dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': symbol %d: version index %d is for requested version\n"),
2757dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       idx, section_name (ebl, idx), cnt, (int) *versym);
2758dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2759dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2760dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2761dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper}
2762dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2763dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2764dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperstatic int
2765dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperunknown_dependency_p (Elf *elf, GElf_Ehdr *ehdr, const char *fname)
2766dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper{
2767dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Phdr phdr_mem;
2768dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Phdr *phdr = NULL;
2769dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2770dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  int i;
2771dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (i = 0; i < ehdr->e_phnum; ++i)
2772dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    if ((phdr = gelf_getphdr (elf, i, &phdr_mem)) != NULL
2773dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	&& phdr->p_type == PT_DYNAMIC)
2774dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      break;
2775dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2776dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (i == ehdr->e_phnum)
2777dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    return 1;
2778dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  assert (phdr != NULL);
2779dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
2780dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr shdr_mem;
2781dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2782dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (scn, NULL);
2783dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL)
2784dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    for (size_t j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
2785dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      {
2786dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Dyn dyn_mem;
2787dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
2788dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	if (dyn != NULL && dyn->d_tag == DT_NEEDED)
2789dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  {
2790dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    const char *str = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
2791dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    if (str != NULL && strcmp (str, fname) == 0)
2792dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      /* Found it.  */
2793dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      return 0;
2794dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  }
2795dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      }
2796dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2797dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  return 1;
2798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
2799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2801acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic unsigned int nverneed;
2802acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
2804dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppercheck_verneed (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
2806acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (++nverneed == 2)
2807acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("more than one version reference section present\n"));
2808acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2809acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr strshdr_mem;
2810acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2811acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &strshdr_mem);
2812acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr == NULL)
2813acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    return;
2814acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
2815acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("\
2816acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': sh_link does not link to string table\n"),
2817acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	   idx, section_name (ebl, idx));
2818dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2819dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2820dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2821dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2822dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2823dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
2824dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
2825dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2826dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  unsigned int offset = 0;
2827dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (int cnt = shdr->sh_info; --cnt >= 0; )
2828dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2829dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Get the data at the next offset.  */
2830dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verneed needmem;
2831dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
2832dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need == NULL)
2833dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	break;
2834dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2835dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      unsigned int auxoffset = offset + need->vn_aux;
2836dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2837dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need->vn_version != EV_CURRENT)
2838dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2839dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong version %d\n"),
2840dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) need->vn_version);
2841dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2842dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (need->vn_cnt > 0 && need->vn_aux < gelf_fsize (ebl->elf, ELF_T_VNEED,
2843dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper							 1, EV_CURRENT))
2844dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2845dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
2846dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2847dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2848dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      const char *libname = elf_strptr (ebl->elf, shdr->sh_link,
2849dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					need->vn_file);
2850dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (libname == NULL)
2851dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2852dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
2853dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid file reference\n"),
2854dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
2855dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  goto next_need;
2856dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2857dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2858dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Check that there is a DT_NEEDED entry for the referenced library.  */
2859dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (unknown_dependency_p (ebl->elf, ehdr, libname))
2860dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2861dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d references unknown dependency\n"),
2862dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2863dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2864dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2865dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2866dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  GElf_Vernaux auxmem;
2867dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2868dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (aux == NULL)
2869dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    break;
2870dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2871dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vna_flags & ~VER_FLG_WEAK) != 0)
2872dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2873dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"),
2874dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2875dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2876dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  const char *verstr = elf_strptr (ebl->elf, shdr->sh_link,
2877dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					   aux->vna_name);
2878dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (verstr == NULL)
2879dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2880dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has invalid name reference\n"),
2881dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2882dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  else
2883dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2884dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      GElf_Word hashval = elf_hash (verstr);
2885dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (hashval != aux->vna_hash)
2886dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		ERROR (gettext ("\
2887dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: %#x, expected %#x\n"),
2888dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       idx, section_name (ebl, idx), need->vn_cnt - cnt2,
2889dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		       cnt, (int) hashval, (int) aux->vna_hash);
2890dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2891dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      int res = add_version (libname, verstr, aux->vna_other,
2892dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper				     ver_need);
2893dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (unlikely (res !=0))
2894dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		{
2895dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  assert (res > 0);
2896dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  ERROR (gettext ("\
2897dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has duplicate version name '%s'\n"),
2898dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 idx, section_name (ebl, idx), need->vn_cnt - cnt2,
2899dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 cnt, verstr);
2900dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		}
2901dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2902dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2903dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vna_next != 0 || cnt2 > 0)
2904dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && aux->vna_next < gelf_fsize (ebl->elf, ELF_T_VNAUX, 1,
2905dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					     EV_CURRENT))
2906dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
2907dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      ERROR (gettext ("\
2908dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"),
2909dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		     idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2910dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
2911dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
2912dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2913dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  auxoffset += MAX (aux->vna_next,
2914dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			    gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, EV_CURRENT));
2915dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2916dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2917dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Find the next offset.  */
2918dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    next_need:
2919dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      offset += need->vn_next;
2920dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2921dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((need->vn_next != 0 || cnt > 0)
2922dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && offset < auxoffset)
2923dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2924dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid offset to next entry\n"),
2925dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2926dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2927acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper}
2928b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2929acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2930acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic unsigned int nverdef;
2931acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2932acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic void
2933acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_verdef (Ebl *ebl, GElf_Shdr *shdr, int idx)
2934acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper{
2935acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (++nverdef == 2)
2936acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("more than one version definition section present\n"));
2937acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
2938acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr strshdr_mem;
2939acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2940acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper				     &strshdr_mem);
2941acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr == NULL)
2942acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    return;
2943acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  if (strshdr->sh_type != SHT_STRTAB)
2944acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    ERROR (gettext ("\
2945acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2d] '%s': sh_link does not link to string table\n"),
2946acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	   idx, section_name (ebl, idx));
2947dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2948dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2949dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (data == NULL)
2950dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2951dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    no_data:
2952dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2953dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     idx, section_name (ebl, idx));
2954dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      return;
2955dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
2956dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2957dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Iterate over all version definition entries.  We check that there
2958dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     is a BASE entry and that each index is unique.  To do the later
2959dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     we collection the information in a list which is later
2960dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper     examined.  */
2961dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct namelist
2962dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  {
2963dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    const char *name;
2964dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    struct namelist *next;
2965dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  } *namelist = NULL;
2966dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  struct namelist *refnamelist = NULL;
2967dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2968dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  bool has_base = false;
2969dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  unsigned int offset = 0;
2970dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  for (int cnt = shdr->sh_info; --cnt >= 0; )
2971dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
2972dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Get the data at the next offset.  */
2973dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdef defmem;
2974dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2975dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def == NULL)
2976dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	goto no_data;
2977dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2978dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_flags & VER_FLG_BASE) != 0)
2979dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
2980dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (has_base)
2981dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2982dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': more than one BASE definition\n"),
2983dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx));
2984dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (def->vd_ndx != VER_NDX_GLOBAL)
2985dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("\
2986dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"),
2987dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		   idx, section_name (ebl, idx));
2988dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  has_base = true;
2989dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
2990dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_flags & ~(VER_FLG_BASE|VER_FLG_WEAK)) != 0)
2991dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2992dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has unknown flag\n"),
2993dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
2994dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
2995dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_version != EV_CURRENT)
2996dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
2997dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong version %d\n"),
2998dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) def->vd_version);
2999dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3000dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_cnt > 0 && def->vd_aux < gelf_fsize (ebl->elf, ELF_T_VDEF,
3001dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper						       1, EV_CURRENT))
3002dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3003dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
3004dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
3005dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3006dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      unsigned int auxoffset = offset + def->vd_aux;
3007dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdaux auxmem;
3008dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
3009dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (aux == NULL)
3010dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	goto no_data;
3011dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3012dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      const char *name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
3013dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (name == NULL)
3014dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3015dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
3016dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid name reference\n"),
3017dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt);
3018dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  goto next_def;
3019dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3020dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      GElf_Word hashval = elf_hash (name);
3021dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (def->vd_hash != hashval)
3022dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3023dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"),
3024dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt, (int) hashval,
3025dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       (int) def->vd_hash);
3026dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3027dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      int res = add_version (NULL, name, def->vd_ndx, ver_def);
3028dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (unlikely (res !=0))
3029dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3030dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  assert (res > 0);
3031dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  ERROR (gettext ("\
3032dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has duplicate version name '%s'\n"),
3033dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		 idx, section_name (ebl, idx), cnt, name);
3034dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3035dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3036dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      struct namelist *newname = alloca (sizeof (*newname));
30376247d634c33be4c9ee4bfc650bb8f06f5add41e5Ulrich Drepper      newname->name = name;
3038dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      newname->next = namelist;
3039dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      namelist = newname;
3040dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3041dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      auxoffset += aux->vda_next;
3042dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
3043dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3044dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
3045dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (aux == NULL)
3046dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    goto no_data;
3047dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3048c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
3049c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  if (name == NULL)
3050c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    ERROR (gettext ("\
3051c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Dreppersection [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"),
3052c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper		   idx, section_name (ebl, idx), cnt);
3053c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	  else
3054c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    {
3055c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname = alloca (sizeof (*newname));
3056c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname->name = name;
3057c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      newname->next = refnamelist;
3058c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	      refnamelist = newname;
3059c2e3135df6741db94a9ec98f1eb57b02277a00b8Ulrich Drepper	    }
3060dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3061dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if ((aux->vda_next != 0 || cnt2 + 1 < def->vd_cnt)
3062dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && aux->vda_next < gelf_fsize (ebl->elf, ELF_T_VDAUX, 1,
3063dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper					     EV_CURRENT))
3064dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
3065dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      ERROR (gettext ("\
3066dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has wrong next field in auxiliary data\n"),
3067dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		     idx, section_name (ebl, idx), cnt);
3068dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      break;
3069dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
3070dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3071dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  auxoffset += MAX (aux->vda_next,
3072dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			    gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, EV_CURRENT));
3073dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3074dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3075dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Find the next offset.  */
3076dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    next_def:
3077dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      offset += def->vd_next;
3078dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3079dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if ((def->vd_next != 0 || cnt > 0)
3080dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  && offset < auxoffset)
3081dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3082dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': entry %d has invalid offset to next entry\n"),
3083dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), cnt);
3084dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3085dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3086dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (!has_base)
3087dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("section [%2d] '%s': no BASE definition\n"),
3088dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	   idx, section_name (ebl, idx));
3089dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3090dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  /* Check whether the referenced names are available.  */
3091dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  while (namelist != NULL)
3092dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
3093dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      struct version_namelist *runp = version_namelist;
3094dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      while (runp != NULL)
3095dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3096dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (runp->type == ver_def
3097dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      && strcmp (runp->name, namelist->name) == 0)
3098dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    break;
3099dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  runp = runp->next;
3100dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3101dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3102dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (runp == NULL)
3103dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	ERROR (gettext ("\
3104dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Dreppersection [%2d] '%s': unknown parent version '%s'\n"),
3105dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	       idx, section_name (ebl, idx), namelist->name);
3106dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3107dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      namelist = namelist->next;
3108dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3109acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper}
3110acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3111059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathstatic void
3112059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathcheck_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
3113059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath{
3114059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (shdr->sh_size == 0)
3115059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3116059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ERROR (gettext ("section [%2d] '%s': empty object attributes section\n"),
3117059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	     idx, section_name (ebl, idx));
3118059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      return;
3119059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3120059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3121059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL);
3122059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (data == NULL || data->d_size == 0)
3123059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3124059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
3125059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	     idx, section_name (ebl, idx));
3126059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      return;
3127059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3128059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3129059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  inline size_t pos (const unsigned char *p)
3130059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  {
3131059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    return p - (const unsigned char *) data->d_buf;
3132059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  }
3133059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3134059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  const unsigned char *p = data->d_buf;
3135059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (*p++ != 'A')
3136059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3137059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ERROR (gettext ("section [%2d] '%s': unrecognized attribute format\n"),
3138059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	     idx, section_name (ebl, idx));
3139059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      return;
3140059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3141059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3142059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  inline size_t left (void)
3143059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  {
3144059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    return (const unsigned char *) data->d_buf + data->d_size - p;
3145059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  }
3146059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3147059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  while (left () >= 4)
3148059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
3149059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      uint32_t len;
3150059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      memcpy (&len, p, sizeof len);
3151059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3152059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (len == 0)
3153059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	ERROR (gettext ("\
3154059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: zero length field in attribute section\n"),
3155059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	       idx, section_name (ebl, idx), pos (p));
3156059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3157059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3158059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	CONVERT (len);
3159059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3160059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (len > left ())
3161059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	{
3162059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  ERROR (gettext ("\
3163059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: invalid length in attribute section\n"),
3164059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		 idx, section_name (ebl, idx), pos (p));
3165059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  break;
3166059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	}
3167059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3168059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      const unsigned char *name = p + sizeof len;
3169059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      p += len;
3170059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3171059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      unsigned const char *q = memchr (name, '\0', len);
3172059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (q == NULL)
3173059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	{
3174059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  ERROR (gettext ("\
3175059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unterminated vendor name string\n"),
3176059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		 idx, section_name (ebl, idx), pos (p));
3177059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  continue;
3178059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	}
3179059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      ++q;
3180059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3181059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (q - name == sizeof "gnu" && !memcmp (name, "gnu", sizeof "gnu"))
3182059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	while (q < p)
3183059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  {
3184059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    unsigned const char *chunk = q;
3185059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3186059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    unsigned int subsection_tag;
3187059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    get_uleb128 (subsection_tag, q);
3188059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3189059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (q >= p)
3190059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3191059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3192059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"),
3193059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (chunk));
3194059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		break;
3195059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3196059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3197059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    uint32_t subsection_len;
3198059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (p - q < (ptrdiff_t) sizeof subsection_len)
3199059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3200059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3201059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: truncated attribute section\n"),
3202059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (q));
3203059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		break;
3204059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3205059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3206059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    memcpy (&subsection_len, q, sizeof subsection_len);
3207059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (subsection_len == 0)
3208059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3209059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3210059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
3211059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (q));
3212059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3213059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		q += sizeof subsection_len;
3214059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		continue;
3215059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3216059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3217059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3218059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      CONVERT (subsection_len);
3219059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
322047c5c35de6bc548dff7577e3dae38d183b719232Roland McGrath	    if (p - chunk < (ptrdiff_t) subsection_len)
3221059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3222059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		ERROR (gettext ("\
3223059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
3224059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		       idx, section_name (ebl, idx), pos (q));
3225059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		break;
3226059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3227059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3228059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    const unsigned char *subsection_end = chunk + subsection_len;
3229059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    chunk = q;
3230059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    q = subsection_end;
3231059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3232059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    if (subsection_tag != 1) /* Tag_File */
3233059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      ERROR (gettext ("\
3234059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
3235059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		     idx, section_name (ebl, idx), pos (chunk), subsection_tag);
3236059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    else
3237059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      {
3238059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		chunk += sizeof subsection_len;
3239059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		while (chunk < q)
3240059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		  {
3241059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    unsigned int tag;
3242059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    get_uleb128 (tag, chunk);
3243059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3244059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    uint64_t value = 0;
3245059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    const unsigned char *r = chunk;
3246059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    if (tag == 32 || (tag & 1) == 0)
3247059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      {
3248059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			get_uleb128 (value, r);
3249059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			if (r > q)
3250059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  {
3251059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    ERROR (gettext ("\
3252059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"),
3253059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath				   idx, section_name (ebl, idx), pos (chunk));
3254059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    break;
3255059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  }
3256059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      }
3257059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    if (tag == 32 || (tag & 1) != 0)
3258059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      {
3259059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			r = memchr (r, '\0', q - r);
3260059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			if (r == NULL)
3261059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  {
3262059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    ERROR (gettext ("\
3263059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unterminated string in attribute\n"),
3264059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath				   idx, section_name (ebl, idx), pos (chunk));
3265059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			    break;
3266059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			  }
3267059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			++r;
3268059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      }
3269059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3270059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    const char *tag_name = NULL;
3271059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    const char *value_name = NULL;
3272059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    if (!ebl_check_object_attribute (ebl, (const char *) name,
3273059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath						     tag, value,
3274059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath						     &tag_name, &value_name))
3275059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      ERROR (gettext ("\
3276059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"),
3277059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			     idx, section_name (ebl, idx), pos (chunk), tag);
3278059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    else if ((tag & 1) == 0 && value_name == NULL)
3279059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		      ERROR (gettext ("\
3280059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"),
3281059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			     idx, section_name (ebl, idx), pos (chunk),
3282059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath			     tag_name, value);
3283059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3284059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		    chunk = r;
3285059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath		  }
3286059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      }
3287059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  }
3288059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      else
3289059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	ERROR (gettext ("\
3290059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: vendor '%s' unknown\n"),
3291059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	       idx, section_name (ebl, idx), pos (p), name);
3292059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
3293059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3294059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (left () != 0)
3295059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    ERROR (gettext ("\
3296059c83e5db89955913a39fe6705acca571c32c3fRoland McGrathsection [%2d] '%s': offset %zu: extra bytes after last attribute section\n"),
3297059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	   idx, section_name (ebl, idx), pos (p));
3298059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath}
3299acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3300637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic bool has_loadable_segment;
3301637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic bool has_interp_segment;
3302637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3303637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepperstatic const struct
3304637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper{
3305637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  const char *name;
3306637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  size_t namelen;
3307637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word type;
3308b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  enum { unused, exact, atleast, exact_or_gnuld } attrflag;
3309637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word attr;
3310637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  GElf_Word attr2;
3311637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper} special_sections[] =
3312637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  {
3313637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    /* See figure 4-14 in the gABI.  */
3314637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3315637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".comment", 8, SHT_PROGBITS, exact, 0, 0 },
3316637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3317637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3318b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    { ".debug_str", 11, SHT_PROGBITS, exact_or_gnuld, SHF_MERGE | SHF_STRINGS, 0 },
3319b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    { ".debug", 6, SHT_PROGBITS, exact, 0, 0 },
3320637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE },
3321637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 },
3322637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 },
3323637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3324637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3325637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info?
3326637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 },
3327637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3328637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3329637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests?
3330637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".line", 6, SHT_PROGBITS, exact, 0, 0 },
3331099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath    { ".note", 6, SHT_NOTE, atleast, 0, SHF_ALLOC },
3332637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
3333637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3334637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC }, // XXX more tests
3335637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC }, // XXX more tests
3336637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3337637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3338637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 },
3339637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3340637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3341637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests
3342637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3343637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3344637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3345637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3346637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3347637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    /* The following are GNU extensions.  */
3348637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version", 13, SHT_GNU_versym, exact, SHF_ALLOC, 0 },
3349637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper    { ".gnu.version_d", 15, SHT_GNU_verdef, exact, SHF_ALLOC, 0 },
3350059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 },
3351059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    { ".gnu.attributes", 16, SHT_GNU_ATTRIBUTES, exact, 0, 0 },
3352637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  };
3353637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper#define nspecial_sections \
3354637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper  (sizeof (special_sections) / sizeof (special_sections[0]))
3355637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3356b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper#define IS_KNOWN_SPECIAL(idx, string, prefix)			      \
3357b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  (special_sections[idx].namelen == sizeof string - (prefix ? 1 : 0)  \
3358b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper   && !memcmp (special_sections[idx].name, string, \
3359b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	       sizeof string - (prefix ? 1 : 0)))
3360637963b564240fe6db4908b28238b75aa0758a06Ulrich Drepper
3361978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3362978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper/* Indeces of some sections we need later.  */
3363978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic size_t eh_frame_hdr_scnndx;
3364978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic size_t eh_frame_scnndx;
3365978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic size_t gcc_except_table_scnndx;
3366978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3367978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3368acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepperstatic void
3369acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppercheck_sections (Ebl *ebl, GElf_Ehdr *ehdr)
3370acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper{
3371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_shoff == 0)
3372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* No section header.  */
3373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
3374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Allocate array to count references in section groups.  */
3376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  scnref = (int *) xcalloc (shnum, sizeof (int));
3377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the zeroth section first.  It must not have any contents
3379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     and the section header must contain nonzero value at most in the
3380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     sh_size and sh_link fields.  */
3381acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr shdr_mem;
3382acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
3383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (shdr == NULL)
3384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("cannot get section header of zeroth section\n"));
3385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
3386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
3387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_name != 0)
3388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero name\n"));
3389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type != 0)
3390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero type\n"));
3391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags != 0)
3392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero flags\n"));
3393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_addr != 0)
3394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero address\n"));
3395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_offset != 0)
3396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero offset\n"));
3397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_info != 0)
3398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero info field\n"));
3399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_addralign != 0)
3400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero align value\n"));
3401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_entsize != 0)
3402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("zeroth section has nonzero entry size value\n"));
3403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_size != 0 && ehdr->e_shnum != 0)
3405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperzeroth section has nonzero size value while ELF header has nonzero shnum value\n"));
3407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX)
3409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperzeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n"));
3411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
341313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath  int *segment_flags = xcalloc (ehdr->e_phnum, sizeof segment_flags[0]);
341413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
3415acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  bool dot_interp_section = false;
3416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
34177c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  size_t hash_idx = 0;
34187c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  size_t gnu_hash_idx = 0;
34197c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
3420dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  size_t versym_scnndx = 0;
3421acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  for (size_t cnt = 1; cnt < shnum; ++cnt)
3422acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper    {
3423acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper      shdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &shdr_mem);
3424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr == NULL)
3425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("\
3427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot get section header for section [%2zu] '%s': %s\n"),
3428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, section_name (ebl, cnt), elf_errmsg (-1));
3429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
3430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
3433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (scnname == NULL)
3435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("section [%2zu]: invalid name\n"), cnt);
3436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
3437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Check whether it is one of the special sections defined in
3439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     the gABI.  */
3440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t s;
3441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (s = 0; s < nspecial_sections; ++s)
3442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (strncmp (scnname, special_sections[s].name,
3443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 special_sections[s].namelen) == 0)
3444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
3445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf1[100];
3446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf2[100];
3447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		char stbuf3[100];
3448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3449653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		GElf_Word good_type = special_sections[s].type;
3450b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		if (IS_KNOWN_SPECIAL (s, ".plt", false)
3451c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		    && ebl_bss_plt_p (ebl, ehdr))
3452653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		  good_type = SHT_NOBITS;
3453653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
3454b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		/* In a debuginfo file, any normal section can be SHT_NOBITS.
3455b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		   This is only invalid for DWARF sections and .shstrtab.  */
3456653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		if (shdr->sh_type != good_type
3457b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		    && (shdr->sh_type != SHT_NOBITS
3458b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| !is_debuginfo
3459b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| IS_KNOWN_SPECIAL (s, ".debug_str", false)
3460b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| IS_KNOWN_SPECIAL (s, ".debug", true)
3461b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			|| IS_KNOWN_SPECIAL (s, ".shstrtab", false)))
3462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  ERROR (gettext ("\
3463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2d] '%s' has wrong type: expected %s, is %s\n"),
3464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 (int) cnt, scnname,
3465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 ebl_section_type_name (ebl, special_sections[s].type,
3466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						stbuf1, sizeof (stbuf1)),
3467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 ebl_section_type_name (ebl, shdr->sh_type,
3468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						stbuf2, sizeof (stbuf2)));
3469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3470b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		if (special_sections[s].attrflag == exact
3471b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		    || special_sections[s].attrflag == exact_or_gnuld)
3472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* Except for the link order and group bit all the
3474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       other bits should match exactly.  */
3475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP))
3476b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			!= special_sections[s].attr
3477b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			&& (special_sections[s].attrflag == exact || !gnuld))
3478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has wrong flags: expected %s, is %s\n"),
3480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname,
3481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr,
3482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf1, sizeof (stbuf1)),
3483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (shdr->sh_flags
3484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   & ~SHF_LINK_ORDER,
3485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf2, sizeof (stbuf2)));
3486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else if (special_sections[s].attrflag == atleast)
3488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & special_sections[s].attr)
3490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			!= special_sections[s].attr
3491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			|| ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP
3492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						| special_sections[s].attr
3493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						| special_sections[s].attr2))
3494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    != 0))
3495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"),
3497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname,
3498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr,
3499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf1, sizeof (stbuf1)),
3500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (special_sections[s].attr2,
3501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf2, sizeof (stbuf2)),
3502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     section_flags_string (shdr->sh_flags
3503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   & ~(SHF_LINK_ORDER
3504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						       | SHF_GROUP),
3505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						   stbuf3, sizeof (stbuf3)));
3506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (strcmp (scnname, ".interp") == 0)
3509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    dot_interp_section = true;
3511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (ehdr->e_type == ET_REL)
3513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' present in object file\n"),
3515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !has_loadable_segment)
3519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     && has_loadable_segment)
3524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
3529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (strcmp (scnname, ".symtab_shndx") == 0
3531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& ehdr->e_type != ET_REL)
3532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' is extension section index table in non-object file\n"),
3534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    /* These sections must have the SHF_ALLOC flag set iff
3537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       a loadable segment is available.
3538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .relxxx
3540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .strtab
3541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .symtab
3542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       .symtab_shndx
3543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       Check that if there is a reference from the
3545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       loaded section these sections also have the
3546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       ALLOC flag set.  */
3547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if 0
3548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    // XXX TODO
3549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !has_loadable_segment)
3551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     && has_loadable_segment)
3556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, scnname);
3559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
3560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		break;
3563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
3564978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
3565978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  /* Remember a few special sections for later.  */
3566978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  if (strcmp (scnname, ".eh_frame_hdr") == 0)
3567978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	    eh_frame_hdr_scnndx = cnt;
3568978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  else if (strcmp (scnname, ".eh_frame") == 0)
3569978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	    eh_frame_scnndx = cnt;
3570978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  else if (strcmp (scnname, ".gcc_except_table") == 0)
3571978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	    gcc_except_table_scnndx = cnt;
3572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize)
3575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': size not multiple of entry size\n"),
3577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL)
3580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("cannot get section header\n"));
3581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type >= SHT_NUM
3583059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  && shdr->sh_type != SHT_GNU_ATTRIBUTES
3584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_LIBLIST
3585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_CHECKSUM
3586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_verdef
3587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && shdr->sh_type != SHT_GNU_verneed
358818e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && shdr->sh_type != SHT_GNU_versym
358918e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	  && ebl_section_type_name (ebl, shdr->sh_type, NULL, 0) == NULL)
359018e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	ERROR (gettext ("section [%2zu] '%s' has unsupported type %d\n"),
359118e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	       cnt, section_name (ebl, cnt),
359218e13427fa32a5464f1678be31512c0e0fec59c7Roland McGrath	       (int) shdr->sh_type);
3593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \
3595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \
3596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS)
3597aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper      if (shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS)
3598aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	{
3599aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS;
3600aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  if (sh_flags & SHF_MASKPROC)
3601aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    {
3602aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	      if (!ebl_machine_section_flag_check (ebl,
3603aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper						   sh_flags & SHF_MASKPROC))
3604aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		ERROR (gettext ("section [%2zu] '%s'"
3605aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper				" contains invalid processor-specific flag(s)"
3606aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper				" %#" PRIx64 "\n"),
3607aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		       cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
3608aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	      sh_flags &= ~(GElf_Xword) SHF_MASKPROC;
3609aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    }
3610aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	  if (sh_flags != 0)
3611aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	    ERROR (gettext ("section [%2zu] '%s' contains unknown flag(s)"
3612aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper			    " %#" PRIx64 "\n"),
3613aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper		   cnt, section_name (ebl, cnt), sh_flags);
3614aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper	}
3615aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper      if (shdr->sh_flags & SHF_TLS)
3616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX Correct?
3618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr->sh_addr != 0 && !gnuld)
3619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': thread-local data sections address not zero\n"),
3621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, section_name (ebl, cnt));
3622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX TODO more tests!?
3624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_link >= shnum)
3627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': invalid section reference in link value\n"),
3629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum)
3632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': invalid section reference in info value\n"),
3634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_flags & SHF_MERGE) == 0
3637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && (shdr->sh_flags & SHF_STRINGS) != 0
3638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && be_strict)
3639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': strings flag set without merge flag\n"),
3641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0)
3644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': merge flag set but entry size is zero\n"),
3646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_flags & SHF_GROUP)
3649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	check_scn_group (ebl, cnt);
3650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
365113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath      if (shdr->sh_flags & SHF_EXECINSTR)
365213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	{
365313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	  switch (shdr->sh_type)
365413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    {
365513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    case SHT_PROGBITS:
365613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      break;
365713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
365813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    case SHT_NOBITS:
365913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      if (is_debuginfo)
366013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		break;
366113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    default:
366213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      ERROR (gettext ("\
366313b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' has unexpected type %d for an executable section\n"),
366413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		     cnt, section_name (ebl, cnt), shdr->sh_type);
366513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      break;
366613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    }
366713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
366813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	  if ((shdr->sh_flags & SHF_WRITE)
366913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      && !ebl_check_special_section (ebl, cnt, shdr,
367013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath					     section_name (ebl, cnt)))
367113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    ERROR (gettext ("\
367213b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' is both executable and writable\n"),
367313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		   cnt, section_name (ebl, cnt));
367413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	}
367513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
3676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0)
3677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Make sure the section is contained in a loaded segment
3679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     and that the initialization part matches NOBITS sections.  */
3680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  int pcnt;
3681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Phdr phdr_mem;
3682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Phdr *phdr;
3683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
3685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL
3686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& ((phdr->p_type == PT_LOAD
3687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     && (shdr->sh_flags & SHF_TLS) == 0)
3688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    || (phdr->p_type == PT_TLS
3689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& (shdr->sh_flags & SHF_TLS) != 0))
3690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& phdr->p_offset <= shdr->sh_offset
36919aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath		&& (phdr->p_offset + phdr->p_filesz > shdr->sh_offset
36929aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath		    || (phdr->p_offset + phdr->p_memsz > shdr->sh_offset
36939aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath			&& shdr->sh_type == SHT_NOBITS)))
3694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
3695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* Found the segment.  */
3696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (phdr->p_offset + phdr->p_memsz
3697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    < shdr->sh_offset + shdr->sh_size)
3698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  ERROR (gettext ("\
3699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' not fully contained in segment of program header entry %d\n"),
3700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
3701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (shdr->sh_type == SHT_NOBITS)
3703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz
3705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			&& !is_debuginfo)
3706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"),
3708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
3709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else
3711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
3712653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    const GElf_Off end = phdr->p_offset + phdr->p_filesz;
3713653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath		    if (shdr->sh_offset > end ||
3714653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath			(shdr->sh_offset == end && shdr->sh_size != 0))
3715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ERROR (gettext ("\
3716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"),
3717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 cnt, section_name (ebl, cnt), pcnt);
3718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
3719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
372013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		if (shdr->sh_type != SHT_NOBITS)
372113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		  {
372213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		    if ((shdr->sh_flags & SHF_EXECINSTR) != 0)
372313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      {
372413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			segment_flags[pcnt] |= PF_X;
372513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			if ((phdr->p_flags & PF_X) == 0)
372613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			  ERROR (gettext ("\
372713b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' is executable in nonexecutable segment %d\n"),
372813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath				 cnt, section_name (ebl, cnt), pcnt);
372913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      }
373013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
373113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		    if ((shdr->sh_flags & SHF_WRITE) != 0)
373213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      {
373313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			segment_flags[pcnt] |= PF_W;
373413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			if (0	/* XXX vdso images have this */
373513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			    && (phdr->p_flags & PF_W) == 0)
373613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath			  ERROR (gettext ("\
373713b69609bcd5638e6194d940855fea3dd0519605Roland McGrathsection [%2zu] '%s' is writable in unwritable segment %d\n"),
373813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath				 cnt, section_name (ebl, cnt), pcnt);
373913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		      }
374013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		  }
374113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
3742b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		break;
3743b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
3744b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (pcnt == ehdr->e_phnum)
3746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
3747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': alloc flag set but section not in any loaded segment\n"),
3748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   cnt, section_name (ebl, cnt));
3749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB)
3752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
3753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersection [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"),
3754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt, section_name (ebl, cnt));
3755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      switch (shdr->sh_type)
3757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
3758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNSYM:
3759acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  if (ehdr->e_type == ET_REL)
3760acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	    ERROR (gettext ("\
3761acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Dreppersection [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"),
3762acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper		   cnt, section_name (ebl, cnt));
3763acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  /* FALLTHROUGH */
3764acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_SYMTAB:
3765dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  check_symtab (ebl, ehdr, shdr, cnt);
3766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_RELA:
3769c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  check_rela (ebl, ehdr, shdr, cnt);
3770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_REL:
3773c911c9efe553d9af2d4fb0d420d8b614983e16acUlrich Drepper	  check_rel (ebl, ehdr, shdr, cnt);
3774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNAMIC:
3777607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  check_dynamic (ebl, ehdr, shdr, cnt);
3778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_SYMTAB_SHNDX:
3781acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  check_symtab_shndx (ebl, ehdr, shdr, cnt);
3782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3783b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3784b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_HASH:
37857c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
37867c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  hash_idx = cnt;
37877c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  break;
37887c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
378928ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	case SHT_GNU_HASH:
379028ed895fdc303b2a793506bb1fcdd35d5fd14e70Ulrich Drepper	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
37917c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper	  gnu_hash_idx = cnt;
3792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_NULL:
3795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  check_null (ebl, shdr, cnt);
3796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_GROUP:
3799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  check_group (ebl, ehdr, shdr, cnt);
3800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
380259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	case SHT_NOTE:
380359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  check_note_section (ebl, ehdr, shdr, cnt);
380459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  break;
380559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
3806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_GNU_versym:
3807dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  /* We cannot process this section now since we have no guarantee
3808dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     that the verneed and verdef sections have already been read.
3809dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	     Just remember the section index.  */
3810dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  if (versym_scnndx != 0)
3811dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    ERROR (gettext ("more than one version symbol table present\n"));
3812dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  versym_scnndx = cnt;
3813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3814b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3815acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_GNU_verneed:
3816dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  check_verneed (ebl, ehdr, shdr, cnt);
3817acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  break;
3818acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3819acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	case SHT_GNU_verdef:
3820acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  check_verdef (ebl, shdr, cnt);
3821acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper	  break;
3822acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper
3823059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	case SHT_GNU_ATTRIBUTES:
3824059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  check_attributes (ebl, ehdr, shdr, cnt);
3825059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  break;
3826059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
3827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	default:
3828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Nothing.  */
3829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
3830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (has_interp_segment && !dot_interp_section)
3834b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("INTERP program header entry but no .interp section\n"));
3835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
383613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath  if (!is_debuginfo)
383713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath    for (int pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
383813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath      {
383913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	GElf_Phdr phdr_mem;
384013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
384113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	if (phdr != NULL && (phdr->p_type == PT_LOAD || phdr->p_type == PT_TLS))
384213b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	  {
384313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    if ((phdr->p_flags & PF_X) != 0
384413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		&& (segment_flags[pcnt] & PF_X) == 0)
384513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      ERROR (gettext ("\
384613b69609bcd5638e6194d940855fea3dd0519605Roland McGrathloadable segment [%u] is executable but contains no executable sections\n"),
384713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		     pcnt);
384813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
384913b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	    if ((phdr->p_flags & PF_W) != 0
385013b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		&& (segment_flags[pcnt] & PF_W) == 0)
385113b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	      ERROR (gettext ("\
385213b69609bcd5638e6194d940855fea3dd0519605Roland McGrathloadable segment [%u] is writable but contains no writable sections\n"),
385313b69609bcd5638e6194d940855fea3dd0519605Roland McGrath		     pcnt);
385413b69609bcd5638e6194d940855fea3dd0519605Roland McGrath	  }
385513b69609bcd5638e6194d940855fea3dd0519605Roland McGrath      }
385613b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
385713b69609bcd5638e6194d940855fea3dd0519605Roland McGrath  free (segment_flags);
385813b69609bcd5638e6194d940855fea3dd0519605Roland McGrath
3859dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  if (version_namelist != NULL)
3860dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    {
3861dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      if (versym_scnndx == 0)
3862dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("\
3863dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepperno .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section exist\n"));
3864dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      else
3865dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	check_versym (ebl, versym_scnndx);
3866dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3867dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      /* Check for duplicate index numbers.  */
3868dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      do
3869dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	{
3870dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *runp = version_namelist->next;
3871dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  while (runp != NULL)
3872dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    {
3873dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      if (version_namelist->ndx == runp->ndx)
3874dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		{
3875dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  ERROR (gettext ("duplicate version index %d\n"),
3876dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper			 (int) version_namelist->ndx);
3877dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		  break;
3878dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper		}
3879dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	      runp = runp->next;
3880dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	    }
3881dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
3882dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  struct version_namelist *old = version_namelist;
3883dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  version_namelist = version_namelist->next;
3884dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	  free (old);
3885dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper	}
3886dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper      while (version_namelist != NULL);
3887dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    }
3888dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper  else if (versym_scnndx != 0)
3889dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper    ERROR (gettext ("\
3890dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper.gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"));
3891dbace2389b6f89cd4f8f2713aac50a16b16964a2Ulrich Drepper
38927c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper  if (hash_idx != 0 && gnu_hash_idx != 0)
38937c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper    compare_hash_gnu_hash (ebl, ehdr, hash_idx, gnu_hash_idx);
38947c0e79ffc201e4828a050b35f2c9d96e3001cb48Ulrich Drepper
3895b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  free (scnref);
3896b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
3897b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3898b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
389959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic GElf_Off
390059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathcheck_note_data (Ebl *ebl, const GElf_Ehdr *ehdr,
390159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		 Elf_Data *data, int shndx, int phndx, GElf_Off start)
3902b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
390359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t offset = 0;
390459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t last_offset = 0;
390559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  GElf_Nhdr nhdr;
390659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t name_offset;
390759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  size_t desc_offset;
390859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  while (offset < data->d_size
390959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	 && (offset = gelf_getnote (data, offset,
391059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath				    &nhdr, &name_offset, &desc_offset)) > 0)
3911b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
391259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      last_offset = offset;
3913b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3914b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Make sure it is one of the note types we know about.  */
3915b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr->e_type == ET_CORE)
391659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	switch (nhdr.n_type)
391759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  {
391859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRSTATUS:
391959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_FPREGSET:
392059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRPSINFO:
392159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_TASKSTRUCT:		/* NT_PRXREG on Solaris.  */
392259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PLATFORM:
392359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_AUXV:
392459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_GWINDOWS:
392559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_ASRS:
392659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PSTATUS:
392759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PSINFO:
392859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRCRED:
392959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_UTSNAME:
393059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_LWPSTATUS:
393159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_LWPSINFO:
393259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_PRFPXREG:
393359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    /* Known type.  */
393459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    break;
3935b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
393659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  default:
393759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    if (shndx == 0)
3938b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ERROR (gettext ("\
393959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathphdr[%d]: unknown core file note type %" PRIu32 " at offset %" PRIu64 "\n"),
394059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     phndx, (uint32_t) nhdr.n_type, start + offset);
394159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    else
394259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	      ERROR (gettext ("\
394359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathsection [%2d] '%s': unknown core file note type %" PRIu32
394459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath			      " at offset %Zu\n"),
394559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     shndx, section_name (ebl, shndx),
394659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     (uint32_t) nhdr.n_type, offset);
394759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  }
3948b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
394959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	switch (nhdr.n_type)
3950d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  {
395159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	  case NT_GNU_ABI_TAG:
3952d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  case NT_GNU_HWCAP:
3953d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  case NT_GNU_BUILD_ID:
3954d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	    break;
3955d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath
3956099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath	  case 0:
3957099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath	    /* Linux vDSOs use a type 0 note for the kernel version word.  */
395859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    if (nhdr.n_namesz == sizeof "Linux"
395959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		&& !memcmp (data->d_buf + name_offset, "Linux", sizeof "Linux"))
3960099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath	      break;
3961099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath
3962d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  default:
396359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    if (shndx == 0)
396459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	      ERROR (gettext ("\
396559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathphdr[%d]: unknown object file note type %" PRIu32 " at offset %Zu\n"),
396659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     phndx, (uint32_t) nhdr.n_type, offset);
396759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	    else
396859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	      ERROR (gettext ("\
396959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathsection [%2d] '%s': unknown object file note type %" PRIu32
397059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath			      " at offset %Zu\n"),
397159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     shndx, section_name (ebl, shndx),
397259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		     (uint32_t) nhdr.n_type, offset);
3973d82217264c4ac9108dbda1502a545ea25f6d22feRoland McGrath	  }
3974b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
3975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
397659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  return last_offset;
397759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath}
397859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
3979978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
398059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic void
398159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathcheck_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt)
398259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath{
398359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
398459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
398559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("\
398659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathphdr[%d]: no note entries defined for the type of file\n"),
398759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   cnt);
398859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
398959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (is_debuginfo)
399059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    /* The p_offset values in a separate debug file are bogus.  */
399159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    return;
399259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
3993b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (phdr->p_filesz == 0)
3994b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    return;
3995b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
399659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  GElf_Off notes_size = 0;
399759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  Elf_Data *data = elf_getdata_rawchunk (ebl->elf,
399859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath					 phdr->p_offset, phdr->p_filesz,
399959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath					 ELF_T_NHDR);
400059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (data != NULL)
400159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    notes_size = check_note_data (ebl, ehdr, data, 0, cnt, phdr->p_offset);
400259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
400359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (notes_size == 0)
400459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("phdr[%d]: cannot get content of note section: %s\n"),
400559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   cnt, elf_errmsg (-1));
400659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  else if (notes_size != phdr->p_filesz)
400759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("phdr[%d]: extra %" PRIu64 " bytes after last note\n"),
400859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   cnt, phdr->p_filesz - notes_size);
4009b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
4010b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4011978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
401259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic void
401359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathcheck_note_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
401459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath{
4015b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (shdr->sh_size == 0)
4016b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    return;
4017b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
401859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
401959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (data == NULL)
402059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    {
402159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
402259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	     idx, section_name (ebl, idx));
402359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      return;
402459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    }
402559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
402659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
402759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
402859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("\
402959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathsection [%2d] '%s': no note entries defined for the type of file\n"),
403059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	     idx, section_name (ebl, idx));
403159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
403259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  GElf_Off notes_size = check_note_data (ebl, ehdr, data, idx, 0, 0);
403359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath
403459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  if (notes_size == 0)
403559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("section [%2d] '%s': cannot get content of note section\n"),
403659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   idx, section_name (ebl, idx));
403759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath  else if (notes_size != shdr->sh_size)
403859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath    ERROR (gettext ("section [%2d] '%s': extra %" PRIu64
403959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath		    " bytes after last note\n"),
404059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath	   idx, section_name (ebl, idx), shdr->sh_size - notes_size);
404159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath}
4042b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4043978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4044978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper/* Index of the PT_GNU_EH_FRAME program eader entry.  */
4045978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic int pt_gnu_eh_frame_pndx;
4046978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4047978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4048b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
4049b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
4050b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
4051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_phoff == 0)
4052b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return;
4053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
4055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      && ehdr->e_type != ET_CORE)
4056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    ERROR (gettext ("\
4057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperonly executables, shared objects, and core files can have program headers\n"));
4058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_interp = 0;
4060b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_tls = 0;
4061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int num_pt_relro = 0;
4062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (int cnt = 0; cnt < ehdr->e_phnum; ++cnt)
4064b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
4065b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr phdr_mem;
4066b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr *phdr;
4067b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4068b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
4069b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr == NULL)
4070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4071b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ERROR (gettext ("cannot get program header entry %d: %s\n"),
4072b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 cnt, elf_errmsg (-1));
4073b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  continue;
4074b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME
4077f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  && phdr->p_type != PT_GNU_STACK && phdr->p_type != PT_GNU_RELRO
4078f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  /* Check for a known machine-specific type.  */
4079f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	  && ebl_segment_type_name (ebl, phdr->p_type, NULL, 0) == NULL)
4080b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
4081f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrathprogram header entry %d: unknown program header entry type %#" PRIx64 "\n"),
4082f6895046ad74f67fc357d2c9f76dcb6313c13ab9Roland McGrath	       cnt, (uint64_t) phdr->p_type);
4083b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4084b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_type == PT_LOAD)
4085b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	has_loadable_segment = true;
4086b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_INTERP)
4087b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_interp != 1)
4089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
4090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (num_pt_interp == 2)
4091b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
4092b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermore than one INTERP entry in program header\n"));
4093b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
4094b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  has_interp_segment = true;
4095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_TLS)
4097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4098b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_tls == 2)
4099b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("more than one TLS entry in program header\n"));
4100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_NOTE)
4102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	check_note (ebl, ehdr, phdr, cnt);
410341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper      else if (phdr->p_type == PT_DYNAMIC)
410441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	{
410541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  if (ehdr->e_type == ET_EXEC && ! has_interp_segment)
410641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    ERROR (gettext ("\
410741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperstatic executable cannot have dynamic sections\n"));
410841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	  else
410941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    {
411041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      /* Check that the .dynamic section, if it exists, has
411141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		 the same address.  */
411241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      Elf_Scn *scn = NULL;
411341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
411441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		{
411541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr shdr_mem;
411641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
411741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
411841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    {
411941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      if (phdr->p_offset != shdr->sh_offset)
412041de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			ERROR (gettext ("\
412141de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperdynamic section reference in program header has wrong offset\n"));
412241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      if (phdr->p_memsz != shdr->sh_size)
412341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper			ERROR (gettext ("\
412441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepperdynamic section size mismatch in program and section header\n"));
412541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		      break;
412641de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		    }
412741de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper		}
412841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	    }
412941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper	}
4130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (phdr->p_type == PT_GNU_RELRO)
4131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (++num_pt_relro == 2)
4133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
4134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermore than one GNU_RELRO entry in program header\n"));
4135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
4136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
4137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* Check that the region is in a writable segment.  */
4138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      int inner;
4139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      for (inner = 0; inner < ehdr->e_phnum; ++inner)
4140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
4141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Phdr phdr2_mem;
4142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Phdr *phdr2;
4143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
4145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (phdr2 == NULL)
4146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    continue;
4147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (phdr2->p_type == PT_LOAD
4149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && phdr->p_vaddr >= phdr2->p_vaddr
4150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && (phdr->p_vaddr + phdr->p_memsz
4151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  <= phdr2->p_vaddr + phdr2->p_memsz))
4152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
4153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if ((phdr2->p_flags & PF_W) == 0)
4154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
4155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperloadable segment GNU_RELRO applies to is not writable\n"));
41563a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		      if ((phdr2->p_flags & ~PF_W) != (phdr->p_flags & ~PF_W))
4157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			ERROR (gettext ("\
4158d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrathloadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"),
4159d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrath			       cnt, inner);
4160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      break;
4161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
4162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
4163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (inner >= ehdr->e_phnum)
4165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		ERROR (gettext ("\
4166607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper%s segment not contained in a loaded segment\n"), "GNU_RELRO");
4167607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    }
4168607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	}
4169607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper      else if (phdr->p_type == PT_PHDR)
4170607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	{
4171607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* Check that the region is in a writable segment.  */
4172607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  int inner;
4173607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  for (inner = 0; inner < ehdr->e_phnum; ++inner)
4174607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    {
4175607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr phdr2_mem;
4176607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      GElf_Phdr *phdr2;
4177607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
4178607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
4179607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	      if (phdr2 != NULL
4180607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr2->p_type == PT_LOAD
4181607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && phdr->p_vaddr >= phdr2->p_vaddr
4182607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		  && (phdr->p_vaddr + phdr->p_memsz
4183607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		      <= phdr2->p_vaddr + phdr2->p_memsz))
4184607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper		break;
4185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
4186607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
4187607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (inner >= ehdr->e_phnum)
4188607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    ERROR (gettext ("\
4189607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper%s segment not contained in a loaded segment\n"), "PHDR");
4190607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper
4191607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  /* Check that offset in segment corresponds to offset in ELF
4192607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	     header.  */
4193607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	  if (phdr->p_offset != ehdr->e_phoff)
4194607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepper	    ERROR (gettext ("\
4195607e05466d3fef5e3ad90aa200d3bba1950cf982Ulrich Drepperprogram header offset in ELF header and PHDR entry do not match"));
4196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
41973a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper      else if (phdr->p_type == PT_GNU_EH_FRAME)
41983a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	{
41993a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	  /* If there is an .eh_frame_hdr section it must be
42003a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	     referenced by this program header entry.  */
42013a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	  Elf_Scn *scn = NULL;
4202935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper	  GElf_Shdr shdr_mem;
4203935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper	  GElf_Shdr *shdr = NULL;
4204f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	  bool any = false;
42053a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
42063a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	    {
4207f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      any = true;
4208935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper	      shdr = gelf_getshdr (scn, &shdr_mem);
4209f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if (shdr != NULL
4210f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		  && shdr->sh_type == (is_debuginfo
4211f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper				       ? SHT_NOBITS : SHT_PROGBITS)
42123a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		  && ! strcmp (".eh_frame_hdr",
42133a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper			       elf_strptr (ebl->elf, shstrndx, shdr->sh_name)))
42143a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		{
4215f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		  if (! is_debuginfo)
4216f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		    {
4217f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		      if (phdr->p_offset != shdr->sh_offset)
4218f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper			ERROR (gettext ("\
42193a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table reference in program header has wrong offset\n"));
4220f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		      if (phdr->p_memsz != shdr->sh_size)
4221f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper			ERROR (gettext ("\
42223a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table size mismatch in program and section header\n"));
4223f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		    }
42243a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		  break;
42253a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper		}
42263a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	    }
42273a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper
4228f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	  if (scn == NULL)
4229f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    {
4230f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      /* If there is no section header table we don't
4231f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		 complain.  But if there is one there should be an
4232f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		 entry for .eh_frame_hdr.  */
4233f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if (any)
4234f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4235f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich DrepperPT_GNU_EH_FRAME present but no .eh_frame_hdr section\n"));
4236f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    }
4237f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	  else
4238f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    {
4239f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      /* The section must be allocated and not be writable and
4240f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		 executable.  */
4241f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if ((phdr->p_flags & PF_R) == 0)
4242f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
42433a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table must be allocated\n"));
4244f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      else if (shdr != NULL && (shdr->sh_flags & SHF_ALLOC) == 0)
4245f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4246935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppersection [%2zu] '%s' must be allocated\n"), elf_ndxscn (scn), ".eh_frame_hdr");
4247935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper
4248f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if ((phdr->p_flags & PF_W) != 0)
4249f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
42503a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table must not be writable\n"));
4251f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      else if (shdr != NULL && (shdr->sh_flags & SHF_WRITE) != 0)
4252f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4253935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppersection [%2zu] '%s' must not be writable\n"),
4254f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		       elf_ndxscn (scn), ".eh_frame_hdr");
4255935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper
4256f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      if ((phdr->p_flags & PF_X) != 0)
4257f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
42583a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Dreppercall frame search table must not be executable\n"));
4259f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	      else if (shdr != NULL && (shdr->sh_flags & SHF_EXECINSTR) != 0)
4260f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		ERROR (gettext ("\
4261935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppersection [%2zu] '%s' must not be executable\n"),
4262f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper		       elf_ndxscn (scn), ".eh_frame_hdr");
4263f93ee8d7dcd0d58f7aab96773af084aca82d5798Ulrich Drepper	    }
4264978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4265978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  /* Remember which entry this is.  */
4266978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper	  pt_gnu_eh_frame_pndx = cnt;
42673a52c7a528e41cc28e69e68ef817f0b2d7f130e5Ulrich Drepper	}
4268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
42698190db6a86a37aec86c81626ab1b083c96aff891Roland McGrath      if (phdr->p_filesz > phdr->p_memsz
427056bc0b83ea81b7e959aaa4e1d01f8b36f2804a52Ulrich Drepper	  && (phdr->p_memsz != 0 || phdr->p_type != PT_NOTE))
4271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ERROR (gettext ("\
4272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: file size greater than memory size\n"),
4273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       cnt);
4274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_align > 1)
4276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
4277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (!powerof2 (phdr->p_align))
4278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
4279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: alignment not a power of 2\n"), cnt);
4280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0)
4281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ERROR (gettext ("\
4282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprogram header entry %d: file offset and virtual address not module of alignment\n"), cnt);
4283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
4284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
4286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4288978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepperstatic void
4289935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Dreppercheck_exception_data (Ebl *ebl __attribute__ ((unused)),
4290935eddef3db5cc2fdc317fa943f93502281d3a42Ulrich Drepper		      GElf_Ehdr *ehdr __attribute__ ((unused)))
4291978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper{
4292daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper  if ((ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
4293daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper      && pt_gnu_eh_frame_pndx == 0 && eh_frame_hdr_scnndx != 0)
4294daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper    ERROR (gettext ("executable/DSO with .eh_frame_hdr section does not have "
4295daf0fda7c0e6dcdcc6d011c89a7c6e94ecd238e1Ulrich Drepper		    "a PT_GNU_EH_FRAME program header entry"));
4296978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper}
4297978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4298978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
4299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Process one file.  */
4300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
4301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprocess_elf_file (Elf *elf, const char *prefix, const char *suffix,
4302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  const char *fname, size_t size, bool only_one)
4303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
4304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Reset variables.  */
4305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ndynamic = 0;
4306acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  nverneed = 0;
4307acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  nverdef = 0;
430841de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  textrel = false;
430941de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  needed_textrel = false;
4310acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  has_loadable_segment = false;
4311acb8983909a3f031041ee5d7cbe09fbeb3c31b9aUlrich Drepper  has_interp_segment = false;
4312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr ehdr_mem;
4314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
4315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Ebl *ebl;
4316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Print the file name.  */
4318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (!only_one)
4319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
4320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (prefix != NULL)
4321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	printf ("\n%s(%s)%s:\n", prefix, fname, suffix);
4322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
4323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	printf ("\n%s:\n", fname);
4324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr == NULL)
4327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
4328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ERROR (gettext ("cannot read ELF header: %s\n"), elf_errmsg (-1));
4329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return;
4330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
4331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl = ebl_openbackend (elf);
4333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If there is no appropriate backend library we cannot test
4334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     architecture and OS specific features.  Any encountered extension
4335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     is an error.  */
4336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Go straight by the gABI, check all the parts in turn.  */
4338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_elf_header (ebl, ehdr, size);
4339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Check the program header.  */
4341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_program_header (ebl, ehdr);
4342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Next the section headers.  It is OK if there are no section
4344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     headers at all.  */
4345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  check_sections (ebl, ehdr);
4346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4347978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper  /* Check the exception handling data, if it exists.  */
4348978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper  if (pt_gnu_eh_frame_pndx != 0 || eh_frame_hdr_scnndx != 0
4349978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper      || eh_frame_scnndx != 0 || gcc_except_table_scnndx != 0)
4350978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper    check_exception_data (ebl, ehdr);
4351978360c6ec51192ab7f1333ae9f1c105bcdb5ecdUlrich Drepper
435241de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  /* Report if no relocation section needed the text relocation flag.  */
435341de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper  if (textrel && !needed_textrel)
435441de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper    ERROR (gettext ("text relocation flag set but not needed\n"));
435541de488a0ad6679e816dbab960351e5f62ab8eadUlrich Drepper
4356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Free the resources.  */
4357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  ebl_closebackend (ebl);
4358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
43593cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
43603cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
43613cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper#include "debugpred.h"
4362