elflint.c revision 13b69609bcd5638e6194d940855fea3dd0519605
1f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov/* Pedantic checking of ELF files compliance with gABI/psABI spec.
2f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.
3f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   This file is part of Red Hat elfutils.
4f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
5f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov
6f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   Red Hat elfutils is free software; you can redistribute it and/or modify
7f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   it under the terms of the GNU General Public License as published by the
8f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   Free Software Foundation; version 2 of the License.
9f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov
10f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   Red Hat elfutils is distributed in the hope that it will be useful, but
11f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   WITHOUT ANY WARRANTY; without even the implied warranty of
12f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   General Public License for more details.
14f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov
15f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   You should have received a copy of the GNU General Public License along
16f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   with Red Hat elfutils; if not, write to the Free Software Foundation,
17f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
1806ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov
19f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   Red Hat elfutils is an included package of the Open Invention Network.
20f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   An included package of the Open Invention Network is a package for which
21f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   Open Invention Network licensees cross-license their patents.  No patent
22f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   license is granted, either expressly or impliedly, by designation as an
23f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   included package.  Should you wish to participate in the Open Invention
24f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   Network licensing program, please visit www.openinventionnetwork.com
25f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov   <http://www.openinventionnetwork.com>.  */
26f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov
27f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov#ifdef HAVE_CONFIG_H
28f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov# include <config.h>
29f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov#endif
30f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov
31f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov#include <argp.h>
32c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov#include <assert.h>
33f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov#include <byteswap.h>
34f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov#include <endian.h>
35f0144127b98425d214e59e4a1a4b342b78e3642bChris Lattner#include <error.h>
36b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include <fcntl.h>
37f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov#include <gelf.h>
38804e0fea4033e3b91dbc8198cef30de30f141bb5Torok Edwin#include <inttypes.h>
394437ae213d5435390f0750213b53ec807c047f22Chris Lattner#include <libintl.h>
40f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov#include <locale.h>
41f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov#include <stdbool.h>
42f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov#include <stdlib.h>
43b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include <string.h>
44b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include <unistd.h>
45b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include <sys/param.h>
46b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov
47b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include <elf-knowledge.h>
48b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include <system.h>
49b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include "../libelf/libelfP.h"
50b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include "../libelf/common.h"
51b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include "../libebl/libeblP.h"
52b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include "../libdw/libdwP.h"
53b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include "../libdwfl/libdwflP.h"
54b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov#include "../libdw/memory-access.h"
55b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov
56b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov
57b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov/* Name and version of program.  */
58b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikovstatic void print_version (FILE *stream, struct argp_state *state);
59b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikovvoid (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
60b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov
61b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov/* Bug report address.  */
62f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikovconst char *argp_program_bug_address = PACKAGE_BUGREPORT;
63f0144127b98425d214e59e4a1a4b342b78e3642bChris Lattner
64f0144127b98425d214e59e4a1a4b342b78e3642bChris Lattner#define ARGP_strict	300
65f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov#define ARGP_gnuld	301
6606ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov
6706ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov/* Definitions of arguments for argp functions.  */
68f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikovstatic const struct argp_option options[] =
69825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson{
70825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
71f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov  { "strict", ARGP_strict, NULL, 0,
72f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov    N_("Be extremely strict, flag level 2 features."), 0 },
73f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov  { "quiet", 'q', NULL, 0, N_("Do not print anything if successful"), 0 },
74fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  { "debuginfo", 'd', NULL, 0, N_("Binary is a separate debuginfo file"), 0 },
751476d97037e07d17635468fcd3a2ee0111972574Anton Korobeynikov  { "gnu-ld", ARGP_gnuld, NULL, 0,
761476d97037e07d17635468fcd3a2ee0111972574Anton Korobeynikov    N_("Binary has been created with GNU ld and is therefore known to be \
771476d97037e07d17635468fcd3a2ee0111972574Anton Korobeynikovbroken in certain ways"), 0 },
781476d97037e07d17635468fcd3a2ee0111972574Anton Korobeynikov  { NULL, 0, NULL, 0, NULL, 0 }
791476d97037e07d17635468fcd3a2ee0111972574Anton Korobeynikov};
80d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov
81d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov/* Short description of program.  */
82825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic const char doc[] = N_("\
83d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton KorobeynikovPedantic checking of ELF files compliance with gABI/psABI spec.");
84c08163e72dca43ff5421a13505503314e0d7074aAnton Korobeynikov
85c08163e72dca43ff5421a13505503314e0d7074aAnton Korobeynikov/* Strings for arguments in help texts.  */
86c08163e72dca43ff5421a13505503314e0d7074aAnton Korobeynikovstatic const char args_doc[] = N_("FILE...");
87c08163e72dca43ff5421a13505503314e0d7074aAnton Korobeynikov
8806ac0820a6cefa6896000054d8e4906326c0cce6Anton Korobeynikov/* Prototype for option handler.  */
896534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikovstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
906534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov
916534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov/* Data structure to communicate with argp functions.  */
926534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikovstatic struct argp argp =
936534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov{
946534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov  options, parse_opt, args_doc, doc, NULL, NULL, NULL
956534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov};
96825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
9736b6e533c1aac85452438161f7034a9f54bd1830Anton Korobeynikov
9854f30d3fc94e055f13e6744378323d05c5c050baAnton Korobeynikov/* Declarations of local functions.  */
99825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic void process_file (int fd, Elf *elf, const char *prefix,
100825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson			  const char *suffix, const char *fname, size_t size,
101825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson			  bool only_one);
102825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic void process_elf_file (Elf *elf, const char *prefix, const char *suffix,
103825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson			      const char *fname, size_t size, bool only_one);
104825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic void check_note_section (Ebl *ebl, GElf_Ehdr *ehdr,
105825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson				GElf_Shdr *shdr, int idx);
106825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
107825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
108825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson/* Report an error.  */
109825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson#define ERROR(str, args...) \
110825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  do {									      \
111825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    printf (str, ##args);						      \
112825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    ++error_count;							      \
113825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } while (0)
114825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic unsigned int error_count;
115825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
116825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson/* True if we should perform very strict testing.  */
117825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic bool be_strict;
118825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
119825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson/* True if no message is to be printed if the run is succesful.  */
120825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic bool be_quiet;
121825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
122825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson/* True if binary is from strip -f, not a normal ELF file.  */
123825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic bool is_debuginfo;
124825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
125379a087cc7175532ff0c24c60069da5eec596879Anton Korobeynikov/* True if binary is assumed to be generated with GNU ld.  */
126379a087cc7175532ff0c24c60069da5eec596879Anton Korobeynikovstatic bool gnuld;
127825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
128825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson/* Index of section header string table.  */
129825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic uint32_t shstrndx;
130825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
131825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson/* Array to count references in section groups.  */
132825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic int *scnref;
133825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
134825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
135825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonint
136825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonmain (int argc, char *argv[])
137825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson{
138825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  /* Set locale.  */
139825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  setlocale (LC_ALL, "");
140825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
141825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  /* Initialize the message catalog.  */
142825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  textdomain (PACKAGE_TARNAME);
143e4ce880dfa340bf45ddce10bb1dbe856553677b6Eli Friedman
1448725bd22bf91c29e2351a127295c19fea996e2c7Anton Korobeynikov  /* Parse and process arguments.  */
1458983da729aa1ca99a11a3b98ae6280dfcdbadb39Anton Korobeynikov  int remaining;
1468983da729aa1ca99a11a3b98ae6280dfcdbadb39Anton Korobeynikov  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
1478983da729aa1ca99a11a3b98ae6280dfcdbadb39Anton Korobeynikov
1488983da729aa1ca99a11a3b98ae6280dfcdbadb39Anton Korobeynikov  /* Before we start tell the ELF library which version we are using.  */
1498983da729aa1ca99a11a3b98ae6280dfcdbadb39Anton Korobeynikov  elf_version (EV_CURRENT);
150825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
151825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  /* Now process all the files given at the command line.  */
152825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  bool only_one = remaining + 1 == argc;
153825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  do
154825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    {
155825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson      /* Open the file.  */
1568983da729aa1ca99a11a3b98ae6280dfcdbadb39Anton Korobeynikov      int fd = open (argv[remaining], O_RDONLY);
1578983da729aa1ca99a11a3b98ae6280dfcdbadb39Anton Korobeynikov      if (fd == -1)
1588983da729aa1ca99a11a3b98ae6280dfcdbadb39Anton Korobeynikov	{
1598983da729aa1ca99a11a3b98ae6280dfcdbadb39Anton Korobeynikov	  error (0, errno, gettext ("cannot open input file"));
1608983da729aa1ca99a11a3b98ae6280dfcdbadb39Anton Korobeynikov	  continue;
1618983da729aa1ca99a11a3b98ae6280dfcdbadb39Anton Korobeynikov	}
162825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
163825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson      /* Create an `Elf' descriptor.  */
164825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson      Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
165825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson      if (elf == NULL)
166825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson	ERROR (gettext ("cannot generate Elf descriptor: %s\n"),
167825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson	       elf_errmsg (-1));
168b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov      else
169b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov	{
170b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov	  unsigned int prev_error_count = error_count;
171b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov	  struct stat64 st;
172b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov
173b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov	  if (fstat64 (fd, &st) != 0)
174b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov	    {
175b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov	      printf ("cannot stat '%s': %m\n", argv[remaining]);
176b2de1ea29bbb6cde06d34eb3cfea4df9f99b5b8dAnton Korobeynikov	      close (fd);
177f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov	      continue;
178f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov	    }
179b8639f52143c99a3902b83555db4c54766c783caAnton Korobeynikov
180f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov	  process_file (fd, elf, NULL, NULL, argv[remaining], st.st_size,
181ea54c9846b2973cafa8ffd40626f5676ba9ccfeeAnton Korobeynikov			only_one);
182e699d0f549151a2cca993c21407aea4a6eff7d3fAnton Korobeynikov
1834428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  /* Now we can close the descriptor.  */
1843513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov	  if (elf_end (elf) != 0)
1855d59f68ade7573175f1ace09061a94286e59076bAnton Korobeynikov	    ERROR (gettext ("error while closing Elf descriptor: %s\n"),
1861bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov		   elf_errmsg (-1));
1871bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov
188b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov	  if (prev_error_count == error_count && !be_quiet)
18906ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov	    puts (gettext ("No errors"));
19006ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov	}
191f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov
192c23197a26f34f559ea9797de51e187087c039c42Torok Edwin      close (fd);
193f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov    }
194f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov  while (++remaining < argc);
195f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov
196f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov  return error_count != 0;
197b4202b84d7e54efe5e144885c7da63e6cc465f80Bill Wendling}
19820c568f366be211323eeaf0e45ef053278ec9ddcBill Wendling
1993741be39f98795a841a4d8c35bf54928769ac3cdAnton Korobeynikov
20020c568f366be211323eeaf0e45ef053278ec9ddcBill Wendling/* Handle program arguments.  */
20120c568f366be211323eeaf0e45ef053278ec9ddcBill Wendlingstatic error_t
202c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikovparse_opt (int key, char *arg __attribute__ ((unused)),
203cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov	   struct argp_state *state __attribute__ ((unused)))
204cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov{
205cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov  switch (key)
206cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov    {
207cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov    case ARGP_strict:
208cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov      be_strict = true;
209cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov      break;
210cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov
211cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov    case 'q':
212cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov      be_quiet = true;
213cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov      break;
214cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov
215cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov    case 'd':
216cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov      is_debuginfo = true;
217cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov
218cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov    case ARGP_gnuld:
219cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov      gnuld = true;
220cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov      break;
221cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov
222cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov    case ARGP_KEY_NO_ARGS:
223cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov      fputs (gettext ("Missing file name.\n"), stderr);
224cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov      argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
225cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov		 program_invocation_short_name);
226cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov      exit (1);
227cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov
228cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov    default:
229cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov      return ARGP_ERR_UNKNOWN;
230cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov    }
231cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov  return 0;
232cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov}
233cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov
234cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov
235cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov/* Print the version information.  */
236cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikovstatic void
237cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikovprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
238cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov{
239cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov  fprintf (stream, "elflint (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
240cd76128f182b9a9f3986384523cf90f4c30e4d35Anton Korobeynikov  fprintf (stream, gettext ("\
241c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton KorobeynikovCopyright (C) %s Red Hat, Inc.\n\
242c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton KorobeynikovThis is free software; see the source for copying conditions.  There is NO\n\
243c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikovwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
244f2c3e179ecc2a6ebc259382828a5e5dc5a61d2f8Anton Korobeynikov"), "2008");
245c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
24698ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman}
24798ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman
24865c3c8f323198b99b88b109654194540cf9b3fa5Sandeep Patel
24998ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman/* Process one file.  */
25098ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohmanstatic void
25198ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohmanprocess_file (int fd, Elf *elf, const char *prefix, const char *suffix,
25298ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	      const char *fname, size_t size, bool only_one)
25398ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman{
25498ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  /* We can handle two types of files: ELF files and archives.  */
25598ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  Elf_Kind kind = elf_kind (elf);
25698ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman
257c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  switch (kind)
258c23197a26f34f559ea9797de51e187087c039c42Torok Edwin    {
259c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    case ELF_K_ELF:
260c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov      /* Yes!  It's an ELF file.  */
26198ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman      process_elf_file (elf, prefix, suffix, fname, size, only_one);
262e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov      break;
263e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov
264e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov    case ELF_K_AR:
265e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov      {
266e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov	Elf *subelf;
267e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov	Elf_Cmd cmd = ELF_C_READ_MMAP;
268e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov	size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
269c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov	size_t fname_len = strlen (fname) + 1;
270c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov	char new_prefix[prefix_len + 1 + fname_len];
271c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov	char new_suffix[(suffix == NULL ? 0 : strlen (suffix)) + 2];
27298ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	char *cp = new_prefix;
27398ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman
27465c3c8f323198b99b88b109654194540cf9b3fa5Sandeep Patel	/* Create the full name of the file.  */
27598ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	if (prefix != NULL)
27698ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	  {
27798ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	    cp = mempcpy (cp, prefix, prefix_len);
27898ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	    *cp++ = '(';
27998ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	    strcpy (stpcpy (new_suffix, suffix), ")");
28098ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	  }
28198ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	else
2824428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  new_suffix[0] = '\0';
283c23197a26f34f559ea9797de51e187087c039c42Torok Edwin	memcpy (cp, fname, fname_len);
2844428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
2854428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	/* It's an archive.  We process each file in it.  */
28698ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
28798ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	  {
288e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov	    kind = elf_kind (subelf);
289e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov
290e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov	    /* Call this function recursively.  */
2914428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	    if (kind == ELF_K_ELF || kind == ELF_K_AR)
2924428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	      {
2934428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov		Elf_Arhdr *arhdr = elf_getarhdr (subelf);
294c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov		assert (arhdr != NULL);
295c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov
296c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov		process_file (fd, subelf, new_prefix, new_suffix,
297c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov			      arhdr->ar_name, arhdr->ar_size, false);
29898ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	      }
29998ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman
30065c3c8f323198b99b88b109654194540cf9b3fa5Sandeep Patel	    /* Get next archive element.  */
30198ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	    cmd = elf_next (subelf);
30298ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	    if (elf_end (subelf) != 0)
30398ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	      ERROR (gettext (" error while freeing sub-ELF descriptor: %s\n"),
30498ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman		     elf_errmsg (-1));
30598ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	  }
30698ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman      }
307c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov      break;
308c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov
309c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    default:
310c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov      /* We cannot do anything.  */
311c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov      ERROR (gettext ("\
312c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton KorobeynikovNot an ELF file - it has the wrong magic bytes at the start\n"));
31398ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman      break;
31498ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman    }
31598ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman}
316c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov
317c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov
318c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikovstatic const char *
319c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikovsection_name (Ebl *ebl, int idx)
320c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov{
321c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  GElf_Shdr shdr_mem;
322c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  GElf_Shdr *shdr;
323e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson
324825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  shdr = gelf_getshdr (elf_getscn (ebl->elf, idx), &shdr_mem);
325804e0fea4033e3b91dbc8198cef30de30f141bb5Torok Edwin
326804e0fea4033e3b91dbc8198cef30de30f141bb5Torok Edwin  return elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
327dac237e18209b697a8ba122d0ddd9cad4dfba1f8Torok Edwin}
3284437ae213d5435390f0750213b53ec807c047f22Chris Lattner
329825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
330dac237e18209b697a8ba122d0ddd9cad4dfba1f8Torok Edwinstatic const int valid_e_machine[] =
331c23197a26f34f559ea9797de51e187087c039c42Torok Edwin  {
332804e0fea4033e3b91dbc8198cef30de30f141bb5Torok Edwin    EM_M32, EM_SPARC, EM_386, EM_68K, EM_88K, EM_860, EM_MIPS, EM_S370,
333825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    EM_MIPS_RS3_LE, EM_PARISC, EM_VPP500, EM_SPARC32PLUS, EM_960, EM_PPC,
334c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    EM_PPC64, EM_S390, EM_V800, EM_FR20, EM_RH32, EM_RCE, EM_ARM,
3351df221f2bb8e8380e255d1bec73ab07b388d01a2Anton Korobeynikov    EM_FAKE_ALPHA, EM_SH, EM_SPARCV9, EM_TRICORE, EM_ARC, EM_H8_300,
336c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    EM_H8_300H, EM_H8S, EM_H8_500, EM_IA_64, EM_MIPS_X, EM_COLDFIRE,
33798ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman    EM_68HC12, EM_MMA, EM_PCP, EM_NCPU, EM_NDR1, EM_STARCORE, EM_ME16,
338c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    EM_ST100, EM_TINYJ, EM_X86_64, EM_PDSP, EM_FX66, EM_ST9PLUS, EM_ST7,
339c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX,
340c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM,
341c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300,
342c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA, EM_ALPHA
343c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  };
344c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov#define nvalid_e_machine \
345c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  (sizeof (valid_e_machine) / sizeof (valid_e_machine[0]))
346c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov
347c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov
348c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov/* Number of sections.  */
349c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikovstatic unsigned int shnum;
350c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov
351c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov
35298ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohmanstatic void
353c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikovcheck_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size)
354c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov{
355c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  char buf[512];
356c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  size_t cnt;
357c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov
358c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  /* Check e_ident field.  */
359c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  if (ehdr->e_ident[EI_MAG0] != ELFMAG0)
3604437ae213d5435390f0750213b53ec807c047f22Chris Lattner    ERROR ("e_ident[%d] != '%c'\n", EI_MAG0, ELFMAG0);
361825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  if (ehdr->e_ident[EI_MAG1] != ELFMAG1)
362c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    ERROR ("e_ident[%d] != '%c'\n", EI_MAG1, ELFMAG1);
363c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  if (ehdr->e_ident[EI_MAG2] != ELFMAG2)
364c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    ERROR ("e_ident[%d] != '%c'\n", EI_MAG2, ELFMAG2);
3653f2bf85d14759cc4b28a86805f566ac805a54d00David Greene  if (ehdr->e_ident[EI_MAG3] != ELFMAG3)
366c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov    ERROR ("e_ident[%d] != '%c'\n", EI_MAG3, ELFMAG3);
367c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov
368c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  if (ehdr->e_ident[EI_CLASS] != ELFCLASS32
369825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson      && ehdr->e_ident[EI_CLASS] != ELFCLASS64)
37098ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman    ERROR (gettext ("e_ident[%d] == %d is no known class\n"),
3716553155172a2e74feff1253837daa608123de54aEvan Cheng	   EI_CLASS, ehdr->e_ident[EI_CLASS]);
372c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov
373c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB
374c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov      && ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
37598ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman    ERROR (gettext ("e_ident[%d] == %d is no known data encoding\n"),
376c8fbb6ae2041f17285e4ba73d54d388e703b9689Anton Korobeynikov	   EI_DATA, ehdr->e_ident[EI_DATA]);
377fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov
37898ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  if (ehdr->e_ident[EI_VERSION] != EV_CURRENT)
37998ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman    ERROR (gettext ("unknown ELF header version number e_ident[%d] == %d\n"),
38065c3c8f323198b99b88b109654194540cf9b3fa5Sandeep Patel	   EI_VERSION, ehdr->e_ident[EI_VERSION]);
38198ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman
38298ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  /* We currently don't handle any OS ABIs.  */
38398ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  if (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE)
384fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov    ERROR (gettext ("unsupported OS ABI e_ident[%d] == '%s'\n"),
385fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov	   EI_OSABI,
386fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov	   ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
387e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov
388e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov  /* No ABI versions other than zero supported either.  */
389e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov  if (ehdr->e_ident[EI_ABIVERSION] != 0)
390e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov    ERROR (gettext ("unsupport ABI version e_ident[%d] == %d\n"),
391e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov	   EI_ABIVERSION, ehdr->e_ident[EI_ABIVERSION]);
392e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov
393fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  for (cnt = EI_PAD; cnt < EI_NIDENT; ++cnt)
39498ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman    if (ehdr->e_ident[cnt] != 0)
39598ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman      ERROR (gettext ("e_ident[%zu] is not zero\n"), cnt);
396fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov
39798ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  /* Check the e_type field.  */
39898ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  if (ehdr->e_type != ET_REL && ehdr->e_type != ET_EXEC
399fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov      && ehdr->e_type != ET_DYN && ehdr->e_type != ET_CORE)
400fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov    ERROR (gettext ("unknown object file type %d\n"), ehdr->e_type);
401fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov
402fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  /* Check the e_machine field.  */
403fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  for (cnt = 0; cnt < nvalid_e_machine; ++cnt)
404fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov    if (valid_e_machine[cnt] == ehdr->e_machine)
405fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov      break;
406fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  if (cnt == nvalid_e_machine)
407fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov    ERROR (gettext ("unknown machine type %d\n"), ehdr->e_machine);
408fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov
409fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  /* Check the e_version field.  */
410fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  if (ehdr->e_version != EV_CURRENT)
411fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov    ERROR (gettext ("unknown object file version\n"));
412fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov
413fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  /* Check the e_phoff and e_phnum fields.  */
414fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  if (ehdr->e_phoff == 0)
415fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov    {
41698ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman      if (ehdr->e_phnum != 0)
417fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov	ERROR (gettext ("invalid program header offset\n"));
418dcb802cf7be8e540e487c699f25d89c4821536abAnton Korobeynikov      else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
419dcb802cf7be8e540e487c699f25d89c4821536abAnton Korobeynikov	ERROR (gettext ("\
420fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikovexecutables and DSOs cannot have zero program header offset\n"));
421fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov    }
422fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  else if (ehdr->e_phnum == 0)
423e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov    ERROR (gettext ("invalid number of program header entries\n"));
424e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov
425e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov  /* Check the e_shoff field.  */
426fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  shnum = ehdr->e_shnum;
427e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov  shstrndx = ehdr->e_shstrndx;
428fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov  if (ehdr->e_shoff == 0)
429fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov    {
430e662f7a8b22e7d31fb55e6502af94d49b78bc942Anton Korobeynikov      if (ehdr->e_shnum != 0)
431fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov	ERROR (gettext ("invalid section header table offset\n"));
432fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov      else if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
4334428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	       && ehdr->e_type != ET_CORE)
4344428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("section header table must be present\n"));
4354428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov    }
43698ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  else
43798ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman    {
43865c3c8f323198b99b88b109654194540cf9b3fa5Sandeep Patel      if (ehdr->e_shnum == 0)
43998ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	{
44098ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	  /* Get the header of the zeroth section.  The sh_size field
44198ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	     might contain the section number.  */
44298ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	  GElf_Shdr shdr_mem;
44398ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
44498ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	  if (shdr != NULL)
4454428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	    {
4464428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	      /* The error will be reported later.  */
44798ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	      if (shdr->sh_size == 0)
44898ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman		ERROR (gettext ("\
4494428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikovinvalid number of section header table entries\n"));
45098ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	      else
4514428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov		shnum = shdr->sh_size;
4524428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	    }
4534428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	}
4544428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
4554428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      if (ehdr->e_shstrndx == SHN_XINDEX)
4564428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	{
4574428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  /* Get the header of the zeroth section.  The sh_size field
4584428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	     might contain the section number.  */
4594428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  GElf_Shdr shdr_mem;
4604428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
4614428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  if (shdr != NULL && shdr->sh_link < shnum)
4624428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	    shstrndx = shdr->sh_link;
4634428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	}
4644428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      else if (shstrndx >= shnum)
4654428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("invalid section header index\n"));
46698ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman    }
4674428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
4684428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov  /* Check the e_flags field.  */
4694428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov  if (!ebl_machine_flag_check (ebl, ehdr->e_flags))
470c23197a26f34f559ea9797de51e187087c039c42Torok Edwin    ERROR (gettext ("invalid machine flags: %s\n"),
4714428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	   ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
4724428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
4734428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov  /* Check e_ehsize, e_phentsize, and e_shentsize fields.  */
4744428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov  if (gelf_getclass (ebl->elf) == ELFCLASS32)
4754428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov    {
4764428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf32_Ehdr))
4774428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
4784428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
4794428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr))
4804428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("invalid program header size: %hd\n"),
4814428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	       ehdr->e_phentsize);
4824428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
4834428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("invalid program header position or size\n"));
4844428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
4854428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr))
4864428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("invalid section header size: %hd\n"),
4874428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	       ehdr->e_shentsize);
4884428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
4894428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("invalid section header position or size\n"));
4904428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov    }
4914428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov  else if (gelf_getclass (ebl->elf) == ELFCLASS64)
4924428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov    {
4934428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf64_Ehdr))
4944428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
4954428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
4964428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr))
4974428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("invalid program header size: %hd\n"),
4984428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	       ehdr->e_phentsize);
4994428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
5004428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("invalid program header position or size\n"));
5014428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
5024428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr))
5034428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("invalid section header size: %hd\n"),
5044428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	       ehdr->e_shentsize);
5054428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
5064428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("invalid section header position or size\n"));
507825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    }
5084428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov}
5094428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
5104428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
5114428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov/* Check that there is a section group section with index < IDX which
5124428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov   contains section IDX and that there is exactly one.  */
5134428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikovstatic void
5144428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikovcheck_scn_group (Ebl *ebl, int idx)
5154428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov{
5164428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov  if (scnref[idx] == 0)
5174428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov    {
5184428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      /* No reference so far.  Search following sections, maybe the
5194428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	 order is wrong.  */
5204428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      size_t cnt;
5214428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
5224428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      for (cnt = idx + 1; cnt < shnum; ++cnt)
5234428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	{
524825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson	  Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
5254428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  GElf_Shdr shdr_mem;
526825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
5274428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  if (shdr == NULL)
5284428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	    /* We cannot get the section header so we cannot check it.
529825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson	       The error to get the section header will be shown
5304428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	       somewhere else.  */
5314428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	    continue;
5324428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
5334428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  if (shdr->sh_type != SHT_GROUP)
5344428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	    continue;
5354428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
5364428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  Elf_Data *data = elf_getdata (scn, NULL);
5374428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  if (data == NULL || data->d_size < sizeof (Elf32_Word))
5384428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	    /* Cannot check the section.  */
5394428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	    continue;
5404428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
5414428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  Elf32_Word *grpdata = (Elf32_Word *) data->d_buf;
5424428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	  for (size_t inner = 1; inner < data->d_size / sizeof (Elf32_Word);
5434428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	       ++inner)
5444428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	    if (grpdata[inner] == (Elf32_Word) idx)
5454428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	      goto out;
5464428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	}
5474428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
5484428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov    out:
5494428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      if (cnt == shnum)
5504428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("\
5514428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikovsection [%2d] '%s': section with SHF_GROUP flag set not part of a section group\n"),
5524428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	       idx, section_name (ebl, idx));
5534428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      else
5544428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	ERROR (gettext ("\
55598ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohmansection [%2d] '%s': section group [%2zu] '%s' does not preceed group member\n"),
55698ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	       idx, section_name (ebl, idx),
5574428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	       cnt, section_name (ebl, cnt));
5584428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov    }
55998ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman}
56098ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman
56198ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman
56298ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohmanstatic void
5634428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikovcheck_symtab (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
56465c3c8f323198b99b88b109654194540cf9b3fa5Sandeep Patel{
56598ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  bool no_xndx_warned = false;
56698ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  int no_pt_tls = 0;
56798ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
5684428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov  if (data == NULL)
5694428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov    {
5704428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
57198ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	     idx, section_name (ebl, idx));
572e922c0201916e0b980ab3cfe91e1413e68d55647Owen Anderson      return;
5734428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov    }
57498ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman
5754428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov  GElf_Shdr strshdr_mem;
5764428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
5774428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov				     &strshdr_mem);
5784428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov  if (strshdr == NULL)
5794428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov    return;
5804428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
58198ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman  if (strshdr->sh_type != SHT_STRTAB)
5824428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov    ERROR (gettext ("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
5834428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov	   shdr->sh_link, section_name (ebl, shdr->sh_link),
58498ca4f2a325f72374a477f9deba7d09e8999c29bDan Gohman	   idx, section_name (ebl, idx));
5854428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov
5864428885c5acfffbbdd03ad2aab23960531c47753Anton Korobeynikov  /* Search for an extended section index table section.  */
587d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov  Elf_Data *xndxdata = NULL;
588d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov  Elf32_Word xndxscnidx = 0;
589ea54c9846b2973cafa8ffd40626f5676ba9ccfeeAnton Korobeynikov  bool found_xndx = false;
590d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov  for (size_t cnt = 1; cnt < shnum; ++cnt)
591e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    if (cnt != (size_t) idx)
592d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov      {
593d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov	Elf_Scn *xndxscn = elf_getscn (ebl->elf, cnt);
594ea54c9846b2973cafa8ffd40626f5676ba9ccfeeAnton Korobeynikov	GElf_Shdr xndxshdr_mem;
595d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov	GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
596d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov	if (xndxshdr == NULL)
597d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov	  continue;
598d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov
599d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov	if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
600d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov	    && xndxshdr->sh_link == (GElf_Word) idx)
601d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov	  {
602d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov	    if (found_xndx)
603d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov	      ERROR (gettext ("\
604e699d0f549151a2cca993c21407aea4a6eff7d3fAnton Korobeynikovsection [%2d] '%s': symbol table cannot have more than one extended index section\n"),
605e699d0f549151a2cca993c21407aea4a6eff7d3fAnton Korobeynikov		     idx, section_name (ebl, idx));
606e699d0f549151a2cca993c21407aea4a6eff7d3fAnton Korobeynikov
607e699d0f549151a2cca993c21407aea4a6eff7d3fAnton Korobeynikov	    xndxdata = elf_getdata (xndxscn, NULL);
608bf8ef3f29de28529b5d65970af9015c41f7c809bAnton Korobeynikov	    xndxscnidx = elf_ndxscn (xndxscn);
609e699d0f549151a2cca993c21407aea4a6eff7d3fAnton Korobeynikov	    found_xndx = true;
610e699d0f549151a2cca993c21407aea4a6eff7d3fAnton Korobeynikov	  }
611e699d0f549151a2cca993c21407aea4a6eff7d3fAnton Korobeynikov      }
612d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov
613aceb620de855485a4fb2eed343d880d76f6c701cAnton Korobeynikov  if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT))
614ea54c9846b2973cafa8ffd40626f5676ba9ccfeeAnton Korobeynikov    ERROR (gettext ("\
615d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikovsection [%2u] '%s': entry size is does not match ElfXX_Sym\n"),
616d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov	   idx, section_name (ebl, idx));
617d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov
618d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov  /* Test the zeroth entry.  */
6193513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov  GElf_Sym sym_mem;
6203513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov  Elf32_Word xndx;
6213513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov  GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, 0, &sym_mem, &xndx);
6223513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov  if (sym == NULL)
6233513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov      ERROR (gettext ("section [%2d] '%s': cannot get symbol %d: %s\n"),
6243513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov	     idx, section_name (ebl, idx), 0, elf_errmsg (-1));
6253513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov  else
6263513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov    {
6273513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov      if (sym->st_name != 0)
6283513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
6295d59f68ade7573175f1ace09061a94286e59076bAnton Korobeynikov	       idx, section_name (ebl, idx), "st_name");
6305d59f68ade7573175f1ace09061a94286e59076bAnton Korobeynikov      if (sym->st_value != 0)
6315d59f68ade7573175f1ace09061a94286e59076bAnton Korobeynikov	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
6325d59f68ade7573175f1ace09061a94286e59076bAnton Korobeynikov	       idx, section_name (ebl, idx), "st_value");
6335d59f68ade7573175f1ace09061a94286e59076bAnton Korobeynikov      if (sym->st_size != 0)
6345d59f68ade7573175f1ace09061a94286e59076bAnton Korobeynikov	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
6355d59f68ade7573175f1ace09061a94286e59076bAnton Korobeynikov	       idx, section_name (ebl, idx), "st_size");
6365d59f68ade7573175f1ace09061a94286e59076bAnton Korobeynikov      if (sym->st_info != 0)
6375d59f68ade7573175f1ace09061a94286e59076bAnton Korobeynikov	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
6383926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov	       idx, section_name (ebl, idx), "st_info");
6391bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov      if (sym->st_other != 0)
6401bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
641ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	       idx, section_name (ebl, idx), "st_other");
642ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov      if (sym->st_shndx != 0)
643ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
644ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	       idx, section_name (ebl, idx), "st_shndx");
6453926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov      if (xndxdata != NULL && xndx != 0)
646ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	ERROR (gettext ("\
647c23197a26f34f559ea9797de51e187087c039c42Torok Edwinsection [%2d] '%s': XINDEX for zeroth entry not zero\n"),
648ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	       xndxscnidx, section_name (ebl, xndxscnidx));
6493926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov    }
6501722f061a3e7c2f6ef8be9f2f0f7c81ab763c7beAnton Korobeynikov
6511722f061a3e7c2f6ef8be9f2f0f7c81ab763c7beAnton Korobeynikov  for (size_t cnt = 1; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
6521722f061a3e7c2f6ef8be9f2f0f7c81ab763c7beAnton Korobeynikov    {
6531722f061a3e7c2f6ef8be9f2f0f7c81ab763c7beAnton Korobeynikov      sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx);
654ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov      if (sym == NULL)
655ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	{
6563926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov	  ERROR (gettext ("section [%2d] '%s': cannot get symbol %zu: %s\n"),
6571722f061a3e7c2f6ef8be9f2f0f7c81ab763c7beAnton Korobeynikov		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
6581722f061a3e7c2f6ef8be9f2f0f7c81ab763c7beAnton Korobeynikov	  continue;
6591722f061a3e7c2f6ef8be9f2f0f7c81ab763c7beAnton Korobeynikov	}
6601722f061a3e7c2f6ef8be9f2f0f7c81ab763c7beAnton Korobeynikov
661ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov      const char *name = NULL;
662ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov      if (sym->st_name >= strshdr->sh_size)
663ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	ERROR (gettext ("\
664ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikovsection [%2d] '%s': symbol %zu: invalid name value\n"),
6653926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov	       idx, section_name (ebl, idx), cnt);
666ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov      else
667ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	{
668ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	  name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name);
669ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	  assert (name != NULL);
6703926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov	}
671ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov
672ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov      if (sym->st_shndx == SHN_XINDEX)
673ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	{
674ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	  if (xndxdata == NULL)
6753926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov	    {
676ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	      ERROR (gettext ("\
677ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikovsection [%2d] '%s': symbol %zu: too large section index but no extended section index section\n"),
678ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov		     idx, section_name (ebl, idx), cnt);
679ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	      no_xndx_warned = true;
6803926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov	    }
681ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	  else if (xndx < SHN_LORESERVE)
682ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	    ERROR (gettext ("\
683ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikovsection [%2d] '%s': symbol %zu: XINDEX used for index which would fit in st_shndx (%" PRIu32 ")\n"),
6843926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov		   xndxscnidx, section_name (ebl, xndxscnidx), cnt,
685825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson		   xndx);
686ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	}
687ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov      else if ((sym->st_shndx >= SHN_LORESERVE
6881bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov		// && sym->st_shndx <= SHN_HIRESERVE    always true
6891bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov		&& sym->st_shndx != SHN_ABS
690ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov		&& sym->st_shndx != SHN_COMMON)
6911bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov	       || (sym->st_shndx >= shnum
6921bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov		   && (sym->st_shndx < SHN_LORESERVE
6931bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov		       /* || sym->st_shndx > SHN_HIRESERVE  always false */)))
6941bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov	ERROR (gettext ("\
6951bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikovsection [%2d] '%s': symbol %zu: invalid section index\n"),
6961bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov	       idx, section_name (ebl, idx), cnt);
6973926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov      else
6981bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov	xndx = sym->st_shndx;
6991bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov
7001bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov      if (GELF_ST_TYPE (sym->st_info) >= STT_NUM
7013926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov	  && !ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), NULL, 0))
702ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	ERROR (gettext ("section [%2d] '%s': symbol %zu: unknown type\n"),
703ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov	       idx, section_name (ebl, idx), cnt);
7041bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov
7051bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov      if (GELF_ST_BIND (sym->st_info) >= STB_NUM)
7061bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov	ERROR (gettext ("\
7071bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikovsection [%2d] '%s': symbol %zu: unknown symbol binding\n"),
7081bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov	       idx, section_name (ebl, idx), cnt);
7091bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov
7108b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov      if (xndx == SHN_COMMON)
7111bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov	{
7123926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikov	  /* Common symbols can only appear in relocatable files.  */
7131bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov	  if (ehdr->e_type != ET_REL)
7148b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	    ERROR (gettext ("\
715825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonsection [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n"),
7168b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		   idx, section_name (ebl, idx), cnt);
7178b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	  if (cnt < shdr->sh_info)
7188b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	    ERROR (gettext ("\
7193926fb63c24ceeefc0215b8e14eb81c85403639eAnton Korobeynikovsection [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n"),
7201bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov		   idx, section_name (ebl, idx), cnt);
7218b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	  if (GELF_R_TYPE (sym->st_info) == STT_FUNC)
7221bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov	    ERROR (gettext ("\
7238b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikovsection [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"),
7248b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		   idx, section_name (ebl, idx), cnt);
725b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov	}
726b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov      else if (xndx > 0 && xndx < shnum)
727b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov	{
728e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson	  GElf_Shdr destshdr_mem;
729b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov	  GElf_Shdr *destshdr;
730b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov
731825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson	  destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), &destshdr_mem);
732b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov	  if (destshdr != NULL)
733b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov	    {
734b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov	      GElf_Addr sh_addr = (ehdr->e_type == ET_REL ? 0
735b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov				   : destshdr->sh_addr);
736b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov	      if (GELF_ST_TYPE (sym->st_info) != STT_TLS)
737b78e214274d397407b6167a293b7cd7c3b526ddeAnton Korobeynikov		{
73806ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		  if (! ebl_check_special_symbol (ebl, ehdr, sym, name,
73906ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov						  destshdr))
74006ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		    {
74106ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		      if (sym->st_value - sh_addr > destshdr->sh_size)
74206ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			{
74306ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			  /* GNU ld has severe bugs.  When it decides to remove
74406ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			     empty sections it leaves symbols referencing them
74506ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			     behind.  These are symbols in .symtab.  */
74606ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			  if (!gnuld
74706ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			      || strcmp (section_name (ebl, idx), ".symtab")
74806ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			      || (strcmp (name, "__preinit_array_start") != 0
74906ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov				  && strcmp (name, "__preinit_array_end") != 0
75006ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov				  && strcmp (name, "__init_array_start") != 0
75106ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov				  && strcmp (name, "__init_array_end") != 0
75206ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov				  && strcmp (name, "__fini_array_start") != 0
75306ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov				  && strcmp (name, "__fini_array_end") != 0))
75406ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			    ERROR (gettext ("\
75506ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikovsection [%2d] '%s': symbol %zu: st_value out of bounds\n"),
75606ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov				   idx, section_name (ebl, idx), cnt);
75706ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			}
75806ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		      else if ((sym->st_value - sh_addr
75906ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov				+ sym->st_size) > destshdr->sh_size)
76006ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			ERROR (gettext ("\
76106ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikovsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
76206ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			       idx, section_name (ebl, idx), cnt,
76306ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			       (int) xndx, section_name (ebl, xndx));
76406ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		    }
76506ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		}
76606ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov	      else
76706ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		{
76806ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		  if ((destshdr->sh_flags & SHF_TLS) == 0)
76906ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		    ERROR (gettext ("\
77006ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikovsection [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_TLS flag set\n"),
77106ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			   idx, section_name (ebl, idx), cnt,
77206ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			   (int) xndx, section_name (ebl, xndx));
77306ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov
77406ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		  if (ehdr->e_type == ET_REL)
77506ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		    {
77606ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		      /* For object files the symbol value must fall
77706ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov                         into the section.  */
77806ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		      if (sym->st_value > destshdr->sh_size)
77906ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			ERROR (gettext ("\
78006ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikovsection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
78106ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			       idx, section_name (ebl, idx), cnt,
78206ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			       (int) xndx, section_name (ebl, xndx));
78306ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov		      else if (sym->st_value + sym->st_size
78406ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			       > destshdr->sh_size)
78506ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikov			ERROR (gettext ("\
78606ccca5f70ef5f9c3e4add60b6fc842916705029Anton Korobeynikovsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
7876534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			       idx, section_name (ebl, idx), cnt,
7886534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			       (int) xndx, section_name (ebl, xndx));
7896534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov		    }
7906534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov		  else
7916534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov		    {
7926534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov		      GElf_Phdr phdr_mem;
7936534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov		      GElf_Phdr *phdr = NULL;
7946534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov		      int pcnt;
7956534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov
7966534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov		      for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
7976534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			{
7986534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			  phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
7996534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			  if (phdr != NULL && phdr->p_type == PT_TLS)
8006534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			    break;
8016534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			}
8026534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov
8036534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov		      if (pcnt == ehdr->e_phnum)
8046534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			{
8056534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			  if (no_pt_tls++ == 0)
8066534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			    ERROR (gettext ("\
8076534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikovsection [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"),
8086534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov				   idx, section_name (ebl, idx), cnt);
8096534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			}
8106534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov		      else
8116534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			{
8126534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			  if (sym->st_value
8136534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			      < destshdr->sh_offset - phdr->p_offset)
8146534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			    ERROR (gettext ("\
8156534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikovsection [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"),
8166534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov				   idx, section_name (ebl, idx), cnt,
8176534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov				   (int) xndx, section_name (ebl, xndx));
8186534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			  else if (sym->st_value
8196534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov				   > (destshdr->sh_offset - phdr->p_offset
8206534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov				      + destshdr->sh_size))
8216534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikov			    ERROR (gettext ("\
8226534f83ae8c39284ae51fbf478ce0c37d0c892a2Anton Korobeynikovsection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
823fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov				   idx, section_name (ebl, idx), cnt,
824fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov				   (int) xndx, section_name (ebl, xndx));
825fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov			  else if (sym->st_value + sym->st_size
826fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov				   > (destshdr->sh_offset - phdr->p_offset
827d2c94ae49e546e68b591e838cdfc2fd016d928d9Anton Korobeynikov				      + destshdr->sh_size))
828e699d0f549151a2cca993c21407aea4a6eff7d3fAnton Korobeynikov			    ERROR (gettext ("\
829e699d0f549151a2cca993c21407aea4a6eff7d3fAnton Korobeynikovsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
830b561264d2b2e33e1e6322a99d600b5daece5bbdeAnton Korobeynikov				   idx, section_name (ebl, idx), cnt,
8313513ca81c6beda087a281a66f1b0e612879c0aadAnton Korobeynikov				   (int) xndx, section_name (ebl, xndx));
8321bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov			}
833ed1a51af376b9027db60ff060e0a2572493df07bAnton Korobeynikov		    }
8341bb8cd723d9fc89701fd3e54951c6bb419f798d3Anton Korobeynikov		}
835fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov	    }
836fd1b7c778c0c332a676b1003115d2b4bc6f9a46aAnton Korobeynikov	}
8378b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov
8388b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov      if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
8398b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	{
8408b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	  if (cnt >= shdr->sh_info)
8418b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	    ERROR (gettext ("\
8428b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikovsection [%2d] '%s': symbol %zu: local symbol outside range described in sh_info\n"),
8438b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		   idx, section_name (ebl, idx), cnt);
844fb2e752e4175920d0531f2afc93a23d0cdf4db14Evan Cheng	}
845fb2e752e4175920d0531f2afc93a23d0cdf4db14Evan Cheng      else
8468b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	{
8478b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	  if (cnt < shdr->sh_info)
848da4d2f63d8b138569ec732d970bb452a0403a3abAnton Korobeynikov	    ERROR (gettext ("\
849da4d2f63d8b138569ec732d970bb452a0403a3abAnton Korobeynikovsection [%2d] '%s': symbol %zu: non-local symbol outside range described in sh_info\n"),
8508b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		   idx, section_name (ebl, idx), cnt);
8518b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	}
8528b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov
8538b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov      if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
8548b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	  && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
8558b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	ERROR (gettext ("\
8568b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikovsection [%2d] '%s': symbol %zu: non-local section symbol\n"),
8578b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	       idx, section_name (ebl, idx), cnt);
8588b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov
8598b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov      if (name != NULL)
8608b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	{
8618b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
8628b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	    {
8638b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	      /* Check that address and size match the global offset table.  */
8648b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov
8658b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	      GElf_Shdr destshdr_mem;
8668b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	      GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx),
8678b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov						  &destshdr_mem);
8688b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov
8698b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	      if (destshdr == NULL && xndx == SHN_ABS)
8708b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		{
8718b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		  /* In a DSO, we have to find the GOT section by name.  */
8728b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		  Elf_Scn *gotscn = NULL;
8738b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		  Elf_Scn *gscn = NULL;
8748b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		  while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL)
875ce31910eae5bd4896fa6c27798e7b26885691d3bEvan Cheng		    {
876ce31910eae5bd4896fa6c27798e7b26885691d3bEvan Cheng		      destshdr = gelf_getshdr (gscn, &destshdr_mem);
877ce31910eae5bd4896fa6c27798e7b26885691d3bEvan Cheng		      assert (destshdr != NULL);
878ce31910eae5bd4896fa6c27798e7b26885691d3bEvan Cheng		      const char *sname = elf_strptr (ebl->elf,
8798b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov						      ehdr->e_shstrndx,
8808b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov						      destshdr->sh_name);
8818b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		      if (sname != NULL)
8828b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov			{
8838b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov			  if (strcmp (sname, ".got.plt") == 0)
8848b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov			    break;
8858b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov			  if (strcmp (sname, ".got") == 0)
8868b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov			    /* Do not stop looking.
8878b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov			       There might be a .got.plt section.  */
8888b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov			    gotscn = gscn;
8898b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov			}
8908b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov
8918b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		      destshdr = NULL;
8928b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		    }
8938b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov
8948b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		  if (destshdr == NULL && gotscn != NULL)
8958b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		    destshdr = gelf_getshdr (gotscn, &destshdr_mem);
8968b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		}
8978b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov
8988b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	      const char *sname = ((destshdr == NULL || xndx == SHN_UNDEF)
8998b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov				   ? NULL
9008b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov				   : elf_strptr (ebl->elf, ehdr->e_shstrndx,
9018b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov						 destshdr->sh_name));
9028b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov	      if (sname == NULL)
9038b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		{
9048b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		  if (xndx != SHN_UNDEF || ehdr->e_type != ET_REL)
9058b528e52ee6018b0d0e7e46b3b4cf6f41fdaa0d9Anton Korobeynikov		    ERROR (gettext ("\
906section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
907bad section [%2d]\n"),
908			   idx, section_name (ebl, idx), xndx);
909		}
910	      else if (strcmp (sname, ".got.plt") != 0
911		       && strcmp (sname, ".got") != 0)
912		ERROR (gettext ("\
913section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
914section [%2d] '%s'\n"),
915		       idx, section_name (ebl, idx), xndx, sname);
916
917	      if (destshdr != NULL)
918		{
919		  /* Found it.  */
920		  if (!ebl_check_special_symbol (ebl, ehdr, sym, name,
921						 destshdr))
922		    {
923		      if (ehdr->e_type != ET_REL
924			  && sym->st_value != destshdr->sh_addr)
925			/* This test is more strict than the psABIs which
926			   usually allow the symbol to be in the middle of
927			   the .got section, allowing negative offsets.  */
928			ERROR (gettext ("\
929section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match %s section address %#" PRIx64 "\n"),
930			       idx, section_name (ebl, idx),
931			       (uint64_t) sym->st_value,
932			       sname, (uint64_t) destshdr->sh_addr);
933
934		      if (!gnuld && sym->st_size != destshdr->sh_size)
935			ERROR (gettext ("\
936section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match %s section size %" PRIu64 "\n"),
937			       idx, section_name (ebl, idx),
938			       (uint64_t) sym->st_size,
939			       sname, (uint64_t) destshdr->sh_size);
940		    }
941		}
942	      else
943		ERROR (gettext ("\
944section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"),
945		       idx, section_name (ebl, idx));
946	    }
947	  else if (strcmp (name, "_DYNAMIC") == 0)
948	    /* Check that address and size match the dynamic section.
949	       We locate the dynamic section via the program header
950	       entry.  */
951	    for (int pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
952	      {
953		GElf_Phdr phdr_mem;
954		GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
955
956		if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
957		  {
958		    if (sym->st_value != phdr->p_vaddr)
959		      ERROR (gettext ("\
960section [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"),
961			     idx, section_name (ebl, idx),
962			     (uint64_t) sym->st_value,
963			     (uint64_t) phdr->p_vaddr);
964
965		    if (!gnuld && sym->st_size != phdr->p_memsz)
966		      ERROR (gettext ("\
967section [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"),
968			     idx, section_name (ebl, idx),
969			     (uint64_t) sym->st_size,
970			     (uint64_t) phdr->p_memsz);
971
972		    break;
973		  }
974	    }
975	}
976    }
977}
978
979
980static bool
981is_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr,
982	    bool is_rela)
983{
984  /* If this is no executable or DSO it cannot be a .rel.dyn section.  */
985  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
986    return false;
987
988  /* Check the section name.  Unfortunately necessary.  */
989  if (strcmp (section_name (ebl, idx), is_rela ? ".rela.dyn" : ".rel.dyn"))
990    return false;
991
992  /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section
993     entry can be present as well.  */
994  Elf_Scn *scn = NULL;
995  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
996    {
997      GElf_Shdr rcshdr_mem;
998      const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem);
999      assert (rcshdr != NULL);
1000
1001      if (rcshdr->sh_type == SHT_DYNAMIC)
1002	{
1003	  /* Found the dynamic section.  Look through it.  */
1004	  Elf_Data *d = elf_getdata (scn, NULL);
1005	  size_t cnt;
1006
1007	  for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt)
1008	    {
1009	      GElf_Dyn dyn_mem;
1010	      GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem);
1011	      assert (dyn != NULL);
1012
1013	      if (dyn->d_tag == DT_RELCOUNT)
1014		{
1015		  /* Found it.  Does the type match.  */
1016		  if (is_rela)
1017		    ERROR (gettext ("\
1018section [%2d] '%s': DT_RELCOUNT used for this RELA section\n"),
1019			   idx, section_name (ebl, idx));
1020		  else
1021		    {
1022		      /* Does the number specified number of relative
1023			 relocations exceed the total number of
1024			 relocations?  */
1025		      if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
1026			ERROR (gettext ("\
1027section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
1028			       idx, section_name (ebl, idx),
1029			       (int) dyn->d_un.d_val);
1030
1031		      /* Make sure the specified number of relocations are
1032			 relative.  */
1033		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
1034								   idx), NULL);
1035		      if (reldata != NULL)
1036			for (size_t inner = 0;
1037			     inner < shdr->sh_size / shdr->sh_entsize;
1038			     ++inner)
1039			  {
1040			    GElf_Rel rel_mem;
1041			    GElf_Rel *rel = gelf_getrel (reldata, inner,
1042							 &rel_mem);
1043			    if (rel == NULL)
1044			      /* The problem will be reported elsewhere.  */
1045			      break;
1046
1047			    if (ebl_relative_reloc_p (ebl,
1048						      GELF_R_TYPE (rel->r_info)))
1049			      {
1050				if (inner >= dyn->d_un.d_val)
1051				  ERROR (gettext ("\
1052section [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
1053					 idx, section_name (ebl, idx),
1054					 (int) dyn->d_un.d_val);
1055			      }
1056			    else if (inner < dyn->d_un.d_val)
1057			      ERROR (gettext ("\
1058section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
1059				     idx, section_name (ebl, idx),
1060				     inner, (int) dyn->d_un.d_val);
1061			  }
1062		    }
1063		}
1064
1065	      if (dyn->d_tag == DT_RELACOUNT)
1066		{
1067		  /* Found it.  Does the type match.  */
1068		  if (!is_rela)
1069		    ERROR (gettext ("\
1070section [%2d] '%s': DT_RELACOUNT used for this REL section\n"),
1071			   idx, section_name (ebl, idx));
1072		  else
1073		    {
1074		      /* Does the number specified number of relative
1075			 relocations exceed the total number of
1076			 relocations?  */
1077		      if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
1078			ERROR (gettext ("\
1079section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
1080			       idx, section_name (ebl, idx),
1081			       (int) dyn->d_un.d_val);
1082
1083		      /* Make sure the specified number of relocations are
1084			 relative.  */
1085		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
1086								   idx), NULL);
1087		      if (reldata != NULL)
1088			for (size_t inner = 0;
1089			     inner < shdr->sh_size / shdr->sh_entsize;
1090			     ++inner)
1091			  {
1092			    GElf_Rela rela_mem;
1093			    GElf_Rela *rela = gelf_getrela (reldata, inner,
1094							    &rela_mem);
1095			    if (rela == NULL)
1096			      /* The problem will be reported elsewhere.  */
1097			      break;
1098
1099			    if (ebl_relative_reloc_p (ebl,
1100						      GELF_R_TYPE (rela->r_info)))
1101			      {
1102				if (inner >= dyn->d_un.d_val)
1103				  ERROR (gettext ("\
1104section [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
1105					 idx, section_name (ebl, idx),
1106					 (int) dyn->d_un.d_val);
1107			      }
1108			    else if (inner < dyn->d_un.d_val)
1109			      ERROR (gettext ("\
1110section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
1111				     idx, section_name (ebl, idx),
1112				     inner, (int) dyn->d_un.d_val);
1113			  }
1114		    }
1115		}
1116	    }
1117
1118	  break;
1119	}
1120    }
1121
1122  return true;
1123}
1124
1125
1126struct loaded_segment
1127{
1128  GElf_Addr from;
1129  GElf_Addr to;
1130  bool read_only;
1131  struct loaded_segment *next;
1132};
1133
1134
1135/* Check whether binary has text relocation flag set.  */
1136static bool textrel;
1137
1138/* Keep track of whether text relocation flag is needed.  */
1139static bool needed_textrel;
1140
1141
1142static bool
1143check_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr,
1144		  int idx, int reltype, GElf_Shdr **destshdrp,
1145		  GElf_Shdr *destshdr_memp, struct loaded_segment **loadedp)
1146{
1147  bool reldyn = false;
1148
1149  /* Check whether the link to the section we relocate is reasonable.  */
1150  if (shdr->sh_info >= shnum)
1151    ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"),
1152	   idx, section_name (ebl, idx));
1153  else if (shdr->sh_info != 0)
1154    {
1155      *destshdrp = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1156				 destshdr_memp);
1157      if (*destshdrp != NULL)
1158	{
1159	  if((*destshdrp)->sh_type != SHT_PROGBITS
1160	     && (*destshdrp)->sh_type != SHT_NOBITS)
1161	    {
1162	      reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true);
1163	      if (!reldyn)
1164		ERROR (gettext ("\
1165section [%2d] '%s': invalid destination section type\n"),
1166		       idx, section_name (ebl, idx));
1167	      else
1168		{
1169		  /* There is no standard, but we require that .rel{,a}.dyn
1170		     sections have a sh_info value of zero.  */
1171		  if (shdr->sh_info != 0)
1172		    ERROR (gettext ("\
1173section [%2d] '%s': sh_info should be zero\n"),
1174			   idx, section_name (ebl, idx));
1175		}
1176	    }
1177
1178	  if (((*destshdrp)->sh_flags & (SHF_MERGE | SHF_STRINGS)) != 0)
1179	    ERROR (gettext ("\
1180section [%2d] '%s': no relocations for merge-able sections possible\n"),
1181		   idx, section_name (ebl, idx));
1182	}
1183    }
1184
1185  if (shdr->sh_entsize != gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT))
1186    ERROR (gettext (reltype == ELF_T_RELA ? "\
1187section [%2d] '%s': section entry size does not match ElfXX_Rela\n" : "\
1188section [%2d] '%s': section entry size does not match ElfXX_Rel\n"),
1189	   idx, section_name (ebl, idx));
1190
1191  /* In preparation of checking whether relocations are text
1192     relocations or not we need to determine whether the file is
1193     flagged to have text relocation and we need to determine a) what
1194     the loaded segments are and b) which are read-only.  This will
1195     also allow us to determine whether the same reloc section is
1196     modifying loaded and not loaded segments.  */
1197  for (int i = 0; i < ehdr->e_phnum; ++i)
1198    {
1199      GElf_Phdr phdr_mem;
1200      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
1201      if (phdr == NULL)
1202	continue;
1203
1204      if (phdr->p_type == PT_LOAD)
1205	{
1206	  struct loaded_segment *newp = xmalloc (sizeof (*newp));
1207	  newp->from = phdr->p_vaddr;
1208	  newp->to = phdr->p_vaddr + phdr->p_memsz;
1209	  newp->read_only = (phdr->p_flags & PF_W) == 0;
1210	  newp->next = *loadedp;
1211	  *loadedp = newp;
1212	}
1213      else if (phdr->p_type == PT_DYNAMIC)
1214	{
1215	  Elf_Scn *dynscn = gelf_offscn (ebl->elf, phdr->p_offset);
1216	  GElf_Shdr dynshdr_mem;
1217	  GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem);
1218	  Elf_Data *dyndata = elf_getdata (dynscn, NULL);
1219	  if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC
1220	      && dyndata != NULL)
1221	    for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j)
1222	      {
1223		GElf_Dyn dyn_mem;
1224		GElf_Dyn *dyn = gelf_getdyn (dyndata, j, &dyn_mem);
1225		if (dyn != NULL
1226		    && (dyn->d_tag == DT_TEXTREL
1227			|| (dyn->d_tag == DT_FLAGS
1228			    && (dyn->d_un.d_val & DF_TEXTREL) != 0)))
1229		  {
1230		    textrel = true;
1231		    break;
1232		  }
1233	      }
1234	}
1235    }
1236
1237  /* A quick test which can be easily done here (although it is a bit
1238     out of place): the text relocation flag makes only sense if there
1239     is a segment which is not writable.  */
1240  if (textrel)
1241    {
1242      struct loaded_segment *seg = *loadedp;
1243      while (seg != NULL && !seg->read_only)
1244	seg = seg->next;
1245      if (seg == NULL)
1246	ERROR (gettext ("\
1247text relocation flag set but there is no read-only segment\n"));
1248    }
1249
1250  return reldyn;
1251}
1252
1253
1254enum load_state
1255  {
1256    state_undecided,
1257    state_loaded,
1258    state_unloaded,
1259    state_error
1260  };
1261
1262
1263static void
1264check_one_reloc (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *relshdr, int idx,
1265		 size_t cnt, const GElf_Shdr *symshdr, Elf_Data *symdata,
1266		 GElf_Addr r_offset, GElf_Xword r_info,
1267		 const GElf_Shdr *destshdr, bool reldyn,
1268		 struct loaded_segment *loaded, enum load_state *statep)
1269{
1270  bool known_broken = gnuld;
1271
1272  if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (r_info)))
1273    ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"),
1274	   idx, section_name (ebl, idx), cnt);
1275  else if (((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1276	    /* The executable/DSO can contain relocation sections with
1277	       all the relocations the linker has applied.  Those sections
1278	       are marked non-loaded, though.  */
1279	    || (relshdr->sh_flags & SHF_ALLOC) != 0)
1280	   && !ebl_reloc_valid_use (ebl, GELF_R_TYPE (r_info)))
1281    ERROR (gettext ("\
1282section [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
1283	   idx, section_name (ebl, idx), cnt);
1284
1285  if (symshdr != NULL
1286      && ((GELF_R_SYM (r_info) + 1)
1287	  * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
1288	  > symshdr->sh_size))
1289    ERROR (gettext ("\
1290section [%2d] '%s': relocation %zu: invalid symbol index\n"),
1291	   idx, section_name (ebl, idx), cnt);
1292
1293  /* No more tests if this is a no-op relocation.  */
1294  if (ebl_none_reloc_p (ebl, GELF_R_TYPE (r_info)))
1295    return;
1296
1297  if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (r_info)))
1298    {
1299      const char *name;
1300      char buf[64];
1301      GElf_Sym sym_mem;
1302      GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
1303      if (sym != NULL
1304	  /* Get the name for the symbol.  */
1305	  && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1306	  && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
1307	ERROR (gettext ("\
1308section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
1309	       idx, section_name (ebl, idx), cnt,
1310	       ebl_reloc_type_name (ebl, GELF_R_SYM (r_info),
1311				    buf, sizeof (buf)));
1312    }
1313
1314  if (reldyn)
1315    {
1316      // XXX TODO Check .rel.dyn section addresses.
1317    }
1318  else if (!known_broken)
1319    {
1320      if (destshdr != NULL
1321	  && GELF_R_TYPE (r_info) != 0
1322	  && (r_offset - (ehdr->e_type == ET_REL ? 0
1323			  : destshdr->sh_addr)) >= destshdr->sh_size)
1324	ERROR (gettext ("\
1325section [%2d] '%s': relocation %zu: offset out of bounds\n"),
1326	       idx, section_name (ebl, idx), cnt);
1327    }
1328
1329  GElf_Sym sym_mem;
1330  GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
1331
1332  if (ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info))
1333      /* Make sure the referenced symbol is an object or unspecified.  */
1334      && sym != NULL
1335      && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE
1336      && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
1337    {
1338      char buf[64];
1339      ERROR (gettext ("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"),
1340	     idx, section_name (ebl, idx), cnt,
1341	     ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
1342				   buf, sizeof (buf)));
1343    }
1344
1345  if ((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1346      || (relshdr->sh_flags & SHF_ALLOC) != 0)
1347    {
1348      bool in_loaded_seg = false;
1349      while (loaded != NULL)
1350	{
1351	  if (r_offset < loaded->to
1352	      && r_offset + (sym == NULL ? 0 : sym->st_size) >= loaded->from)
1353	    {
1354	      /* The symbol is in this segment.  */
1355	      if  (loaded->read_only)
1356		{
1357		  if (textrel)
1358		    needed_textrel = true;
1359		  else
1360		    ERROR (gettext ("section [%2d] '%s': relocation %zu: read-only section modified but text relocation flag not set\n"),
1361			   idx, section_name (ebl, idx), cnt);
1362		}
1363
1364	      in_loaded_seg = true;
1365	    }
1366
1367	  loaded = loaded->next;
1368	}
1369
1370      if (*statep == state_undecided)
1371	*statep = in_loaded_seg ? state_loaded : state_unloaded;
1372      else if ((*statep == state_unloaded && in_loaded_seg)
1373	       || (*statep == state_loaded && !in_loaded_seg))
1374	{
1375	  ERROR (gettext ("\
1376section [%2d] '%s': relocations are against loaded and unloaded data\n"),
1377		 idx, section_name (ebl, idx));
1378	  *statep = state_error;
1379	}
1380    }
1381}
1382
1383
1384static void
1385check_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1386{
1387  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1388  if (data == NULL)
1389    {
1390      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1391	     idx, section_name (ebl, idx));
1392      return;
1393    }
1394
1395  /* Check the fields of the section header.  */
1396  GElf_Shdr destshdr_mem;
1397  GElf_Shdr *destshdr = NULL;
1398  struct loaded_segment *loaded = NULL;
1399  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELA, &destshdr,
1400				  &destshdr_mem, &loaded);
1401
1402  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1403  GElf_Shdr symshdr_mem;
1404  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1405  Elf_Data *symdata = elf_getdata (symscn, NULL);
1406  enum load_state state = state_undecided;
1407
1408  for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1409    {
1410      GElf_Rela rela_mem;
1411      GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem);
1412      if (rela == NULL)
1413	{
1414	  ERROR (gettext ("\
1415section [%2d] '%s': cannot get relocation %zu: %s\n"),
1416		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1417	  continue;
1418	}
1419
1420      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1421		       rela->r_offset, rela->r_info, destshdr, reldyn, loaded,
1422		       &state);
1423    }
1424
1425  while (loaded != NULL)
1426    {
1427      struct loaded_segment *old = loaded;
1428      loaded = loaded->next;
1429      free (old);
1430    }
1431}
1432
1433
1434static void
1435check_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1436{
1437  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1438  if (data == NULL)
1439    {
1440      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1441	     idx, section_name (ebl, idx));
1442      return;
1443    }
1444
1445  /* Check the fields of the section header.  */
1446  GElf_Shdr destshdr_mem;
1447  GElf_Shdr *destshdr = NULL;
1448  struct loaded_segment *loaded = NULL;
1449  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_REL, &destshdr,
1450				  &destshdr_mem, &loaded);
1451
1452  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1453  GElf_Shdr symshdr_mem;
1454  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1455  Elf_Data *symdata = elf_getdata (symscn, NULL);
1456  enum load_state state = state_undecided;
1457
1458  for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1459    {
1460      GElf_Rel rel_mem;
1461      GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem);
1462      if (rel == NULL)
1463	{
1464	  ERROR (gettext ("\
1465section [%2d] '%s': cannot get relocation %zu: %s\n"),
1466		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1467	  continue;
1468	}
1469
1470      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
1471		       rel->r_offset, rel->r_info, destshdr, reldyn, loaded,
1472		       &state);
1473    }
1474
1475  while (loaded != NULL)
1476    {
1477      struct loaded_segment *old = loaded;
1478      loaded = loaded->next;
1479      free (old);
1480    }
1481}
1482
1483
1484/* Number of dynamic sections.  */
1485static int ndynamic;
1486
1487
1488static void
1489check_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1490{
1491  Elf_Data *data;
1492  GElf_Shdr strshdr_mem;
1493  GElf_Shdr *strshdr;
1494  size_t cnt;
1495  static const bool dependencies[DT_NUM][DT_NUM] =
1496    {
1497      [DT_NEEDED] = { [DT_STRTAB] = true },
1498      [DT_PLTRELSZ] = { [DT_JMPREL] = true },
1499      [DT_HASH] = { [DT_SYMTAB] = true },
1500      [DT_STRTAB] = { [DT_STRSZ] = true },
1501      [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_SYMENT] = true },
1502      [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true },
1503      [DT_RELASZ] = { [DT_RELA] = true },
1504      [DT_RELAENT] = { [DT_RELA] = true },
1505      [DT_STRSZ] = { [DT_STRTAB] = true },
1506      [DT_SYMENT] = { [DT_SYMTAB] = true },
1507      [DT_SONAME] = { [DT_STRTAB] = true },
1508      [DT_RPATH] = { [DT_STRTAB] = true },
1509      [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true },
1510      [DT_RELSZ] = { [DT_REL] = true },
1511      [DT_RELENT] = { [DT_REL] = true },
1512      [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true },
1513      [DT_RUNPATH] = { [DT_STRTAB] = true },
1514      [DT_PLTREL] = { [DT_JMPREL] = true },
1515    };
1516  bool has_dt[DT_NUM];
1517  bool has_val_dt[DT_VALNUM];
1518  bool has_addr_dt[DT_ADDRNUM];
1519  static const bool level2[DT_NUM] =
1520    {
1521      [DT_RPATH] = true,
1522      [DT_SYMBOLIC] = true,
1523      [DT_TEXTREL] = true,
1524      [DT_BIND_NOW] = true
1525    };
1526  static const bool mandatory[DT_NUM] =
1527    {
1528      [DT_NULL] = true,
1529      [DT_STRTAB] = true,
1530      [DT_SYMTAB] = true,
1531      [DT_STRSZ] = true,
1532      [DT_SYMENT] = true
1533    };
1534  GElf_Addr reladdr = 0;
1535  GElf_Word relsz = 0;
1536  GElf_Addr pltreladdr = 0;
1537  GElf_Word pltrelsz = 0;
1538
1539  memset (has_dt, '\0', sizeof (has_dt));
1540  memset (has_val_dt, '\0', sizeof (has_val_dt));
1541  memset (has_addr_dt, '\0', sizeof (has_addr_dt));
1542
1543  if (++ndynamic == 2)
1544    ERROR (gettext ("more than one dynamic section present\n"));
1545
1546  data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1547  if (data == NULL)
1548    {
1549      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1550	     idx, section_name (ebl, idx));
1551      return;
1552    }
1553
1554  strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem);
1555  if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB)
1556    ERROR (gettext ("\
1557section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
1558	   shdr->sh_link, section_name (ebl, shdr->sh_link),
1559	   idx, section_name (ebl, idx));
1560
1561  if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT))
1562    ERROR (gettext ("\
1563section [%2d] '%s': section entry size does not match ElfXX_Dyn\n"),
1564	   idx, section_name (ebl, idx));
1565
1566  if (shdr->sh_info != 0)
1567    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1568	   idx, section_name (ebl, idx));
1569
1570  bool non_null_warned = false;
1571  for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1572    {
1573      GElf_Dyn dyn_mem;
1574      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dyn_mem);
1575      if (dyn == NULL)
1576	{
1577	  ERROR (gettext ("\
1578section [%2d] '%s': cannot get dynamic section entry %zu: %s\n"),
1579		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
1580	  continue;
1581	}
1582
1583      if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned)
1584	{
1585	  ERROR (gettext ("\
1586section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"),
1587		 idx, section_name (ebl, idx));
1588	  non_null_warned = true;
1589	}
1590
1591      if (!ebl_dynamic_tag_check (ebl, dyn->d_tag))
1592	ERROR (gettext ("section [%2d] '%s': entry %zu: unknown tag\n"),
1593	       idx, section_name (ebl, idx), cnt);
1594
1595      if (dyn->d_tag >= 0 && dyn->d_tag < DT_NUM)
1596	{
1597	  if (has_dt[dyn->d_tag]
1598	      && dyn->d_tag != DT_NEEDED
1599	      && dyn->d_tag != DT_NULL
1600	      && dyn->d_tag != DT_POSFLAG_1)
1601	    {
1602	      char buf[50];
1603	      ERROR (gettext ("\
1604section [%2d] '%s': entry %zu: more than one entry with tag %s\n"),
1605		     idx, section_name (ebl, idx), cnt,
1606		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1607					   buf, sizeof (buf)));
1608	    }
1609
1610	  if (be_strict && level2[dyn->d_tag])
1611	    {
1612	      char buf[50];
1613	      ERROR (gettext ("\
1614section [%2d] '%s': entry %zu: level 2 tag %s used\n"),
1615		     idx, section_name (ebl, idx), cnt,
1616		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1617					   buf, sizeof (buf)));
1618	    }
1619
1620	  has_dt[dyn->d_tag] = true;
1621	}
1622      else if (dyn->d_tag <= DT_VALRNGHI
1623	       && DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
1624	has_val_dt[DT_VALTAGIDX (dyn->d_tag)] = true;
1625      else if (dyn->d_tag <= DT_ADDRRNGHI
1626	       && DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
1627	has_addr_dt[DT_ADDRTAGIDX (dyn->d_tag)] = true;
1628
1629      if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL
1630	  && dyn->d_un.d_val != DT_RELA)
1631	ERROR (gettext ("\
1632section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"),
1633	       idx, section_name (ebl, idx), cnt);
1634
1635      if (dyn->d_tag == DT_REL)
1636	reladdr = dyn->d_un.d_ptr;
1637      if (dyn->d_tag == DT_RELSZ)
1638	relsz = dyn->d_un.d_val;
1639      if (dyn->d_tag == DT_JMPREL)
1640	pltreladdr = dyn->d_un.d_ptr;
1641      if (dyn->d_tag == DT_PLTRELSZ)
1642	pltrelsz = dyn->d_un.d_val;
1643
1644      /* Check that addresses for entries are in loaded segments.  */
1645      switch (dyn->d_tag)
1646	{
1647	  size_t n;
1648	case DT_STRTAB:
1649	  /* We require the referenced section is the same as the one
1650	     specified in sh_link.  */
1651	  if (strshdr->sh_addr != dyn->d_un.d_val)
1652	    {
1653	      ERROR (gettext ("\
1654section [%2d] '%s': entry %zu: pointer does not match address of section [%2d] '%s' referenced by sh_link\n"),
1655		     idx, section_name (ebl, idx), cnt,
1656		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1657	      break;
1658	    }
1659	  goto check_addr;
1660
1661	default:
1662	  if (dyn->d_tag < DT_ADDRRNGLO || dyn->d_tag > DT_ADDRRNGHI)
1663	    /* Value is no pointer.  */
1664	    break;
1665	  /* FALLTHROUGH */
1666
1667	case DT_AUXILIARY:
1668	case DT_FILTER:
1669	case DT_FINI:
1670	case DT_FINI_ARRAY:
1671	case DT_HASH:
1672	case DT_INIT:
1673	case DT_INIT_ARRAY:
1674	case DT_JMPREL:
1675	case DT_PLTGOT:
1676	case DT_REL:
1677	case DT_RELA:
1678	case DT_SYMBOLIC:
1679	case DT_SYMTAB:
1680	case DT_VERDEF:
1681	case DT_VERNEED:
1682	case DT_VERSYM:
1683	check_addr:
1684	  for (n = 0; n < ehdr->e_phnum; ++n)
1685	    {
1686	      GElf_Phdr phdr_mem;
1687	      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, n, &phdr_mem);
1688	      if (phdr != NULL && phdr->p_type == PT_LOAD
1689		  && phdr->p_vaddr <= dyn->d_un.d_ptr
1690		  && phdr->p_vaddr + phdr->p_memsz > dyn->d_un.d_ptr)
1691		break;
1692	    }
1693	  if (unlikely (n >= ehdr->e_phnum))
1694	    {
1695	      char buf[50];
1696	      ERROR (gettext ("\
1697section [%2d] '%s': entry %zu: %s value must point into loaded segment\n"),
1698		     idx, section_name (ebl, idx), cnt,
1699		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1700					   sizeof (buf)));
1701	    }
1702	  break;
1703
1704	case DT_NEEDED:
1705	case DT_RPATH:
1706	case DT_RUNPATH:
1707	case DT_SONAME:
1708	  if (dyn->d_un.d_ptr >= strshdr->sh_size)
1709	    {
1710	      char buf[50];
1711	      ERROR (gettext ("\
1712section [%2d] '%s': entry %zu: %s value must be valid offset in section [%2d] '%s'\n"),
1713		     idx, section_name (ebl, idx), cnt,
1714		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
1715					   sizeof (buf)),
1716		     shdr->sh_link, section_name (ebl, shdr->sh_link));
1717	    }
1718	  break;
1719	}
1720    }
1721
1722  for (cnt = 1; cnt < DT_NUM; ++cnt)
1723    if (has_dt[cnt])
1724      {
1725	for (int inner = 0; inner < DT_NUM; ++inner)
1726	  if (dependencies[cnt][inner] && ! has_dt[inner])
1727	    {
1728	      char buf1[50];
1729	      char buf2[50];
1730
1731	      ERROR (gettext ("\
1732section [%2d] '%s': contains %s entry but not %s\n"),
1733		     idx, section_name (ebl, idx),
1734		     ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)),
1735		     ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2)));
1736	    }
1737      }
1738    else
1739      {
1740	if (mandatory[cnt])
1741	  {
1742	    char buf[50];
1743	    ERROR (gettext ("\
1744section [%2d] '%s': mandatory tag %s not present\n"),
1745		   idx, section_name (ebl, idx),
1746		   ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf)));
1747	  }
1748      }
1749
1750  /* Make sure we have an hash table.  */
1751  if (!has_dt[DT_HASH] && !has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)])
1752    ERROR (gettext ("\
1753section [%2d] '%s': no hash section present\n"),
1754	   idx, section_name (ebl, idx));
1755
1756  /* The GNU-style hash table also needs a symbol table.  */
1757  if (!has_dt[DT_HASH] && has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)]
1758      && !has_dt[DT_SYMTAB])
1759    ERROR (gettext ("\
1760section [%2d] '%s': contains %s entry but not %s\n"),
1761	   idx, section_name (ebl, idx),
1762	   "DT_GNU_HASH", "DT_SYMTAB");
1763
1764  /* Check the rel/rela tags.  At least one group must be available.  */
1765  if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT])
1766      && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT]))
1767    ERROR (gettext ("\
1768section [%2d] '%s': not all of %s, %s, and %s are present\n"),
1769	   idx, section_name (ebl, idx),
1770	   "DT_RELA", "DT_RELASZ", "DT_RELAENT");
1771
1772  if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT])
1773      && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT]))
1774    ERROR (gettext ("\
1775section [%2d] '%s': not all of %s, %s, and %s are present\n"),
1776	   idx, section_name (ebl, idx),
1777	   "DT_REL", "DT_RELSZ", "DT_RELENT");
1778
1779  /* Check that all prelink sections are present if any of them is.  */
1780  if (has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)]
1781      || has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1782    {
1783      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)])
1784	ERROR (gettext ("\
1785section [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1786	       idx, section_name (ebl, idx), "DT_GNU_PRELINKED");
1787      if (!has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
1788	ERROR (gettext ("\
1789section [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
1790	       idx, section_name (ebl, idx), "DT_CHECKSUM");
1791
1792      /* Only DSOs can be marked like this.  */
1793      if (ehdr->e_type != ET_DYN)
1794	ERROR (gettext ("\
1795section [%2d] '%s': non-DSO file marked as dependency during prelink\n"),
1796	       idx, section_name (ebl, idx));
1797    }
1798
1799  if (has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)]
1800      || has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)]
1801      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)]
1802      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1803    {
1804      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)])
1805	ERROR (gettext ("\
1806section [%2d] '%s': %s tag missing in prelinked executable\n"),
1807	       idx, section_name (ebl, idx), "DT_GNU_CONFLICTSZ");
1808      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)])
1809	ERROR (gettext ("\
1810section [%2d] '%s': %s tag missing in prelinked executable\n"),
1811	       idx, section_name (ebl, idx), "DT_GNU_LIBLISTSZ");
1812      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)])
1813	ERROR (gettext ("\
1814section [%2d] '%s': %s tag missing in prelinked executable\n"),
1815	       idx, section_name (ebl, idx), "DT_GNU_CONFLICT");
1816      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
1817	ERROR (gettext ("\
1818section [%2d] '%s': %s tag missing in prelinked executable\n"),
1819	       idx, section_name (ebl, idx), "DT_GNU_LIBLIST");
1820    }
1821}
1822
1823
1824static void
1825check_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1826{
1827  if (ehdr->e_type != ET_REL)
1828    {
1829      ERROR (gettext ("\
1830section [%2d] '%s': only relocatable files can have extended section index\n"),
1831	     idx, section_name (ebl, idx));
1832      return;
1833    }
1834
1835  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1836  GElf_Shdr symshdr_mem;
1837  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1838  if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB)
1839    ERROR (gettext ("\
1840section [%2d] '%s': extended section index section not for symbol table\n"),
1841	   idx, section_name (ebl, idx));
1842  Elf_Data *symdata = elf_getdata (symscn, NULL);
1843  if (symdata == NULL)
1844    ERROR (gettext ("cannot get data for symbol section\n"));
1845
1846  if (shdr->sh_entsize != sizeof (Elf32_Word))
1847    ERROR (gettext ("\
1848section [%2d] '%s': entry size does not match Elf32_Word\n"),
1849	   idx, section_name (ebl, idx));
1850
1851  if (symshdr != NULL
1852      && (shdr->sh_size / shdr->sh_entsize
1853	  < symshdr->sh_size / symshdr->sh_entsize))
1854    ERROR (gettext ("\
1855section [%2d] '%s': extended index table too small for symbol table\n"),
1856	   idx, section_name (ebl, idx));
1857
1858  if (shdr->sh_info != 0)
1859    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1860	   idx, section_name (ebl, idx));
1861
1862  for (size_t cnt = idx + 1; cnt < shnum; ++cnt)
1863    {
1864      GElf_Shdr rshdr_mem;
1865      GElf_Shdr *rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem);
1866      if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX
1867	  && rshdr->sh_link == shdr->sh_link)
1868	{
1869	  ERROR (gettext ("\
1870section [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"),
1871		 idx, section_name (ebl, idx),
1872		 cnt, section_name (ebl, cnt));
1873	  break;
1874	}
1875    }
1876
1877  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1878
1879  if (*((Elf32_Word *) data->d_buf) != 0)
1880    ERROR (gettext ("symbol 0 should have zero extended section index\n"));
1881
1882  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1883    {
1884      Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt];
1885
1886      if (xndx != 0)
1887	{
1888	  GElf_Sym sym_data;
1889	  GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data);
1890	  if (sym == NULL)
1891	    {
1892	      ERROR (gettext ("cannot get data for symbol %zu\n"), cnt);
1893	      continue;
1894	    }
1895
1896	  if (sym->st_shndx != SHN_XINDEX)
1897	    ERROR (gettext ("\
1898extended section index is %" PRIu32 " but symbol index is not XINDEX\n"),
1899		   (uint32_t) xndx);
1900	}
1901    }
1902}
1903
1904
1905static void
1906check_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
1907		 GElf_Shdr *symshdr)
1908{
1909  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
1910  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
1911
1912  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
1913    ERROR (gettext ("\
1914section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
1915	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
1916	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
1917
1918  size_t maxidx = nchain;
1919
1920  if (symshdr != NULL)
1921    {
1922      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
1923
1924      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
1925	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
1926	       idx, section_name (ebl, idx));
1927
1928      maxidx = symsize;
1929    }
1930
1931  size_t cnt;
1932  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
1933    if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx)
1934      ERROR (gettext ("\
1935section [%2d] '%s': hash bucket reference %zu out of bounds\n"),
1936	     idx, section_name (ebl, idx), cnt - 2);
1937
1938  for (; cnt < 2 + nbucket + nchain; ++cnt)
1939    if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx)
1940      ERROR (gettext ("\
1941section [%2d] '%s': hash chain reference %zu out of bounds\n"),
1942	     idx, section_name (ebl, idx), cnt - 2 - nbucket);
1943}
1944
1945
1946static void
1947check_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
1948		 GElf_Shdr *symshdr)
1949{
1950  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
1951  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
1952
1953  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
1954    ERROR (gettext ("\
1955section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
1956	   idx, section_name (ebl, idx), (long int) shdr->sh_size,
1957	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
1958
1959  size_t maxidx = nchain;
1960
1961  if (symshdr != NULL)
1962    {
1963      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
1964
1965      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
1966	ERROR (gettext ("section [%2d] '%s': chain array too large\n"),
1967	       idx, section_name (ebl, idx));
1968
1969      maxidx = symsize;
1970    }
1971
1972  size_t cnt;
1973  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
1974    if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx)
1975      ERROR (gettext ("\
1976section [%2d] '%s': hash bucket reference %zu out of bounds\n"),
1977	     idx, section_name (ebl, idx), cnt - 2);
1978
1979  for (; cnt < 2 + nbucket + nchain; ++cnt)
1980    if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx)
1981      ERROR (gettext ("\
1982section [%2d] '%s': hash chain reference %" PRIu64 " out of bounds\n"),
1983	     idx, section_name (ebl, idx), (uint64_t) (cnt - 2 - nbucket));
1984}
1985
1986
1987static void
1988check_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
1989		GElf_Shdr *symshdr)
1990{
1991  Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0];
1992  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
1993  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
1994
1995  if (!powerof2 (bitmask_words))
1996    ERROR (gettext ("\
1997section [%2d] '%s': bitmask size not power of 2: %u\n"),
1998	   idx, section_name (ebl, idx), bitmask_words);
1999
2000  size_t bitmask_idxmask = bitmask_words - 1;
2001  if (gelf_getclass (ebl->elf) == ELFCLASS64)
2002    bitmask_words *= 2;
2003  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
2004
2005  if (shdr->sh_size < (4 + bitmask_words + nbuckets) * sizeof (Elf32_Word))
2006    {
2007      ERROR (gettext ("\
2008section [%2d] '%s': hash table section is too small (is %ld, expected at least%ld)\n"),
2009	     idx, section_name (ebl, idx), (long int) shdr->sh_size,
2010	     (long int) ((4 + bitmask_words + nbuckets) * sizeof (Elf32_Word)));
2011      return;
2012    }
2013
2014  if (shift > 31)
2015    ERROR (gettext ("\
2016section [%2d] '%s': 2nd hash function shift too big: %u\n"),
2017	   idx, section_name (ebl, idx), shift);
2018
2019  size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words
2020							 + nbuckets);
2021
2022  if (symshdr != NULL)
2023    maxidx = MIN (maxidx, symshdr->sh_size / symshdr->sh_entsize);
2024
2025  /* We need the symbol section data.  */
2026  Elf_Data *symdata = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link), NULL);
2027
2028  union
2029  {
2030    Elf32_Word *p32;
2031    Elf64_Xword *p64;
2032  } bitmask = { .p32 = &((Elf32_Word *) data->d_buf)[4] },
2033      collected = { .p32 = xcalloc (bitmask_words, sizeof (Elf32_Word)) };
2034
2035  size_t classbits = gelf_getclass (ebl->elf) == ELFCLASS32 ? 32 : 64;
2036
2037  size_t cnt;
2038  for (cnt = 4 + bitmask_words; cnt < 4 + bitmask_words + nbuckets; ++cnt)
2039    {
2040      Elf32_Word symidx = ((Elf32_Word *) data->d_buf)[cnt];
2041
2042      if (symidx == 0)
2043	continue;
2044
2045      if (symidx < symbias)
2046	{
2047	  ERROR (gettext ("\
2048section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"),
2049		 idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
2050	  continue;
2051	}
2052
2053      while (symidx - symbias < maxidx)
2054	{
2055	  Elf32_Word chainhash = ((Elf32_Word *) data->d_buf)[4
2056							      + bitmask_words
2057							      + nbuckets
2058							      + symidx
2059							      - symbias];
2060
2061	  if (symdata != NULL)
2062	    {
2063	      /* Check that the referenced symbol is not undefined.  */
2064	      GElf_Sym sym_mem;
2065	      GElf_Sym *sym = gelf_getsym (symdata, symidx, &sym_mem);
2066	      if (sym != NULL && sym->st_shndx == SHN_UNDEF
2067		  && GELF_ST_TYPE (sym->st_info) != STT_FUNC)
2068		ERROR (gettext ("\
2069section [%2d] '%s': symbol %u referenced in chain for bucket %zu is undefined\n"),
2070		       idx, section_name (ebl, idx), symidx,
2071		       cnt - (4 + bitmask_words));
2072
2073	      const char *symname = elf_strptr (ebl->elf, symshdr->sh_link,
2074						sym->st_name);
2075	      if (symname != NULL)
2076		{
2077		  Elf32_Word hval = elf_gnu_hash (symname);
2078		  if ((hval & ~1u) != (chainhash & ~1u))
2079		    ERROR (gettext ("\
2080section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"),
2081			   idx, section_name (ebl, idx), symidx,
2082			   cnt - (4 + bitmask_words));
2083
2084		  /* Set the bits in the bitmask.  */
2085		  size_t maskidx = (hval / classbits) & bitmask_idxmask;
2086		  if (classbits == 32)
2087		    {
2088		      collected.p32[maskidx]
2089			|= UINT32_C (1) << (hval & (classbits - 1));
2090		      collected.p32[maskidx]
2091			|= UINT32_C (1) << ((hval >> shift) & (classbits - 1));
2092		    }
2093		  else
2094		    {
2095		      collected.p64[maskidx]
2096			|= UINT64_C (1) << (hval & (classbits - 1));
2097		      collected.p64[maskidx]
2098			|= UINT64_C (1) << ((hval >> shift) & (classbits - 1));
2099		    }
2100		}
2101	    }
2102
2103	  if ((chainhash & 1) != 0)
2104	    break;
2105
2106	  ++symidx;
2107	}
2108
2109      if (symidx - symbias >= maxidx)
2110	ERROR (gettext ("\
2111section [%2d] '%s': hash chain for bucket %zu out of bounds\n"),
2112	       idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
2113      else if (symshdr != NULL
2114	       && symidx > symshdr->sh_size / symshdr->sh_entsize)
2115	ERROR (gettext ("\
2116section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"),
2117	       idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
2118    }
2119
2120  if (memcmp (collected.p32, bitmask.p32, bitmask_words * sizeof (Elf32_Word)))
2121    ERROR (gettext ("\
2122section [%2d] '%s': bitmask does not match names in the hash table\n"),
2123	   idx, section_name (ebl, idx));
2124
2125  free (collected.p32);
2126}
2127
2128
2129static void
2130check_hash (int tag, Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2131{
2132  if (ehdr->e_type == ET_REL)
2133    {
2134      ERROR (gettext ("\
2135section [%2d] '%s': relocatable files cannot have hash tables\n"),
2136	     idx, section_name (ebl, idx));
2137      return;
2138    }
2139
2140  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2141  if (data == NULL)
2142    {
2143      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2144	     idx, section_name (ebl, idx));
2145      return;
2146    }
2147
2148  GElf_Shdr symshdr_mem;
2149  GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2150				     &symshdr_mem);
2151  if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM)
2152    ERROR (gettext ("\
2153section [%2d] '%s': hash table not for dynamic symbol table\n"),
2154	   idx, section_name (ebl, idx));
2155
2156  if (shdr->sh_entsize != (tag == SHT_GNU_HASH
2157			   ? (gelf_getclass (ebl->elf) == ELFCLASS32
2158			      ? sizeof (Elf32_Word) : 0)
2159			   : (size_t) ebl_sysvhash_entrysize (ebl)))
2160    ERROR (gettext ("\
2161section [%2d] '%s': hash table entry size incorrect\n"),
2162	   idx, section_name (ebl, idx));
2163
2164  if ((shdr->sh_flags & SHF_ALLOC) == 0)
2165    ERROR (gettext ("section [%2d] '%s': not marked to be allocated\n"),
2166	   idx, section_name (ebl, idx));
2167
2168  if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (shdr->sh_entsize ?: 4))
2169    {
2170      ERROR (gettext ("\
2171section [%2d] '%s': hash table has not even room for initial administrative entries\n"),
2172	     idx, section_name (ebl, idx));
2173      return;
2174    }
2175
2176  switch (tag)
2177    {
2178    case SHT_HASH:
2179      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
2180	check_sysv_hash64 (ebl, shdr, data, idx, symshdr);
2181      else
2182	check_sysv_hash (ebl, shdr, data, idx, symshdr);
2183      break;
2184
2185    case SHT_GNU_HASH:
2186      check_gnu_hash (ebl, shdr, data, idx, symshdr);
2187      break;
2188
2189    default:
2190      assert (! "should not happen");
2191    }
2192}
2193
2194
2195/* Compare content of both hash tables, it must be identical.  */
2196static void
2197compare_hash_gnu_hash (Ebl *ebl, GElf_Ehdr *ehdr, size_t hash_idx,
2198		       size_t gnu_hash_idx)
2199{
2200  Elf_Scn *hash_scn = elf_getscn (ebl->elf, hash_idx);
2201  Elf_Data *hash_data = elf_getdata (hash_scn, NULL);
2202  GElf_Shdr hash_shdr_mem;
2203  GElf_Shdr *hash_shdr = gelf_getshdr (hash_scn, &hash_shdr_mem);
2204  Elf_Scn *gnu_hash_scn = elf_getscn (ebl->elf, gnu_hash_idx);
2205  Elf_Data *gnu_hash_data = elf_getdata (gnu_hash_scn, NULL);
2206  GElf_Shdr gnu_hash_shdr_mem;
2207  GElf_Shdr *gnu_hash_shdr = gelf_getshdr (gnu_hash_scn, &gnu_hash_shdr_mem);
2208
2209  if (hash_shdr == NULL || gnu_hash_shdr == NULL
2210      || hash_data == NULL || gnu_hash_data == NULL)
2211    /* None of these pointers should be NULL since we used the
2212       sections already.  We are careful nonetheless.  */
2213    return;
2214
2215  /* The link must point to the same symbol table.  */
2216  if (hash_shdr->sh_link != gnu_hash_shdr->sh_link)
2217    {
2218      ERROR (gettext ("\
2219sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"),
2220	     hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
2221	     gnu_hash_idx,
2222	     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
2223      return;
2224    }
2225
2226  Elf_Scn *sym_scn = elf_getscn (ebl->elf, hash_shdr->sh_link);
2227  Elf_Data *sym_data = elf_getdata (sym_scn, NULL);
2228  GElf_Shdr sym_shdr_mem;
2229  GElf_Shdr *sym_shdr = gelf_getshdr (sym_scn, &sym_shdr_mem);
2230
2231  if (sym_data == NULL || sym_shdr == NULL)
2232    return;
2233
2234  int nentries = sym_shdr->sh_size / sym_shdr->sh_entsize;
2235  char *used = alloca (nentries);
2236  memset (used, '\0', nentries);
2237
2238  /* First go over the GNU_HASH table and mark the entries as used.  */
2239  const Elf32_Word *gnu_hasharr = (Elf32_Word *) gnu_hash_data->d_buf;
2240  Elf32_Word gnu_nbucket = gnu_hasharr[0];
2241  const int bitmap_factor = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 1 : 2;
2242  const Elf32_Word *gnu_bucket = (gnu_hasharr
2243				  + (4 + gnu_hasharr[2] * bitmap_factor));
2244  const Elf32_Word *gnu_chain = gnu_bucket + gnu_hasharr[0] - gnu_hasharr[1];
2245
2246  for (Elf32_Word cnt = 0; cnt < gnu_nbucket; ++cnt)
2247    {
2248      Elf32_Word symidx = gnu_bucket[cnt];
2249      if (symidx != STN_UNDEF)
2250	do
2251	  used[symidx] |= 1;
2252	while ((gnu_chain[symidx++] & 1u) == 0);
2253    }
2254
2255  /* Now go over the old hash table and check that we cover the same
2256     entries.  */
2257  if (hash_shdr->sh_entsize == sizeof (Elf32_Word))
2258    {
2259      const Elf32_Word *hasharr = (Elf32_Word *) hash_data->d_buf;
2260      Elf32_Word nbucket = hasharr[0];
2261      const Elf32_Word *bucket = &hasharr[2];
2262      const Elf32_Word *chain = &hasharr[2 + nbucket];
2263
2264      for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2265	{
2266	  Elf32_Word symidx = bucket[cnt];
2267	  while (symidx != STN_UNDEF)
2268	    {
2269	      used[symidx] |= 2;
2270	      symidx = chain[symidx];
2271	    }
2272	}
2273    }
2274  else
2275    {
2276      const Elf64_Xword *hasharr = (Elf64_Xword *) hash_data->d_buf;
2277      Elf64_Xword nbucket = hasharr[0];
2278      const Elf64_Xword *bucket = &hasharr[2];
2279      const Elf64_Xword *chain = &hasharr[2 + nbucket];
2280
2281      for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
2282	{
2283	  Elf64_Xword symidx = bucket[cnt];
2284	  while (symidx != STN_UNDEF)
2285	    {
2286	      used[symidx] |= 2;
2287	      symidx = chain[symidx];
2288	    }
2289	}
2290    }
2291
2292  /* Now see which entries are not set in one or both hash tables
2293     (unless the symbol is undefined in which case it can be omitted
2294     in the new table format).  */
2295  if ((used[0] & 1) != 0)
2296    ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"),
2297	   gnu_hash_idx,
2298	   elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
2299  if ((used[0] & 2) != 0)
2300    ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"),
2301	   hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
2302
2303  for (int cnt = 1; cnt < nentries; ++cnt)
2304    if (used[cnt] != 0 && used[cnt] != 3)
2305      {
2306	if (used[cnt] == 1)
2307	  ERROR (gettext ("\
2308symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash table in [%2zu] '%s'\n"),
2309		 cnt, gnu_hash_idx,
2310		 elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name),
2311		 hash_idx,
2312		 elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
2313	else
2314	  {
2315	    GElf_Sym sym_mem;
2316	    GElf_Sym *sym = gelf_getsym (sym_data, cnt, &sym_mem);
2317
2318	    if (sym != NULL && sym->st_shndx != STN_UNDEF)
2319	      ERROR (gettext ("\
2320symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash table in [%2zu] '%s'\n"),
2321		     cnt, hash_idx,
2322		     elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
2323		     gnu_hash_idx,
2324		     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
2325	  }
2326      }
2327}
2328
2329
2330static void
2331check_null (Ebl *ebl, GElf_Shdr *shdr, int idx)
2332{
2333#define TEST(name, extra) \
2334  if (extra && shdr->sh_##name != 0)					      \
2335    ERROR (gettext ("section [%2d] '%s': nonzero sh_%s for NULL section\n"),  \
2336	   idx, section_name (ebl, idx), #name)
2337
2338  TEST (name, 1);
2339  TEST (flags, 1);
2340  TEST (addr, 1);
2341  TEST (offset, 1);
2342  TEST (size, idx != 0);
2343  TEST (link, idx != 0);
2344  TEST (info, 1);
2345  TEST (addralign, 1);
2346  TEST (entsize, 1);
2347}
2348
2349
2350static void
2351check_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2352{
2353  if (ehdr->e_type != ET_REL)
2354    {
2355      ERROR (gettext ("\
2356section [%2d] '%s': section groups only allowed in relocatable object files\n"),
2357	     idx, section_name (ebl, idx));
2358      return;
2359    }
2360
2361  /* Check that sh_link is an index of a symbol table.  */
2362  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2363  GElf_Shdr symshdr_mem;
2364  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2365  if (symshdr == NULL)
2366    ERROR (gettext ("section [%2d] '%s': cannot get symbol table: %s\n"),
2367	   idx, section_name (ebl, idx), elf_errmsg (-1));
2368  else
2369    {
2370      if (symshdr->sh_type != SHT_SYMTAB)
2371	ERROR (gettext ("\
2372section [%2d] '%s': section reference in sh_link is no symbol table\n"),
2373	       idx, section_name (ebl, idx));
2374
2375      if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM,
2376							  1, EV_CURRENT))
2377	ERROR (gettext ("\
2378section [%2d] '%s': invalid symbol index in sh_info\n"),
2379	       idx, section_name (ebl, idx));
2380
2381      if (shdr->sh_flags != 0)
2382	ERROR (gettext ("section [%2d] '%s': sh_flags not zero\n"),
2383	       idx, section_name (ebl, idx));
2384
2385      GElf_Sym sym_data;
2386      GElf_Sym *sym = gelf_getsym (elf_getdata (symscn, NULL), shdr->sh_info,
2387				   &sym_data);
2388      if (sym == NULL)
2389	ERROR (gettext ("\
2390section [%2d] '%s': cannot get symbol for signature\n"),
2391	       idx, section_name (ebl, idx));
2392      else if (strcmp (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name),
2393		       "") == 0)
2394	ERROR (gettext ("\
2395section [%2d] '%s': signature symbol canot be empty string\n"),
2396	       idx, section_name (ebl, idx));
2397
2398      if (be_strict
2399	  && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT))
2400	ERROR (gettext ("section [%2d] '%s': sh_flags not set correctly\n"),
2401	       idx, section_name (ebl, idx));
2402    }
2403
2404  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2405  if (data == NULL)
2406    ERROR (gettext ("section [%2d] '%s': cannot get data: %s\n"),
2407	   idx, section_name (ebl, idx), elf_errmsg (-1));
2408  else
2409    {
2410      size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
2411      size_t cnt;
2412      Elf32_Word val;
2413
2414      if (data->d_size % elsize != 0)
2415	ERROR (gettext ("\
2416section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"),
2417	       idx, section_name (ebl, idx));
2418
2419      if (data->d_size < elsize)
2420	ERROR (gettext ("\
2421section [%2d] '%s': section group without flags word\n"),
2422	       idx, section_name (ebl, idx));
2423      else if (be_strict)
2424	{
2425	  if (data->d_size < 2 * elsize)
2426	    ERROR (gettext ("\
2427section [%2d] '%s': section group without member\n"),
2428		   idx, section_name (ebl, idx));
2429	  else if (data->d_size < 3 * elsize)
2430	    ERROR (gettext ("\
2431section [%2d] '%s': section group with only one member\n"),
2432		   idx, section_name (ebl, idx));
2433	}
2434
2435#if ALLOW_UNALIGNED
2436      val = *((Elf32_Word *) data->d_buf);
2437#else
2438      memcpy (&val, data->d_buf, elsize);
2439#endif
2440      if ((val & ~GRP_COMDAT) != 0)
2441	ERROR (gettext ("section [%2d] '%s': unknown section group flags\n"),
2442	       idx, section_name (ebl, idx));
2443
2444      for (cnt = elsize; cnt < data->d_size; cnt += elsize)
2445	{
2446#if ALLOW_UNALIGNED
2447	  val = *((Elf32_Word *) ((char *) data->d_buf + cnt));
2448#else
2449	  memcpy (&val, (char *) data->d_buf + cnt, elsize);
2450#endif
2451
2452	  if (val > shnum)
2453	    ERROR (gettext ("\
2454section [%2d] '%s': section index %Zu out of range\n"),
2455		   idx, section_name (ebl, idx), cnt / elsize);
2456	  else
2457	    {
2458	      GElf_Shdr refshdr_mem;
2459	      GElf_Shdr *refshdr = gelf_getshdr (elf_getscn (ebl->elf, val),
2460						 &refshdr_mem);
2461	      if (refshdr == NULL)
2462		ERROR (gettext ("\
2463section [%2d] '%s': cannot get section header for element %zu: %s\n"),
2464		       idx, section_name (ebl, idx), cnt / elsize,
2465		       elf_errmsg (-1));
2466	      else
2467		{
2468		  if (refshdr->sh_type == SHT_GROUP)
2469		    ERROR (gettext ("\
2470section [%2d] '%s': section group contains another group [%2d] '%s'\n"),
2471			   idx, section_name (ebl, idx),
2472			   val, section_name (ebl, val));
2473
2474		  if ((refshdr->sh_flags & SHF_GROUP) == 0)
2475		    ERROR (gettext ("\
2476section [%2d] '%s': element %Zu references section [%2d] '%s' without SHF_GROUP flag set\n"),
2477			   idx, section_name (ebl, idx), cnt / elsize,
2478			   val, section_name (ebl, val));
2479		}
2480
2481	      if (++scnref[val] == 2)
2482		ERROR (gettext ("\
2483section [%2d] '%s' is contained in more than one section group\n"),
2484		       val, section_name (ebl, val));
2485	    }
2486	}
2487    }
2488}
2489
2490
2491static const char *
2492section_flags_string (GElf_Word flags, char *buf, size_t len)
2493{
2494  if (flags == 0)
2495    return "none";
2496
2497  static const struct
2498  {
2499    GElf_Word flag;
2500    const char *name;
2501  } known_flags[] =
2502    {
2503#define NEWFLAG(name) { SHF_##name, #name }
2504      NEWFLAG (WRITE),
2505      NEWFLAG (ALLOC),
2506      NEWFLAG (EXECINSTR),
2507      NEWFLAG (MERGE),
2508      NEWFLAG (STRINGS),
2509      NEWFLAG (INFO_LINK),
2510      NEWFLAG (LINK_ORDER),
2511      NEWFLAG (OS_NONCONFORMING),
2512      NEWFLAG (GROUP),
2513      NEWFLAG (TLS)
2514    };
2515#undef NEWFLAG
2516  const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
2517
2518  char *cp = buf;
2519
2520  for (size_t cnt = 0; cnt < nknown_flags; ++cnt)
2521    if (flags & known_flags[cnt].flag)
2522      {
2523	if (cp != buf && len > 1)
2524	  {
2525	    *cp++ = '|';
2526	    --len;
2527	  }
2528
2529	size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name));
2530	cp = mempcpy (cp, known_flags[cnt].name, ncopy);
2531	len -= ncopy;
2532
2533	flags ^= known_flags[cnt].flag;
2534      }
2535
2536  if (flags != 0 || cp == buf)
2537    snprintf (cp, len - 1, "%" PRIx64, (uint64_t) flags);
2538
2539  *cp = '\0';
2540
2541  return buf;
2542}
2543
2544
2545static int
2546has_copy_reloc (Ebl *ebl, unsigned int symscnndx, unsigned int symndx)
2547{
2548  /* First find the relocation section for the symbol table.  */
2549  Elf_Scn *scn = NULL;
2550  GElf_Shdr shdr_mem;
2551  GElf_Shdr *shdr = NULL;
2552  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2553    {
2554      shdr = gelf_getshdr (scn, &shdr_mem);
2555      if (shdr != NULL
2556	  && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
2557	  && shdr->sh_link == symscnndx)
2558	/* Found the section.  */
2559	break;
2560    }
2561
2562  if (scn == NULL)
2563    return 0;
2564
2565  Elf_Data *data = elf_getdata (scn, NULL);
2566  if (data == NULL)
2567    return 0;
2568
2569  if (shdr->sh_type == SHT_REL)
2570    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2571      {
2572	GElf_Rel rel_mem;
2573	GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
2574	if (rel == NULL)
2575	  continue;
2576
2577	if (GELF_R_SYM (rel->r_info) == symndx
2578	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info)))
2579	  return 1;
2580      }
2581  else
2582    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
2583      {
2584	GElf_Rela rela_mem;
2585	GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
2586	if (rela == NULL)
2587	  continue;
2588
2589	if (GELF_R_SYM (rela->r_info) == symndx
2590	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info)))
2591	  return 1;
2592      }
2593
2594  return 0;
2595}
2596
2597
2598static int
2599in_nobits_scn (Ebl *ebl, unsigned int shndx)
2600{
2601  GElf_Shdr shdr_mem;
2602  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, shndx), &shdr_mem);
2603  return shdr != NULL && shdr->sh_type == SHT_NOBITS;
2604}
2605
2606
2607static struct version_namelist
2608{
2609  const char *objname;
2610  const char *name;
2611  GElf_Versym ndx;
2612  enum { ver_def, ver_need } type;
2613  struct version_namelist *next;
2614} *version_namelist;
2615
2616
2617static int
2618add_version (const char *objname, const char *name, GElf_Versym ndx, int type)
2619{
2620  /* Check that there are no duplications.  */
2621  struct version_namelist *nlp = version_namelist;
2622  while (nlp != NULL)
2623    {
2624      if (((nlp->objname == NULL && objname == NULL)
2625	   || (nlp->objname != NULL && objname != NULL
2626	       && strcmp (nlp->objname, objname) == 0))
2627	  && strcmp (nlp->name, name) == 0)
2628	return nlp->type == ver_def ? 1 : -1;
2629      nlp = nlp->next;
2630    }
2631
2632  nlp = xmalloc (sizeof (*nlp));
2633  nlp->objname = objname;
2634  nlp->name = name;
2635  nlp->ndx = ndx;
2636  nlp->type = type;
2637  nlp->next = version_namelist;
2638  version_namelist = nlp;
2639
2640  return 0;
2641}
2642
2643
2644static void
2645check_versym (Ebl *ebl, int idx)
2646{
2647  Elf_Scn *scn = elf_getscn (ebl->elf, idx);
2648  GElf_Shdr shdr_mem;
2649  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2650  if (shdr == NULL)
2651    /* The error has already been reported.  */
2652    return;
2653
2654  Elf_Data *data = elf_getdata (scn, NULL);
2655  if (data == NULL)
2656    {
2657      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2658	     idx, section_name (ebl, idx));
2659      return;
2660    }
2661
2662  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2663  GElf_Shdr symshdr_mem;
2664  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2665  if (symshdr == NULL)
2666    /* The error has already been reported.  */
2667    return;
2668
2669  if (symshdr->sh_type != SHT_DYNSYM)
2670    {
2671      ERROR (gettext ("\
2672section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"),
2673	     idx, section_name (ebl, idx),
2674	     shdr->sh_link, section_name (ebl, shdr->sh_link));
2675      return;
2676    }
2677
2678  /* The number of elements in the version symbol table must be the
2679     same as the number of symbols.  */
2680  if (shdr->sh_size / shdr->sh_entsize
2681      != symshdr->sh_size / symshdr->sh_entsize)
2682    ERROR (gettext ("\
2683section [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"),
2684	   idx, section_name (ebl, idx),
2685	   shdr->sh_link, section_name (ebl, shdr->sh_link));
2686
2687  Elf_Data *symdata = elf_getdata (symscn, NULL);
2688  if (symdata == NULL)
2689    /* The error has already been reported.  */
2690    return;
2691
2692  for (int cnt = 1; (size_t) cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2693    {
2694      GElf_Versym versym_mem;
2695      GElf_Versym *versym = gelf_getversym (data, cnt, &versym_mem);
2696      if (versym == NULL)
2697	{
2698	  ERROR (gettext ("\
2699section [%2d] '%s': symbol %d: cannot read version data\n"),
2700		 idx, section_name (ebl, idx), cnt);
2701	  break;
2702	}
2703
2704      GElf_Sym sym_mem;
2705      GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_mem);
2706      if (sym == NULL)
2707	/* Already reported elsewhere.  */
2708	continue;
2709
2710      if (*versym == VER_NDX_GLOBAL)
2711	{
2712	  /* Global symbol.  Make sure it is not defined as local.  */
2713	  if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2714	    ERROR (gettext ("\
2715section [%2d] '%s': symbol %d: local symbol with global scope\n"),
2716		   idx, section_name (ebl, idx), cnt);
2717	}
2718      else if (*versym != VER_NDX_LOCAL)
2719	{
2720	  /* Versioned symbol.  Make sure it is not defined as local.  */
2721	  if (!gnuld && GELF_ST_BIND (sym->st_info) == STB_LOCAL)
2722	    ERROR (gettext ("\
2723section [%2d] '%s': symbol %d: local symbol with version\n"),
2724		   idx, section_name (ebl, idx), cnt);
2725
2726	  /* Look through the list of defined versions and locate the
2727	     index we need for this symbol.  */
2728	  struct version_namelist *runp = version_namelist;
2729	  while (runp != NULL)
2730	    if (runp->ndx == (*versym & (GElf_Versym) 0x7fff))
2731	      break;
2732	    else
2733	      runp = runp->next;
2734
2735	  if (runp == NULL)
2736	    ERROR (gettext ("\
2737section [%2d] '%s': symbol %d: invalid version index %d\n"),
2738		   idx, section_name (ebl, idx), cnt, (int) *versym);
2739	  else if (sym->st_shndx == SHN_UNDEF
2740		   && runp->type == ver_def)
2741	    ERROR (gettext ("\
2742section [%2d] '%s': symbol %d: version index %d is for defined version\n"),
2743		   idx, section_name (ebl, idx), cnt, (int) *versym);
2744	  else if (sym->st_shndx != SHN_UNDEF
2745		   && runp->type == ver_need)
2746	    {
2747	      /* Unless this symbol has a copy relocation associated
2748		 this must not happen.  */
2749	      if (!has_copy_reloc (ebl, shdr->sh_link, cnt)
2750		  && !in_nobits_scn (ebl, sym->st_shndx))
2751		ERROR (gettext ("\
2752section [%2d] '%s': symbol %d: version index %d is for requested version\n"),
2753		       idx, section_name (ebl, idx), cnt, (int) *versym);
2754	    }
2755	}
2756    }
2757}
2758
2759
2760static int
2761unknown_dependency_p (Elf *elf, GElf_Ehdr *ehdr, const char *fname)
2762{
2763  GElf_Phdr phdr_mem;
2764  GElf_Phdr *phdr = NULL;
2765
2766  int i;
2767  for (i = 0; i < ehdr->e_phnum; ++i)
2768    if ((phdr = gelf_getphdr (elf, i, &phdr_mem)) != NULL
2769	&& phdr->p_type == PT_DYNAMIC)
2770      break;
2771
2772  if (i == ehdr->e_phnum)
2773    return 1;
2774  assert (phdr != NULL);
2775  Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
2776  GElf_Shdr shdr_mem;
2777  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2778  Elf_Data *data = elf_getdata (scn, NULL);
2779  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL)
2780    for (size_t j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
2781      {
2782	GElf_Dyn dyn_mem;
2783	GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
2784	if (dyn != NULL && dyn->d_tag == DT_NEEDED)
2785	  {
2786	    const char *str = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
2787	    if (str != NULL && strcmp (str, fname) == 0)
2788	      /* Found it.  */
2789	      return 0;
2790	  }
2791      }
2792
2793  return 1;
2794}
2795
2796
2797static unsigned int nverneed;
2798
2799static void
2800check_verneed (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
2801{
2802  if (++nverneed == 2)
2803    ERROR (gettext ("more than one version reference section present\n"));
2804
2805  GElf_Shdr strshdr_mem;
2806  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2807				     &strshdr_mem);
2808  if (strshdr == NULL)
2809    return;
2810  if (strshdr->sh_type != SHT_STRTAB)
2811    ERROR (gettext ("\
2812section [%2d] '%s': sh_link does not link to string table\n"),
2813	   idx, section_name (ebl, idx));
2814
2815  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2816  if (data == NULL)
2817    {
2818      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2819	     idx, section_name (ebl, idx));
2820      return;
2821    }
2822  unsigned int offset = 0;
2823  for (int cnt = shdr->sh_info; --cnt >= 0; )
2824    {
2825      /* Get the data at the next offset.  */
2826      GElf_Verneed needmem;
2827      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
2828      if (need == NULL)
2829	break;
2830
2831      unsigned int auxoffset = offset + need->vn_aux;
2832
2833      if (need->vn_version != EV_CURRENT)
2834	ERROR (gettext ("\
2835section [%2d] '%s': entry %d has wrong version %d\n"),
2836	       idx, section_name (ebl, idx), cnt, (int) need->vn_version);
2837
2838      if (need->vn_cnt > 0 && need->vn_aux < gelf_fsize (ebl->elf, ELF_T_VNEED,
2839							 1, EV_CURRENT))
2840	ERROR (gettext ("\
2841section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
2842	       idx, section_name (ebl, idx), cnt);
2843
2844      const char *libname = elf_strptr (ebl->elf, shdr->sh_link,
2845					need->vn_file);
2846      if (libname == NULL)
2847	{
2848	  ERROR (gettext ("\
2849section [%2d] '%s': entry %d has invalid file reference\n"),
2850		 idx, section_name (ebl, idx), cnt);
2851	  goto next_need;
2852	}
2853
2854      /* Check that there is a DT_NEEDED entry for the referenced library.  */
2855      if (unknown_dependency_p (ebl->elf, ehdr, libname))
2856	ERROR (gettext ("\
2857section [%2d] '%s': entry %d references unknown dependency\n"),
2858	       idx, section_name (ebl, idx), cnt);
2859
2860      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2861	{
2862	  GElf_Vernaux auxmem;
2863	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2864	  if (aux == NULL)
2865	    break;
2866
2867	  if ((aux->vna_flags & ~VER_FLG_WEAK) != 0)
2868	    ERROR (gettext ("\
2869section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"),
2870		   idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2871
2872	  const char *verstr = elf_strptr (ebl->elf, shdr->sh_link,
2873					   aux->vna_name);
2874	  if (verstr == NULL)
2875	    ERROR (gettext ("\
2876section [%2d] '%s': auxiliary entry %d of entry %d has invalid name reference\n"),
2877		   idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2878	  else
2879	    {
2880	      GElf_Word hashval = elf_hash (verstr);
2881	      if (hashval != aux->vna_hash)
2882		ERROR (gettext ("\
2883section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: %#x, expected %#x\n"),
2884		       idx, section_name (ebl, idx), need->vn_cnt - cnt2,
2885		       cnt, (int) hashval, (int) aux->vna_hash);
2886
2887	      int res = add_version (libname, verstr, aux->vna_other,
2888				     ver_need);
2889	      if (unlikely (res !=0))
2890		{
2891		  assert (res > 0);
2892		  ERROR (gettext ("\
2893section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version name '%s'\n"),
2894			 idx, section_name (ebl, idx), need->vn_cnt - cnt2,
2895			 cnt, verstr);
2896		}
2897	    }
2898
2899	  if ((aux->vna_next != 0 || cnt2 > 0)
2900	      && aux->vna_next < gelf_fsize (ebl->elf, ELF_T_VNAUX, 1,
2901					     EV_CURRENT))
2902	    {
2903	      ERROR (gettext ("\
2904section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"),
2905		     idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
2906	      break;
2907	    }
2908
2909	  auxoffset += MAX (aux->vna_next,
2910			    gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, EV_CURRENT));
2911	}
2912
2913      /* Find the next offset.  */
2914    next_need:
2915      offset += need->vn_next;
2916
2917      if ((need->vn_next != 0 || cnt > 0)
2918	  && offset < auxoffset)
2919	ERROR (gettext ("\
2920section [%2d] '%s': entry %d has invalid offset to next entry\n"),
2921	       idx, section_name (ebl, idx), cnt);
2922    }
2923}
2924
2925
2926static unsigned int nverdef;
2927
2928static void
2929check_verdef (Ebl *ebl, GElf_Shdr *shdr, int idx)
2930{
2931  if (++nverdef == 2)
2932    ERROR (gettext ("more than one version definition section present\n"));
2933
2934  GElf_Shdr strshdr_mem;
2935  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2936				     &strshdr_mem);
2937  if (strshdr == NULL)
2938    return;
2939  if (strshdr->sh_type != SHT_STRTAB)
2940    ERROR (gettext ("\
2941section [%2d] '%s': sh_link does not link to string table\n"),
2942	   idx, section_name (ebl, idx));
2943
2944  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
2945  if (data == NULL)
2946    {
2947    no_data:
2948      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
2949	     idx, section_name (ebl, idx));
2950      return;
2951    }
2952
2953  /* Iterate over all version definition entries.  We check that there
2954     is a BASE entry and that each index is unique.  To do the later
2955     we collection the information in a list which is later
2956     examined.  */
2957  struct namelist
2958  {
2959    const char *name;
2960    struct namelist *next;
2961  } *namelist = NULL;
2962  struct namelist *refnamelist = NULL;
2963
2964  bool has_base = false;
2965  unsigned int offset = 0;
2966  for (int cnt = shdr->sh_info; --cnt >= 0; )
2967    {
2968      /* Get the data at the next offset.  */
2969      GElf_Verdef defmem;
2970      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2971      if (def == NULL)
2972	goto no_data;
2973
2974      if ((def->vd_flags & VER_FLG_BASE) != 0)
2975	{
2976	  if (has_base)
2977	    ERROR (gettext ("\
2978section [%2d] '%s': more than one BASE definition\n"),
2979		   idx, section_name (ebl, idx));
2980	  if (def->vd_ndx != VER_NDX_GLOBAL)
2981	    ERROR (gettext ("\
2982section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"),
2983		   idx, section_name (ebl, idx));
2984	  has_base = true;
2985	}
2986      if ((def->vd_flags & ~(VER_FLG_BASE|VER_FLG_WEAK)) != 0)
2987	ERROR (gettext ("\
2988section [%2d] '%s': entry %d has unknown flag\n"),
2989	       idx, section_name (ebl, idx), cnt);
2990
2991      if (def->vd_version != EV_CURRENT)
2992	ERROR (gettext ("\
2993section [%2d] '%s': entry %d has wrong version %d\n"),
2994	       idx, section_name (ebl, idx), cnt, (int) def->vd_version);
2995
2996      if (def->vd_cnt > 0 && def->vd_aux < gelf_fsize (ebl->elf, ELF_T_VDEF,
2997						       1, EV_CURRENT))
2998	ERROR (gettext ("\
2999section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
3000	       idx, section_name (ebl, idx), cnt);
3001
3002      unsigned int auxoffset = offset + def->vd_aux;
3003      GElf_Verdaux auxmem;
3004      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
3005      if (aux == NULL)
3006	goto no_data;
3007
3008      const char *name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
3009      if (name == NULL)
3010	{
3011	  ERROR (gettext ("\
3012section [%2d] '%s': entry %d has invalid name reference\n"),
3013		 idx, section_name (ebl, idx), cnt);
3014	  goto next_def;
3015	}
3016      GElf_Word hashval = elf_hash (name);
3017      if (def->vd_hash != hashval)
3018	ERROR (gettext ("\
3019section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"),
3020	       idx, section_name (ebl, idx), cnt, (int) hashval,
3021	       (int) def->vd_hash);
3022
3023      int res = add_version (NULL, name, def->vd_ndx, ver_def);
3024      if (unlikely (res !=0))
3025	{
3026	  assert (res > 0);
3027	  ERROR (gettext ("\
3028section [%2d] '%s': entry %d has duplicate version name '%s'\n"),
3029		 idx, section_name (ebl, idx), cnt, name);
3030	}
3031
3032      struct namelist *newname = alloca (sizeof (*newname));
3033      newname->name = name;
3034      newname->next = namelist;
3035      namelist = newname;
3036
3037      auxoffset += aux->vda_next;
3038      for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
3039	{
3040	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
3041	  if (aux == NULL)
3042	    goto no_data;
3043
3044	  name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
3045	  if (name == NULL)
3046	    ERROR (gettext ("\
3047section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"),
3048		   idx, section_name (ebl, idx), cnt);
3049	  else
3050	    {
3051	      newname = alloca (sizeof (*newname));
3052	      newname->name = name;
3053	      newname->next = refnamelist;
3054	      refnamelist = newname;
3055	    }
3056
3057	  if ((aux->vda_next != 0 || cnt2 + 1 < def->vd_cnt)
3058	      && aux->vda_next < gelf_fsize (ebl->elf, ELF_T_VDAUX, 1,
3059					     EV_CURRENT))
3060	    {
3061	      ERROR (gettext ("\
3062section [%2d] '%s': entry %d has wrong next field in auxiliary data\n"),
3063		     idx, section_name (ebl, idx), cnt);
3064	      break;
3065	    }
3066
3067	  auxoffset += MAX (aux->vda_next,
3068			    gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, EV_CURRENT));
3069	}
3070
3071      /* Find the next offset.  */
3072    next_def:
3073      offset += def->vd_next;
3074
3075      if ((def->vd_next != 0 || cnt > 0)
3076	  && offset < auxoffset)
3077	ERROR (gettext ("\
3078section [%2d] '%s': entry %d has invalid offset to next entry\n"),
3079	       idx, section_name (ebl, idx), cnt);
3080    }
3081
3082  if (!has_base)
3083    ERROR (gettext ("section [%2d] '%s': no BASE definition\n"),
3084	   idx, section_name (ebl, idx));
3085
3086  /* Check whether the referenced names are available.  */
3087  while (namelist != NULL)
3088    {
3089      struct version_namelist *runp = version_namelist;
3090      while (runp != NULL)
3091	{
3092	  if (runp->type == ver_def
3093	      && strcmp (runp->name, namelist->name) == 0)
3094	    break;
3095	  runp = runp->next;
3096	}
3097
3098      if (runp == NULL)
3099	ERROR (gettext ("\
3100section [%2d] '%s': unknown parent version '%s'\n"),
3101	       idx, section_name (ebl, idx), namelist->name);
3102
3103      namelist = namelist->next;
3104    }
3105}
3106
3107static void
3108check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
3109{
3110  if (shdr->sh_size == 0)
3111    {
3112      ERROR (gettext ("section [%2d] '%s': empty object attributes section\n"),
3113	     idx, section_name (ebl, idx));
3114      return;
3115    }
3116
3117  Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL);
3118  if (data == NULL || data->d_size == 0)
3119    {
3120      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
3121	     idx, section_name (ebl, idx));
3122      return;
3123    }
3124
3125  inline size_t pos (const unsigned char *p)
3126  {
3127    return p - (const unsigned char *) data->d_buf;
3128  }
3129
3130  const unsigned char *p = data->d_buf;
3131  if (*p++ != 'A')
3132    {
3133      ERROR (gettext ("section [%2d] '%s': unrecognized attribute format\n"),
3134	     idx, section_name (ebl, idx));
3135      return;
3136    }
3137
3138  inline size_t left (void)
3139  {
3140    return (const unsigned char *) data->d_buf + data->d_size - p;
3141  }
3142
3143  while (left () >= 4)
3144    {
3145      uint32_t len;
3146      memcpy (&len, p, sizeof len);
3147
3148      if (len == 0)
3149	ERROR (gettext ("\
3150section [%2d] '%s': offset %zu: zero length field in attribute section\n"),
3151	       idx, section_name (ebl, idx), pos (p));
3152
3153      if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3154	CONVERT (len);
3155
3156      if (len > left ())
3157	{
3158	  ERROR (gettext ("\
3159section [%2d] '%s': offset %zu: invalid length in attribute section\n"),
3160		 idx, section_name (ebl, idx), pos (p));
3161	  break;
3162	}
3163
3164      const unsigned char *name = p + sizeof len;
3165      p += len;
3166
3167      unsigned const char *q = memchr (name, '\0', len);
3168      if (q == NULL)
3169	{
3170	  ERROR (gettext ("\
3171section [%2d] '%s': offset %zu: unterminated vendor name string\n"),
3172		 idx, section_name (ebl, idx), pos (p));
3173	  continue;
3174	}
3175      ++q;
3176
3177      if (q - name == sizeof "gnu" && !memcmp (name, "gnu", sizeof "gnu"))
3178	while (q < p)
3179	  {
3180	    unsigned const char *chunk = q;
3181
3182	    unsigned int subsection_tag;
3183	    get_uleb128 (subsection_tag, q);
3184
3185	    if (q >= p)
3186	      {
3187		ERROR (gettext ("\
3188section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"),
3189		       idx, section_name (ebl, idx), pos (chunk));
3190		break;
3191	      }
3192
3193	    uint32_t subsection_len;
3194	    if (p - q < (ptrdiff_t) sizeof subsection_len)
3195	      {
3196		ERROR (gettext ("\
3197section [%2d] '%s': offset %zu: truncated attribute section\n"),
3198		       idx, section_name (ebl, idx), pos (q));
3199		break;
3200	      }
3201
3202	    memcpy (&subsection_len, q, sizeof subsection_len);
3203	    if (subsection_len == 0)
3204	      {
3205		ERROR (gettext ("\
3206section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
3207		       idx, section_name (ebl, idx), pos (q));
3208
3209		q += sizeof subsection_len;
3210		continue;
3211	      }
3212
3213	    if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
3214	      CONVERT (subsection_len);
3215
3216	    if (p - chunk < (ptrdiff_t) subsection_len)
3217	      {
3218		ERROR (gettext ("\
3219section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
3220		       idx, section_name (ebl, idx), pos (q));
3221		break;
3222	      }
3223
3224	    const unsigned char *subsection_end = chunk + subsection_len;
3225	    chunk = q;
3226	    q = subsection_end;
3227
3228	    if (subsection_tag != 1) /* Tag_File */
3229	      ERROR (gettext ("\
3230section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
3231		     idx, section_name (ebl, idx), pos (chunk), subsection_tag);
3232	    else
3233	      {
3234		chunk += sizeof subsection_len;
3235		while (chunk < q)
3236		  {
3237		    unsigned int tag;
3238		    get_uleb128 (tag, chunk);
3239
3240		    uint64_t value = 0;
3241		    const unsigned char *r = chunk;
3242		    if (tag == 32 || (tag & 1) == 0)
3243		      {
3244			get_uleb128 (value, r);
3245			if (r > q)
3246			  {
3247			    ERROR (gettext ("\
3248section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"),
3249				   idx, section_name (ebl, idx), pos (chunk));
3250			    break;
3251			  }
3252		      }
3253		    if (tag == 32 || (tag & 1) != 0)
3254		      {
3255			r = memchr (r, '\0', q - r);
3256			if (r == NULL)
3257			  {
3258			    ERROR (gettext ("\
3259section [%2d] '%s': offset %zu: unterminated string in attribute\n"),
3260				   idx, section_name (ebl, idx), pos (chunk));
3261			    break;
3262			  }
3263			++r;
3264		      }
3265
3266		    const char *tag_name = NULL;
3267		    const char *value_name = NULL;
3268		    if (!ebl_check_object_attribute (ebl, (const char *) name,
3269						     tag, value,
3270						     &tag_name, &value_name))
3271		      ERROR (gettext ("\
3272section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"),
3273			     idx, section_name (ebl, idx), pos (chunk), tag);
3274		    else if ((tag & 1) == 0 && value_name == NULL)
3275		      ERROR (gettext ("\
3276section [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"),
3277			     idx, section_name (ebl, idx), pos (chunk),
3278			     tag_name, value);
3279
3280		    chunk = r;
3281		  }
3282	      }
3283	  }
3284      else
3285	ERROR (gettext ("\
3286section [%2d] '%s': offset %zu: vendor '%s' unknown\n"),
3287	       idx, section_name (ebl, idx), pos (p), name);
3288    }
3289
3290  if (left () != 0)
3291    ERROR (gettext ("\
3292section [%2d] '%s': offset %zu: extra bytes after last attribute section\n"),
3293	   idx, section_name (ebl, idx), pos (p));
3294}
3295
3296static bool has_loadable_segment;
3297static bool has_interp_segment;
3298
3299static const struct
3300{
3301  const char *name;
3302  size_t namelen;
3303  GElf_Word type;
3304  enum { unused, exact, atleast, exact_or_gnuld } attrflag;
3305  GElf_Word attr;
3306  GElf_Word attr2;
3307} special_sections[] =
3308  {
3309    /* See figure 4-14 in the gABI.  */
3310    { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3311    { ".comment", 8, SHT_PROGBITS, exact, 0, 0 },
3312    { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3313    { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
3314    { ".debug_str", 11, SHT_PROGBITS, exact_or_gnuld, SHF_MERGE | SHF_STRINGS, 0 },
3315    { ".debug", 6, SHT_PROGBITS, exact, 0, 0 },
3316    { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE },
3317    { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 },
3318    { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 },
3319    { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3320    { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3321    { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info?
3322    { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 },
3323    { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3324    { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3325    { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests?
3326    { ".line", 6, SHT_PROGBITS, exact, 0, 0 },
3327    { ".note", 6, SHT_NOTE, atleast, 0, SHF_ALLOC },
3328    { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
3329    { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
3330    { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC }, // XXX more tests
3331    { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC }, // XXX more tests
3332    { ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3333    { ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
3334    { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 },
3335    { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3336    { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
3337    { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests
3338    { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3339    { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3340    { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
3341    { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
3342
3343    /* The following are GNU extensions.  */
3344    { ".gnu.version", 13, SHT_GNU_versym, exact, SHF_ALLOC, 0 },
3345    { ".gnu.version_d", 15, SHT_GNU_verdef, exact, SHF_ALLOC, 0 },
3346    { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 },
3347    { ".gnu.attributes", 16, SHT_GNU_ATTRIBUTES, exact, 0, 0 },
3348  };
3349#define nspecial_sections \
3350  (sizeof (special_sections) / sizeof (special_sections[0]))
3351
3352#define IS_KNOWN_SPECIAL(idx, string, prefix)			      \
3353  (special_sections[idx].namelen == sizeof string - (prefix ? 1 : 0)  \
3354   && !memcmp (special_sections[idx].name, string, \
3355	       sizeof string - (prefix ? 1 : 0)))
3356
3357static void
3358check_sections (Ebl *ebl, GElf_Ehdr *ehdr)
3359{
3360  if (ehdr->e_shoff == 0)
3361    /* No section header.  */
3362    return;
3363
3364  /* Allocate array to count references in section groups.  */
3365  scnref = (int *) xcalloc (shnum, sizeof (int));
3366
3367  /* Check the zeroth section first.  It must not have any contents
3368     and the section header must contain nonzero value at most in the
3369     sh_size and sh_link fields.  */
3370  GElf_Shdr shdr_mem;
3371  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
3372  if (shdr == NULL)
3373    ERROR (gettext ("cannot get section header of zeroth section\n"));
3374  else
3375    {
3376      if (shdr->sh_name != 0)
3377	ERROR (gettext ("zeroth section has nonzero name\n"));
3378      if (shdr->sh_type != 0)
3379	ERROR (gettext ("zeroth section has nonzero type\n"));
3380      if (shdr->sh_flags != 0)
3381	ERROR (gettext ("zeroth section has nonzero flags\n"));
3382      if (shdr->sh_addr != 0)
3383	ERROR (gettext ("zeroth section has nonzero address\n"));
3384      if (shdr->sh_offset != 0)
3385	ERROR (gettext ("zeroth section has nonzero offset\n"));
3386      if (shdr->sh_info != 0)
3387	ERROR (gettext ("zeroth section has nonzero info field\n"));
3388      if (shdr->sh_addralign != 0)
3389	ERROR (gettext ("zeroth section has nonzero align value\n"));
3390      if (shdr->sh_entsize != 0)
3391	ERROR (gettext ("zeroth section has nonzero entry size value\n"));
3392
3393      if (shdr->sh_size != 0 && ehdr->e_shnum != 0)
3394	ERROR (gettext ("\
3395zeroth section has nonzero size value while ELF header has nonzero shnum value\n"));
3396
3397      if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX)
3398	ERROR (gettext ("\
3399zeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n"));
3400    }
3401
3402  int *segment_flags = xcalloc (ehdr->e_phnum, sizeof segment_flags[0]);
3403
3404  bool dot_interp_section = false;
3405
3406  size_t hash_idx = 0;
3407  size_t gnu_hash_idx = 0;
3408
3409  size_t versym_scnndx = 0;
3410  for (size_t cnt = 1; cnt < shnum; ++cnt)
3411    {
3412      shdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &shdr_mem);
3413      if (shdr == NULL)
3414	{
3415	  ERROR (gettext ("\
3416cannot get section header for section [%2zu] '%s': %s\n"),
3417		 cnt, section_name (ebl, cnt), elf_errmsg (-1));
3418	  continue;
3419	}
3420
3421      const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
3422
3423      if (scnname == NULL)
3424	ERROR (gettext ("section [%2zu]: invalid name\n"), cnt);
3425      else
3426	{
3427	  /* Check whether it is one of the special sections defined in
3428	     the gABI.  */
3429	  size_t s;
3430	  for (s = 0; s < nspecial_sections; ++s)
3431	    if (strncmp (scnname, special_sections[s].name,
3432			 special_sections[s].namelen) == 0)
3433	      {
3434		char stbuf1[100];
3435		char stbuf2[100];
3436		char stbuf3[100];
3437
3438		GElf_Word good_type = special_sections[s].type;
3439		if (IS_KNOWN_SPECIAL (s, ".plt", false)
3440		    && ebl_bss_plt_p (ebl, ehdr))
3441		  good_type = SHT_NOBITS;
3442
3443		/* In a debuginfo file, any normal section can be SHT_NOBITS.
3444		   This is only invalid for DWARF sections and .shstrtab.  */
3445		if (shdr->sh_type != good_type
3446		    && (shdr->sh_type != SHT_NOBITS
3447			|| !is_debuginfo
3448			|| IS_KNOWN_SPECIAL (s, ".debug_str", false)
3449			|| IS_KNOWN_SPECIAL (s, ".debug", true)
3450			|| IS_KNOWN_SPECIAL (s, ".shstrtab", false)))
3451		  ERROR (gettext ("\
3452section [%2d] '%s' has wrong type: expected %s, is %s\n"),
3453			 (int) cnt, scnname,
3454			 ebl_section_type_name (ebl, special_sections[s].type,
3455						stbuf1, sizeof (stbuf1)),
3456			 ebl_section_type_name (ebl, shdr->sh_type,
3457						stbuf2, sizeof (stbuf2)));
3458
3459		if (special_sections[s].attrflag == exact
3460		    || special_sections[s].attrflag == exact_or_gnuld)
3461		  {
3462		    /* Except for the link order and group bit all the
3463		       other bits should match exactly.  */
3464		    if ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP))
3465			!= special_sections[s].attr
3466			&& (special_sections[s].attrflag == exact || !gnuld))
3467		      ERROR (gettext ("\
3468section [%2zu] '%s' has wrong flags: expected %s, is %s\n"),
3469			     cnt, scnname,
3470			     section_flags_string (special_sections[s].attr,
3471						   stbuf1, sizeof (stbuf1)),
3472			     section_flags_string (shdr->sh_flags
3473						   & ~SHF_LINK_ORDER,
3474						   stbuf2, sizeof (stbuf2)));
3475		  }
3476		else if (special_sections[s].attrflag == atleast)
3477		  {
3478		    if ((shdr->sh_flags & special_sections[s].attr)
3479			!= special_sections[s].attr
3480			|| ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP
3481						| special_sections[s].attr
3482						| special_sections[s].attr2))
3483			    != 0))
3484		      ERROR (gettext ("\
3485section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"),
3486			     cnt, scnname,
3487			     section_flags_string (special_sections[s].attr,
3488						   stbuf1, sizeof (stbuf1)),
3489			     section_flags_string (special_sections[s].attr2,
3490						   stbuf2, sizeof (stbuf2)),
3491			     section_flags_string (shdr->sh_flags
3492						   & ~(SHF_LINK_ORDER
3493						       | SHF_GROUP),
3494						   stbuf3, sizeof (stbuf3)));
3495		  }
3496
3497		if (strcmp (scnname, ".interp") == 0)
3498		  {
3499		    dot_interp_section = true;
3500
3501		    if (ehdr->e_type == ET_REL)
3502		      ERROR (gettext ("\
3503section [%2zu] '%s' present in object file\n"),
3504			     cnt, scnname);
3505
3506		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3507			&& !has_loadable_segment)
3508		      ERROR (gettext ("\
3509section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3510			     cnt, scnname);
3511		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3512			     && has_loadable_segment)
3513		      ERROR (gettext ("\
3514section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3515			     cnt, scnname);
3516		  }
3517		else
3518		  {
3519		    if (strcmp (scnname, ".symtab_shndx") == 0
3520			&& ehdr->e_type != ET_REL)
3521		      ERROR (gettext ("\
3522section [%2zu] '%s' is extension section index table in non-object file\n"),
3523			     cnt, scnname);
3524
3525		    /* These sections must have the SHF_ALLOC flag set iff
3526		       a loadable segment is available.
3527
3528		       .relxxx
3529		       .strtab
3530		       .symtab
3531		       .symtab_shndx
3532
3533		       Check that if there is a reference from the
3534		       loaded section these sections also have the
3535		       ALLOC flag set.  */
3536#if 0
3537		    // XXX TODO
3538		    if ((shdr->sh_flags & SHF_ALLOC) != 0
3539			&& !has_loadable_segment)
3540		      ERROR (gettext ("\
3541section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
3542			     cnt, scnname);
3543		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
3544			     && has_loadable_segment)
3545		      ERROR (gettext ("\
3546section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
3547			     cnt, scnname);
3548#endif
3549		  }
3550
3551		break;
3552	      }
3553	}
3554
3555      if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize)
3556	ERROR (gettext ("\
3557section [%2zu] '%s': size not multiple of entry size\n"),
3558	       cnt, section_name (ebl, cnt));
3559
3560      if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL)
3561	ERROR (gettext ("cannot get section header\n"));
3562
3563      if (shdr->sh_type >= SHT_NUM
3564	  && shdr->sh_type != SHT_GNU_ATTRIBUTES
3565	  && shdr->sh_type != SHT_GNU_LIBLIST
3566	  && shdr->sh_type != SHT_CHECKSUM
3567	  && shdr->sh_type != SHT_GNU_verdef
3568	  && shdr->sh_type != SHT_GNU_verneed
3569	  && shdr->sh_type != SHT_GNU_versym
3570	  && ebl_section_type_name (ebl, shdr->sh_type, NULL, 0) == NULL)
3571	ERROR (gettext ("section [%2zu] '%s' has unsupported type %d\n"),
3572	       cnt, section_name (ebl, cnt),
3573	       (int) shdr->sh_type);
3574
3575#define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \
3576		      | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \
3577		      | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS)
3578      if (shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS)
3579	{
3580	  GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS;
3581	  if (sh_flags & SHF_MASKPROC)
3582	    {
3583	      if (!ebl_machine_section_flag_check (ebl,
3584						   sh_flags & SHF_MASKPROC))
3585		ERROR (gettext ("section [%2zu] '%s'"
3586				" contains invalid processor-specific flag(s)"
3587				" %#" PRIx64 "\n"),
3588		       cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
3589	      sh_flags &= ~(GElf_Xword) SHF_MASKPROC;
3590	    }
3591	  if (sh_flags != 0)
3592	    ERROR (gettext ("section [%2zu] '%s' contains unknown flag(s)"
3593			    " %#" PRIx64 "\n"),
3594		   cnt, section_name (ebl, cnt), sh_flags);
3595	}
3596      if (shdr->sh_flags & SHF_TLS)
3597	{
3598	  // XXX Correct?
3599	  if (shdr->sh_addr != 0 && !gnuld)
3600	    ERROR (gettext ("\
3601section [%2zu] '%s': thread-local data sections address not zero\n"),
3602		   cnt, section_name (ebl, cnt));
3603
3604	  // XXX TODO more tests!?
3605	}
3606
3607      if (shdr->sh_link >= shnum)
3608	ERROR (gettext ("\
3609section [%2zu] '%s': invalid section reference in link value\n"),
3610	       cnt, section_name (ebl, cnt));
3611
3612      if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum)
3613	ERROR (gettext ("\
3614section [%2zu] '%s': invalid section reference in info value\n"),
3615	       cnt, section_name (ebl, cnt));
3616
3617      if ((shdr->sh_flags & SHF_MERGE) == 0
3618	  && (shdr->sh_flags & SHF_STRINGS) != 0
3619	  && be_strict)
3620	ERROR (gettext ("\
3621section [%2zu] '%s': strings flag set without merge flag\n"),
3622	       cnt, section_name (ebl, cnt));
3623
3624      if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0)
3625	ERROR (gettext ("\
3626section [%2zu] '%s': merge flag set but entry size is zero\n"),
3627	       cnt, section_name (ebl, cnt));
3628
3629      if (shdr->sh_flags & SHF_GROUP)
3630	check_scn_group (ebl, cnt);
3631
3632      if (shdr->sh_flags & SHF_EXECINSTR)
3633	{
3634	  switch (shdr->sh_type)
3635	    {
3636	    case SHT_PROGBITS:
3637	      break;
3638
3639	    case SHT_NOBITS:
3640	      if (is_debuginfo)
3641		break;
3642	    default:
3643	      ERROR (gettext ("\
3644section [%2zu] '%s' has unexpected type %d for an executable section\n"),
3645		     cnt, section_name (ebl, cnt), shdr->sh_type);
3646	      break;
3647	    }
3648
3649	  if ((shdr->sh_flags & SHF_WRITE)
3650	      && !ebl_check_special_section (ebl, cnt, shdr,
3651					     section_name (ebl, cnt)))
3652	    ERROR (gettext ("\
3653section [%2zu] '%s' is both executable and writable\n"),
3654		   cnt, section_name (ebl, cnt));
3655	}
3656
3657      if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0)
3658	{
3659	  /* Make sure the section is contained in a loaded segment
3660	     and that the initialization part matches NOBITS sections.  */
3661	  int pcnt;
3662	  GElf_Phdr phdr_mem;
3663	  GElf_Phdr *phdr;
3664
3665	  for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
3666	    if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL
3667		&& ((phdr->p_type == PT_LOAD
3668		     && (shdr->sh_flags & SHF_TLS) == 0)
3669		    || (phdr->p_type == PT_TLS
3670			&& (shdr->sh_flags & SHF_TLS) != 0))
3671		&& phdr->p_offset <= shdr->sh_offset
3672		&& (phdr->p_offset + phdr->p_filesz > shdr->sh_offset
3673		    || (phdr->p_offset + phdr->p_memsz > shdr->sh_offset
3674			&& shdr->sh_type == SHT_NOBITS)))
3675	      {
3676		/* Found the segment.  */
3677		if (phdr->p_offset + phdr->p_memsz
3678		    < shdr->sh_offset + shdr->sh_size)
3679		  ERROR (gettext ("\
3680section [%2zu] '%s' not fully contained in segment of program header entry %d\n"),
3681			 cnt, section_name (ebl, cnt), pcnt);
3682
3683		if (shdr->sh_type == SHT_NOBITS)
3684		  {
3685		    if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz
3686			&& !is_debuginfo)
3687		      ERROR (gettext ("\
3688section [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"),
3689			 cnt, section_name (ebl, cnt), pcnt);
3690		  }
3691		else
3692		  {
3693		    const GElf_Off end = phdr->p_offset + phdr->p_filesz;
3694		    if (shdr->sh_offset > end ||
3695			(shdr->sh_offset == end && shdr->sh_size != 0))
3696		      ERROR (gettext ("\
3697section [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"),
3698			 cnt, section_name (ebl, cnt), pcnt);
3699		  }
3700
3701		if (shdr->sh_type != SHT_NOBITS)
3702		  {
3703		    if ((shdr->sh_flags & SHF_EXECINSTR) != 0)
3704		      {
3705			segment_flags[pcnt] |= PF_X;
3706			if ((phdr->p_flags & PF_X) == 0)
3707			  ERROR (gettext ("\
3708section [%2zu] '%s' is executable in nonexecutable segment %d\n"),
3709				 cnt, section_name (ebl, cnt), pcnt);
3710		      }
3711
3712		    if ((shdr->sh_flags & SHF_WRITE) != 0)
3713		      {
3714			segment_flags[pcnt] |= PF_W;
3715			if (0	/* XXX vdso images have this */
3716			    && (phdr->p_flags & PF_W) == 0)
3717			  ERROR (gettext ("\
3718section [%2zu] '%s' is writable in unwritable segment %d\n"),
3719				 cnt, section_name (ebl, cnt), pcnt);
3720		      }
3721		  }
3722
3723		break;
3724	      }
3725
3726	  if (pcnt == ehdr->e_phnum)
3727	    ERROR (gettext ("\
3728section [%2zu] '%s': alloc flag set but section not in any loaded segment\n"),
3729		   cnt, section_name (ebl, cnt));
3730	}
3731
3732      if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB)
3733	ERROR (gettext ("\
3734section [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"),
3735	       cnt, section_name (ebl, cnt));
3736
3737      switch (shdr->sh_type)
3738	{
3739	case SHT_DYNSYM:
3740	  if (ehdr->e_type == ET_REL)
3741	    ERROR (gettext ("\
3742section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"),
3743		   cnt, section_name (ebl, cnt));
3744	  /* FALLTHROUGH */
3745	case SHT_SYMTAB:
3746	  check_symtab (ebl, ehdr, shdr, cnt);
3747	  break;
3748
3749	case SHT_RELA:
3750	  check_rela (ebl, ehdr, shdr, cnt);
3751	  break;
3752
3753	case SHT_REL:
3754	  check_rel (ebl, ehdr, shdr, cnt);
3755	  break;
3756
3757	case SHT_DYNAMIC:
3758	  check_dynamic (ebl, ehdr, shdr, cnt);
3759	  break;
3760
3761	case SHT_SYMTAB_SHNDX:
3762	  check_symtab_shndx (ebl, ehdr, shdr, cnt);
3763	  break;
3764
3765	case SHT_HASH:
3766	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
3767	  hash_idx = cnt;
3768	  break;
3769
3770	case SHT_GNU_HASH:
3771	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
3772	  gnu_hash_idx = cnt;
3773	  break;
3774
3775	case SHT_NULL:
3776	  check_null (ebl, shdr, cnt);
3777	  break;
3778
3779	case SHT_GROUP:
3780	  check_group (ebl, ehdr, shdr, cnt);
3781	  break;
3782
3783	case SHT_NOTE:
3784	  check_note_section (ebl, ehdr, shdr, cnt);
3785	  break;
3786
3787	case SHT_GNU_versym:
3788	  /* We cannot process this section now since we have no guarantee
3789	     that the verneed and verdef sections have already been read.
3790	     Just remember the section index.  */
3791	  if (versym_scnndx != 0)
3792	    ERROR (gettext ("more than one version symbol table present\n"));
3793	  versym_scnndx = cnt;
3794	  break;
3795
3796	case SHT_GNU_verneed:
3797	  check_verneed (ebl, ehdr, shdr, cnt);
3798	  break;
3799
3800	case SHT_GNU_verdef:
3801	  check_verdef (ebl, shdr, cnt);
3802	  break;
3803
3804	case SHT_GNU_ATTRIBUTES:
3805	  check_attributes (ebl, ehdr, shdr, cnt);
3806	  break;
3807
3808	default:
3809	  /* Nothing.  */
3810	  break;
3811	}
3812    }
3813
3814  if (has_interp_segment && !dot_interp_section)
3815    ERROR (gettext ("INTERP program header entry but no .interp section\n"));
3816
3817  if (!is_debuginfo)
3818    for (int pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
3819      {
3820	GElf_Phdr phdr_mem;
3821	GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
3822	if (phdr != NULL && (phdr->p_type == PT_LOAD || phdr->p_type == PT_TLS))
3823	  {
3824	    if ((phdr->p_flags & PF_X) != 0
3825		&& (segment_flags[pcnt] & PF_X) == 0)
3826	      ERROR (gettext ("\
3827loadable segment [%u] is executable but contains no executable sections\n"),
3828		     pcnt);
3829
3830	    if ((phdr->p_flags & PF_W) != 0
3831		&& (segment_flags[pcnt] & PF_W) == 0)
3832	      ERROR (gettext ("\
3833loadable segment [%u] is writable but contains no writable sections\n"),
3834		     pcnt);
3835	  }
3836      }
3837
3838  free (segment_flags);
3839
3840  if (version_namelist != NULL)
3841    {
3842      if (versym_scnndx == 0)
3843    ERROR (gettext ("\
3844no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section exist\n"));
3845      else
3846	check_versym (ebl, versym_scnndx);
3847
3848      /* Check for duplicate index numbers.  */
3849      do
3850	{
3851	  struct version_namelist *runp = version_namelist->next;
3852	  while (runp != NULL)
3853	    {
3854	      if (version_namelist->ndx == runp->ndx)
3855		{
3856		  ERROR (gettext ("duplicate version index %d\n"),
3857			 (int) version_namelist->ndx);
3858		  break;
3859		}
3860	      runp = runp->next;
3861	    }
3862
3863	  struct version_namelist *old = version_namelist;
3864	  version_namelist = version_namelist->next;
3865	  free (old);
3866	}
3867      while (version_namelist != NULL);
3868    }
3869  else if (versym_scnndx != 0)
3870    ERROR (gettext ("\
3871.gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"));
3872
3873  if (hash_idx != 0 && gnu_hash_idx != 0)
3874    compare_hash_gnu_hash (ebl, ehdr, hash_idx, gnu_hash_idx);
3875
3876  free (scnref);
3877}
3878
3879
3880static GElf_Off
3881check_note_data (Ebl *ebl, const GElf_Ehdr *ehdr,
3882		 Elf_Data *data, int shndx, int phndx, GElf_Off start)
3883{
3884  size_t offset = 0;
3885  size_t last_offset = 0;
3886  GElf_Nhdr nhdr;
3887  size_t name_offset;
3888  size_t desc_offset;
3889  while (offset < data->d_size
3890	 && (offset = gelf_getnote (data, offset,
3891				    &nhdr, &name_offset, &desc_offset)) > 0)
3892    {
3893      last_offset = offset;
3894
3895      /* Make sure it is one of the note types we know about.  */
3896      if (ehdr->e_type == ET_CORE)
3897	switch (nhdr.n_type)
3898	  {
3899	  case NT_PRSTATUS:
3900	  case NT_FPREGSET:
3901	  case NT_PRPSINFO:
3902	  case NT_TASKSTRUCT:		/* NT_PRXREG on Solaris.  */
3903	  case NT_PLATFORM:
3904	  case NT_AUXV:
3905	  case NT_GWINDOWS:
3906	  case NT_ASRS:
3907	  case NT_PSTATUS:
3908	  case NT_PSINFO:
3909	  case NT_PRCRED:
3910	  case NT_UTSNAME:
3911	  case NT_LWPSTATUS:
3912	  case NT_LWPSINFO:
3913	  case NT_PRFPXREG:
3914	    /* Known type.  */
3915	    break;
3916
3917	  default:
3918	    if (shndx == 0)
3919	      ERROR (gettext ("\
3920phdr[%d]: unknown core file note type %" PRIu32 " at offset %" PRIu64 "\n"),
3921		     phndx, (uint32_t) nhdr.n_type, start + offset);
3922	    else
3923	      ERROR (gettext ("\
3924section [%2d] '%s': unknown core file note type %" PRIu32
3925			      " at offset %Zu\n"),
3926		     shndx, section_name (ebl, shndx),
3927		     (uint32_t) nhdr.n_type, offset);
3928	  }
3929      else
3930	switch (nhdr.n_type)
3931	  {
3932	  case NT_GNU_ABI_TAG:
3933	  case NT_GNU_HWCAP:
3934	  case NT_GNU_BUILD_ID:
3935	    break;
3936
3937	  case 0:
3938	    /* Linux vDSOs use a type 0 note for the kernel version word.  */
3939	    if (nhdr.n_namesz == sizeof "Linux"
3940		&& !memcmp (data->d_buf + name_offset, "Linux", sizeof "Linux"))
3941	      break;
3942
3943	  default:
3944	    if (shndx == 0)
3945	      ERROR (gettext ("\
3946phdr[%d]: unknown object file note type %" PRIu32 " at offset %Zu\n"),
3947		     phndx, (uint32_t) nhdr.n_type, offset);
3948	    else
3949	      ERROR (gettext ("\
3950section [%2d] '%s': unknown object file note type %" PRIu32
3951			      " at offset %Zu\n"),
3952		     shndx, section_name (ebl, shndx),
3953		     (uint32_t) nhdr.n_type, offset);
3954	  }
3955    }
3956
3957  return last_offset;
3958}
3959
3960static void
3961check_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt)
3962{
3963  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
3964      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
3965    ERROR (gettext ("\
3966phdr[%d]: no note entries defined for the type of file\n"),
3967	   cnt);
3968
3969  if (is_debuginfo)
3970    /* The p_offset values in a separate debug file are bogus.  */
3971    return;
3972
3973  if (phdr->p_filesz == 0)
3974    return;
3975
3976  GElf_Off notes_size = 0;
3977  Elf_Data *data = elf_getdata_rawchunk (ebl->elf,
3978					 phdr->p_offset, phdr->p_filesz,
3979					 ELF_T_NHDR);
3980  if (data != NULL)
3981    notes_size = check_note_data (ebl, ehdr, data, 0, cnt, phdr->p_offset);
3982
3983  if (notes_size == 0)
3984    ERROR (gettext ("phdr[%d]: cannot get content of note section: %s\n"),
3985	   cnt, elf_errmsg (-1));
3986  else if (notes_size != phdr->p_filesz)
3987    ERROR (gettext ("phdr[%d]: extra %" PRIu64 " bytes after last note\n"),
3988	   cnt, phdr->p_filesz - notes_size);
3989}
3990
3991static void
3992check_note_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
3993{
3994  if (shdr->sh_size == 0)
3995    return;
3996
3997  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
3998  if (data == NULL)
3999    {
4000      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
4001	     idx, section_name (ebl, idx));
4002      return;
4003    }
4004
4005  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
4006      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
4007    ERROR (gettext ("\
4008section [%2d] '%s': no note entries defined for the type of file\n"),
4009	     idx, section_name (ebl, idx));
4010
4011  GElf_Off notes_size = check_note_data (ebl, ehdr, data, idx, 0, 0);
4012
4013  if (notes_size == 0)
4014    ERROR (gettext ("section [%2d] '%s': cannot get content of note section\n"),
4015	   idx, section_name (ebl, idx));
4016  else if (notes_size != shdr->sh_size)
4017    ERROR (gettext ("section [%2d] '%s': extra %" PRIu64
4018		    " bytes after last note\n"),
4019	   idx, section_name (ebl, idx), shdr->sh_size - notes_size);
4020}
4021
4022static void
4023check_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
4024{
4025  if (ehdr->e_phoff == 0)
4026    return;
4027
4028  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
4029      && ehdr->e_type != ET_CORE)
4030    ERROR (gettext ("\
4031only executables, shared objects, and core files can have program headers\n"));
4032
4033  int num_pt_interp = 0;
4034  int num_pt_tls = 0;
4035  int num_pt_relro = 0;
4036
4037  for (int cnt = 0; cnt < ehdr->e_phnum; ++cnt)
4038    {
4039      GElf_Phdr phdr_mem;
4040      GElf_Phdr *phdr;
4041
4042      phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
4043      if (phdr == NULL)
4044	{
4045	  ERROR (gettext ("cannot get program header entry %d: %s\n"),
4046		 cnt, elf_errmsg (-1));
4047	  continue;
4048	}
4049
4050      if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME
4051	  && phdr->p_type != PT_GNU_STACK && phdr->p_type != PT_GNU_RELRO
4052	  /* Check for a known machine-specific type.  */
4053	  && ebl_segment_type_name (ebl, phdr->p_type, NULL, 0) == NULL)
4054	ERROR (gettext ("\
4055program header entry %d: unknown program header entry type %#" PRIx64 "\n"),
4056	       cnt, (uint64_t) phdr->p_type);
4057
4058      if (phdr->p_type == PT_LOAD)
4059	has_loadable_segment = true;
4060      else if (phdr->p_type == PT_INTERP)
4061	{
4062	  if (++num_pt_interp != 1)
4063	    {
4064	      if (num_pt_interp == 2)
4065		ERROR (gettext ("\
4066more than one INTERP entry in program header\n"));
4067	    }
4068	  has_interp_segment = true;
4069	}
4070      else if (phdr->p_type == PT_TLS)
4071	{
4072	  if (++num_pt_tls == 2)
4073	    ERROR (gettext ("more than one TLS entry in program header\n"));
4074	}
4075      else if (phdr->p_type == PT_NOTE)
4076	check_note (ebl, ehdr, phdr, cnt);
4077      else if (phdr->p_type == PT_DYNAMIC)
4078	{
4079	  if (ehdr->e_type == ET_EXEC && ! has_interp_segment)
4080	    ERROR (gettext ("\
4081static executable cannot have dynamic sections\n"));
4082	  else
4083	    {
4084	      /* Check that the .dynamic section, if it exists, has
4085		 the same address.  */
4086	      Elf_Scn *scn = NULL;
4087	      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
4088		{
4089		  GElf_Shdr shdr_mem;
4090		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
4091		  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
4092		    {
4093		      if (phdr->p_offset != shdr->sh_offset)
4094			ERROR (gettext ("\
4095dynamic section reference in program header has wrong offset\n"));
4096		      if (phdr->p_memsz != shdr->sh_size)
4097			ERROR (gettext ("\
4098dynamic section size mismatch in program and section header\n"));
4099		      break;
4100		    }
4101		}
4102	    }
4103	}
4104      else if (phdr->p_type == PT_GNU_RELRO)
4105	{
4106	  if (++num_pt_relro == 2)
4107	    ERROR (gettext ("\
4108more than one GNU_RELRO entry in program header\n"));
4109	  else
4110	    {
4111	      /* Check that the region is in a writable segment.  */
4112	      int inner;
4113	      for (inner = 0; inner < ehdr->e_phnum; ++inner)
4114		{
4115		  GElf_Phdr phdr2_mem;
4116		  GElf_Phdr *phdr2;
4117
4118		  phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
4119		  if (phdr2 == NULL)
4120		    continue;
4121
4122		  if (phdr2->p_type == PT_LOAD
4123		      && phdr->p_vaddr >= phdr2->p_vaddr
4124		      && (phdr->p_vaddr + phdr->p_memsz
4125			  <= phdr2->p_vaddr + phdr2->p_memsz))
4126		    {
4127		      if ((phdr2->p_flags & PF_W) == 0)
4128			ERROR (gettext ("\
4129loadable segment GNU_RELRO applies to is not writable\n"));
4130		      if ((phdr2->p_flags &~ PF_W) != (phdr->p_flags &~ PF_W))
4131			ERROR (gettext ("\
4132loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"),
4133			       cnt, inner);
4134		      break;
4135		    }
4136		}
4137
4138	      if (inner >= ehdr->e_phnum)
4139		ERROR (gettext ("\
4140%s segment not contained in a loaded segment\n"), "GNU_RELRO");
4141	    }
4142	}
4143      else if (phdr->p_type == PT_PHDR)
4144	{
4145	  /* Check that the region is in a writable segment.  */
4146	  int inner;
4147	  for (inner = 0; inner < ehdr->e_phnum; ++inner)
4148	    {
4149	      GElf_Phdr phdr2_mem;
4150	      GElf_Phdr *phdr2;
4151
4152	      phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
4153	      if (phdr2 != NULL
4154		  && phdr2->p_type == PT_LOAD
4155		  && phdr->p_vaddr >= phdr2->p_vaddr
4156		  && (phdr->p_vaddr + phdr->p_memsz
4157		      <= phdr2->p_vaddr + phdr2->p_memsz))
4158		break;
4159	    }
4160
4161	  if (inner >= ehdr->e_phnum)
4162	    ERROR (gettext ("\
4163%s segment not contained in a loaded segment\n"), "PHDR");
4164
4165	  /* Check that offset in segment corresponds to offset in ELF
4166	     header.  */
4167	  if (phdr->p_offset != ehdr->e_phoff)
4168	    ERROR (gettext ("\
4169program header offset in ELF header and PHDR entry do not match"));
4170	}
4171
4172      if (phdr->p_filesz > phdr->p_memsz
4173	  && (phdr->p_memsz != 0 || phdr->p_type != PT_NOTE))
4174	ERROR (gettext ("\
4175program header entry %d: file size greater than memory size\n"),
4176	       cnt);
4177
4178      if (phdr->p_align > 1)
4179	{
4180	  if (!powerof2 (phdr->p_align))
4181	    ERROR (gettext ("\
4182program header entry %d: alignment not a power of 2\n"), cnt);
4183	  else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0)
4184	    ERROR (gettext ("\
4185program header entry %d: file offset and virtual address not module of alignment\n"), cnt);
4186	}
4187    }
4188}
4189
4190
4191/* Process one file.  */
4192static void
4193process_elf_file (Elf *elf, const char *prefix, const char *suffix,
4194		  const char *fname, size_t size, bool only_one)
4195{
4196  /* Reset variables.  */
4197  ndynamic = 0;
4198  nverneed = 0;
4199  nverdef = 0;
4200  textrel = false;
4201  needed_textrel = false;
4202  has_loadable_segment = false;
4203  has_interp_segment = false;
4204
4205  GElf_Ehdr ehdr_mem;
4206  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
4207  Ebl *ebl;
4208
4209  /* Print the file name.  */
4210  if (!only_one)
4211    {
4212      if (prefix != NULL)
4213	printf ("\n%s(%s)%s:\n", prefix, fname, suffix);
4214      else
4215	printf ("\n%s:\n", fname);
4216    }
4217
4218  if (ehdr == NULL)
4219    {
4220      ERROR (gettext ("cannot read ELF header: %s\n"), elf_errmsg (-1));
4221      return;
4222    }
4223
4224  ebl = ebl_openbackend (elf);
4225  /* If there is no appropriate backend library we cannot test
4226     architecture and OS specific features.  Any encountered extension
4227     is an error.  */
4228
4229  /* Go straight by the gABI, check all the parts in turn.  */
4230  check_elf_header (ebl, ehdr, size);
4231
4232  /* Check the program header.  */
4233  check_program_header (ebl, ehdr);
4234
4235  /* Next the section headers.  It is OK if there are no section
4236     headers at all.  */
4237  check_sections (ebl, ehdr);
4238
4239  /* Report if no relocation section needed the text relocation flag.  */
4240  if (textrel && !needed_textrel)
4241    ERROR (gettext ("text relocation flag set but not needed\n"));
4242
4243  /* Free the resources.  */
4244  ebl_closebackend (ebl);
4245}
4246
4247
4248#include "debugpred.h"
4249