elflint.c revision 441f72d43a9b550baa779fc82f70816da5f74f0e
1441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Pedantic checking of ELF files compliance with gABI/psABI spec.
2441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc.
3441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
4441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   This program is Open Source software; you can redistribute it and/or
6441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   modify it under the terms of the Open Software License version 1.0 as
7441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   published by the Open Source Initiative.
8441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
9441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   You should have received a copy of the Open Software License along
10441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   with this program; if not, you may obtain a copy of the Open Software
11441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   License version 1.0 from http://www.opensource.org/licenses/osl.php or
12441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   3001 King Ranch Road, Ukiah, CA 95482.   */
14441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
15441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifdef HAVE_CONFIG_H
16441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project# include <config.h>
17441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif
18441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
19441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <argp.h>
20441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <assert.h>
21441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <byteswap.h>
22441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <endian.h>
23441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <error.h>
24441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <fcntl.h>
25441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <gelf.h>
26441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <inttypes.h>
27441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libebl.h>
28441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libintl.h>
29441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <locale.h>
30441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdbool.h>
31441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdlib.h>
32441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <string.h>
33441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <unistd.h>
34441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <sys/param.h>
35441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
36441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <elf-knowledge.h>
37441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <system.h>
38441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
39441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
40441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Name and version of program.  */
41441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void print_version (FILE *stream, struct argp_state *state);
42441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectvoid (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
43441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
44441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
45441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define ARGP_strict	300
46441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define ARGP_gnuld	301
47441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
48441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Definitions of arguments for argp functions.  */
49441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const struct argp_option options[] =
50441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
51441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
52441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "strict", ARGP_strict, NULL, 0,
53441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    N_("Be extremely strict, flag level 2 features.") },
54441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "quiet", 'q', NULL, 0, N_("Do not print anything if successful") },
55441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "gnu-ld", ARGP_gnuld, NULL, 0,
56441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    N_("Binary has been created with GNU ld and is therefore known to be \
57441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectbroken in certain ways") },
58441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { NULL, 0, NULL, 0, NULL }
59441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project};
60441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
61441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Short description of program.  */
62441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char doc[] = N_("\
63441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectPedantic checking of ELF files compliance with gABI/psABI spec.");
64441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
65441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Strings for arguments in help texts.  */
66441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char args_doc[] = N_("FILE...");
67441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
68441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Prototype for option handler.  */
69441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
70441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
71441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Function to print some extra text in the help message.  */
72441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic char *more_help (int key, const char *text, void *input);
73441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
74441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Data structure to communicate with argp functions.  */
75441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic struct argp argp =
76441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
77441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  options, parse_opt, args_doc, doc, NULL, more_help
78441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project};
79441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
80441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
81441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Declarations of local functions.  */
82441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void process_file (int fd, Elf *elf, const char *prefix,
83441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  const char *suffix, const char *fname, size_t size,
84441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  bool only_one);
85441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void process_elf_file (Elf *elf, const char *prefix, const char *suffix,
86441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      const char *fname, size_t size, bool only_one);
87441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
88441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Report an error.  */
89441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define ERROR(str, args...) \
90441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  do {									      \
91441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    printf (str, ##args);						      \
92441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ++error_count;							      \
93441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  } while (0)
94441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int error_count;
95441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
96441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if we should perform very strict testing.  */
97441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool be_strict;
98441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
99441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if no message is to be printed if the run is succesful.  */
100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool be_quiet;
101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if binary is assumed to be generated with GNU ld.  */
103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool gnuld;
104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Index of section header string table.  */
106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic uint32_t shstrndx;
107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Array to count references in section groups.  */
109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int *scnref;
110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectint
113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmain (int argc, char *argv[])
114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int remaining;
116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool only_one;
117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Set locale.  */
119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  setlocale (LC_ALL, "");
120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Initialize the message catalog.  */
122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  textdomain (PACKAGE);
123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Parse and process arguments.  */
125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If no ELF file is given punt.  */
128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (remaining >= argc)
129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 program_invocation_short_name);
132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      exit (1);
133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Before we start tell the ELF library which version we are using.  */
136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  elf_version (EV_CURRENT);
137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Now process all the files given at the command line.  */
139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  only_one = remaining + 1 == argc;
140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  do
141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      int fd;
143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Elf *elf;
144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Open the file.  */
146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      fd = open (argv[remaining], O_RDONLY);
147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (fd == -1)
148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("cannot open input file"));
150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  continue;
151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Create an `Elf' descriptor.  */
154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (elf == NULL)
156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("cannot generate Elf descriptor: %s\n"),
157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       elf_errmsg (-1));
158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int prev_error_count = error_count;
161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  struct stat64 st;
162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (fstat64 (fd, &st) != 0)
164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      printf ("cannot stat '%s': %m\n", argv[remaining]);
166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      close (fd);
167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      continue;
168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  process_file (fd, elf, NULL, NULL, argv[remaining], st.st_size,
171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			only_one);
172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Now we can close the descriptor.  */
174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (elf_end (elf) != 0)
175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("error while closing Elf descriptor: %s\n"),
176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   elf_errmsg (-1));
177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (prev_error_count == error_count && !be_quiet)
179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    puts (gettext ("No errors"));
180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      close (fd);
183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (++remaining < argc);
185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return error_count != 0;
187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Handle program arguments.  */
191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic error_t
192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectparse_opt (int key, char *arg, struct argp_state *state)
193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  switch (key)
195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case ARGP_strict:
197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      be_strict = true;
198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'q':
201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      be_quiet = true;
202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case ARGP_gnuld:
205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      gnuld = true;
206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
207441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    default:
209441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return ARGP_ERR_UNKNOWN;
210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return 0;
212441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic char *
216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmore_help (int key, const char *text, void *input)
217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *buf;
219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  switch (key)
221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case ARGP_KEY_HELP_EXTRA:
223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* We print some extra information.  */
224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    PACKAGE_BUGREPORT) < 0)
226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	buf = NULL;
227441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return buf;
228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    default:
230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return (char *) text;
233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print the version information.  */
237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_version (FILE *stream, struct argp_state *state)
239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fprintf (stream, "elflint (%s) %s\n", PACKAGE_NAME, VERSION);
241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fprintf (stream, gettext ("\
242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectCopyright (C) %s Red Hat, Inc.\n\
243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectThis is free software; see the source for copying conditions.  There is NO\n\
244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project"), "2004");
246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Process one file.  */
251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprocess_file (int fd, Elf *elf, const char *prefix, const char *suffix,
253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      const char *fname, size_t size, bool only_one)
254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We can handle two types of files: ELF files and archives.  */
256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Kind kind = elf_kind (elf);
257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  switch (kind)
259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case ELF_K_ELF:
261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Yes!  It's an ELF file.  */
262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      process_elf_file (elf, prefix, suffix, fname, size, only_one);
263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case ELF_K_AR:
266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	Elf *subelf;
268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	Elf_Cmd cmd = ELF_C_READ_MMAP;
269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	size_t fname_len = strlen (fname) + 1;
271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	char new_prefix[prefix_len + 1 + fname_len];
272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	char new_suffix[(suffix == NULL ? 0 : strlen (suffix)) + 2];
273441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	char *cp = new_prefix;
274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Create the full name of the file.  */
276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (prefix != NULL)
277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    cp = mempcpy (cp, prefix, prefix_len);
279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    *cp++ = '(';
280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    strcpy (stpcpy (new_suffix, suffix), ")");
281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	else
283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  new_suffix[0] = '\0';
284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	memcpy (cp, fname, fname_len);
285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* It's an archive.  We process each file in it.  */
287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    kind = elf_kind (subelf);
290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* Call this function recursively.  */
292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (kind == ELF_K_ELF || kind == ELF_K_AR)
293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      {
294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		Elf_Arhdr *arhdr = elf_getarhdr (subelf);
295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		assert (arhdr != NULL);
296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		process_file (fd, subelf, new_prefix, new_suffix,
298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      arhdr->ar_name, arhdr->ar_size, false);
299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      }
300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* Get next archive element.  */
302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    cmd = elf_next (subelf);
303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (elf_end (subelf) != 0)
304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ERROR (gettext (" error while freeing sub-ELF descriptor: %s\n"),
305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     elf_errmsg (-1));
306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    default:
311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* We cannot do anything.  */
312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("\
313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectNot an ELF file - it has the wrong magic bytes at the start"));
314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
319441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *
320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection_name (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr shdr_mem;
323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *shdr;
324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr = gelf_getshdr (elf_getscn (ebl->elf, idx), &shdr_mem);
326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const int valid_e_machine[] =
332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  {
333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    EM_M32, EM_SPARC, EM_386, EM_68K, EM_88K, EM_860, EM_MIPS, EM_S370,
334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    EM_MIPS_RS3_LE, EM_PARISC, EM_VPP500, EM_SPARC32PLUS, EM_960, EM_PPC,
335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    EM_PPC64, EM_S390, EM_V800, EM_FR20, EM_RH32, EM_RCE, EM_ARM,
336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    EM_FAKE_ALPHA, EM_SH, EM_SPARCV9, EM_TRICORE, EM_ARC, EM_H8_300,
337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    EM_H8_300H, EM_H8S, EM_H8_500, EM_IA_64, EM_MIPS_X, EM_COLDFIRE,
338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    EM_68HC12, EM_MMA, EM_PCP, EM_NCPU, EM_NDR1, EM_STARCORE, EM_ME16,
339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    EM_ST100, EM_TINYJ, EM_X86_64, EM_PDSP, EM_FX66, EM_ST9PLUS, EM_ST7,
340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX,
341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM,
342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300,
343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA
344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  };
345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define nvalid_e_machine \
346441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  (sizeof (valid_e_machine) / sizeof (valid_e_machine[0]))
347441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Number of sections.  */
350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic unsigned int shnum;
351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size)
355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char buf[512];
357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check e_ident field.  */
360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_ident[EI_MAG0] != ELFMAG0)
361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR ("e_ident[%d] != '%c'\n", EI_MAG0, ELFMAG0);
362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_ident[EI_MAG1] != ELFMAG1)
363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR ("e_ident[%d] != '%c'\n", EI_MAG1, ELFMAG1);
364441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_ident[EI_MAG2] != ELFMAG2)
365441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR ("e_ident[%d] != '%c'\n", EI_MAG2, ELFMAG2);
366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_ident[EI_MAG3] != ELFMAG3)
367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR ("e_ident[%d] != '%c'\n", EI_MAG3, ELFMAG3);
368441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
369441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_ident[EI_CLASS] != ELFCLASS32
370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      && ehdr->e_ident[EI_CLASS] != ELFCLASS64)
371441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("e_ident[%d] == %d is no known class\n"),
372441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   EI_CLASS, ehdr->e_ident[EI_CLASS]);
373441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
374441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB
375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      && ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("e_ident[%d] == %d is no known data encoding\n"),
377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   EI_DATA, ehdr->e_ident[EI_DATA]);
378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_ident[EI_VERSION] != EV_CURRENT)
380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("unknown ELF header version number e_ident[%d] == %d\n"),
381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   EI_VERSION, ehdr->e_ident[EI_VERSION]);
382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We currently don't handle any OS ABIs.  */
384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE)
385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("unsupported OS ABI e_ident[%d] == \"%s\"\n"),
386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   EI_OSABI,
387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* No ABI versions other than zero supported either.  */
390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_ident[EI_ABIVERSION] != 0)
391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("unsupport ABI version e_ident[%d] == %d\n"),
392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   EI_ABIVERSION, ehdr->e_ident[EI_ABIVERSION]);
393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = EI_PAD; cnt < EI_NIDENT; ++cnt)
395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    if (ehdr->e_ident[cnt] != 0)
396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("e_ident[%zu] is not zero\n"), cnt);
397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check the e_type field.  */
399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_type != ET_REL && ehdr->e_type != ET_EXEC
400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      && ehdr->e_type != ET_DYN && ehdr->e_type != ET_CORE)
401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("unknown object file type %d\n"), ehdr->e_type);
402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check the e_machine field.  */
404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 0; cnt < nvalid_e_machine; ++cnt)
405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    if (valid_e_machine[cnt] == ehdr->e_machine)
406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (cnt == nvalid_e_machine)
408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("unknown machine type %d\n"), ehdr->e_machine);
409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check the e_version field.  */
411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_version != EV_CURRENT)
412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("unknown object file version\n"));
413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check the e_phoff and e_phnum fields.  */
415441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_phoff == 0)
416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_phnum != 0)
418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid program header offset\n"));
419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectexecutables and DSOs cannot have zero program header offset\n"));
422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else if (ehdr->e_phnum == 0)
424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("invalid number of program header entries\n"));
425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check the e_shoff field.  */
427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shnum = ehdr->e_shnum;
428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shstrndx = ehdr->e_shstrndx;
429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_shoff == 0)
430441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_shnum != 0)
432441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid section header table offset\n"));
433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
434441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       && ehdr->e_type != ET_CORE)
435441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section header table must be present\n"));
436441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_shnum == 0)
440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Get the header of the zeroth section.  The sh_size field
442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     might contain the section number.  */
443441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr shdr_mem;
444441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr *shdr;
445441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
446441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
447441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr != NULL)
448441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
449441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The error will be reported later.  */
450441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr->sh_size == 0)
451441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		ERROR (gettext ("\
452441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectinvalid number of section header table entries\n"));
453441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else
454441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		shnum = shdr->sh_size;
455441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
456441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
457441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
458441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_shstrndx == SHN_XINDEX)
459441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
460441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Get the header of the zeroth section.  The sh_size field
461441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     might contain the section number.  */
462441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr shdr_mem;
463441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr *shdr;
464441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
465441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
466441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr != NULL)
467441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
468441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The error will be reported later.  */
469441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (shdr->sh_link >= shnum)
470441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		ERROR (gettext ("invalid section header index\n"));
471441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else
472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		shstrndx = shdr->sh_link;
473441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
474441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
475441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (shstrndx >= shnum)
476441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid section header index\n"));
477441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
478441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
479441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check the e_flags field.  */
480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (!ebl_machine_flag_check (ebl, ehdr->e_flags))
481441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("invalid machine flags: %s\n"),
482441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
483441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
484441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check e_ehsize, e_phentsize, and e_shentsize fields.  */
485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (gelf_getclass (ebl->elf) == ELFCLASS32)
486441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
487441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf32_Ehdr))
488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
489441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr))
491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid program header size: %hd\n"),
492441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       ehdr->e_phentsize);
493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
494441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid program header position or size\n"));
495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr))
497441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid section header size: %hd\n"),
498441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       ehdr->e_shentsize);
499441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid section header position or size\n"));
501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
502441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else if (gelf_getclass (ebl->elf) == ELFCLASS64)
503441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf64_Ehdr))
505441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
506441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
507441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr))
508441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid program header size: %hd\n"),
509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       ehdr->e_phentsize);
510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid program header position or size\n"));
512441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
513441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr))
514441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid section header size: %hd\n"),
515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       ehdr->e_shentsize);
516441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("invalid section header position or size\n"));
518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
519441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
521441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
522441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Check that there is a section group section with index < IDX which
523441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   contains section IDX and that there is exactly one.  */
524441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_scn_group (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
526441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
527441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (scnref[idx] == 0)
528441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* No reference so far.  Search following sections, maybe the
530441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 order is wrong.  */
531441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t cnt;
532441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
533441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (cnt = idx + 1; cnt < shnum; ++cnt)
534441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
535441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf_Scn *scn;
536441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr shdr_mem;
537441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr *shdr;
538441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf_Data *data;
539441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf32_Word *grpdata;
540441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  size_t inner;
541441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
542441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  scn = elf_getscn (ebl->elf, cnt);
543441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr = gelf_getshdr (scn, &shdr_mem);
544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr == NULL)
545441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* We cannot get the section header so we cannot check it.
546441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       The error to get the section header will be shown
547441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       somewhere else.  */
548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    continue;
549441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
550441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr->sh_type != SHT_GROUP)
551441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    continue;
552441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
553441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  data = elf_getdata (scn, NULL);
554441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (data == NULL || data->d_size < sizeof (Elf32_Word))
555441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* Cannot check the section.  */
556441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    continue;
557441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
558441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  grpdata = (Elf32_Word *) data->d_buf;
559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  for (inner = 1; inner < data->d_size / sizeof (Elf32_Word); ++inner)
560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (grpdata[inner] == (Elf32_Word) idx)
561441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      goto out;
562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
563441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
564441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    out:
565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (cnt == shnum)
566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
567441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section with SHF_GROUP flag set not part of a section group\n"),
568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx));
569441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
571441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section group [%2zu] '%s' does not preceed group member\n"),
572441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx),
573441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       cnt, section_name (ebl, ehdr, cnt));
574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
575441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
576441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
577441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
578441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
579441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
580441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
581441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool no_xndx_warned = false;
582441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int no_pt_tls = 0;
583441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
584441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn = elf_getscn (ebl->elf, idx);
585441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr shdr_mem;
586441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
587441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr strshdr_mem;
588441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
589441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     &strshdr_mem);
590441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr == NULL || strshdr == NULL)
591441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
592441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *data = elf_getdata (scn, NULL);
593441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
594441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
595441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
596441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     idx, section_name (ebl, ehdr, idx));
597441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
598441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
599441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
600441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (strshdr->sh_type != SHT_STRTAB)
601441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
602441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   shdr->sh_link, section_name (ebl, ehdr, shdr->sh_link),
603441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
604441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
605441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Search for an extended section index table section.  */
606441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
607441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr xndxshdr_mem;
608441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *xndxshdr = NULL;
609441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *xndxdata = NULL;
610441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf32_Word xndxscnidx = 0;
611441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 1; cnt < shnum; ++cnt)
612441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    if (cnt != (size_t) idx)
613441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
614441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	Elf_Scn *xndxscn = elf_getscn (ebl->elf, cnt);
615441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
616441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	xndxdata = elf_getdata (xndxscn, NULL);
617441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	xndxscnidx = elf_ndxscn (xndxscn);
618441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
619441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (xndxshdr == NULL || xndxdata == NULL)
620441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  continue;
621441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
622441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
623441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    && xndxshdr->sh_link == (GElf_Word) idx)
624441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (cnt == shnum)
627441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      xndxshdr = NULL;
629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      xndxdata = NULL;
630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
631441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
632441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT))
633441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': entry size is does not match ElfXX_Sym\n"),
635441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   cnt, section_name (ebl, ehdr, cnt));
636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
637441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Test the zeroth entry.  */
638441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Sym sym_mem;
639441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf32_Word xndx;
640441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, 0, &sym_mem, &xndx);
641441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (sym == NULL)
642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("section [%2d] '%s': cannot get symbol %d: %s\n"),
643441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     idx, section_name (ebl, ehdr, idx), 0, elf_errmsg (-1));
644441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
645441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (sym->st_name != 0)
647441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
648441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), "st_name");
649441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (sym->st_value != 0)
650441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
651441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), "st_value");
652441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (sym->st_size != 0)
653441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
654441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), "st_size");
655441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (sym->st_info != 0)
656441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
657441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), "st_info");
658441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (sym->st_other != 0)
659441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
660441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), "st_other");
661441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (sym->st_shndx != 0)
662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
663441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), "st_shndx");
664441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (xndxdata != NULL && xndx != 0)
665441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
666441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': XINDEX for zeroth entry not zero\n"),
667441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       xndxscnidx, section_name (ebl, ehdr, xndxscnidx));
668441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
669441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
670441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 1; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
672441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx);
673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (sym == NULL)
674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ERROR (gettext ("section [%2d] '%s': cannot get symbol %zu: %s\n"),
676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 idx, section_name (ebl, ehdr, idx), cnt, elf_errmsg (-1));
677441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  continue;
678441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
679441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
680441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      const char *name = NULL;
681441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (sym->st_name >= strshdr->sh_size)
682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
683441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: invalid name value\n"),
684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
685441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
686441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
687441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name);
688441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  assert (name != NULL);
689441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
690441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
691441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (sym->st_shndx == SHN_XINDEX)
692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (xndxdata == NULL)
694441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ERROR (gettext ("\
696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: too large section index but no extended section index section\n"),
697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     idx, section_name (ebl, ehdr, idx), cnt);
698441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      no_xndx_warned = true;
699441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
700441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (xndx < SHN_LORESERVE)
701441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
702441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: XINDEX used for index which would fit in st_shndx (%" PRIu32 ")\n"),
703441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   xndxscnidx, section_name (ebl, ehdr, xndxscnidx), cnt,
704441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   xndx);
705441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
706441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if ((sym->st_shndx >= SHN_LORESERVE
707441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		// && sym->st_shndx <= SHN_HIRESERVE    always true
708441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		&& sym->st_shndx != SHN_ABS
709441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		&& sym->st_shndx != SHN_COMMON)
710441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       || (sym->st_shndx >= shnum
711441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   && (sym->st_shndx < SHN_LORESERVE
712441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       /* || sym->st_shndx > SHN_HIRESERVE  always false */)))
713441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
714441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: invalid section index\n"),
715441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
716441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
717441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	xndx = sym->st_shndx;
718441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
719441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (GELF_ST_TYPE (sym->st_info) >= STT_NUM)
720441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': symbol %zu: unknown type\n"),
721441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
722441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (GELF_ST_BIND (sym->st_info) >= STB_NUM)
724441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
725441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: unknown symbol binding\n"),
726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (xndx == SHN_COMMON)
729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Common symbols can only appear in relocatable files.  */
731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (ehdr->e_type != ET_REL)
732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n"),
734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx), cnt);
735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (cnt < shdr->sh_info)
736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n"),
738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx), cnt);
739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (GELF_R_TYPE (sym->st_info) == STT_FUNC)
740441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"),
742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx), cnt);
743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (xndx > 0 && xndx < shnum)
745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr destshdr_mem;
747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr *destshdr;
748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), &destshdr_mem);
750441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (destshdr != NULL)
751441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (GELF_ST_TYPE (sym->st_info) != STT_TLS)
753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if ((sym->st_value - destshdr->sh_addr) > destshdr->sh_size)
755441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ERROR (gettext ("\
756441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: st_value out of bounds\n"),
757441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   idx, section_name (ebl, ehdr, idx), cnt);
758441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  else if ((sym->st_value - destshdr->sh_addr + sym->st_size)
759441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   > destshdr->sh_size)
760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ERROR (gettext ("\
761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   idx, section_name (ebl, ehdr, idx), cnt,
763441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   (int) xndx, section_name (ebl, ehdr, xndx));
764441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
765441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else
766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
767441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if ((destshdr->sh_flags & SHF_TLS) == 0)
768441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ERROR (gettext ("\
769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_TLS flag set\n"),
770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   idx, section_name (ebl, ehdr, idx), cnt,
771441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   (int) xndx, section_name (ebl, ehdr, xndx));
772441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (ehdr->e_type == ET_REL)
774441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      /* For object files the symbol value must fall
776441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project                         into the section.  */
777441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (sym->st_value > destshdr->sh_size)
778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ERROR (gettext ("\
779441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       idx, section_name (ebl, ehdr, idx), cnt,
781441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       (int) xndx, section_name (ebl, ehdr, xndx));
782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      else if (sym->st_value + sym->st_size
783441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       > destshdr->sh_size)
784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ERROR (gettext ("\
785441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
786441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       idx, section_name (ebl, ehdr, idx), cnt,
787441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       (int) xndx, section_name (ebl, ehdr, xndx));
788441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
789441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  else
790441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
791441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      GElf_Phdr phdr_mem;
792441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      GElf_Phdr *phdr = NULL;
793441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      int pcnt;
794441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
795441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
796441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			{
797441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
798441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  if (phdr != NULL && phdr->p_type == PT_TLS)
799441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    break;
800441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			}
801441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
802441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (pcnt == ehdr->e_phnum)
803441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			{
804441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  if (no_pt_tls++ == 0)
805441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    ERROR (gettext ("\
806441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"),
807441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				   idx, section_name (ebl, ehdr, idx), cnt);
808441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			}
809441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      else
810441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			{
811441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  if (sym->st_value
812441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      < destshdr->sh_offset - phdr->p_offset)
813441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    ERROR (gettext ("\
814441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"),
815441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				   idx, section_name (ebl, ehdr, idx), cnt,
816441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				   (int) xndx, section_name (ebl, ehdr, xndx));
817441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  else if (sym->st_value
818441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				   > (destshdr->sh_offset - phdr->p_offset
819441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				      + destshdr->sh_size))
820441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    ERROR (gettext ("\
821441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
822441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				   idx, section_name (ebl, ehdr, idx), cnt,
823441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				   (int) xndx, section_name (ebl, ehdr, xndx));
824441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  else if (sym->st_value + sym->st_size
825441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				   > (destshdr->sh_offset - phdr->p_offset
826441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				      + destshdr->sh_size))
827441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    ERROR (gettext ("\
828441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
829441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				   idx, section_name (ebl, ehdr, idx), cnt,
830441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				   (int) xndx, section_name (ebl, ehdr, xndx));
831441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			}
832441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
833441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
834441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
835441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
836441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
837441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
838441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
839441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (cnt >= shdr->sh_info)
840441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
841441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: local symbol outside range described in sh_info\n"),
842441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx), cnt);
843441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
844441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
845441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
846441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (cnt < shdr->sh_info)
847441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
848441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: non-local symbol outside range described in sh_info\n"),
849441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx), cnt);
850441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
851441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
852441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
853441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
854441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
855441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: non-local section symbol\n"),
856441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
857441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
858441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (name != NULL)
859441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
860441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
861441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
862441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Check that address and size match the global offset
863441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 table.  We have to locate the GOT by searching for a
864441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 section named ".got".  */
865441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      Elf_Scn *gscn = NULL;
866441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
867441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL)
868441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
869441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Shdr gshdr_mem;
870441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Shdr *gshdr = gelf_getshdr (gscn, &gshdr_mem);
871441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  assert (gshdr != NULL);
872441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
873441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  const char *sname = elf_strptr (ebl->elf, ehdr->e_shstrndx,
874441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						  gshdr->sh_name);
875441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (sname != NULL && strcmp (sname, ".got") == 0)
876441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
877441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      /* Found it.  */
878441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (sym->st_value != gshdr->sh_addr)
879441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			/* This test is more strict than the psABIs
880441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   which usually allow the symbol to be in the
881441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   middle of the .got section, allowing
882441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   negative offsets.  */
883441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ERROR (gettext ("\
884441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match .got section address %#" PRIx64 "\n"),
885441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       idx, section_name (ebl, ehdr, idx),
886441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       (uint64_t) sym->st_value,
887441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       (uint64_t) gshdr->sh_addr);
888441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
889441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (sym->st_size != gshdr->sh_size)
890441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ERROR (gettext ("\
891441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match .got section size %" PRIu64 "\n"),
892441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       idx, section_name (ebl, ehdr, idx),
893441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       (uint64_t) sym->st_size,
894441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       (uint64_t) gshdr->sh_size);
895441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
896441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      break;
897441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
898441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
899441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
900441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (gscn == NULL)
901441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		ERROR (gettext ("\
902441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"),
903441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       idx, section_name (ebl, ehdr, idx));
904441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
905441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (strcmp (name, "_DYNAMIC") == 0)
906441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
907441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Check that address and size match the dynamic
908441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 section.  We locate the dynamic section via the
909441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 program header entry.  */
910441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      int pcnt;
911441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
912441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
913441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
914441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Phdr phdr_mem;
915441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
916441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
917441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
918441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
919441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (sym->st_value != phdr->p_vaddr)
920441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ERROR (gettext ("\
921441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"),
922441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       idx, section_name (ebl, ehdr, idx),
923441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       (uint64_t) sym->st_value,
924441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       (uint64_t) phdr->p_vaddr);
925441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
926441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (sym->st_size != phdr->p_memsz)
927441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ERROR (gettext ("\
928441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"),
929441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       idx, section_name (ebl, ehdr, idx),
930441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       (uint64_t) sym->st_size,
931441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       (uint64_t) phdr->p_memsz);
932441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
933441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      break;
934441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
935441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
936441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
937441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
938441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
939441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
940441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
941441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
942441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool
943441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectis_rel_dyn (Ebl *ebl, GElf_Ehdr *ehdr, int idx, GElf_Shdr *shdr, bool rela)
944441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
945441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If this is no executable or DSO it cannot be a .rel.dyn section.  */
946441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
947441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return false;
948441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
949441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check the section name.  Unfortunately necessary.  */
950441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (strcmp (section_name (ebl, ehdr, idx), rela ? ".rela.dyn" : ".rel.dyn"))
951441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return false;
952441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
953441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section
954441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     entry can be present as well.  */
955441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn = NULL;
956441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
957441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
958441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr rcshdr_mem;
959441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem);
960441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      assert (rcshdr != NULL);
961441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
962441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (rcshdr->sh_type == SHT_DYNAMIC)
963441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
964441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Found the dynamic section.  Look through it.  */
965441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf_Data *d = elf_getdata (scn, NULL);
966441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  int cnt;
967441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
968441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt)
969441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
970441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Dyn dyn_mem;
971441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem);
972441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      assert (dyn != NULL);
973441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
974441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (dyn->d_tag == DT_RELCOUNT)
975441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
976441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Found it.  One last check: does the number
977441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     specified number of relative relocations exceed
978441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     the total number of relocations?  */
979441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
980441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ERROR (gettext ("\
981441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
982441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   idx, section_name (ebl, ehdr, idx),
983441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   (int) dyn->d_un.d_val);
984441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
985441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
986441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
987441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
988441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
989441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
990441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
991441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return true;
992441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
993441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
994441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
995441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
996441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_rela (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
997441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
998441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn;
999441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr shdr_mem;
1000441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *shdr;
1001441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *data;
1002441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr destshdr_mem;
1003441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *destshdr = NULL;
1004441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
1005441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool reldyn = false;
1006441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool known_broken = gnuld;
1007441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1008441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  scn = elf_getscn (ebl->elf, idx);
1009441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr = gelf_getshdr (scn, &shdr_mem);
1010441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr == NULL)
1011441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1012441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  data = elf_getdata (scn, NULL);
1013441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
1014441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1015441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1016441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     idx, section_name (ebl, ehdr, idx));
1017441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
1018441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1019441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1020441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check whether the link to the section we relocate is reasonable.  */
1021441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_info >= shnum)
1022441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"),
1023441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1024441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
1025441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1026441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1027441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       &destshdr_mem);
1028441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (destshdr != NULL)
1029441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1030441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if(destshdr->sh_type != SHT_PROGBITS
1031441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     && destshdr->sh_type != SHT_NOBITS)
1032441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1033441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true);
1034441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (!reldyn)
1035441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		ERROR (gettext ("\
1036441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': invalid destination section type\n"),
1037441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       idx, section_name (ebl, ehdr, idx));
1038441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else
1039441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1040441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* There is no standard, but we require that .rela.dyn
1041441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     sections have a sh_info value of zero.  */
1042441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (shdr->sh_info != 0)
1043441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ERROR (gettext ("\
1044441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': sh_info should be zero\n"),
1045441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   idx, section_name (ebl, ehdr, idx));
1046441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
1047441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1048441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1049441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if ((destshdr->sh_flags & (SHF_MERGE | SHF_STRINGS)) != 0)
1050441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
1051441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': no relocations for merge-able sections possible\n"),
1052441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx));
1053441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1054441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1055441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1056441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT))
1057441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1058441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section entry size does not match ElfXX_Rela\n"),
1059441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1060441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1061441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1062441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr symshdr_mem;
1063441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1064441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *symdata = elf_getdata (symscn, NULL);
1065441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1066441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1067441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1068441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Rela rela_mem;
1069441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Rela *rela;
1070441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1071441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      rela = gelf_getrela (data, cnt, &rela_mem);
1072441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (rela == NULL)
1073441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1074441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ERROR (gettext ("\
1075441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': cannot get relocation %zu: %s\n"),
1076441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 idx, section_name (ebl, ehdr, idx), cnt, elf_errmsg (-1));
1077441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  continue;
1078441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1079441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1080441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (rela->r_info)))
1081441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"),
1082441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
1083441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (!ebl_reloc_valid_use (ebl, GELF_R_TYPE (rela->r_info)))
1084441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
1085441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
1086441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
1087441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1088441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (symshdr != NULL
1089441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && ((GELF_R_SYM (rela->r_info) + 1)
1090441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
1091441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      > symshdr->sh_size))
1092441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
1093441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': relocation %zu: invalid symbol index\n"),
1094441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
1095441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1096441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (rela->r_info)))
1097441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1098441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  const char *name;
1099441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  char buf[64];
1100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Sym sym_mem;
1101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (rela->r_info),
1102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				       &sym_mem);
1103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (sym != NULL
1104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Get the name for the symbol.  */
1105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
1107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
1108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
1109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx), cnt,
1110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   ebl_reloc_type_name (ebl, GELF_R_SYM (rela->r_info),
1111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					buf, sizeof (buf)));
1112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (reldyn)
1115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  // XXX TODO Check .rel.dyn section addresses.
1117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (!known_broken)
1119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (destshdr != NULL
1121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && (rela->r_offset - destshdr->sh_addr) >= destshdr->sh_size)
1122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
1123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': relocation %zu: offset out of bounds\n"),
1124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
1125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_rel (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
1132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn;
1134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr shdr_mem;
1135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *shdr;
1136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *data;
1137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr destshdr_mem;
1138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *destshdr = NULL;
1139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
1140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool reldyn = false;
1141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool known_broken = gnuld;
1142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  scn = elf_getscn (ebl->elf, idx);
1144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr = gelf_getshdr (scn, &shdr_mem);
1145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr == NULL)
1146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  data = elf_getdata (scn, NULL);
1148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
1149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     idx, section_name (ebl, ehdr, idx));
1152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
1153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check whether the link to the section we relocate is reasonable.  */
1156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_info >= shnum)
1157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"),
1158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
1160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       &destshdr_mem);
1163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (destshdr != NULL)
1164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (destshdr->sh_type != SHT_PROGBITS
1166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && destshdr->sh_type != SHT_NOBITS)
1167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, false);
1169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (!reldyn)
1170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		ERROR (gettext ("\
1171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': invalid destination section type\n"),
1172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       idx, section_name (ebl, ehdr, idx));
1173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else
1174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* There is no standard, but we require that .rela.dyn
1176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     sections have a sh_info value of zero.  */
1177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (shdr->sh_info != 0)
1178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ERROR (gettext ("\
1179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': sh_info should be zero\n"),
1180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   idx, section_name (ebl, ehdr, idx));
1181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
1182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if ((destshdr->sh_flags & (SHF_MERGE | SHF_STRINGS)) != 0)
1185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
1186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': no relocations for merge-able sections possible\n"),
1187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx));
1188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT))
1192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section entry size does not match ElfXX_Rel\n"),
1194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr symshdr_mem;
1198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *symdata = elf_getdata (symscn, NULL);
1200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Rel rel_mem;
1204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Rel *rel;
1205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      rel = gelf_getrel (data, cnt, &rel_mem);
1207441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (rel == NULL)
1208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1209441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ERROR (gettext ("\
1210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': cannot get relocation %zu: %s\n"),
1211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 idx, section_name (ebl, ehdr, idx), cnt, elf_errmsg (-1));
1212441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  continue;
1213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)))
1216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"),
1217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
1218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (!ebl_reloc_valid_use (ebl, GELF_R_TYPE (rel->r_info)))
1219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
1220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
1221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
1222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (symshdr != NULL
1224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && ((GELF_R_SYM (rel->r_info) + 1)
1225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
1226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      > symshdr->sh_size))
1227441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
1228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': relocation %zu: invalid symbol index\n"),
1229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
1230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (rel->r_info)))
1232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  const char *name;
1234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  char buf[64];
1235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Sym sym_mem;
1236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (rel->r_info),
1237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				       &sym_mem);
1238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (sym != NULL
1239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Get the name for the symbol.  */
1240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
1242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
1243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
1244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx), cnt,
1245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   ebl_reloc_type_name (ebl, GELF_R_SYM (rel->r_info),
1246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					buf, sizeof (buf)));
1247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (reldyn)
1250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  // XXX TODO Check .rel.dyn section addresses.
1252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (!known_broken)
1254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (destshdr != NULL
1256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && GELF_R_TYPE (rel->r_info) != 0
1257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && (rel->r_offset - destshdr->sh_addr) >= destshdr->sh_size)
1258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
1259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': relocation %zu: offset out of bounds\n"),
1260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx), cnt);
1261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Number of dynamic sections.  */
1267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int ndynamic;
1268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
1272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1273441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn;
1274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr shdr_mem;
1275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *shdr;
1276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *data;
1277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr strshdr_mem;
1278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *strshdr;
1279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
1280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  static const bool dependencies[DT_NUM][DT_NUM] =
1281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_NEEDED] = { [DT_STRTAB] = true },
1283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_PLTRELSZ] = { [DT_JMPREL] = true },
1284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_HASH] = { [DT_SYMTAB] = true },
1285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_STRTAB] = { [DT_STRSZ] = true },
1286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_HASH] = true,
1287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      [DT_SYMENT] = true },
1288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true },
1289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_RELASZ] = { [DT_RELA] = true },
1290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_RELAENT] = { [DT_RELA] = true },
1291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_STRSZ] = { [DT_STRTAB] = true },
1292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_SYMENT] = { [DT_SYMTAB] = true },
1293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_SONAME] = { [DT_STRTAB] = true },
1294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_RPATH] = { [DT_STRTAB] = true },
1295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true },
1296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_RELSZ] = { [DT_REL] = true },
1297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_RELENT] = { [DT_REL] = true },
1298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true },
1299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_RUNPATH] = { [DT_STRTAB] = true },
1300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_PLTREL] = { [DT_JMPREL] = true },
1301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_PLTRELSZ] = { [DT_JMPREL] = true }
1302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    };
1303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool has_dt[DT_NUM];
1304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  static const bool level2[DT_NUM] =
1305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_RPATH] = true,
1307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_SYMBOLIC] = true,
1308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_TEXTREL] = true,
1309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_BIND_NOW] = true
1310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    };
1311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  static const bool mandatory[DT_NUM] =
1312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_NULL] = true,
1314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_HASH] = true,
1315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_STRTAB] = true,
1316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_SYMTAB] = true,
1317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_STRSZ] = true,
1318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DT_SYMENT] = true
1319441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    };
1320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Addr reladdr = 0;
1321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Word relsz = 0;
1322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Addr pltreladdr = 0;
1323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Word pltrelsz = 0;
1324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  memset (has_dt, '\0', sizeof (has_dt));
1326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (++ndynamic == 2)
1328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("more than one dynamic section present\n"));
1329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  scn = elf_getscn (ebl->elf, idx);
1331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr = gelf_getshdr (scn, &shdr_mem);
1332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr == NULL)
1333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  data = elf_getdata (scn, NULL);
1335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
1336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     idx, section_name (ebl, ehdr, idx));
1339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
1340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem);
1343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB)
1344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
1346441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   shdr->sh_link, section_name (ebl, ehdr, shdr->sh_link),
1347441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT))
1350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section entry size does not match ElfXX_Dyn\n"),
1352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_info != 0)
1355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool non_null_warned = false;
1359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Dyn dyn_mem;
1362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Dyn *dyn;
1363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1364441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      dyn = gelf_getdyn (data, cnt, &dyn_mem);
1365441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (dyn == NULL)
1366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ERROR (gettext ("\
1368441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': cannot get dynamic section entry %zu: %s\n"),
1369441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 idx, section_name (ebl, ehdr, idx), cnt, elf_errmsg (-1));
1370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  continue;
1371441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1372441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1373441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned)
1374441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ERROR (gettext ("\
1376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"),
1377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 idx, section_name (ebl, ehdr, idx));
1378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  non_null_warned = true;
1379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (!ebl_dynamic_tag_check (ebl, dyn->d_tag))
1382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': entry %zu: unknown tag\n"),
1383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
1384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (dyn->d_tag < DT_NUM)
1386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (has_dt[dyn->d_tag]
1388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && dyn->d_tag != DT_NEEDED
1389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && dyn->d_tag != DT_NULL
1390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && dyn->d_tag != DT_POSFLAG_1)
1391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      char buf[50];
1393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ERROR (gettext ("\
1394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': entry %zu: more than one entry with tag %s\n"),
1395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     idx, section_name (ebl, ehdr, idx), cnt,
1396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					   buf, sizeof (buf)));
1398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (be_strict && level2[dyn->d_tag])
1401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      char buf[50];
1403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ERROR (gettext ("\
1404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': entry %zu: level 2 tag %s used\n"),
1405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     idx, section_name (ebl, ehdr, idx), cnt,
1406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
1407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					   buf, sizeof (buf)));
1408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  has_dt[dyn->d_tag] = true;
1411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL
1414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && dyn->d_un.d_val != DT_RELA)
1415441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
1416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"),
1417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx), cnt);
1418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (dyn->d_tag == DT_REL)
1420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	reladdr = dyn->d_un.d_ptr;
1421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (dyn->d_tag == DT_RELSZ)
1422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	relsz = dyn->d_un.d_val;
1423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (dyn->d_tag == DT_JMPREL)
1424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	pltreladdr = dyn->d_un.d_ptr;
1425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (dyn->d_tag == DT_PLTRELSZ)
1426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	pltrelsz = dyn->d_un.d_val;
1427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 1; cnt < DT_NUM; ++cnt)
1430441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    if (has_dt[cnt])
1431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
1432441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	int inner;
1433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1434441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	for (inner = 0; inner < DT_NUM; ++inner)
1435441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (dependencies[cnt][inner] && ! has_dt[inner])
1436441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      char buf1[50];
1438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      char buf2[50];
1439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ERROR (gettext ("\
1441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': contains %s entry but not %s\n"),
1442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     idx, section_name (ebl, ehdr, idx),
1443441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)),
1444441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2)));
1445441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1446441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
1447441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    else
1448441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
1449441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (mandatory[cnt])
1450441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
1451441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    char buf[50];
1452441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
1453441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': mandatory tag %s not present\n"),
1454441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx),
1455441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf)));
1456441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
1457441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
1458441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1459441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check the rel/rela tags.  At least one group must be available.  */
1460441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT])
1461441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT]))
1462441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1463441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': not all of %s, %s, and %s are present\n"),
1464441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx),
1465441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   "DT_RELA", "DT_RELASZ", "DT_RELAENT");
1466441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1467441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT])
1468441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT]))
1469441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1470441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': not all of %s, %s, and %s are present\n"),
1471441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx),
1472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   "DT_REL", "DT_RELSZ", "DT_RELENT");
1473441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1474441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1475441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1476441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1477441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
1478441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1479441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn;
1480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr shdr_mem;
1481441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *shdr;
1482441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr symshdr_mem;
1483441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *symshdr;
1484441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *symscn;
1485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
1486441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *data;
1487441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *symdata;
1488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1489441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  scn = elf_getscn (ebl->elf, idx);
1490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr = gelf_getshdr (scn, &shdr_mem);
1491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr == NULL)
1492441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1494441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  symscn = elf_getscn (ebl->elf, shdr->sh_link);
1495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  symshdr = gelf_getshdr (symscn, &symshdr_mem);
1496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB)
1497441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1498441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': extended section index section not for symbol table\n"),
1499441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  symdata = elf_getdata (symscn, NULL);
1501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (symdata == NULL)
1502441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("cannot get data for symbol section\n"));
1503441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_entsize != sizeof (Elf32_Word))
1505441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1506441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': entry size does not match Elf32_Word\n"),
1507441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1508441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (symshdr != NULL
1510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      && (shdr->sh_size / shdr->sh_entsize
1511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  < symshdr->sh_size / symshdr->sh_entsize))
1512441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1513441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': extended index table too small for symbol table\n"),
1514441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1516441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_info != 0)
1517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
1518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1519441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = idx + 1; cnt < shnum; ++cnt)
1521441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1522441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr rshdr_mem;
1523441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr *rshdr;
1524441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem);
1526441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX
1527441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && rshdr->sh_link == shdr->sh_link)
1528441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ERROR (gettext ("\
1530441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"),
1531441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 idx, section_name (ebl, ehdr, idx),
1532441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 cnt, section_name (ebl, ehdr, cnt));
1533441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1534441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1535441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1536441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1537441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  data = elf_getdata (scn, NULL);
1538441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1539441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (*((Elf32_Word *) data->d_buf) != 0)
1540441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("symbol 0 should have zero extended section index\n"));
1541441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1542441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1543441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt];
1545441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1546441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (xndx != 0)
1547441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Sym sym_data;
1549441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data);
1550441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (sym == NULL)
1551441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1552441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ERROR (gettext ("cannot get data for symbol %zu\n"), cnt);
1553441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      continue;
1554441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1555441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1556441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (sym->st_shndx != SHN_XINDEX)
1557441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
1558441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectextended section index is %" PRIu32 " but symbol index is not XINDEX\n"),
1559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   (uint32_t) xndx);
1560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1561441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1563441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1564441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_hash (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
1567441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn;
1569441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr shdr_mem;
1570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *shdr;
1571441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *data;
1572441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf32_Word nbucket;
1573441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf32_Word nchain;
1574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr symshdr_mem;
1575441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *symshdr;
1576441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1577441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  scn = elf_getscn (ebl->elf, idx);
1578441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr = gelf_getshdr (scn, &shdr_mem);
1579441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr == NULL)
1580441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1581441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  data = elf_getdata (scn, NULL);
1582441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
1583441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1584441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
1585441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     idx, section_name (ebl, ehdr, idx));
1586441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
1587441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1588441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1589441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &symshdr_mem);
1590441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM)
1591441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1592441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': hash table not for dynamic symbol table\n"),
1593441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1594441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1595441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_entsize != sizeof (Elf32_Word))
1596441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1597441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': entry size does not match Elf32_Word\n"),
1598441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1599441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1600441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if ((shdr->sh_flags & SHF_ALLOC) == 0)
1601441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("section [%2d] '%s': not marked to be allocated\n"),
1602441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx));
1603441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1604441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_size < 2 * shdr->sh_entsize)
1605441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1606441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("\
1607441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': hash table has not even room for nbucket and nchain\n"),
1608441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     idx, section_name (ebl, ehdr, idx));
1609441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
1610441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1611441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1612441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  nbucket = ((Elf32_Word *) data->d_buf)[0];
1613441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  nchain = ((Elf32_Word *) data->d_buf)[1];
1614441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1615441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
1616441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1617441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
1618441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx), (long int) shdr->sh_size,
1619441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
1620441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1621441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (symshdr != NULL)
1622441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1623441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
1624441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t cnt;
1625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (nchain < symshdr->sh_size / symshdr->sh_entsize)
1627441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': chain array not large enough\n"),
1628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx));
1629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (cnt = 2; cnt < 2 + nbucket; ++cnt)
1631441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (((Elf32_Word *) data->d_buf)[cnt] >= symsize)
1632441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ERROR (gettext ("\
1633441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': hash bucket reference %zu out of bounds\n"),
1634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 idx, section_name (ebl, ehdr, idx), cnt - 2);
1635441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (; cnt < 2 + nbucket + nchain; ++cnt)
1637441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (((Elf32_Word *) data->d_buf)[cnt] >= symsize)
1638441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ERROR (gettext ("\
1639441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': hash chain reference %zu out of bounds\n"),
1640441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 idx, section_name (ebl, ehdr, idx), cnt - 2 - nbucket);
1641441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1643441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1644441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1645441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_null (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1647441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1648441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define TEST(name, extra) \
1649441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (extra && shdr->sh_##name != 0)					      \
1650441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("section [%2d] '%s': nonzero sh_%s for NULL section\n"),  \
1651441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx), #name)
1652441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1653441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  TEST (name, 1);
1654441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  TEST (flags, 1);
1655441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  TEST (addr, 1);
1656441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  TEST (offset, 1);
1657441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  TEST (size, idx != 0);
1658441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  TEST (link, idx != 0);
1659441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  TEST (info, 1);
1660441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  TEST (addralign, 1);
1661441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  TEST (entsize, 1);
1662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1663441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1664441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1665441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1666441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1667441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1668441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_type != ET_REL)
1669441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1670441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("\
1671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section groups only allowed in relocatable object files\n"),
1672441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     idx, section_name (ebl, ehdr, idx));
1673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
1674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check that sh_link is an index of a symbol table.  */
1677441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr symshdr_mem;
1678441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1679441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     &symshdr_mem);
1680441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (symshdr == NULL)
1681441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("section [%2d] '%s': cannot get symbol table: %s\n"),
1682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx), elf_errmsg (-1));
1683441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
1684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1685441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (symshdr->sh_type != SHT_SYMTAB)
1686441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
1687441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section reference in sh_link is no symbol table\n"),
1688441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx));
1689441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1690441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM,
1691441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project							  1, EV_CURRENT))
1692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
1693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': invalid symbol index in sh_info\n"),
1694441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx));
1695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags != 0)
1697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': sh_flags not zero\n"),
1698441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx));
1699441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1700441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (be_strict
1701441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT))
1702441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': sh_flags not set correctly\n"),
1703441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx));
1704441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1705441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1706441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
1707441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
1708441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("section [%2d] '%s': cannot get data: %s\n"),
1709441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx), elf_errmsg (-1));
1710441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
1711441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1712441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
1713441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t cnt;
1714441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Elf32_Word val;
1715441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1716441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (data->d_size % elsize != 0)
1717441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
1718441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"),
1719441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx));
1720441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1721441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (data->d_size < elsize)
1722441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
1723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section group without flags word\n"),
1724441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx));
1725441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (be_strict)
1726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (data->d_size < 2 * elsize)
1728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
1729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section group without member\n"),
1730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx));
1731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (data->d_size < 3 * elsize)
1732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
1733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section group with only one member\n"),
1734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx));
1735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#if ALLOW_UNALIGNED
1738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      val = *((Elf32_Word *) data->d_buf);
1739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#else
1740441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      memcpy (&val, data->d_buf, elsize);
1741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif
1742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if ((val & ~GRP_COMDAT) != 0)
1743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2d] '%s': unknown section group flags\n"),
1744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       idx, section_name (ebl, ehdr, idx));
1745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (cnt = elsize; cnt < data->d_size; cnt += elsize)
1747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#if ALLOW_UNALIGNED
1749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  val = *((Elf32_Word *) ((char *) data->d_buf + cnt));
1750441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#else
1751441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  memcpy (&val, (char *) data->d_buf + cnt, elsize);
1752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif
1753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (val > shnum)
1755441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
1756441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section index %Zu out of range\n"),
1757441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   idx, section_name (ebl, ehdr, idx), cnt / elsize);
1758441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
1759441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Shdr refshdr_mem;
1761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Shdr *refshdr;
1762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1763441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      refshdr = gelf_getshdr (elf_getscn (ebl->elf, val),
1764441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				      &refshdr_mem);
1765441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (refshdr == NULL)
1766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		ERROR (gettext ("\
1767441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': cannot get section header for element %zu: %s\n"),
1768441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       idx, section_name (ebl, ehdr, idx), cnt / elsize,
1769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       elf_errmsg (-1));
1770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else
1771441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1772441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (refshdr->sh_type == SHT_GROUP)
1773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ERROR (gettext ("\
1774441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section group contains another group [%2d] '%s'\n"),
1775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   idx, section_name (ebl, ehdr, idx),
1776441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   val, section_name (ebl, ehdr, val));
1777441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if ((refshdr->sh_flags & SHF_GROUP) == 0)
1779441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ERROR (gettext ("\
1780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': element %Zu references section [%2d] '%s' without SHF_GROUP flag set\n"),
1781441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   idx, section_name (ebl, ehdr, idx), cnt / elsize,
1782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   val, section_name (ebl, ehdr, val));
1783441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
1784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1785441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (++scnref[val] == 2)
1786441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		ERROR (gettext ("\
1787441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s' is contained in more than one section group\n"),
1788441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       val, section_name (ebl, ehdr, val));
1789441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1790441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1791441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1792441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1793441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1794441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1795441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool has_loadable_segment;
1796441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool has_interp_segment;
1797441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1798441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const struct
1799441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1800441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const char *name;
1801441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t namelen;
1802441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Word type;
1803441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  enum { unused, exact, atleast } attrflag;
1804441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Word attr;
1805441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Word attr2;
1806441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} special_sections[] =
1807441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  {
1808441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* See figure 4-14 in the gABI.  */
1809441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
1810441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".comment", 8, SHT_PROGBITS, exact, 0, 0 },
1811441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
1812441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
1813441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".debug", 7, SHT_PROGBITS, exact, 0, 0 },
1814441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE },
1815441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 },
1816441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 },
1817441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
1818441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
1819441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info?
1820441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 },
1821441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
1822441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
1823441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests?
1824441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".line", 6, SHT_PROGBITS, exact, 0, 0 },
1825441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".note", 6, SHT_NOTE, exact, 0, 0 },
1826441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
1827441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
1828441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC }, // XXX more tests
1829441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC }, // XXX more tests
1830441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".rodata", 8, SHT_PROGBITS, exact, SHF_ALLOC, 0 },
1831441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".rodata1", 9, SHT_PROGBITS, exact, SHF_ALLOC, 0 },
1832441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 },
1833441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
1834441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
1835441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests
1836441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
1837441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
1838441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
1839441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 }
1840441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  };
1841441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define nspecial_sections \
1842441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  (sizeof (special_sections) / sizeof (special_sections[0]))
1843441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1844441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1845441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *
1846441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection_flags_string (GElf_Word flags, char *buf, size_t len)
1847441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1848441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  static const struct
1849441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  {
1850441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    GElf_Word flag;
1851441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    const char *name;
1852441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  } known_flags[] =
1853441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1854441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define NEWFLAG(name) { SHF_##name, #name }
1855441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      NEWFLAG (WRITE),
1856441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      NEWFLAG (ALLOC),
1857441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      NEWFLAG (EXECINSTR),
1858441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      NEWFLAG (MERGE),
1859441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      NEWFLAG (STRINGS),
1860441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      NEWFLAG (INFO_LINK),
1861441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      NEWFLAG (LINK_ORDER),
1862441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      NEWFLAG (OS_NONCONFORMING),
1863441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      NEWFLAG (GROUP),
1864441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      NEWFLAG (TLS)
1865441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    };
1866441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#undef NEWFLAG
1867441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
1868441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1869441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *cp = buf;
1870441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
1871441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1872441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 0; cnt < nknown_flags; ++cnt)
1873441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    if (flags & known_flags[cnt].flag)
1874441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
1875441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (cp != buf && len > 1)
1876441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
1877441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    *cp++ = '|';
1878441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    --len;
1879441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  }
1880441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1881441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name));
1882441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	cp = mempcpy (cp, known_flags[cnt].name, ncopy);
1883441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	len -= ncopy;
1884441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1885441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	flags ^= known_flags[cnt].flag;
1886441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
1887441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1888441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (flags != 0 || cp == buf)
1889441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    snprintf (cp, len - 1, "%" PRIx64, (uint64_t) flags);
1890441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1891441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  *cp = '\0';
1892441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1893441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return buf;
1894441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1895441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1896441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1897441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1898441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_versym (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
1899441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1900441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* The number of elements in the version symbol table must be the
1901441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     same as the number of symbols.  */
1902441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr symshdr_mem;
1903441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1904441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     &symshdr_mem);
1905441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (symshdr == NULL)
1906441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* The error has already been reported.  */
1907441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1908441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1909441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (symshdr->sh_type != SHT_DYNSYM)
1910441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1911441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("\
1912441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"),
1913441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     idx, section_name (ebl, ehdr, idx),
1914441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     shdr->sh_link, section_name (ebl, ehdr, shdr->sh_link));
1915441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
1916441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1917441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1918441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_size / shdr->sh_entsize
1919441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      != symshdr->sh_size / symshdr->sh_entsize)
1920441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
1921441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"),
1922441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   idx, section_name (ebl, ehdr, idx),
1923441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   shdr->sh_link, section_name (ebl, ehdr, shdr->sh_link));
1924441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1925441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  // XXX TODO A lot more tests
1926441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  // check value of the fields.  local symbols must have zero entries.
1927441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  // nonlocal symbols refer to valid version.  Check that version index
1928441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  // in bound.
1929441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1930441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1931441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1932441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1933441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_sections (Ebl *ebl, GElf_Ehdr *ehdr)
1934441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1935441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr shdr_mem;
1936441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *shdr;
1937441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
1938441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool dot_interp_section = false;
1939441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1940441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_shoff == 0)
1941441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* No section header.  */
1942441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1943441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1944441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Allocate array to count references in section groups.  */
1945441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  scnref = (int *) xcalloc (shnum, sizeof (int));
1946441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1947441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check the zeroth section first.  It must not have any contents
1948441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     and the section header must contain nonzero value at most in the
1949441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     sh_size and sh_link fields.  */
1950441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1951441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr == NULL)
1952441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("cannot get section header of zeroth section\n"));
1953441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
1954441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1955441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_name != 0)
1956441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("zeroth section has nonzero name\n"));
1957441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_type != 0)
1958441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("zeroth section has nonzero type\n"));
1959441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags != 0)
1960441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("zeroth section has nonzero flags\n"));
1961441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_addr != 0)
1962441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("zeroth section has nonzero address\n"));
1963441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_offset != 0)
1964441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("zeroth section has nonzero offset\n"));
1965441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_info != 0)
1966441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("zeroth section has nonzero info field\n"));
1967441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_addralign != 0)
1968441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("zeroth section has nonzero align value\n"));
1969441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_entsize != 0)
1970441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("zeroth section has nonzero entry size value\n"));
1971441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1972441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_size != 0 && ehdr->e_shnum != 0)
1973441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
1974441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectzeroth section has nonzero size value while ELF header has nonzero shnum value\n"));
1975441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1976441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX)
1977441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
1978441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectzeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n"));
1979441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1980441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1981441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 1; cnt < shnum; ++cnt)
1982441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1983441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Elf_Scn *scn;
1984441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1985441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      scn = elf_getscn (ebl->elf, cnt);
1986441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      shdr = gelf_getshdr (scn, &shdr_mem);
1987441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr == NULL)
1988441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1989441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ERROR (gettext ("\
1990441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcannot get section header for section [%2zu] '%s': %s\n"),
1991441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 cnt, section_name (ebl, ehdr, cnt), elf_errmsg (-1));
1992441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  continue;
1993441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1994441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1995441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
1996441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1997441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (scnname == NULL)
1998441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2zu]: invalid name\n"), cnt);
1999441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
2000441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2001441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Check whether it is one of the special sections defined in
2002441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     the gABI.  */
2003441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  size_t s;
2004441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  for (s = 0; s < nspecial_sections; ++s)
2005441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (strncmp (scnname, special_sections[s].name,
2006441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 special_sections[s].namelen) == 0)
2007441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      {
2008441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		char stbuf1[100];
2009441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		char stbuf2[100];
2010441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		char stbuf3[100];
2011441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2012441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (shdr->sh_type != special_sections[s].type)
2013441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  ERROR (gettext ("\
2014441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s' has wrong type: expected %s, is %s\n"),
2015441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 (int) cnt, scnname,
2016441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 ebl_section_type_name (ebl, special_sections[s].type,
2017441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						stbuf1, sizeof (stbuf1)),
2018441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 ebl_section_type_name (ebl, shdr->sh_type,
2019441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						stbuf2, sizeof (stbuf2)));
2020441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2021441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (special_sections[s].attrflag == exact)
2022441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
2023441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* Except for the link order and group bit all the
2024441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       other bits should match exactly.  */
2025441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP))
2026441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			!= special_sections[s].attr)
2027441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ERROR (gettext ("\
2028441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has wrong flags: expected %s, is %s\n"),
2029441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     cnt, scnname,
2030441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     section_flags_string (special_sections[s].attr,
2031441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   stbuf1, sizeof (stbuf1)),
2032441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     section_flags_string (shdr->sh_flags
2033441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   & ~SHF_LINK_ORDER,
2034441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   stbuf2, sizeof (stbuf2)));
2035441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
2036441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		else if (special_sections[s].attrflag == atleast)
2037441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
2038441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if ((shdr->sh_flags & special_sections[s].attr)
2039441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			!= special_sections[s].attr
2040441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			|| ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP
2041441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						| special_sections[s].attr
2042441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						| special_sections[s].attr2))
2043441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    != 0))
2044441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ERROR (gettext ("\
2045441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"),
2046441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     cnt, scnname,
2047441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     section_flags_string (special_sections[s].attr,
2048441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   stbuf1, sizeof (stbuf1)),
2049441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     section_flags_string (special_sections[s].attr2,
2050441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   stbuf2, sizeof (stbuf2)),
2051441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     section_flags_string (shdr->sh_flags
2052441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   & ~(SHF_LINK_ORDER
2053441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						       | SHF_GROUP),
2054441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   stbuf3, sizeof (stbuf3)));
2055441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
2056441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2057441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (strcmp (scnname, ".interp") == 0)
2058441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
2059441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    dot_interp_section = true;
2060441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2061441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (ehdr->e_type == ET_REL)
2062441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ERROR (gettext ("\
2063441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' present in object file\n"),
2064441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     cnt, scnname);
2065441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2066441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if ((shdr->sh_flags & SHF_ALLOC) != 0
2067441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			&& !has_loadable_segment)
2068441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ERROR (gettext ("\
2069441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
2070441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     cnt, scnname);
2071441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
2072441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     && has_loadable_segment)
2073441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ERROR (gettext ("\
2074441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
2075441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     cnt, scnname);
2076441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
2077441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		else
2078441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
2079441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (strcmp (scnname, ".symtab_shndx") == 0
2080441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			&& ehdr->e_type != ET_REL)
2081441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ERROR (gettext ("\
2082441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' is extension section index table in non-object file\n"),
2083441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     cnt, scnname);
2084441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2085441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* These sections must have the SHF_ALLOC flag set iff
2086441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       a loadable segment is available.
2087441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2088441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       .relxxx
2089441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       .strtab
2090441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       .symtab
2091441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       .symtab_shndx
2092441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2093441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       Check that if there is a reference from the
2094441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       loaded section these sections also have the
2095441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       ALLOC flag set.  */
2096441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#if 0
2097441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    // XXX TODO
2098441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if ((shdr->sh_flags & SHF_ALLOC) != 0
2099441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			&& !has_loadable_segment)
2100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ERROR (gettext ("\
2101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
2102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     cnt, scnname);
2103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
2104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     && has_loadable_segment)
2105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ERROR (gettext ("\
2106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
2107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     cnt, scnname);
2108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif
2109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
2110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		break;
2112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      }
2113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize)
2116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
2117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': size not multiple of entry size\n"),
2118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       cnt, section_name (ebl, ehdr, cnt));
2119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL)
2121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("cannot get section header\n"));
2122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_type >= SHT_NUM
2124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && shdr->sh_type != SHT_GNU_LIBLIST
2125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && shdr->sh_type != SHT_CHECKSUM
2126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && shdr->sh_type != SHT_GNU_verdef
2127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && shdr->sh_type != SHT_GNU_verneed
2128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && shdr->sh_type != SHT_GNU_versym)
2129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("unsupported section type %d\n"), (int) shdr->sh_type);
2130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \
2132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \
2133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS)
2134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & ~ALL_SH_FLAGS)
2135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("section [%2zu] '%s' contain unknown flag(s) %d\n"),
2136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       cnt, section_name (ebl, ehdr, cnt),
2137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       (int) shdr->sh_flags & ~ALL_SH_FLAGS);
2138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (shdr->sh_flags & SHF_TLS)
2139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  // XXX Correct?
2141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr->sh_addr != 0 && !gnuld)
2142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
2143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': thread-local data sections address not zero\n"),
2144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   cnt, section_name (ebl, ehdr, cnt));
2145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  // XXX TODO more tests!?
2147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_link >= shnum)
2150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
2151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': invalid section reference in link value\n"),
2152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       cnt, section_name (ebl, ehdr, cnt));
2153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum)
2155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
2156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': invalid section reference in info value\n"),
2157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       cnt, section_name (ebl, ehdr, cnt));
2158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if ((shdr->sh_flags & SHF_MERGE) == 0
2160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && (shdr->sh_flags & SHF_STRINGS) != 0
2161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && be_strict)
2162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
2163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': strings flag set without merge flag\n"),
2164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       cnt, section_name (ebl, ehdr, cnt));
2165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0)
2167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
2168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': merge flag set but entry size is zero\n"),
2169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       cnt, section_name (ebl, ehdr, cnt));
2170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_GROUP)
2172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	check_scn_group (ebl, ehdr, cnt);
2173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0)
2175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Make sure the section is contained in a loaded segment
2177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     and that the initialization part matches NOBITS sections.  */
2178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  int pcnt;
2179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Phdr phdr_mem;
2180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Phdr *phdr;
2181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
2183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL
2184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		&& ((phdr->p_type == PT_LOAD
2185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     && (shdr->sh_flags & SHF_TLS) == 0)
2186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    || (phdr->p_type == PT_TLS
2187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			&& (shdr->sh_flags & SHF_TLS) != 0))
2188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		&& phdr->p_offset <= shdr->sh_offset
2189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		&& phdr->p_offset + phdr->p_memsz > shdr->sh_offset)
2190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      {
2191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		/* Found the segment.  */
2192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (phdr->p_offset + phdr->p_memsz
2193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    < shdr->sh_offset + shdr->sh_size)
2194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  ERROR (gettext ("\
2195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' not fully contained in segment of program header entry %d\n"),
2196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 cnt, section_name (ebl, ehdr, cnt), pcnt);
2197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (shdr->sh_type == SHT_NOBITS)
2199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
2200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz)
2201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ERROR (gettext ("\
2202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"),
2203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 cnt, section_name (ebl, ehdr, cnt), pcnt);
2204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
2205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		else
2206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
2207441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    if (shdr->sh_offset >= phdr->p_offset + phdr->p_filesz)
2208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ERROR (gettext ("\
2209441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"),
2210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 cnt, section_name (ebl, ehdr, cnt), pcnt);
2211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
2212441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		break;
2214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      }
2215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (pcnt == ehdr->e_phnum)
2217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
2218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': alloc flag set but section not in any loaded segment\n"),
2219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   cnt, section_name (ebl, ehdr, cnt));
2220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB)
2223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
2224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"),
2225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       cnt, section_name (ebl, ehdr, cnt));
2226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2227441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      switch (shdr->sh_type)
2228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case SHT_SYMTAB:
2230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case SHT_DYNSYM:
2231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  check_symtab (ebl, ehdr, cnt);
2232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case SHT_RELA:
2235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  check_rela (ebl, ehdr, cnt);
2236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case SHT_REL:
2239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  check_rel (ebl, ehdr, cnt);
2240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case SHT_DYNAMIC:
2243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  check_dynamic (ebl, ehdr, cnt);
2244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case SHT_SYMTAB_SHNDX:
2247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  check_symtab_shndx (ebl, ehdr, cnt);
2248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case SHT_HASH:
2251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  check_hash (ebl, ehdr, cnt);
2252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case SHT_NULL:
2255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  check_null (ebl, ehdr, shdr, cnt);
2256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case SHT_GROUP:
2259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  check_group (ebl, ehdr, shdr, cnt);
2260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case SHT_GNU_versym:
2263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  check_versym (ebl, ehdr, shdr, cnt);
2264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	default:
2267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Nothing.  */
2268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (has_interp_segment && !dot_interp_section)
2273441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("INTERP program header entry but no .interp section\n"));
2274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  free (scnref);
2276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
2277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
2280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt)
2281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
2282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
2283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
2284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
2285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectphdr[%d]: no note entries defined for the type of file\n"),
2286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   cnt);
2287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *notemem = gelf_rawchunk (ebl->elf, phdr->p_offset, phdr->p_filesz);
2289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* ELF64 files often use note section entries in the 32-bit format.
2291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     The p_align field is set to 8 in case the 64-bit format is used.
2292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     In case the p_align value is 0 or 4 the 32-bit format is
2293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     used.  */
2294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Xword align = phdr->p_align == 0 || phdr->p_align == 4 ? 4 : 8;
2295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
2296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Xword idx = 0;
2298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (idx < phdr->p_filesz)
2299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      uint64_t namesz;
2301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      uint64_t descsz;
2302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      uint64_t type;
2303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      uint32_t namesz32;
2304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      uint32_t descsz32;
2305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (align == 4)
2307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  uint32_t *ptr = (uint32_t *) (notemem + idx);
2309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if ((__BYTE_ORDER == __LITTLE_ENDIAN
2311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
2312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      || (__BYTE_ORDER == __BIG_ENDIAN
2313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
2314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      namesz32 = namesz = bswap_32 (*ptr);
2316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ++ptr;
2317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      descsz32 = descsz = bswap_32 (*ptr);
2318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ++ptr;
2319441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      type = bswap_32 (*ptr);
2320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
2322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      namesz32 = namesz = *ptr++;
2324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      descsz32 = descsz = *ptr++;
2325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      type = *ptr;
2326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
2329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  uint64_t *ptr = (uint64_t *) (notemem + idx);
2331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  uint32_t *ptr32 = (uint32_t *) (notemem + idx);
2332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if ((__BYTE_ORDER == __LITTLE_ENDIAN
2334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
2335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      || (__BYTE_ORDER == __BIG_ENDIAN
2336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
2337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      namesz = bswap_64 (*ptr);
2339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ++ptr;
2340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      descsz = bswap_64 (*ptr);
2341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ++ptr;
2342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      type = bswap_64 (*ptr);
2343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      namesz32 = bswap_32 (*ptr32);
2345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ++ptr32;
2346441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      descsz32 = bswap_32 (*ptr32);
2347441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
2349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      namesz = *ptr++;
2351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      descsz = *ptr++;
2352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      type = *ptr;
2353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      namesz32 = *ptr32++;
2355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      descsz32 = *ptr32;
2356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (idx + 3 * align > phdr->p_filesz
2360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  || (idx + 3 * align + ALIGNED_LEN (namesz) + ALIGNED_LEN (descsz)
2361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      > phdr->p_filesz))
2362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (ehdr->e_ident[EI_CLASS] == ELFCLASS64
2364441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && idx + 3 * 4 <= phdr->p_filesz
2365441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && (idx + 3 * 4 + ALIGNED_LEN (namesz32) + ALIGNED_LEN (descsz32)
2366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  <= phdr->p_filesz))
2367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
2368441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectphdr[%d]: note entries probably in form of a 32-bit ELF file\n"), cnt);
2369441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
2370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("phdr[%d]: extra %zu bytes after last note\n"),
2371441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   cnt, (size_t) (phdr->p_filesz - idx));
2372441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2373441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2374441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Make sure it is one of the note types we know about.  */
2376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (ehdr->e_type == ET_CORE)
2377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  switch (type)
2379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_PRSTATUS:
2381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_FPREGSET:
2382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_PRPSINFO:
2383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_TASKSTRUCT:		/* NT_PRXREG on Solaris.  */
2384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_PLATFORM:
2385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_AUXV:
2386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_GWINDOWS:
2387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_ASRS:
2388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_PSTATUS:
2389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_PSINFO:
2390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_PRCRED:
2391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_UTSNAME:
2392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_LWPSTATUS:
2393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_LWPSINFO:
2394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    case NT_PRFPXREG:
2395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Known type.  */
2396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      break;
2397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    default:
2399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ERROR (gettext ("\
2400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectphdr[%d]: unknown core file note type %" PRIu64 " at offset %" PRIu64 "\n"),
2401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     cnt, type, idx);
2402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
2405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (type != NT_VERSION)
2407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
2408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectphdr[%d]: unknown object file note type %" PRIu64 " at offset %" PRIu64 "\n"),
2409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   cnt, type, idx);
2410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Move to the next entry.  */
2413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      idx += 3 * align + ALIGNED_LEN (namesz) + ALIGNED_LEN (descsz);
2414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2415441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  gelf_freechunk (ebl->elf, notemem);
2418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
2419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
2422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
2423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
2424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_phoff == 0)
2425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
2426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
2428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      && ehdr->e_type != ET_CORE)
2429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    ERROR (gettext ("\
2430441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectonly executables, shared objects, and core files can have program headers\n"));
2431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2432441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int num_pt_interp = 0;
2433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int num_pt_tls = 0;
2434441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int num_pt_relro = 0;
2435441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2436441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (int cnt = 0; cnt < ehdr->e_phnum; ++cnt)
2437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Phdr phdr_mem;
2439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Phdr *phdr;
2440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
2442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (phdr == NULL)
2443441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2444441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ERROR (gettext ("cannot get program header entry %d: %s\n"),
2445441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 cnt, elf_errmsg (-1));
2446441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  continue;
2447441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2448441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2449441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME
2450441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  && phdr->p_type != PT_GNU_STACK)
2451441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
2452441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprogram header entry %d: unknown program header entry type\n"),
2453441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       cnt);
2454441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2455441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (phdr->p_type == PT_LOAD)
2456441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	has_loadable_segment = true;
2457441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (phdr->p_type == PT_INTERP)
2458441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2459441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (++num_pt_interp != 1)
2460441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2461441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (num_pt_interp == 2)
2462441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		ERROR (gettext ("\
2463441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmore than one INTERP entry in program header\n"));
2464441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2465441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  has_interp_segment = true;
2466441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2467441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (phdr->p_type == PT_TLS)
2468441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2469441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (++num_pt_tls == 2)
2470441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("more than one TLS entry in program header\n"));
2471441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (phdr->p_type == PT_NOTE)
2473441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	check_note (ebl, ehdr, phdr, cnt);
2474441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (phdr->p_type == PT_DYNAMIC
2475441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       && ehdr->e_type == ET_EXEC && ! has_interp_segment)
2476441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("static executable cannot have dynamic sections\n"));
2477441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (phdr->p_type == PT_GNU_RELRO)
2478441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2479441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (++num_pt_relro == 2)
2480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
2481441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmore than one GNU_RELRO entry in program header\n"));
2482441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
2483441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2484441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Check that the region is in a writable segment.  */
2485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      int inner;
2486441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      for (inner = 0; inner < ehdr->e_phnum; ++inner)
2487441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
2488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Phdr phdr2_mem;
2489441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Phdr *phdr2;
2490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  phdr2 = gelf_getphdr (ebl->elf, cnt, &phdr2_mem);
2492441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (phdr2 == NULL)
2493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    continue;
2494441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (phdr2->p_type == PT_LOAD
2496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      && phdr->p_vaddr >= phdr2->p_vaddr
2497441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      && (phdr->p_vaddr + phdr->p_memsz
2498441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  <= phdr2->p_vaddr + phdr2->p_memsz))
2499441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
2500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if ((phdr2->p_flags & PF_W) == 0)
2501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ERROR (gettext ("\
2502441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectloadable segment GNU_RELRO applies to is not writable\n"));
2503441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if ((phdr2->p_flags & PF_X) != 0)
2504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ERROR (gettext ("\
2505441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectloadable segment GNU_RELRO applies to is executable\n"));
2506441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      break;
2507441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
2508441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
2509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (inner >= ehdr->e_phnum)
2511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		ERROR (gettext ("\
2512441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectGNU_RELRO segment not contained in a loaded segment\n"));
2513441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2514441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2516441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (phdr->p_filesz > phdr->p_memsz)
2517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	ERROR (gettext ("\
2518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprogram header entry %d: file size greater than memory size\n"),
2519441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       cnt);
2520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2521441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (phdr->p_align > 1)
2522441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2523441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (!powerof2 (phdr->p_align))
2524441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
2525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprogram header entry %d: alignment not a power of 2\n"), cnt);
2526441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0)
2527441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ERROR (gettext ("\
2528441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprogram header entry %d: file offset and virtual address not module of alignment\n"), cnt);
2529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2530441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2531441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
2532441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2533441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2534441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Process one file.  */
2535441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
2536441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprocess_elf_file (Elf *elf, const char *prefix, const char *suffix,
2537441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  const char *fname, size_t size, bool only_one)
2538441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
2539441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Reset variables.  */
2540441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  ndynamic = 0;
2541441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2542441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr ehdr_mem;
2543441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
2544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Ebl *ebl;
2545441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2546441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Print the file name.  */
2547441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (!only_one)
2548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2549441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (prefix != NULL)
2550441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	printf ("\n%s(%s)%s:\n", prefix, fname, suffix);
2551441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
2552441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	printf ("\n%s:\n", fname);
2553441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2554441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2555441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr == NULL)
2556441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2557441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ERROR (gettext ("cannot read ELF header: %s\n"), elf_errmsg (-1));
2558441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
2559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2561441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  ebl = ebl_openbackend (elf);
2562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If there is no appropriate backend library we cannot test
2563441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     architecture and OS specific features.  Any encountered extension
2564441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     is an error.  */
2565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Go straight by the gABI, check all the parts in turn.  */
2567441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  check_elf_header (ebl, ehdr, size);
2568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2569441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Check the program header.  */
2570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  check_program_header (ebl, ehdr);
2571441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2572441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Next the section headers.  It is OK if there are no section
2573441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     headers at all.  */
2574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  check_sections (ebl, ehdr);
2575441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2576441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Free the resources.  */
2577441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  ebl_closebackend (ebl);
2578441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
2579