125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Pedantic checking of ELF files compliance with gABI/psABI spec. 225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Copyright (C) 2001-2012 Red Hat, Inc. 325b3c049e70834cf33790a28643ab058b507b35cBen Cheng This file is part of Red Hat elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Written by Ulrich Drepper <drepper@redhat.com>, 2001. 525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is free software; you can redistribute it and/or modify 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng it under the terms of the GNU General Public License as published by the 825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Free Software Foundation; version 2 of the License. 925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is distributed in the hope that it will be useful, but 1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng General Public License for more details. 1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng You should have received a copy of the GNU General Public License along 1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng with Red Hat elfutils; if not, write to the Free Software Foundation, 1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is an included package of the Open Invention Network. 2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng An included package of the Open Invention Network is a package for which 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Open Invention Network licensees cross-license their patents. No patent 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng license is granted, either expressly or impliedly, by designation as an 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng included package. Should you wish to participate in the Open Invention 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Network licensing program, please visit www.openinventionnetwork.com 2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng <http://www.openinventionnetwork.com>. */ 2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H 2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h> 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <argp.h> 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h> 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <byteswap.h> 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <endian.h> 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <error.h> 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <fcntl.h> 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h> 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <inttypes.h> 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libintl.h> 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <locale.h> 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h> 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h> 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h> 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h> 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/stat.h> 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h> 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <elf-knowledge.h> 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h> 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libelf/libelfP.h" 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libelf/common.h" 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libebl/libeblP.h" 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libdw/libdwP.h" 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libdwfl/libdwflP.h" 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libdw/memory-access.h" 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Name and version of program. */ 5925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_version (FILE *stream, struct argp_state *state); 6025b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_VERSION_HOOK_DEF = print_version; 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Bug report address. */ 6325b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define ARGP_strict 300 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define ARGP_gnuld 301 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Definitions of arguments for argp functions. */ 6925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct argp_option options[] = 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { "strict", ARGP_strict, NULL, 0, 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng N_("Be extremely strict, flag level 2 features."), 0 }, 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { "quiet", 'q', NULL, 0, N_("Do not print anything if successful"), 0 }, 7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { "debuginfo", 'd', NULL, 0, N_("Binary is a separate debuginfo file"), 0 }, 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { "gnu-ld", ARGP_gnuld, NULL, 0, 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng N_("Binary has been created with GNU ld and is therefore known to be \ 7725b3c049e70834cf33790a28643ab058b507b35cBen Chengbroken in certain ways"), 0 }, 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { NULL, 0, NULL, 0, NULL, 0 } 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}; 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Short description of program. */ 8225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char doc[] = N_("\ 8325b3c049e70834cf33790a28643ab058b507b35cBen ChengPedantic checking of ELF files compliance with gABI/psABI spec."); 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Strings for arguments in help texts. */ 8625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char args_doc[] = N_("FILE..."); 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Prototype for option handler. */ 8925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t parse_opt (int key, char *arg, struct argp_state *state); 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Data structure to communicate with argp functions. */ 9225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct argp argp = 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng options, parse_opt, args_doc, doc, NULL, NULL, NULL 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}; 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Declarations of local functions. */ 9925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void process_file (int fd, Elf *elf, const char *prefix, 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *suffix, const char *fname, size_t size, 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool only_one); 10225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void process_elf_file (Elf *elf, const char *prefix, const char *suffix, 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *fname, size_t size, bool only_one); 10425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void check_note_section (Ebl *ebl, GElf_Ehdr *ehdr, 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr, int idx); 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Report an error. */ 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define ERROR(str, args...) \ 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng do { \ 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf (str, ##args); \ 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++error_count; \ 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } while (0) 11425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int error_count; 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if we should perform very strict testing. */ 11725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool be_strict; 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if no message is to be printed if the run is succesful. */ 12025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool be_quiet; 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if binary is from strip -f, not a normal ELF file. */ 12325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool is_debuginfo; 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if binary is assumed to be generated with GNU ld. */ 12625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool gnuld; 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Index of section header string table. */ 12925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic uint32_t shstrndx; 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Array to count references in section groups. */ 13225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int *scnref; 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13525b3c049e70834cf33790a28643ab058b507b35cBen Chengint 13625b3c049e70834cf33790a28643ab058b507b35cBen Chengmain (int argc, char *argv[]) 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Set locale. */ 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng setlocale (LC_ALL, ""); 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Initialize the message catalog. */ 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng textdomain (PACKAGE_TARNAME); 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Parse and process arguments. */ 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int remaining; 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng argp_parse (&argp, argc, argv, 0, &remaining, NULL); 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Before we start tell the ELF library which version we are using. */ 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_version (EV_CURRENT); 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now process all the files given at the command line. */ 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool only_one = remaining + 1 == argc; 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Open the file. */ 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int fd = open (argv[remaining], O_RDONLY); 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fd == -1) 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng error (0, errno, gettext ("cannot open input file")); 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Create an `Elf' descriptor. */ 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf == NULL) 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("cannot generate Elf descriptor: %s\n"), 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_errmsg (-1)); 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int prev_error_count = error_count; 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct stat64 st; 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fstat64 (fd, &st) != 0) 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf ("cannot stat '%s': %m\n", argv[remaining]); 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng close (fd); 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng process_file (fd, elf, NULL, NULL, argv[remaining], st.st_size, 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng only_one); 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now we can close the descriptor. */ 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf_end (elf) != 0) 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("error while closing Elf descriptor: %s\n"), 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_errmsg (-1)); 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prev_error_count == error_count && !be_quiet) 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng puts (gettext ("No errors")); 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng close (fd); 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (++remaining < argc); 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return error_count != 0; 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle program arguments. */ 20125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t 20225b3c049e70834cf33790a28643ab058b507b35cBen Chengparse_opt (int key, char *arg __attribute__ ((unused)), 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct argp_state *state __attribute__ ((unused))) 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (key) 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ARGP_strict: 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng be_strict = true; 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'q': 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng be_quiet = true; 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'd': 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng is_debuginfo = true; 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ARGP_gnuld: 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng gnuld = true; 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ARGP_KEY_NO_ARGS: 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng fputs (gettext ("Missing file name.\n"), stderr); 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name); 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng exit (EXIT_FAILURE); 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return ARGP_ERR_UNKNOWN; 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the version information. */ 23525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 23625b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng fprintf (stream, "elflint (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng fprintf (stream, gettext ("\ 24025b3c049e70834cf33790a28643ab058b507b35cBen ChengCopyright (C) %s Red Hat, Inc.\n\ 24125b3c049e70834cf33790a28643ab058b507b35cBen ChengThis is free software; see the source for copying conditions. There is NO\n\ 24225b3c049e70834cf33790a28643ab058b507b35cBen Chengwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng"), "2012"); 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Process one file. */ 24925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 25025b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_file (int fd, Elf *elf, const char *prefix, const char *suffix, 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *fname, size_t size, bool only_one) 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We can handle two types of files: ELF files and archives. */ 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Kind kind = elf_kind (elf); 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (kind) 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_K_ELF: 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Yes! It's an ELF file. */ 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng process_elf_file (elf, prefix, suffix, fname, size, only_one); 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_K_AR: 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *subelf; 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Cmd cmd = ELF_C_READ_MMAP; 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t prefix_len = prefix == NULL ? 0 : strlen (prefix); 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t fname_len = strlen (fname) + 1; 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng char new_prefix[prefix_len + 1 + fname_len]; 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng char new_suffix[(suffix == NULL ? 0 : strlen (suffix)) + 2]; 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *cp = new_prefix; 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Create the full name of the file. */ 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefix != NULL) 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp = mempcpy (cp, prefix, prefix_len); 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = '('; 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng strcpy (stpcpy (new_suffix, suffix), ")"); 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng new_suffix[0] = '\0'; 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (cp, fname, fname_len); 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* It's an archive. We process each file in it. */ 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((subelf = elf_begin (fd, cmd, elf)) != NULL) 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng kind = elf_kind (subelf); 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Call this function recursively. */ 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (kind == ELF_K_ELF || kind == ELF_K_AR) 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Arhdr *arhdr = elf_getarhdr (subelf); 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (arhdr != NULL); 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng process_file (fd, subelf, new_prefix, new_suffix, 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng arhdr->ar_name, arhdr->ar_size, false); 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get next archive element. */ 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng cmd = elf_next (subelf); 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf_end (subelf) != 0) 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext (" error while freeing sub-ELF descriptor: %s\n"), 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_errmsg (-1)); 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We cannot do anything. */ 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 31125b3c049e70834cf33790a28643ab058b507b35cBen ChengNot an ELF file - it has the wrong magic bytes at the start\n")); 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char * 31825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection_name (Ebl *ebl, int idx) 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr; 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr = gelf_getshdr (elf_getscn (ebl->elf, idx), &shdr_mem); 32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return elf_strptr (ebl->elf, shstrndx, shdr->sh_name); 32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const int valid_e_machine[] = 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng EM_M32, EM_SPARC, EM_386, EM_68K, EM_88K, EM_860, EM_MIPS, EM_S370, 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng EM_MIPS_RS3_LE, EM_PARISC, EM_VPP500, EM_SPARC32PLUS, EM_960, EM_PPC, 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng EM_PPC64, EM_S390, EM_V800, EM_FR20, EM_RH32, EM_RCE, EM_ARM, 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng EM_FAKE_ALPHA, EM_SH, EM_SPARCV9, EM_TRICORE, EM_ARC, EM_H8_300, 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng EM_H8_300H, EM_H8S, EM_H8_500, EM_IA_64, EM_MIPS_X, EM_COLDFIRE, 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng EM_68HC12, EM_MMA, EM_PCP, EM_NCPU, EM_NDR1, EM_STARCORE, EM_ME16, 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng EM_ST100, EM_TINYJ, EM_X86_64, EM_PDSP, EM_FX66, EM_ST9PLUS, EM_ST7, 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX, 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM, 34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300, 34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA, EM_ALPHA 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define nvalid_e_machine \ 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (sizeof (valid_e_machine) / sizeof (valid_e_machine[0])) 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Numbers of sections and program headers. */ 34825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int shnum; 34925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int phnum; 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 35325b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size) 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf[512]; 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t cnt; 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check e_ident field. */ 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ident[EI_MAG0] != ELFMAG0) 36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR ("e_ident[%d] != '%c'\n", EI_MAG0, ELFMAG0); 36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ident[EI_MAG1] != ELFMAG1) 36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR ("e_ident[%d] != '%c'\n", EI_MAG1, ELFMAG1); 36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ident[EI_MAG2] != ELFMAG2) 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR ("e_ident[%d] != '%c'\n", EI_MAG2, ELFMAG2); 36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ident[EI_MAG3] != ELFMAG3) 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR ("e_ident[%d] != '%c'\n", EI_MAG3, ELFMAG3); 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ident[EI_CLASS] != ELFCLASS32 36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ehdr->e_ident[EI_CLASS] != ELFCLASS64) 37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("e_ident[%d] == %d is no known class\n"), 37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng EI_CLASS, ehdr->e_ident[EI_CLASS]); 37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB 37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ehdr->e_ident[EI_DATA] != ELFDATA2MSB) 37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("e_ident[%d] == %d is no known data encoding\n"), 37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng EI_DATA, ehdr->e_ident[EI_DATA]); 37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) 37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("unknown ELF header version number e_ident[%d] == %d\n"), 38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng EI_VERSION, ehdr->e_ident[EI_VERSION]); 38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We currently don't handle any OS ABIs other than Linux. */ 38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE 38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ehdr->e_ident[EI_OSABI] != ELFOSABI_LINUX) 38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("unsupported OS ABI e_ident[%d] == '%s'\n"), 38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng EI_OSABI, 38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf))); 38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* No ABI versions other than zero supported either. */ 39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ident[EI_ABIVERSION] != 0) 39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("unsupport ABI version e_ident[%d] == %d\n"), 39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng EI_ABIVERSION, ehdr->e_ident[EI_ABIVERSION]); 39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (cnt = EI_PAD; cnt < EI_NIDENT; ++cnt) 39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ident[cnt] != 0) 39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("e_ident[%zu] is not zero\n"), cnt); 39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the e_type field. */ 39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_REL && ehdr->e_type != ET_EXEC 40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ehdr->e_type != ET_DYN && ehdr->e_type != ET_CORE) 40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("unknown object file type %d\n"), ehdr->e_type); 40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the e_machine field. */ 40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (cnt = 0; cnt < nvalid_e_machine; ++cnt) 40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (valid_e_machine[cnt] == ehdr->e_machine) 40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cnt == nvalid_e_machine) 40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("unknown machine type %d\n"), ehdr->e_machine); 40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the e_version field. */ 41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_version != EV_CURRENT) 41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("unknown object file version\n")); 41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the e_phoff and e_phnum fields. */ 41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_phoff == 0) 41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_phnum != 0) 41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid program header offset\n")); 41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN) 42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 42125b3c049e70834cf33790a28643ab058b507b35cBen Chengexecutables and DSOs cannot have zero program header offset\n")); 42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (ehdr->e_phnum == 0) 42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid number of program header entries\n")); 42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the e_shoff field. */ 42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng shnum = ehdr->e_shnum; 42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng shstrndx = ehdr->e_shstrndx; 42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_shoff == 0) 43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_shnum != 0) 43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid section header table offset\n")); 43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN 43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ehdr->e_type != ET_CORE) 43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section header table must be present\n")); 43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_shnum == 0) 44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get the header of the zeroth section. The sh_size field 44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng might contain the section number. */ 44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem); 44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr != NULL) 44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The error will be reported later. */ 44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_size == 0) 44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 45025b3c049e70834cf33790a28643ab058b507b35cBen Chenginvalid number of section header table entries\n")); 45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng shnum = shdr->sh_size; 45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_shstrndx == SHN_XINDEX) 45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get the header of the zeroth section. The sh_size field 45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng might contain the section number. */ 46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem); 46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr != NULL && shdr->sh_link < shnum) 46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng shstrndx = shdr->sh_link; 46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (shstrndx >= shnum) 46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid section header index\n")); 46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng phnum = ehdr->e_phnum; 47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_phnum == PN_XNUM) 47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get the header of the zeroth section. The sh_info field 47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng might contain the phnum count. */ 47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem); 47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr != NULL) 47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The error will be reported later. */ 47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_info < PN_XNUM) 48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 48125b3c049e70834cf33790a28643ab058b507b35cBen Chenginvalid number of program header table entries\n")); 48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng phnum = shdr->sh_info; 48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the e_flags field. */ 48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!ebl_machine_flag_check (ebl, ehdr->e_flags)) 48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid machine flags: %s\n"), 49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf))); 49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check e_ehsize, e_phentsize, and e_shentsize fields. */ 49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (gelf_getclass (ebl->elf) == ELFCLASS32) 49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf32_Ehdr)) 49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize); 49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr)) 49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid program header size: %hd\n"), 50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr->e_phentsize); 50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size) 50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid program header position or size\n")); 50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr)) 50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid section header size: %hd\n"), 50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr->e_shentsize); 50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (ehdr->e_shoff + shnum * ehdr->e_shentsize > size) 50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid section header position or size\n")); 50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (gelf_getclass (ebl->elf) == ELFCLASS64) 51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf64_Ehdr)) 51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize); 51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr)) 51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid program header size: %hd\n"), 51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr->e_phentsize); 51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size) 51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid program header position or size\n")); 52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr)) 52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid section header size: %hd\n"), 52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr->e_shentsize); 52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size) 52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("invalid section header position or size\n")); 52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Check that there is a section group section with index < IDX which 53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng contains section IDX and that there is exactly one. */ 53225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 53325b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_scn_group (Ebl *ebl, int idx) 53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scnref[idx] == 0) 53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* No reference so far. Search following sections, maybe the 53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng order is wrong. */ 53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t cnt; 54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (cnt = idx + 1; cnt < shnum; ++cnt) 54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = elf_getscn (ebl->elf, cnt); 54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr == NULL) 54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We cannot get the section header so we cannot check it. 54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng The error to get the section header will be shown 54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng somewhere else. */ 55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_type != SHT_GROUP) 55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (scn, NULL); 55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL || data->d_size < sizeof (Elf32_Word)) 55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Cannot check the section. */ 55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word *grpdata = (Elf32_Word *) data->d_buf; 56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t inner = 1; inner < data->d_size / sizeof (Elf32_Word); 56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++inner) 56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (grpdata[inner] == (Elf32_Word) idx) 56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto out; 56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng out: 56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cnt == shnum) 56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 57025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section with SHF_GROUP flag set not part of a section group\n"), 57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 57425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section group [%2zu] '%s' does not precede group member\n"), 57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 58225b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_symtab (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool no_xndx_warned = false; 58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int no_pt_tls = 0; 58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr strshdr_mem; 59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng &strshdr_mem); 59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strshdr == NULL) 59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strshdr->sh_type != SHT_STRTAB) 60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"), 60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr->sh_link, section_name (ebl, shdr->sh_link), 60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng strshdr = NULL; 60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Search for an extended section index table section. */ 60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *xndxdata = NULL; 61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word xndxscnidx = 0; 61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool found_xndx = false; 61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 1; cnt < shnum; ++cnt) 61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cnt != (size_t) idx) 61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *xndxscn = elf_getscn (ebl->elf, cnt); 61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr xndxshdr_mem; 61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem); 61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (xndxshdr == NULL) 61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX 62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && xndxshdr->sh_link == (GElf_Word) idx) 62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (found_xndx) 62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 62625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol table cannot have more than one extended index section\n"), 62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng xndxdata = elf_getdata (xndxscn, NULL); 63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng xndxscnidx = elf_ndxscn (xndxscn); 63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng found_xndx = true; 63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)) 63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 63725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2u] '%s': entry size is does not match ElfXX_Sym\n"), 63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Test the zeroth entry. */ 64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym sym_mem; 64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word xndx; 64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, 0, &sym_mem, &xndx); 64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym == NULL) 64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get symbol %d: %s\n"), 64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 0, elf_errmsg (-1)); 64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_name != 0) 65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "st_name"); 65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_value != 0) 65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "st_value"); 65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_size != 0) 65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "st_size"); 65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_info != 0) 65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "st_info"); 66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_other != 0) 66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "st_other"); 66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_shndx != 0) 66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "st_shndx"); 66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (xndxdata != NULL && xndx != 0) 66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 66925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': XINDEX for zeroth entry not zero\n"), 67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng xndxscnidx, section_name (ebl, xndxscnidx)); 67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 1; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx); 67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym == NULL) 67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get symbol %zu: %s\n"), 67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, elf_errmsg (-1)); 68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *name = NULL; 68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strshdr == NULL) 68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng name = ""; 68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sym->st_name >= strshdr->sh_size) 68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 68825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: invalid name value\n"), 68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name); 69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (name != NULL); 69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_shndx == SHN_XINDEX) 69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (xndxdata == NULL) 69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!no_xndx_warned) 70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 70225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: too large section index but no extended section index section\n"), 70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng no_xndx_warned = true; 70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (xndx < SHN_LORESERVE) 70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 70825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: XINDEX used for index which would fit in st_shndx (%" PRIu32 ")\n"), 70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng xndxscnidx, section_name (ebl, xndxscnidx), cnt, 71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng xndx); 71125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 71225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((sym->st_shndx >= SHN_LORESERVE 71325b3c049e70834cf33790a28643ab058b507b35cBen Cheng // && sym->st_shndx <= SHN_HIRESERVE always true 71425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && sym->st_shndx != SHN_ABS 71525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && sym->st_shndx != SHN_COMMON) 71625b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (sym->st_shndx >= shnum 71725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (sym->st_shndx < SHN_LORESERVE 71825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* || sym->st_shndx > SHN_HIRESERVE always false */))) 71925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 72025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: invalid section index\n"), 72125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng xndx = sym->st_shndx; 72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (GELF_ST_TYPE (sym->st_info) >= STT_NUM 72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), NULL, 0)) 72725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': symbol %zu: unknown type\n"), 72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (GELF_ST_BIND (sym->st_info) >= STB_NUM 73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info), NULL, 73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 0)) 73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 73425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: unknown symbol binding\n"), 73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE 73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && GELF_ST_TYPE (sym->st_info) != STT_OBJECT) 73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 73925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: unique symbol not of object type\n"), 74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (xndx == SHN_COMMON) 74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Common symbols can only appear in relocatable files. */ 74525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_REL) 74625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 74725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n"), 74825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 74925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cnt < shdr->sh_info) 75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 75125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n"), 75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (GELF_R_TYPE (sym->st_info) == STT_FUNC) 75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 75525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"), 75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (xndx > 0 && xndx < shnum) 75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr destshdr_mem; 76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *destshdr; 76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), &destshdr_mem); 76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (destshdr != NULL) 76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr sh_addr = (ehdr->e_type == ET_REL ? 0 76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng : destshdr->sh_addr); 76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (GELF_ST_TYPE (sym->st_info) != STT_TLS) 76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (! ebl_check_special_symbol (ebl, ehdr, sym, name, 77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng destshdr)) 77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_value - sh_addr > destshdr->sh_size) 77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* GNU ld has severe bugs. When it decides to remove 77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng empty sections it leaves symbols referencing them 77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng behind. These are symbols in .symtab. */ 77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!gnuld 77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng || strcmp (section_name (ebl, idx), ".symtab") 78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (strcmp (name, "__preinit_array_start") != 0 78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && strcmp (name, "__preinit_array_end") != 0 78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && strcmp (name, "__init_array_start") != 0 78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && strcmp (name, "__init_array_end") != 0 78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && strcmp (name, "__fini_array_start") != 0 78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && strcmp (name, "__fini_array_end") != 0)) 78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 78725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: st_value out of bounds\n"), 78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((sym->st_value - sh_addr 79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng + sym->st_size) > destshdr->sh_size) 79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 79325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"), 79425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 79525b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) xndx, section_name (ebl, xndx)); 79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((destshdr->sh_flags & SHF_TLS) == 0) 80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 80225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_TLS flag set\n"), 80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) xndx, section_name (ebl, xndx)); 80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type == ET_REL) 80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* For object files the symbol value must fall 80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng into the section. */ 81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_value > destshdr->sh_size) 81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 81225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"), 81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 81425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) xndx, section_name (ebl, xndx)); 81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sym->st_value + sym->st_size 81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng > destshdr->sh_size) 81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 81825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"), 81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) xndx, section_name (ebl, xndx)); 82125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 82225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 82325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 82425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 82525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr = NULL; 82625b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int pcnt; 82725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 82825b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (pcnt = 0; pcnt < phnum; ++pcnt) 82925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 83025b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem); 83125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr != NULL && phdr->p_type == PT_TLS) 83225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 83325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 83425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 83525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (pcnt == phnum) 83625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 83725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (no_pt_tls++ == 0) 83825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 83925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"), 84025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 84125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 84225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 84325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 84425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_value 84525b3c049e70834cf33790a28643ab058b507b35cBen Cheng < destshdr->sh_offset - phdr->p_offset) 84625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 84725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"), 84825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 84925b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) xndx, section_name (ebl, xndx)); 85025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sym->st_value 85125b3c049e70834cf33790a28643ab058b507b35cBen Cheng > (destshdr->sh_offset - phdr->p_offset 85225b3c049e70834cf33790a28643ab058b507b35cBen Cheng + destshdr->sh_size)) 85325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 85425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"), 85525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 85625b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) xndx, section_name (ebl, xndx)); 85725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sym->st_value + sym->st_size 85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng > (destshdr->sh_offset - phdr->p_offset 85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng + destshdr->sh_size)) 86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 86125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"), 86225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 86325b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) xndx, section_name (ebl, xndx)); 86425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 87025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (GELF_ST_BIND (sym->st_info) == STB_LOCAL) 87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 87225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cnt >= shdr->sh_info) 87325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 87425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: local symbol outside range described in sh_info\n"), 87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cnt < shdr->sh_info) 88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 88125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: non-local symbol outside range described in sh_info\n"), 88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 88325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 88425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (GELF_ST_TYPE (sym->st_info) == STT_SECTION 88625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && GELF_ST_BIND (sym->st_info) != STB_LOCAL) 88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 88825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: non-local section symbol\n"), 88925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 89025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 89125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (name != NULL) 89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0) 89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that address and size match the global offset table. */ 89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr destshdr_mem; 89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), 89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng &destshdr_mem); 90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (destshdr == NULL && xndx == SHN_ABS) 90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* In a DSO, we have to find the GOT section by name. */ 90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *gotscn = NULL; 90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *gscn = NULL; 90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL) 90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng destshdr = gelf_getshdr (gscn, &destshdr_mem); 90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (destshdr != NULL); 91025b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *sname = elf_strptr (ebl->elf, 91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr->e_shstrndx, 91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng destshdr->sh_name); 91325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sname != NULL) 91425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 91525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strcmp (sname, ".got.plt") == 0) 91625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 91725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strcmp (sname, ".got") == 0) 91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Do not stop looking. 91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng There might be a .got.plt section. */ 92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng gotscn = gscn; 92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng destshdr = NULL; 92425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 92525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (destshdr == NULL && gotscn != NULL) 92725b3c049e70834cf33790a28643ab058b507b35cBen Cheng destshdr = gelf_getshdr (gotscn, &destshdr_mem); 92825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 92925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 93025b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *sname = ((destshdr == NULL || xndx == SHN_UNDEF) 93125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? NULL 93225b3c049e70834cf33790a28643ab058b507b35cBen Cheng : elf_strptr (ebl->elf, ehdr->e_shstrndx, 93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng destshdr->sh_name)); 93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sname == NULL) 93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (xndx != SHN_UNDEF || ehdr->e_type != ET_REL) 93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 93825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \ 93925b3c049e70834cf33790a28643ab058b507b35cBen Chengbad section [%2d]\n"), 94025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), xndx); 94125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (strcmp (sname, ".got.plt") != 0 94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && strcmp (sname, ".got") != 0) 94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 94525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \ 94625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s'\n"), 94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), xndx, sname); 94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 94925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (destshdr != NULL) 95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Found it. */ 95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!ebl_check_special_symbol (ebl, ehdr, sym, name, 95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng destshdr)) 95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_REL 95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && sym->st_value != destshdr->sh_addr) 95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This test is more strict than the psABIs which 95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng usually allow the symbol to be in the middle of 95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng the .got section, allowing negative offsets. */ 96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 96125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match %s section address %#" PRIx64 "\n"), 96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 96325b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint64_t) sym->st_value, 96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sname, (uint64_t) destshdr->sh_addr); 96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!gnuld && sym->st_size != destshdr->sh_size) 96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 96825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match %s section size %" PRIu64 "\n"), 96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 97025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint64_t) sym->st_size, 97125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sname, (uint64_t) destshdr->sh_size); 97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 97425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 97525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 97625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"), 97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (strcmp (name, "_DYNAMIC") == 0) 98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that address and size match the dynamic section. 98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng We locate the dynamic section via the program header 98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng entry. */ 98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt) 98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem); 98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr != NULL && phdr->p_type == PT_DYNAMIC) 98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_value != phdr->p_vaddr) 99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 99225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"), 99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint64_t) sym->st_value, 99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint64_t) phdr->p_vaddr); 99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!gnuld && sym->st_size != phdr->p_memsz) 99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 99925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"), 100025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint64_t) sym->st_size, 100225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint64_t) phdr->p_memsz); 100325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 100825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (GELF_ST_VISIBILITY (sym->st_other) != STV_DEFAULT 101025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr->sh_type == SHT_DYNSYM) 101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 101225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: symbol in dynamic symbol table with non-default visibility\n"), 101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (! ebl_check_st_other_bits (ebl, sym->st_other)) 101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 101625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %zu: unknown bit set in st_other\n"), 101725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 101925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 102125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 102225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 102325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool 102425b3c049e70834cf33790a28643ab058b507b35cBen Chengis_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr, 102525b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool is_rela) 102625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 102725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If this is no executable or DSO it cannot be a .rel.dyn section. */ 102825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 102925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 103025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 103125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the section name. Unfortunately necessary. */ 103225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strcmp (section_name (ebl, idx), is_rela ? ".rela.dyn" : ".rel.dyn")) 103325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 103425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 103525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section 103625b3c049e70834cf33790a28643ab058b507b35cBen Cheng entry can be present as well. */ 103725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = NULL; 103825b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 103925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 104025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr rcshdr_mem; 104125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem); 104225b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (rcshdr != NULL); 104325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 104425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (rcshdr->sh_type == SHT_DYNAMIC) 104525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 104625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Found the dynamic section. Look through it. */ 104725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *d = elf_getdata (scn, NULL); 104825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t cnt; 104925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 105025b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt) 105125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 105225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Dyn dyn_mem; 105325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem); 105425b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (dyn != NULL); 105525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 105625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn->d_tag == DT_RELCOUNT) 105725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 105825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Found it. Does the type match. */ 105925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (is_rela) 106025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 106125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': DT_RELCOUNT used for this RELA section\n"), 106225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 106325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 106425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 106525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Does the number specified number of relative 106625b3c049e70834cf33790a28643ab058b507b35cBen Cheng relocations exceed the total number of 106725b3c049e70834cf33790a28643ab058b507b35cBen Cheng relocations? */ 106825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize) 106925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 107025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"), 107125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 107225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) dyn->d_un.d_val); 107325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 107425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure the specified number of relocations are 107525b3c049e70834cf33790a28643ab058b507b35cBen Cheng relative. */ 107625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf, 107725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx), NULL); 107825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (reldata != NULL) 107925b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t inner = 0; 108025b3c049e70834cf33790a28643ab058b507b35cBen Cheng inner < shdr->sh_size / shdr->sh_entsize; 108125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++inner) 108225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 108325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rel rel_mem; 108425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rel *rel = gelf_getrel (reldata, inner, 108525b3c049e70834cf33790a28643ab058b507b35cBen Cheng &rel_mem); 108625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (rel == NULL) 108725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The problem will be reported elsewhere. */ 108825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 108925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 109025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ebl_relative_reloc_p (ebl, 109125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GELF_R_TYPE (rel->r_info))) 109225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 109325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (inner >= dyn->d_un.d_val) 109425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 109525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"), 109625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 109725b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) dyn->d_un.d_val); 109825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 109925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (inner < dyn->d_un.d_val) 110025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 110125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"), 110225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 110325b3c049e70834cf33790a28643ab058b507b35cBen Cheng inner, (int) dyn->d_un.d_val); 110425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 110525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 110625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 110725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 110825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn->d_tag == DT_RELACOUNT) 110925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 111025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Found it. Does the type match. */ 111125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!is_rela) 111225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 111325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': DT_RELACOUNT used for this REL section\n"), 111425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 111525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 111625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 111725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Does the number specified number of relative 111825b3c049e70834cf33790a28643ab058b507b35cBen Cheng relocations exceed the total number of 111925b3c049e70834cf33790a28643ab058b507b35cBen Cheng relocations? */ 112025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize) 112125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 112225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"), 112325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 112425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) dyn->d_un.d_val); 112525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 112625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure the specified number of relocations are 112725b3c049e70834cf33790a28643ab058b507b35cBen Cheng relative. */ 112825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf, 112925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx), NULL); 113025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (reldata != NULL) 113125b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t inner = 0; 113225b3c049e70834cf33790a28643ab058b507b35cBen Cheng inner < shdr->sh_size / shdr->sh_entsize; 113325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++inner) 113425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 113525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rela rela_mem; 113625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rela *rela = gelf_getrela (reldata, inner, 113725b3c049e70834cf33790a28643ab058b507b35cBen Cheng &rela_mem); 113825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (rela == NULL) 113925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The problem will be reported elsewhere. */ 114025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 114125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 114225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ebl_relative_reloc_p (ebl, 114325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GELF_R_TYPE (rela->r_info))) 114425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 114525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (inner >= dyn->d_un.d_val) 114625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 114725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"), 114825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 114925b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) dyn->d_un.d_val); 115025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 115125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (inner < dyn->d_un.d_val) 115225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 115325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"), 115425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 115525b3c049e70834cf33790a28643ab058b507b35cBen Cheng inner, (int) dyn->d_un.d_val); 115625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 115725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 115825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 115925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 116025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 116125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 116225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 116325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 116425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 116525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 116625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 116725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 116825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 116925b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct loaded_segment 117025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 117125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr from; 117225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr to; 117325b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool read_only; 117425b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct loaded_segment *next; 117525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}; 117625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 117725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 117825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Check whether binary has text relocation flag set. */ 117925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool textrel; 118025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 118125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Keep track of whether text relocation flag is needed. */ 118225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool needed_textrel; 118325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 118425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 118525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool 118625b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr, 118725b3c049e70834cf33790a28643ab058b507b35cBen Cheng int idx, int reltype, GElf_Shdr **destshdrp, 118825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *destshdr_memp, struct loaded_segment **loadedp) 118925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 119025b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool reldyn = false; 119125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 119225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check whether the link to the section we relocate is reasonable. */ 119325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_info >= shnum) 119425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"), 119525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 119625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (shdr->sh_info != 0) 119725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 119825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *destshdrp = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info), 119925b3c049e70834cf33790a28643ab058b507b35cBen Cheng destshdr_memp); 120025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*destshdrp != NULL) 120125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 120225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if((*destshdrp)->sh_type != SHT_PROGBITS 120325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (*destshdrp)->sh_type != SHT_NOBITS) 120425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 120525b3c049e70834cf33790a28643ab058b507b35cBen Cheng reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true); 120625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!reldyn) 120725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 120825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': invalid destination section type\n"), 120925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 121025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 121125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 121225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* There is no standard, but we require that .rel{,a}.dyn 121325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sections have a sh_info value of zero. */ 121425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_info != 0) 121525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 121625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': sh_info should be zero\n"), 121725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 121825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 121925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 122025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 122125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (((*destshdrp)->sh_flags & (SHF_MERGE | SHF_STRINGS)) != 0) 122225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 122325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': no relocations for merge-able sections possible\n"), 122425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 122525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 122625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 122725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 122825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_entsize != gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT)) 122925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext (reltype == ELF_T_RELA ? "\ 123025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section entry size does not match ElfXX_Rela\n" : "\ 123125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section entry size does not match ElfXX_Rel\n"), 123225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 123325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 123425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* In preparation of checking whether relocations are text 123525b3c049e70834cf33790a28643ab058b507b35cBen Cheng relocations or not we need to determine whether the file is 123625b3c049e70834cf33790a28643ab058b507b35cBen Cheng flagged to have text relocation and we need to determine a) what 123725b3c049e70834cf33790a28643ab058b507b35cBen Cheng the loaded segments are and b) which are read-only. This will 123825b3c049e70834cf33790a28643ab058b507b35cBen Cheng also allow us to determine whether the same reloc section is 123925b3c049e70834cf33790a28643ab058b507b35cBen Cheng modifying loaded and not loaded segments. */ 124025b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (unsigned int i = 0; i < phnum; ++i) 124125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 124225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 124325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem); 124425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr == NULL) 124525b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 124625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 124725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_type == PT_LOAD) 124825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 124925b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct loaded_segment *newp = xmalloc (sizeof (*newp)); 125025b3c049e70834cf33790a28643ab058b507b35cBen Cheng newp->from = phdr->p_vaddr; 125125b3c049e70834cf33790a28643ab058b507b35cBen Cheng newp->to = phdr->p_vaddr + phdr->p_memsz; 125225b3c049e70834cf33790a28643ab058b507b35cBen Cheng newp->read_only = (phdr->p_flags & PF_W) == 0; 125325b3c049e70834cf33790a28643ab058b507b35cBen Cheng newp->next = *loadedp; 125425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *loadedp = newp; 125525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 125625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (phdr->p_type == PT_DYNAMIC) 125725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 125825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *dynscn = gelf_offscn (ebl->elf, phdr->p_offset); 125925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr dynshdr_mem; 126025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem); 126125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *dyndata = elf_getdata (dynscn, NULL); 126225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC 126325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && dyndata != NULL) 126425b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j) 126525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 126625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Dyn dyn_mem; 126725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Dyn *dyn = gelf_getdyn (dyndata, j, &dyn_mem); 126825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn != NULL 126925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (dyn->d_tag == DT_TEXTREL 127025b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (dyn->d_tag == DT_FLAGS 127125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (dyn->d_un.d_val & DF_TEXTREL) != 0))) 127225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 127325b3c049e70834cf33790a28643ab058b507b35cBen Cheng textrel = true; 127425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 127525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 127625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 127725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 127825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 127925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 128025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* A quick test which can be easily done here (although it is a bit 128125b3c049e70834cf33790a28643ab058b507b35cBen Cheng out of place): the text relocation flag makes only sense if there 128225b3c049e70834cf33790a28643ab058b507b35cBen Cheng is a segment which is not writable. */ 128325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (textrel) 128425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 128525b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct loaded_segment *seg = *loadedp; 128625b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (seg != NULL && !seg->read_only) 128725b3c049e70834cf33790a28643ab058b507b35cBen Cheng seg = seg->next; 128825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (seg == NULL) 128925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 129025b3c049e70834cf33790a28643ab058b507b35cBen Chengtext relocation flag set but there is no read-only segment\n")); 129125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 129225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 129325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return reldyn; 129425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 129525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 129625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 129725b3c049e70834cf33790a28643ab058b507b35cBen Chengenum load_state 129825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 129925b3c049e70834cf33790a28643ab058b507b35cBen Cheng state_undecided, 130025b3c049e70834cf33790a28643ab058b507b35cBen Cheng state_loaded, 130125b3c049e70834cf33790a28643ab058b507b35cBen Cheng state_unloaded, 130225b3c049e70834cf33790a28643ab058b507b35cBen Cheng state_error 130325b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 130425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 130525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 130625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 130725b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_one_reloc (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *relshdr, int idx, 130825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t cnt, const GElf_Shdr *symshdr, Elf_Data *symdata, 130925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr r_offset, GElf_Xword r_info, 131025b3c049e70834cf33790a28643ab058b507b35cBen Cheng const GElf_Shdr *destshdr, bool reldyn, 131125b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct loaded_segment *loaded, enum load_state *statep) 131225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 131325b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool known_broken = gnuld; 131425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 131525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (r_info))) 131625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"), 131725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 131825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 131925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The executable/DSO can contain relocation sections with 132025b3c049e70834cf33790a28643ab058b507b35cBen Cheng all the relocations the linker has applied. Those sections 132125b3c049e70834cf33790a28643ab058b507b35cBen Cheng are marked non-loaded, though. */ 132225b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (relshdr->sh_flags & SHF_ALLOC) != 0) 132325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !ebl_reloc_valid_use (ebl, GELF_R_TYPE (r_info))) 132425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 132525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"), 132625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 132725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 132825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symshdr != NULL 132925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ((GELF_R_SYM (r_info) + 1) 133025b3c049e70834cf33790a28643ab058b507b35cBen Cheng * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT) 133125b3c049e70834cf33790a28643ab058b507b35cBen Cheng > symshdr->sh_size)) 133225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 133325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': relocation %zu: invalid symbol index\n"), 133425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 133525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 133625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* No more tests if this is a no-op relocation. */ 133725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ebl_none_reloc_p (ebl, GELF_R_TYPE (r_info))) 133825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 133925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 134025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (r_info))) 134125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 134225b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *name; 134325b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf[64]; 134425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym sym_mem; 134525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem); 134625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym != NULL 134725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get the name for the symbol. */ 134825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)) 134925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 ) 135025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 135125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"), 135225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 135325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_reloc_type_name (ebl, GELF_R_SYM (r_info), 135425b3c049e70834cf33790a28643ab058b507b35cBen Cheng buf, sizeof (buf))); 135525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 135625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 135725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (reldyn) 135825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 135925b3c049e70834cf33790a28643ab058b507b35cBen Cheng // XXX TODO Check .rel.dyn section addresses. 136025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 136125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (!known_broken) 136225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 136325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (destshdr != NULL 136425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && GELF_R_TYPE (r_info) != 0 136525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (r_offset - (ehdr->e_type == ET_REL ? 0 136625b3c049e70834cf33790a28643ab058b507b35cBen Cheng : destshdr->sh_addr)) >= destshdr->sh_size) 136725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 136825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': relocation %zu: offset out of bounds\n"), 136925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 137025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 137125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 137225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym sym_mem; 137325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem); 137425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 137525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info)) 137625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure the referenced symbol is an object or unspecified. */ 137725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && sym != NULL 137825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE 137925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && GELF_ST_TYPE (sym->st_info) != STT_OBJECT) 138025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 138125b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf[64]; 138225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"), 138325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 138425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), 138525b3c049e70834cf33790a28643ab058b507b35cBen Cheng buf, sizeof (buf))); 138625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 138725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 138825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 138925b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (relshdr->sh_flags & SHF_ALLOC) != 0) 139025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 139125b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool in_loaded_seg = false; 139225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (loaded != NULL) 139325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 139425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r_offset < loaded->to 139525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && r_offset + (sym == NULL ? 0 : sym->st_size) >= loaded->from) 139625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 139725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The symbol is in this segment. */ 139825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (loaded->read_only) 139925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 140025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (textrel) 140125b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed_textrel = true; 140225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 140325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': relocation %zu: read-only section modified but text relocation flag not set\n"), 140425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 140525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 140625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 140725b3c049e70834cf33790a28643ab058b507b35cBen Cheng in_loaded_seg = true; 140825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 140925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 141025b3c049e70834cf33790a28643ab058b507b35cBen Cheng loaded = loaded->next; 141125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 141225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 141325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*statep == state_undecided) 141425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *statep = in_loaded_seg ? state_loaded : state_unloaded; 141525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((*statep == state_unloaded && in_loaded_seg) 141625b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (*statep == state_loaded && !in_loaded_seg)) 141725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 141825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 141925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': relocations are against loaded and unloaded data\n"), 142025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 142125b3c049e70834cf33790a28643ab058b507b35cBen Cheng *statep = state_error; 142225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 142325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 142425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 142525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 142625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 142725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 142825b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 142925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 143025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 143125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 143225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 143325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 143425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 143525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 143625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 143725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 143825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the fields of the section header. */ 143925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr destshdr_mem; 144025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *destshdr = NULL; 144125b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct loaded_segment *loaded = NULL; 144225b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELA, &destshdr, 144325b3c049e70834cf33790a28643ab058b507b35cBen Cheng &destshdr_mem, &loaded); 144425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 144525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 144625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr symshdr_mem; 144725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 144825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *symdata = elf_getdata (symscn, NULL); 144925b3c049e70834cf33790a28643ab058b507b35cBen Cheng enum load_state state = state_undecided; 145025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 145125b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 145225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 145325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rela rela_mem; 145425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem); 145525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (rela == NULL) 145625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 145725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 145825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': cannot get relocation %zu: %s\n"), 145925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, elf_errmsg (-1)); 146025b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 146125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 146225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 146325b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata, 146425b3c049e70834cf33790a28643ab058b507b35cBen Cheng rela->r_offset, rela->r_info, destshdr, reldyn, loaded, 146525b3c049e70834cf33790a28643ab058b507b35cBen Cheng &state); 146625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 146725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 146825b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (loaded != NULL) 146925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 147025b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct loaded_segment *old = loaded; 147125b3c049e70834cf33790a28643ab058b507b35cBen Cheng loaded = loaded->next; 147225b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (old); 147325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 147425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 147525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 147625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 147725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 147825b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 147925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 148025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 148125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 148225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 148325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 148425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 148525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 148625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 148725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 148825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the fields of the section header. */ 148925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr destshdr_mem; 149025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *destshdr = NULL; 149125b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct loaded_segment *loaded = NULL; 149225b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_REL, &destshdr, 149325b3c049e70834cf33790a28643ab058b507b35cBen Cheng &destshdr_mem, &loaded); 149425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 149525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 149625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr symshdr_mem; 149725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 149825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *symdata = elf_getdata (symscn, NULL); 149925b3c049e70834cf33790a28643ab058b507b35cBen Cheng enum load_state state = state_undecided; 150025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 150125b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 150225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 150325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rel rel_mem; 150425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem); 150525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (rel == NULL) 150625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 150725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 150825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': cannot get relocation %zu: %s\n"), 150925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, elf_errmsg (-1)); 151025b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 151125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 151225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 151325b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata, 151425b3c049e70834cf33790a28643ab058b507b35cBen Cheng rel->r_offset, rel->r_info, destshdr, reldyn, loaded, 151525b3c049e70834cf33790a28643ab058b507b35cBen Cheng &state); 151625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 151725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 151825b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (loaded != NULL) 151925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 152025b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct loaded_segment *old = loaded; 152125b3c049e70834cf33790a28643ab058b507b35cBen Cheng loaded = loaded->next; 152225b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (old); 152325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 152425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 152525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 152625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 152725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Number of dynamic sections. */ 152825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int ndynamic; 152925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 153025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 153125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 153225b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 153325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 153425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data; 153525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr strshdr_mem; 153625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *strshdr; 153725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t cnt; 153825b3c049e70834cf33790a28643ab058b507b35cBen Cheng static const bool dependencies[DT_NUM][DT_NUM] = 153925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 154025b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_NEEDED] = { [DT_STRTAB] = true }, 154125b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_PLTRELSZ] = { [DT_JMPREL] = true }, 154225b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_HASH] = { [DT_SYMTAB] = true }, 154325b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_STRTAB] = { [DT_STRSZ] = true }, 154425b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_SYMENT] = true }, 154525b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true }, 154625b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_RELASZ] = { [DT_RELA] = true }, 154725b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_RELAENT] = { [DT_RELA] = true }, 154825b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_STRSZ] = { [DT_STRTAB] = true }, 154925b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_SYMENT] = { [DT_SYMTAB] = true }, 155025b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_SONAME] = { [DT_STRTAB] = true }, 155125b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_RPATH] = { [DT_STRTAB] = true }, 155225b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true }, 155325b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_RELSZ] = { [DT_REL] = true }, 155425b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_RELENT] = { [DT_REL] = true }, 155525b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true }, 155625b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_RUNPATH] = { [DT_STRTAB] = true }, 155725b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_PLTREL] = { [DT_JMPREL] = true }, 155825b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 155925b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool has_dt[DT_NUM]; 156025b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool has_val_dt[DT_VALNUM]; 156125b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool has_addr_dt[DT_ADDRNUM]; 156225b3c049e70834cf33790a28643ab058b507b35cBen Cheng static const bool level2[DT_NUM] = 156325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 156425b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_RPATH] = true, 156525b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_SYMBOLIC] = true, 156625b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_TEXTREL] = true, 156725b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_BIND_NOW] = true 156825b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 156925b3c049e70834cf33790a28643ab058b507b35cBen Cheng static const bool mandatory[DT_NUM] = 157025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 157125b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_NULL] = true, 157225b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_STRTAB] = true, 157325b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_SYMTAB] = true, 157425b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_STRSZ] = true, 157525b3c049e70834cf33790a28643ab058b507b35cBen Cheng [DT_SYMENT] = true 157625b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 157725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 157825b3c049e70834cf33790a28643ab058b507b35cBen Cheng memset (has_dt, '\0', sizeof (has_dt)); 157925b3c049e70834cf33790a28643ab058b507b35cBen Cheng memset (has_val_dt, '\0', sizeof (has_val_dt)); 158025b3c049e70834cf33790a28643ab058b507b35cBen Cheng memset (has_addr_dt, '\0', sizeof (has_addr_dt)); 158125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 158225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (++ndynamic == 2) 158325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("more than one dynamic section present\n")); 158425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 158525b3c049e70834cf33790a28643ab058b507b35cBen Cheng data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 158625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 158725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 158825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 158925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 159025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 159125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 159225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 159325b3c049e70834cf33790a28643ab058b507b35cBen Cheng strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem); 159425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB) 159525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 159625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"), 159725b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr->sh_link, section_name (ebl, shdr->sh_link), 159825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 159925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 160025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT)) 160125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 160225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section entry size does not match ElfXX_Dyn\n"), 160325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 160425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 160525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_info != 0) 160625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"), 160725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 160825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 160925b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool non_null_warned = false; 161025b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 161125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 161225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Dyn dyn_mem; 161325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dyn_mem); 161425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn == NULL) 161525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 161625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 161725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': cannot get dynamic section entry %zu: %s\n"), 161825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, elf_errmsg (-1)); 161925b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 162025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 162125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 162225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned) 162325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 162425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 162525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"), 162625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 162725b3c049e70834cf33790a28643ab058b507b35cBen Cheng non_null_warned = true; 162825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 162925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 163025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!ebl_dynamic_tag_check (ebl, dyn->d_tag)) 163125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': entry %zu: unknown tag\n"), 163225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 163325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 163425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn->d_tag >= 0 && dyn->d_tag < DT_NUM) 163525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 163625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (has_dt[dyn->d_tag] 163725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && dyn->d_tag != DT_NEEDED 163825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && dyn->d_tag != DT_NULL 163925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && dyn->d_tag != DT_POSFLAG_1) 164025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 164125b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf[50]; 164225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 164325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %zu: more than one entry with tag %s\n"), 164425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 164525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_dynamic_tag_name (ebl, dyn->d_tag, 164625b3c049e70834cf33790a28643ab058b507b35cBen Cheng buf, sizeof (buf))); 164725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 164825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 164925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (be_strict && level2[dyn->d_tag]) 165025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 165125b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf[50]; 165225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 165325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %zu: level 2 tag %s used\n"), 165425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 165525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_dynamic_tag_name (ebl, dyn->d_tag, 165625b3c049e70834cf33790a28643ab058b507b35cBen Cheng buf, sizeof (buf))); 165725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 165825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 165925b3c049e70834cf33790a28643ab058b507b35cBen Cheng has_dt[dyn->d_tag] = true; 166025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 166125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (dyn->d_tag <= DT_VALRNGHI 166225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM) 166325b3c049e70834cf33790a28643ab058b507b35cBen Cheng has_val_dt[DT_VALTAGIDX (dyn->d_tag)] = true; 166425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (dyn->d_tag <= DT_ADDRRNGHI 166525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM) 166625b3c049e70834cf33790a28643ab058b507b35cBen Cheng has_addr_dt[DT_ADDRTAGIDX (dyn->d_tag)] = true; 166725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 166825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL 166925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && dyn->d_un.d_val != DT_RELA) 167025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 167125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"), 167225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 167325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 167425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that addresses for entries are in loaded segments. */ 167525b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (dyn->d_tag) 167625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 167725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t n; 167825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_STRTAB: 167925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We require the referenced section is the same as the one 168025b3c049e70834cf33790a28643ab058b507b35cBen Cheng specified in sh_link. */ 168125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strshdr->sh_addr != dyn->d_un.d_val) 168225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 168325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 168425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %zu: pointer does not match address of section [%2d] '%s' referenced by sh_link\n"), 168525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 168625b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr->sh_link, section_name (ebl, shdr->sh_link)); 168725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 168825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 168925b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto check_addr; 169025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 169125b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 169225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn->d_tag < DT_ADDRRNGLO || dyn->d_tag > DT_ADDRRNGHI) 169325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Value is no pointer. */ 169425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 169525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* FALLTHROUGH */ 169625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 169725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_AUXILIARY: 169825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_FILTER: 169925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_FINI: 170025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_FINI_ARRAY: 170125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_HASH: 170225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_INIT: 170325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_INIT_ARRAY: 170425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_JMPREL: 170525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_PLTGOT: 170625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_REL: 170725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_RELA: 170825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_SYMBOLIC: 170925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_SYMTAB: 171025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_VERDEF: 171125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_VERNEED: 171225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_VERSYM: 171325b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_addr: 171425b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (n = 0; n < phnum; ++n) 171525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 171625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 171725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr = gelf_getphdr (ebl->elf, n, &phdr_mem); 171825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr != NULL && phdr->p_type == PT_LOAD 171925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && phdr->p_vaddr <= dyn->d_un.d_ptr 172025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && phdr->p_vaddr + phdr->p_memsz > dyn->d_un.d_ptr) 172125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 172225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 172325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (n >= phnum)) 172425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 172525b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf[50]; 172625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 172725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %zu: %s value must point into loaded segment\n"), 172825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 172925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, 173025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (buf))); 173125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 173225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 173325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 173425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_NEEDED: 173525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_RPATH: 173625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_RUNPATH: 173725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DT_SONAME: 173825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn->d_un.d_ptr >= strshdr->sh_size) 173925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 174025b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf[50]; 174125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 174225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %zu: %s value must be valid offset in section [%2d] '%s'\n"), 174325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, 174425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, 174525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (buf)), 174625b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr->sh_link, section_name (ebl, shdr->sh_link)); 174725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 174825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 174925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 175025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 175125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 175225b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (cnt = 1; cnt < DT_NUM; ++cnt) 175325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (has_dt[cnt]) 175425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 175525b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (int inner = 0; inner < DT_NUM; ++inner) 175625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dependencies[cnt][inner] && ! has_dt[inner]) 175725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 175825b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf1[50]; 175925b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf2[50]; 176025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 176125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 176225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': contains %s entry but not %s\n"), 176325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 176425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)), 176525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2))); 176625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 176725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 176825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 176925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 177025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mandatory[cnt]) 177125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 177225b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf[50]; 177325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 177425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': mandatory tag %s not present\n"), 177525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 177625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf))); 177725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 177825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 177925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 178025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure we have an hash table. */ 178125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!has_dt[DT_HASH] && !has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)]) 178225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 178325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': no hash section present\n"), 178425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 178525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 178625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The GNU-style hash table also needs a symbol table. */ 178725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!has_dt[DT_HASH] && has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)] 178825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !has_dt[DT_SYMTAB]) 178925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 179025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': contains %s entry but not %s\n"), 179125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 179225b3c049e70834cf33790a28643ab058b507b35cBen Cheng "DT_GNU_HASH", "DT_SYMTAB"); 179325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 179425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the rel/rela tags. At least one group must be available. */ 179525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT]) 179625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT])) 179725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 179825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': not all of %s, %s, and %s are present\n"), 179925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 180025b3c049e70834cf33790a28643ab058b507b35cBen Cheng "DT_RELA", "DT_RELASZ", "DT_RELAENT"); 180125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 180225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT]) 180325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT])) 180425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 180525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': not all of %s, %s, and %s are present\n"), 180625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 180725b3c049e70834cf33790a28643ab058b507b35cBen Cheng "DT_REL", "DT_RELSZ", "DT_RELENT"); 180825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 180925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that all prelink sections are present if any of them is. */ 181025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)] 181125b3c049e70834cf33790a28643ab058b507b35cBen Cheng || has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)]) 181225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 181325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)]) 181425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 181525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"), 181625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "DT_GNU_PRELINKED"); 181725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)]) 181825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 181925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"), 182025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "DT_CHECKSUM"); 182125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 182225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Only DSOs can be marked like this. */ 182325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_DYN) 182425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 182525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': non-DSO file marked as dependency during prelink\n"), 182625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 182725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 182825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 182925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)] 183025b3c049e70834cf33790a28643ab058b507b35cBen Cheng || has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)] 183125b3c049e70834cf33790a28643ab058b507b35cBen Cheng || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)] 183225b3c049e70834cf33790a28643ab058b507b35cBen Cheng || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)]) 183325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 183425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)]) 183525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 183625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': %s tag missing in prelinked executable\n"), 183725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "DT_GNU_CONFLICTSZ"); 183825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)]) 183925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 184025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': %s tag missing in prelinked executable\n"), 184125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "DT_GNU_LIBLISTSZ"); 184225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)]) 184325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 184425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': %s tag missing in prelinked executable\n"), 184525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "DT_GNU_CONFLICT"); 184625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)]) 184725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 184825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': %s tag missing in prelinked executable\n"), 184925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), "DT_GNU_LIBLIST"); 185025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 185125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 185225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 185325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 185425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 185525b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 185625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 185725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_REL) 185825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 185925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 186025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': only relocatable files can have extended section index\n"), 186125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 186225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 186325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 186425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 186525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 186625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr symshdr_mem; 186725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 186825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB) 186925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 187025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': extended section index section not for symbol table\n"), 187125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 187225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *symdata = elf_getdata (symscn, NULL); 187325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symdata == NULL) 187425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("cannot get data for symbol section\n")); 187525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 187625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_entsize != sizeof (Elf32_Word)) 187725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 187825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry size does not match Elf32_Word\n"), 187925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 188025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 188125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symshdr != NULL 188225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (shdr->sh_size / shdr->sh_entsize 188325b3c049e70834cf33790a28643ab058b507b35cBen Cheng < symshdr->sh_size / symshdr->sh_entsize)) 188425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 188525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': extended index table too small for symbol table\n"), 188625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 188725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 188825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_info != 0) 188925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"), 189025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 189125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 189225b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = idx + 1; cnt < shnum; ++cnt) 189325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 189425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr rshdr_mem; 189525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem); 189625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX 189725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && rshdr->sh_link == shdr->sh_link) 189825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 189925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 190025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"), 190125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 190225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 190325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 190425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 190525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 190625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 190725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 190825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 190925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*((Elf32_Word *) data->d_buf) != 0) 191025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("symbol 0 should have zero extended section index\n")); 191125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 191225b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt) 191325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 191425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt]; 191525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 191625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (xndx != 0) 191725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 191825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym sym_data; 191925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data); 192025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym == NULL) 192125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 192225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("cannot get data for symbol %zu\n"), cnt); 192325b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 192425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 192525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 192625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym->st_shndx != SHN_XINDEX) 192725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 192825b3c049e70834cf33790a28643ab058b507b35cBen Chengextended section index is %" PRIu32 " but symbol index is not XINDEX\n"), 192925b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint32_t) xndx); 193025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 193125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 193225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 193325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 193425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 193525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 193625b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx, 193725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *symshdr) 193825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 193925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0]; 194025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1]; 194125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 194225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize) 194325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 194425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"), 194525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), (long int) shdr->sh_size, 194625b3c049e70834cf33790a28643ab058b507b35cBen Cheng (long int) ((2 + nbucket + nchain) * shdr->sh_entsize)); 194725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 194825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t maxidx = nchain; 194925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 195025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symshdr != NULL) 195125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 195225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t symsize = symshdr->sh_size / symshdr->sh_entsize; 195325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 195425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (nchain > symshdr->sh_size / symshdr->sh_entsize) 195525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': chain array too large\n"), 195625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 195725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 195825b3c049e70834cf33790a28643ab058b507b35cBen Cheng maxidx = symsize; 195925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 196025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 196125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t cnt; 196225b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (cnt = 2; cnt < 2 + nbucket; ++cnt) 196325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx) 196425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 196525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash bucket reference %zu out of bounds\n"), 196625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt - 2); 196725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 196825b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (; cnt < 2 + nbucket + nchain; ++cnt) 196925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx) 197025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 197125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash chain reference %zu out of bounds\n"), 197225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt - 2 - nbucket); 197325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 197425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 197525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 197625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 197725b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx, 197825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *symshdr) 197925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 198025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0]; 198125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1]; 198225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 198325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize) 198425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 198525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"), 198625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), (long int) shdr->sh_size, 198725b3c049e70834cf33790a28643ab058b507b35cBen Cheng (long int) ((2 + nbucket + nchain) * shdr->sh_entsize)); 198825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 198925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t maxidx = nchain; 199025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 199125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symshdr != NULL) 199225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 199325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t symsize = symshdr->sh_size / symshdr->sh_entsize; 199425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 199525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (nchain > symshdr->sh_size / symshdr->sh_entsize) 199625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': chain array too large\n"), 199725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 199825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 199925b3c049e70834cf33790a28643ab058b507b35cBen Cheng maxidx = symsize; 200025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 200125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 200225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t cnt; 200325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (cnt = 2; cnt < 2 + nbucket; ++cnt) 200425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx) 200525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 200625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash bucket reference %zu out of bounds\n"), 200725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt - 2); 200825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 200925b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (; cnt < 2 + nbucket + nchain; ++cnt) 201025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx) 201125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 201225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash chain reference %" PRIu64 " out of bounds\n"), 201325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), (uint64_t) (cnt - 2 - nbucket)); 201425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 201525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 201625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 201725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 201825b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx, 201925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *symshdr) 202025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 202125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0]; 202225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1]; 202325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2]; 202425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 202525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!powerof2 (bitmask_words)) 202625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 202725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': bitmask size not power of 2: %u\n"), 202825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), bitmask_words); 202925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 203025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t bitmask_idxmask = bitmask_words - 1; 203125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (gelf_getclass (ebl->elf) == ELFCLASS64) 203225b3c049e70834cf33790a28643ab058b507b35cBen Cheng bitmask_words *= 2; 203325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3]; 203425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 203525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_size < (4 + bitmask_words + nbuckets) * sizeof (Elf32_Word)) 203625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 203725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 203825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash table section is too small (is %ld, expected at least%ld)\n"), 203925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), (long int) shdr->sh_size, 204025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (long int) ((4 + bitmask_words + nbuckets) * sizeof (Elf32_Word))); 204125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 204225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 204325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 204425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shift > 31) 204525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 204625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': 2nd hash function shift too big: %u\n"), 204725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), shift); 204825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 204925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words 205025b3c049e70834cf33790a28643ab058b507b35cBen Cheng + nbuckets); 205125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 205225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symshdr != NULL) 205325b3c049e70834cf33790a28643ab058b507b35cBen Cheng maxidx = MIN (maxidx, symshdr->sh_size / symshdr->sh_entsize); 205425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 205525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We need the symbol section data. */ 205625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *symdata = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link), NULL); 205725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 205825b3c049e70834cf33790a28643ab058b507b35cBen Cheng union 205925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 206025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word *p32; 206125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Xword *p64; 206225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } bitmask = { .p32 = &((Elf32_Word *) data->d_buf)[4] }, 206325b3c049e70834cf33790a28643ab058b507b35cBen Cheng collected = { .p32 = xcalloc (bitmask_words, sizeof (Elf32_Word)) }; 206425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 206525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t classbits = gelf_getclass (ebl->elf) == ELFCLASS32 ? 32 : 64; 206625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 206725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t cnt; 206825b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (cnt = 4 + bitmask_words; cnt < 4 + bitmask_words + nbuckets; ++cnt) 206925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 207025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word symidx = ((Elf32_Word *) data->d_buf)[cnt]; 207125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 207225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symidx == 0) 207325b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 207425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 207525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symidx < symbias) 207625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 207725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 207825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"), 207925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt - (4 + bitmask_words)); 208025b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 208125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 208225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 208325b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (symidx - symbias < maxidx) 208425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 208525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word chainhash = ((Elf32_Word *) data->d_buf)[4 208625b3c049e70834cf33790a28643ab058b507b35cBen Cheng + bitmask_words 208725b3c049e70834cf33790a28643ab058b507b35cBen Cheng + nbuckets 208825b3c049e70834cf33790a28643ab058b507b35cBen Cheng + symidx 208925b3c049e70834cf33790a28643ab058b507b35cBen Cheng - symbias]; 209025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 209125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symdata != NULL) 209225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 209325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that the referenced symbol is not undefined. */ 209425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym sym_mem; 209525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym *sym = gelf_getsym (symdata, symidx, &sym_mem); 209625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym != NULL && sym->st_shndx == SHN_UNDEF 209725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && GELF_ST_TYPE (sym->st_info) != STT_FUNC) 209825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 209925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %u referenced in chain for bucket %zu is undefined\n"), 210025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), symidx, 210125b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt - (4 + bitmask_words)); 210225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 210325b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *symname = elf_strptr (ebl->elf, symshdr->sh_link, 210425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sym->st_name); 210525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symname != NULL) 210625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 210725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word hval = elf_gnu_hash (symname); 210825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((hval & ~1u) != (chainhash & ~1u)) 210925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 211025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"), 211125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), symidx, 211225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt - (4 + bitmask_words)); 211325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 211425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Set the bits in the bitmask. */ 211525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t maskidx = (hval / classbits) & bitmask_idxmask; 211625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (classbits == 32) 211725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 211825b3c049e70834cf33790a28643ab058b507b35cBen Cheng collected.p32[maskidx] 211925b3c049e70834cf33790a28643ab058b507b35cBen Cheng |= UINT32_C (1) << (hval & (classbits - 1)); 212025b3c049e70834cf33790a28643ab058b507b35cBen Cheng collected.p32[maskidx] 212125b3c049e70834cf33790a28643ab058b507b35cBen Cheng |= UINT32_C (1) << ((hval >> shift) & (classbits - 1)); 212225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 212325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 212425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 212525b3c049e70834cf33790a28643ab058b507b35cBen Cheng collected.p64[maskidx] 212625b3c049e70834cf33790a28643ab058b507b35cBen Cheng |= UINT64_C (1) << (hval & (classbits - 1)); 212725b3c049e70834cf33790a28643ab058b507b35cBen Cheng collected.p64[maskidx] 212825b3c049e70834cf33790a28643ab058b507b35cBen Cheng |= UINT64_C (1) << ((hval >> shift) & (classbits - 1)); 212925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 213025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 213125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 213225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 213325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((chainhash & 1) != 0) 213425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 213525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 213625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++symidx; 213725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 213825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 213925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symidx - symbias >= maxidx) 214025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 214125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash chain for bucket %zu out of bounds\n"), 214225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt - (4 + bitmask_words)); 214325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (symshdr != NULL 214425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && symidx > symshdr->sh_size / symshdr->sh_entsize) 214525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 214625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"), 214725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt - (4 + bitmask_words)); 214825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 214925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 215025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (memcmp (collected.p32, bitmask.p32, bitmask_words * sizeof (Elf32_Word))) 215125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 215225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': bitmask does not match names in the hash table\n"), 215325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 215425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 215525b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (collected.p32); 215625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 215725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 215825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 215925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 216025b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_hash (int tag, Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 216125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 216225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type == ET_REL) 216325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 216425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 216525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': relocatable files cannot have hash tables\n"), 216625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 216725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 216825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 216925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 217025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 217125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 217225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 217325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 217425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 217525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 217625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 217725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 217825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr symshdr_mem; 217925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 218025b3c049e70834cf33790a28643ab058b507b35cBen Cheng &symshdr_mem); 218125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM) 218225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 218325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash table not for dynamic symbol table\n"), 218425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 218525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 218625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_entsize != (tag == SHT_GNU_HASH 218725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? (gelf_getclass (ebl->elf) == ELFCLASS32 218825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? sizeof (Elf32_Word) : 0) 218925b3c049e70834cf33790a28643ab058b507b35cBen Cheng : (size_t) ebl_sysvhash_entrysize (ebl))) 219025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 219125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash table entry size incorrect\n"), 219225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 219325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 219425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_ALLOC) == 0) 219525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': not marked to be allocated\n"), 219625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 219725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 219825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (shdr->sh_entsize ?: 4)) 219925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 220025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 220125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': hash table has not even room for initial administrative entries\n"), 220225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 220325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 220425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 220525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 220625b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (tag) 220725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 220825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_HASH: 220925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword)) 221025b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_sysv_hash64 (ebl, shdr, data, idx, symshdr); 221125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 221225b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_sysv_hash (ebl, shdr, data, idx, symshdr); 221325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 221425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 221525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_GNU_HASH: 221625b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_gnu_hash (ebl, shdr, data, idx, symshdr); 221725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 221825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 221925b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 222025b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (! "should not happen"); 222125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 222225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 222325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 222425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 222525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Compare content of both hash tables, it must be identical. */ 222625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 222725b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_hash_gnu_hash (Ebl *ebl, GElf_Ehdr *ehdr, size_t hash_idx, 222825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t gnu_hash_idx) 222925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 223025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *hash_scn = elf_getscn (ebl->elf, hash_idx); 223125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *hash_data = elf_getdata (hash_scn, NULL); 223225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr hash_shdr_mem; 223325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *hash_shdr = gelf_getshdr (hash_scn, &hash_shdr_mem); 223425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *gnu_hash_scn = elf_getscn (ebl->elf, gnu_hash_idx); 223525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *gnu_hash_data = elf_getdata (gnu_hash_scn, NULL); 223625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr gnu_hash_shdr_mem; 223725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *gnu_hash_shdr = gelf_getshdr (gnu_hash_scn, &gnu_hash_shdr_mem); 223825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 223925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (hash_shdr == NULL || gnu_hash_shdr == NULL 224025b3c049e70834cf33790a28643ab058b507b35cBen Cheng || hash_data == NULL || gnu_hash_data == NULL) 224125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* None of these pointers should be NULL since we used the 224225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sections already. We are careful nonetheless. */ 224325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 224425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 224525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The link must point to the same symbol table. */ 224625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (hash_shdr->sh_link != gnu_hash_shdr->sh_link) 224725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 224825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 224925b3c049e70834cf33790a28643ab058b507b35cBen Chengsh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"), 225025b3c049e70834cf33790a28643ab058b507b35cBen Cheng hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name), 225125b3c049e70834cf33790a28643ab058b507b35cBen Cheng gnu_hash_idx, 225225b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name)); 225325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 225425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 225525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 225625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *sym_scn = elf_getscn (ebl->elf, hash_shdr->sh_link); 225725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *sym_data = elf_getdata (sym_scn, NULL); 225825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr sym_shdr_mem; 225925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *sym_shdr = gelf_getshdr (sym_scn, &sym_shdr_mem); 226025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 226125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym_data == NULL || sym_shdr == NULL) 226225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 226325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 226425b3c049e70834cf33790a28643ab058b507b35cBen Cheng int nentries = sym_shdr->sh_size / sym_shdr->sh_entsize; 226525b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *used = alloca (nentries); 226625b3c049e70834cf33790a28643ab058b507b35cBen Cheng memset (used, '\0', nentries); 226725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 226825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* First go over the GNU_HASH table and mark the entries as used. */ 226925b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf32_Word *gnu_hasharr = (Elf32_Word *) gnu_hash_data->d_buf; 227025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word gnu_nbucket = gnu_hasharr[0]; 227125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const int bitmap_factor = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 1 : 2; 227225b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf32_Word *gnu_bucket = (gnu_hasharr 227325b3c049e70834cf33790a28643ab058b507b35cBen Cheng + (4 + gnu_hasharr[2] * bitmap_factor)); 227425b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf32_Word *gnu_chain = gnu_bucket + gnu_hasharr[0] - gnu_hasharr[1]; 227525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 227625b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (Elf32_Word cnt = 0; cnt < gnu_nbucket; ++cnt) 227725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 227825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word symidx = gnu_bucket[cnt]; 227925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symidx != STN_UNDEF) 228025b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 228125b3c049e70834cf33790a28643ab058b507b35cBen Cheng used[symidx] |= 1; 228225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((gnu_chain[symidx++] & 1u) == 0); 228325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 228425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 228525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now go over the old hash table and check that we cover the same 228625b3c049e70834cf33790a28643ab058b507b35cBen Cheng entries. */ 228725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (hash_shdr->sh_entsize == sizeof (Elf32_Word)) 228825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 228925b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf32_Word *hasharr = (Elf32_Word *) hash_data->d_buf; 229025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word nbucket = hasharr[0]; 229125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf32_Word *bucket = &hasharr[2]; 229225b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf32_Word *chain = &hasharr[2 + nbucket]; 229325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 229425b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt) 229525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 229625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word symidx = bucket[cnt]; 229725b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (symidx != STN_UNDEF) 229825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 229925b3c049e70834cf33790a28643ab058b507b35cBen Cheng used[symidx] |= 2; 230025b3c049e70834cf33790a28643ab058b507b35cBen Cheng symidx = chain[symidx]; 230125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 230225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 230325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 230425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 230525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 230625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf64_Xword *hasharr = (Elf64_Xword *) hash_data->d_buf; 230725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Xword nbucket = hasharr[0]; 230825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf64_Xword *bucket = &hasharr[2]; 230925b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf64_Xword *chain = &hasharr[2 + nbucket]; 231025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 231125b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt) 231225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 231325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Xword symidx = bucket[cnt]; 231425b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (symidx != STN_UNDEF) 231525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 231625b3c049e70834cf33790a28643ab058b507b35cBen Cheng used[symidx] |= 2; 231725b3c049e70834cf33790a28643ab058b507b35cBen Cheng symidx = chain[symidx]; 231825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 231925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 232025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 232125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 232225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now see which entries are not set in one or both hash tables 232325b3c049e70834cf33790a28643ab058b507b35cBen Cheng (unless the symbol is undefined in which case it can be omitted 232425b3c049e70834cf33790a28643ab058b507b35cBen Cheng in the new table format). */ 232525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((used[0] & 1) != 0) 232625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"), 232725b3c049e70834cf33790a28643ab058b507b35cBen Cheng gnu_hash_idx, 232825b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name)); 232925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((used[0] & 2) != 0) 233025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"), 233125b3c049e70834cf33790a28643ab058b507b35cBen Cheng hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name)); 233225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 233325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (int cnt = 1; cnt < nentries; ++cnt) 233425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (used[cnt] != 0 && used[cnt] != 3) 233525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 233625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (used[cnt] == 1) 233725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 233825b3c049e70834cf33790a28643ab058b507b35cBen Chengsymbol %d referenced in new hash table in [%2zu] '%s' but not in old hash table in [%2zu] '%s'\n"), 233925b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, gnu_hash_idx, 234025b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name), 234125b3c049e70834cf33790a28643ab058b507b35cBen Cheng hash_idx, 234225b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name)); 234325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 234425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 234525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym sym_mem; 234625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym *sym = gelf_getsym (sym_data, cnt, &sym_mem); 234725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 234825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym != NULL && sym->st_shndx != STN_UNDEF) 234925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 235025b3c049e70834cf33790a28643ab058b507b35cBen Chengsymbol %d referenced in old hash table in [%2zu] '%s' but not in new hash table in [%2zu] '%s'\n"), 235125b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, hash_idx, 235225b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name), 235325b3c049e70834cf33790a28643ab058b507b35cBen Cheng gnu_hash_idx, 235425b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name)); 235525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 235625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 235725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 235825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 235925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 236025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 236125b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_null (Ebl *ebl, GElf_Shdr *shdr, int idx) 236225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 236325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define TEST(name, extra) \ 236425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (extra && shdr->sh_##name != 0) \ 236525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': nonzero sh_%s for NULL section\n"), \ 236625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), #name) 236725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 236825b3c049e70834cf33790a28643ab058b507b35cBen Cheng TEST (name, 1); 236925b3c049e70834cf33790a28643ab058b507b35cBen Cheng TEST (flags, 1); 237025b3c049e70834cf33790a28643ab058b507b35cBen Cheng TEST (addr, 1); 237125b3c049e70834cf33790a28643ab058b507b35cBen Cheng TEST (offset, 1); 237225b3c049e70834cf33790a28643ab058b507b35cBen Cheng TEST (size, idx != 0); 237325b3c049e70834cf33790a28643ab058b507b35cBen Cheng TEST (link, idx != 0); 237425b3c049e70834cf33790a28643ab058b507b35cBen Cheng TEST (info, 1); 237525b3c049e70834cf33790a28643ab058b507b35cBen Cheng TEST (addralign, 1); 237625b3c049e70834cf33790a28643ab058b507b35cBen Cheng TEST (entsize, 1); 237725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 237825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 237925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 238025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 238125b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 238225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 238325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_REL) 238425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 238525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 238625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section groups only allowed in relocatable object files\n"), 238725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 238825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 238925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 239025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 239125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that sh_link is an index of a symbol table. */ 239225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 239325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr symshdr_mem; 239425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 239525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symshdr == NULL) 239625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get symbol table: %s\n"), 239725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), elf_errmsg (-1)); 239825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 239925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 240025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symshdr->sh_type != SHT_SYMTAB) 240125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 240225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section reference in sh_link is no symbol table\n"), 240325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 240425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 240525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM, 240625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1, EV_CURRENT)) 240725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 240825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': invalid symbol index in sh_info\n"), 240925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 241025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 241125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_flags != 0) 241225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': sh_flags not zero\n"), 241325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 241425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 241525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym sym_data; 241625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym *sym = gelf_getsym (elf_getdata (symscn, NULL), shdr->sh_info, 241725b3c049e70834cf33790a28643ab058b507b35cBen Cheng &sym_data); 241825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym == NULL) 241925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 242025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': cannot get symbol for signature\n"), 242125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 242225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (strcmp (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name), 242325b3c049e70834cf33790a28643ab058b507b35cBen Cheng "") == 0) 242425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 242525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': signature symbol cannot be empty string\n"), 242625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 242725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 242825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (be_strict 242925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT)) 243025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': sh_flags not set correctly\n"), 243125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 243225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 243325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 243425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 243525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 243625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get data: %s\n"), 243725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), elf_errmsg (-1)); 243825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 243925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 244025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT); 244125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t cnt; 244225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word val; 244325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 244425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data->d_size % elsize != 0) 244525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 244625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"), 244725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 244825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 244925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data->d_size < elsize) 245025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 245125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section group without flags word\n"), 245225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 245325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (be_strict) 245425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 245525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data->d_size < 2 * elsize) 245625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 245725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section group without member\n"), 245825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 245925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (data->d_size < 3 * elsize) 246025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 246125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section group with only one member\n"), 246225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 246325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 246425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 246525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if ALLOW_UNALIGNED 246625b3c049e70834cf33790a28643ab058b507b35cBen Cheng val = *((Elf32_Word *) data->d_buf); 246725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 246825b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&val, data->d_buf, elsize); 246925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 247025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((val & ~GRP_COMDAT) != 0) 247125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': unknown section group flags\n"), 247225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 247325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 247425b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (cnt = elsize; cnt < data->d_size; cnt += elsize) 247525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 247625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if ALLOW_UNALIGNED 247725b3c049e70834cf33790a28643ab058b507b35cBen Cheng val = *((Elf32_Word *) ((char *) data->d_buf + cnt)); 247825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 247925b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&val, (char *) data->d_buf + cnt, elsize); 248025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 248125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 248225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (val > shnum) 248325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 248425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section index %Zu out of range\n"), 248525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt / elsize); 248625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 248725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 248825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr refshdr_mem; 248925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *refshdr = gelf_getshdr (elf_getscn (ebl->elf, val), 249025b3c049e70834cf33790a28643ab058b507b35cBen Cheng &refshdr_mem); 249125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (refshdr == NULL) 249225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 249325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': cannot get section header for element %zu: %s\n"), 249425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt / elsize, 249525b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_errmsg (-1)); 249625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 249725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 249825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (refshdr->sh_type == SHT_GROUP) 249925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 250025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': section group contains another group [%2d] '%s'\n"), 250125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 250225b3c049e70834cf33790a28643ab058b507b35cBen Cheng val, section_name (ebl, val)); 250325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 250425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((refshdr->sh_flags & SHF_GROUP) == 0) 250525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 250625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': element %Zu references section [%2d] '%s' without SHF_GROUP flag set\n"), 250725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt / elsize, 250825b3c049e70834cf33790a28643ab058b507b35cBen Cheng val, section_name (ebl, val)); 250925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 251025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 251125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (++scnref[val] == 2) 251225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 251325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s' is contained in more than one section group\n"), 251425b3c049e70834cf33790a28643ab058b507b35cBen Cheng val, section_name (ebl, val)); 251525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 251625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 251725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 251825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 251925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 252025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 252125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char * 252225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection_flags_string (GElf_Word flags, char *buf, size_t len) 252325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 252425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (flags == 0) 252525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return "none"; 252625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 252725b3c049e70834cf33790a28643ab058b507b35cBen Cheng static const struct 252825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 252925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Word flag; 253025b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *name; 253125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } known_flags[] = 253225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 253325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define NEWFLAG(name) { SHF_##name, #name } 253425b3c049e70834cf33790a28643ab058b507b35cBen Cheng NEWFLAG (WRITE), 253525b3c049e70834cf33790a28643ab058b507b35cBen Cheng NEWFLAG (ALLOC), 253625b3c049e70834cf33790a28643ab058b507b35cBen Cheng NEWFLAG (EXECINSTR), 253725b3c049e70834cf33790a28643ab058b507b35cBen Cheng NEWFLAG (MERGE), 253825b3c049e70834cf33790a28643ab058b507b35cBen Cheng NEWFLAG (STRINGS), 253925b3c049e70834cf33790a28643ab058b507b35cBen Cheng NEWFLAG (INFO_LINK), 254025b3c049e70834cf33790a28643ab058b507b35cBen Cheng NEWFLAG (LINK_ORDER), 254125b3c049e70834cf33790a28643ab058b507b35cBen Cheng NEWFLAG (OS_NONCONFORMING), 254225b3c049e70834cf33790a28643ab058b507b35cBen Cheng NEWFLAG (GROUP), 254325b3c049e70834cf33790a28643ab058b507b35cBen Cheng NEWFLAG (TLS) 254425b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 254525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef NEWFLAG 254625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]); 254725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 254825b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *cp = buf; 254925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 255025b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < nknown_flags; ++cnt) 255125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (flags & known_flags[cnt].flag) 255225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 255325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cp != buf && len > 1) 255425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 255525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = '|'; 255625b3c049e70834cf33790a28643ab058b507b35cBen Cheng --len; 255725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 255825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 255925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name)); 256025b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp = mempcpy (cp, known_flags[cnt].name, ncopy); 256125b3c049e70834cf33790a28643ab058b507b35cBen Cheng len -= ncopy; 256225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 256325b3c049e70834cf33790a28643ab058b507b35cBen Cheng flags ^= known_flags[cnt].flag; 256425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 256525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 256625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (flags != 0 || cp == buf) 256725b3c049e70834cf33790a28643ab058b507b35cBen Cheng snprintf (cp, len - 1, "%" PRIx64, (uint64_t) flags); 256825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 256925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp = '\0'; 257025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 257125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return buf; 257225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 257325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 257425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 257525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 257625b3c049e70834cf33790a28643ab058b507b35cBen Chenghas_copy_reloc (Ebl *ebl, unsigned int symscnndx, unsigned int symndx) 257725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 257825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* First find the relocation section for the symbol table. */ 257925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = NULL; 258025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 258125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = NULL; 258225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 258325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 258425b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr = gelf_getshdr (scn, &shdr_mem); 258525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr != NULL 258625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) 258725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr->sh_link == symscnndx) 258825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Found the section. */ 258925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 259025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 259125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 259225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scn == NULL) 259325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 259425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 259525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (scn, NULL); 259625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 259725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 259825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 259925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_type == SHT_REL) 260025b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i) 260125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 260225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rel rel_mem; 260325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rel *rel = gelf_getrel (data, i, &rel_mem); 260425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (rel == NULL) 260525b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 260625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 260725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (GELF_R_SYM (rel->r_info) == symndx 260825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info))) 260925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 261025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 261125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 261225b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i) 261325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 261425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rela rela_mem; 261525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Rela *rela = gelf_getrela (data, i, &rela_mem); 261625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (rela == NULL) 261725b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 261825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 261925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (GELF_R_SYM (rela->r_info) == symndx 262025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info))) 262125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 262225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 262325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 262425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 262525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 262625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 262725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 262825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 262925b3c049e70834cf33790a28643ab058b507b35cBen Chengin_nobits_scn (Ebl *ebl, unsigned int shndx) 263025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 263125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 263225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, shndx), &shdr_mem); 263325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return shdr != NULL && shdr->sh_type == SHT_NOBITS; 263425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 263525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 263625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 263725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct version_namelist 263825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 263925b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *objname; 264025b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *name; 264125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Versym ndx; 264225b3c049e70834cf33790a28643ab058b507b35cBen Cheng enum { ver_def, ver_need } type; 264325b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct version_namelist *next; 264425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} *version_namelist; 264525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 264625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 264725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 264825b3c049e70834cf33790a28643ab058b507b35cBen Chengadd_version (const char *objname, const char *name, GElf_Versym ndx, int type) 264925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 265025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that there are no duplications. */ 265125b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct version_namelist *nlp = version_namelist; 265225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (nlp != NULL) 265325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 265425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (((nlp->objname == NULL && objname == NULL) 265525b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (nlp->objname != NULL && objname != NULL 265625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && strcmp (nlp->objname, objname) == 0)) 265725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && strcmp (nlp->name, name) == 0) 265825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nlp->type == ver_def ? 1 : -1; 265925b3c049e70834cf33790a28643ab058b507b35cBen Cheng nlp = nlp->next; 266025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 266125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 266225b3c049e70834cf33790a28643ab058b507b35cBen Cheng nlp = xmalloc (sizeof (*nlp)); 266325b3c049e70834cf33790a28643ab058b507b35cBen Cheng nlp->objname = objname; 266425b3c049e70834cf33790a28643ab058b507b35cBen Cheng nlp->name = name; 266525b3c049e70834cf33790a28643ab058b507b35cBen Cheng nlp->ndx = ndx; 266625b3c049e70834cf33790a28643ab058b507b35cBen Cheng nlp->type = type; 266725b3c049e70834cf33790a28643ab058b507b35cBen Cheng nlp->next = version_namelist; 266825b3c049e70834cf33790a28643ab058b507b35cBen Cheng version_namelist = nlp; 266925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 267025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 267125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 267225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 267325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 267425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 267525b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_versym (Ebl *ebl, int idx) 267625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 267725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = elf_getscn (ebl->elf, idx); 267825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 267925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 268025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr == NULL) 268125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The error has already been reported. */ 268225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 268325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 268425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (scn, NULL); 268525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 268625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 268725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 268825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 268925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 269025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 269125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 269225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 269325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr symshdr_mem; 269425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 269525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symshdr == NULL) 269625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The error has already been reported. */ 269725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 269825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 269925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symshdr->sh_type != SHT_DYNSYM) 270025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 270125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 270225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"), 270325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 270425b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr->sh_link, section_name (ebl, shdr->sh_link)); 270525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 270625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 270725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 270825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The number of elements in the version symbol table must be the 270925b3c049e70834cf33790a28643ab058b507b35cBen Cheng same as the number of symbols. */ 271025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_size / shdr->sh_entsize 271125b3c049e70834cf33790a28643ab058b507b35cBen Cheng != symshdr->sh_size / symshdr->sh_entsize) 271225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 271325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"), 271425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), 271525b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr->sh_link, section_name (ebl, shdr->sh_link)); 271625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 271725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *symdata = elf_getdata (symscn, NULL); 271825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symdata == NULL) 271925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The error has already been reported. */ 272025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 272125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 272225b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (int cnt = 1; (size_t) cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 272325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 272425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Versym versym_mem; 272525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Versym *versym = gelf_getversym (data, cnt, &versym_mem); 272625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (versym == NULL) 272725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 272825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 272925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %d: cannot read version data\n"), 273025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 273125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 273225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 273325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 273425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym sym_mem; 273525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_mem); 273625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sym == NULL) 273725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Already reported elsewhere. */ 273825b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 273925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 274025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*versym == VER_NDX_GLOBAL) 274125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 274225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Global symbol. Make sure it is not defined as local. */ 274325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (GELF_ST_BIND (sym->st_info) == STB_LOCAL) 274425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 274525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %d: local symbol with global scope\n"), 274625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 274725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 274825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (*versym != VER_NDX_LOCAL) 274925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 275025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Versioned symbol. Make sure it is not defined as local. */ 275125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!gnuld && GELF_ST_BIND (sym->st_info) == STB_LOCAL) 275225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 275325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %d: local symbol with version\n"), 275425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 275525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 275625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Look through the list of defined versions and locate the 275725b3c049e70834cf33790a28643ab058b507b35cBen Cheng index we need for this symbol. */ 275825b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct version_namelist *runp = version_namelist; 275925b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (runp != NULL) 276025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (runp->ndx == (*versym & (GElf_Versym) 0x7fff)) 276125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 276225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 276325b3c049e70834cf33790a28643ab058b507b35cBen Cheng runp = runp->next; 276425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 276525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (runp == NULL) 276625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 276725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %d: invalid version index %d\n"), 276825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, (int) *versym); 276925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sym->st_shndx == SHN_UNDEF 277025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && runp->type == ver_def) 277125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 277225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %d: version index %d is for defined version\n"), 277325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, (int) *versym); 277425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sym->st_shndx != SHN_UNDEF 277525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && runp->type == ver_need) 277625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 277725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Unless this symbol has a copy relocation associated 277825b3c049e70834cf33790a28643ab058b507b35cBen Cheng this must not happen. */ 277925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!has_copy_reloc (ebl, shdr->sh_link, cnt) 278025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !in_nobits_scn (ebl, sym->st_shndx)) 278125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 278225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': symbol %d: version index %d is for requested version\n"), 278325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, (int) *versym); 278425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 278525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 278625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 278725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 278825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 278925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 279025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 279125b3c049e70834cf33790a28643ab058b507b35cBen Chengunknown_dependency_p (Elf *elf, const char *fname) 279225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 279325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 279425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr = NULL; 279525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 279625b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int i; 279725b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (i = 0; i < phnum; ++i) 279825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((phdr = gelf_getphdr (elf, i, &phdr_mem)) != NULL 279925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && phdr->p_type == PT_DYNAMIC) 280025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 280125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 280225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (i == phnum) 280325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 280425b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (phdr != NULL); 280525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset); 280625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 280725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 280825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (scn, NULL); 280925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL) 281025b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j) 281125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 281225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Dyn dyn_mem; 281325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem); 281425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn != NULL && dyn->d_tag == DT_NEEDED) 281525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 281625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *str = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val); 281725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (str != NULL && strcmp (str, fname) == 0) 281825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Found it. */ 281925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 282025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 282125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 282225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 282325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 282425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 282525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 282625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 282725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int nverneed; 282825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 282925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 283025b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_verneed (Ebl *ebl, GElf_Shdr *shdr, int idx) 283125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 283225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (++nverneed == 2) 283325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("more than one version reference section present\n")); 283425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 283525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr strshdr_mem; 283625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 283725b3c049e70834cf33790a28643ab058b507b35cBen Cheng &strshdr_mem); 283825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strshdr == NULL) 283925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 284025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strshdr->sh_type != SHT_STRTAB) 284125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 284225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': sh_link does not link to string table\n"), 284325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 284425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 284525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 284625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 284725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 284825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 284925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 285025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 285125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 285225b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int offset = 0; 285325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (int cnt = shdr->sh_info; --cnt >= 0; ) 285425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 285525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get the data at the next offset. */ 285625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Verneed needmem; 285725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Verneed *need = gelf_getverneed (data, offset, &needmem); 285825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (need == NULL) 285925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 286025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 286125b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int auxoffset = offset + need->vn_aux; 286225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 286325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (need->vn_version != EV_CURRENT) 286425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 286525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has wrong version %d\n"), 286625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, (int) need->vn_version); 286725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 286825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (need->vn_cnt > 0 && need->vn_aux < gelf_fsize (ebl->elf, ELF_T_VNEED, 286925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1, EV_CURRENT)) 287025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 287125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"), 287225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 287325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 287425b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *libname = elf_strptr (ebl->elf, shdr->sh_link, 287525b3c049e70834cf33790a28643ab058b507b35cBen Cheng need->vn_file); 287625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (libname == NULL) 287725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 287825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 287925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has invalid file reference\n"), 288025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 288125b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto next_need; 288225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 288325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 288425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that there is a DT_NEEDED entry for the referenced library. */ 288525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unknown_dependency_p (ebl->elf, libname)) 288625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 288725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d references unknown dependency\n"), 288825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 288925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 289025b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (int cnt2 = need->vn_cnt; --cnt2 >= 0; ) 289125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 289225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Vernaux auxmem; 289325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem); 289425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (aux == NULL) 289525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 289625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 289725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((aux->vna_flags & ~VER_FLG_WEAK) != 0) 289825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 289925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"), 290025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt); 290125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 290225b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *verstr = elf_strptr (ebl->elf, shdr->sh_link, 290325b3c049e70834cf33790a28643ab058b507b35cBen Cheng aux->vna_name); 290425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (verstr == NULL) 290525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 290625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': auxiliary entry %d of entry %d has invalid name reference\n"), 290725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt); 290825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 290925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 291025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Word hashval = elf_hash (verstr); 291125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (hashval != aux->vna_hash) 291225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 291325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: %#x, expected %#x\n"), 291425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), need->vn_cnt - cnt2, 291525b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, (int) hashval, (int) aux->vna_hash); 291625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 291725b3c049e70834cf33790a28643ab058b507b35cBen Cheng int res = add_version (libname, verstr, aux->vna_other, 291825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ver_need); 291925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (res !=0)) 292025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 292125b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (res > 0); 292225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 292325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': auxiliary entry %d of entry %d has duplicate version name '%s'\n"), 292425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), need->vn_cnt - cnt2, 292525b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, verstr); 292625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 292725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 292825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 292925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((aux->vna_next != 0 || cnt2 > 0) 293025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && aux->vna_next < gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, 293125b3c049e70834cf33790a28643ab058b507b35cBen Cheng EV_CURRENT)) 293225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 293325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 293425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"), 293525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt); 293625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 293725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 293825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 293925b3c049e70834cf33790a28643ab058b507b35cBen Cheng auxoffset += MAX (aux->vna_next, 294025b3c049e70834cf33790a28643ab058b507b35cBen Cheng gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, EV_CURRENT)); 294125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 294225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 294325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Find the next offset. */ 294425b3c049e70834cf33790a28643ab058b507b35cBen Cheng next_need: 294525b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset += need->vn_next; 294625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 294725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((need->vn_next != 0 || cnt > 0) 294825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && offset < auxoffset) 294925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 295025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has invalid offset to next entry\n"), 295125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 295225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 295325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 295425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 295525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 295625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int nverdef; 295725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 295825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 295925b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_verdef (Ebl *ebl, GElf_Shdr *shdr, int idx) 296025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 296125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (++nverdef == 2) 296225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("more than one version definition section present\n")); 296325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 296425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr strshdr_mem; 296525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 296625b3c049e70834cf33790a28643ab058b507b35cBen Cheng &strshdr_mem); 296725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strshdr == NULL) 296825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 296925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strshdr->sh_type != SHT_STRTAB) 297025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 297125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': sh_link does not link to string table\n"), 297225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 297325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 297425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 297525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 297625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 297725b3c049e70834cf33790a28643ab058b507b35cBen Cheng no_data: 297825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 297925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 298025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 298125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 298225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 298325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Iterate over all version definition entries. We check that there 298425b3c049e70834cf33790a28643ab058b507b35cBen Cheng is a BASE entry and that each index is unique. To do the later 298525b3c049e70834cf33790a28643ab058b507b35cBen Cheng we collection the information in a list which is later 298625b3c049e70834cf33790a28643ab058b507b35cBen Cheng examined. */ 298725b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct namelist 298825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 298925b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *name; 299025b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct namelist *next; 299125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } *namelist = NULL; 299225b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct namelist *refnamelist = NULL; 299325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 299425b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool has_base = false; 299525b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int offset = 0; 299625b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (int cnt = shdr->sh_info; --cnt >= 0; ) 299725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 299825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get the data at the next offset. */ 299925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Verdef defmem; 300025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Verdef *def = gelf_getverdef (data, offset, &defmem); 300125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (def == NULL) 300225b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto no_data; 300325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 300425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((def->vd_flags & VER_FLG_BASE) != 0) 300525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 300625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (has_base) 300725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 300825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': more than one BASE definition\n"), 300925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 301025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (def->vd_ndx != VER_NDX_GLOBAL) 301125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 301225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"), 301325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 301425b3c049e70834cf33790a28643ab058b507b35cBen Cheng has_base = true; 301525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 301625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((def->vd_flags & ~(VER_FLG_BASE|VER_FLG_WEAK)) != 0) 301725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 301825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has unknown flag\n"), 301925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 302025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 302125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (def->vd_version != EV_CURRENT) 302225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 302325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has wrong version %d\n"), 302425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, (int) def->vd_version); 302525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 302625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (def->vd_cnt > 0 && def->vd_aux < gelf_fsize (ebl->elf, ELF_T_VDEF, 302725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1, EV_CURRENT)) 302825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 302925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"), 303025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 303125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 303225b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int auxoffset = offset + def->vd_aux; 303325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Verdaux auxmem; 303425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem); 303525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (aux == NULL) 303625b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto no_data; 303725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 303825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name); 303925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (name == NULL) 304025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 304125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 304225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has invalid name reference\n"), 304325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 304425b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto next_def; 304525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 304625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Word hashval = elf_hash (name); 304725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (def->vd_hash != hashval) 304825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 304925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"), 305025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, (int) hashval, 305125b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) def->vd_hash); 305225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 305325b3c049e70834cf33790a28643ab058b507b35cBen Cheng int res = add_version (NULL, name, def->vd_ndx, ver_def); 305425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (res !=0)) 305525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 305625b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (res > 0); 305725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 305825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has duplicate version name '%s'\n"), 305925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt, name); 306025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 306125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 306225b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct namelist *newname = alloca (sizeof (*newname)); 306325b3c049e70834cf33790a28643ab058b507b35cBen Cheng newname->name = name; 306425b3c049e70834cf33790a28643ab058b507b35cBen Cheng newname->next = namelist; 306525b3c049e70834cf33790a28643ab058b507b35cBen Cheng namelist = newname; 306625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 306725b3c049e70834cf33790a28643ab058b507b35cBen Cheng auxoffset += aux->vda_next; 306825b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2) 306925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 307025b3c049e70834cf33790a28643ab058b507b35cBen Cheng aux = gelf_getverdaux (data, auxoffset, &auxmem); 307125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (aux == NULL) 307225b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto no_data; 307325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 307425b3c049e70834cf33790a28643ab058b507b35cBen Cheng name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name); 307525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (name == NULL) 307625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 307725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"), 307825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 307925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 308025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 308125b3c049e70834cf33790a28643ab058b507b35cBen Cheng newname = alloca (sizeof (*newname)); 308225b3c049e70834cf33790a28643ab058b507b35cBen Cheng newname->name = name; 308325b3c049e70834cf33790a28643ab058b507b35cBen Cheng newname->next = refnamelist; 308425b3c049e70834cf33790a28643ab058b507b35cBen Cheng refnamelist = newname; 308525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 308625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 308725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((aux->vda_next != 0 || cnt2 + 1 < def->vd_cnt) 308825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && aux->vda_next < gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, 308925b3c049e70834cf33790a28643ab058b507b35cBen Cheng EV_CURRENT)) 309025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 309125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 309225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has wrong next field in auxiliary data\n"), 309325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 309425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 309525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 309625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 309725b3c049e70834cf33790a28643ab058b507b35cBen Cheng auxoffset += MAX (aux->vda_next, 309825b3c049e70834cf33790a28643ab058b507b35cBen Cheng gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, EV_CURRENT)); 309925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 310025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 310125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Find the next offset. */ 310225b3c049e70834cf33790a28643ab058b507b35cBen Cheng next_def: 310325b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset += def->vd_next; 310425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 310525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((def->vd_next != 0 || cnt > 0) 310625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && offset < auxoffset) 310725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 310825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': entry %d has invalid offset to next entry\n"), 310925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), cnt); 311025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 311125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 311225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!has_base) 311325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': no BASE definition\n"), 311425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 311525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 311625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check whether the referenced names are available. */ 311725b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (namelist != NULL) 311825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 311925b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct version_namelist *runp = version_namelist; 312025b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (runp != NULL) 312125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 312225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (runp->type == ver_def 312325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && strcmp (runp->name, namelist->name) == 0) 312425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 312525b3c049e70834cf33790a28643ab058b507b35cBen Cheng runp = runp->next; 312625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 312725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 312825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (runp == NULL) 312925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 313025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': unknown parent version '%s'\n"), 313125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), namelist->name); 313225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 313325b3c049e70834cf33790a28643ab058b507b35cBen Cheng namelist = namelist->next; 313425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 313525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 313625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 313725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 313825b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 313925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 314025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_size == 0) 314125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 314225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': empty object attributes section\n"), 314325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 314425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 314525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 314625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 314725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL); 314825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL || data->d_size == 0) 314925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 315025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 315125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 315225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 315325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 315425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 315525b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline size_t pos (const unsigned char *p) 315625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 315725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return p - (const unsigned char *) data->d_buf; 315825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 315925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 316025b3c049e70834cf33790a28643ab058b507b35cBen Cheng const unsigned char *p = data->d_buf; 316125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*p++ != 'A') 316225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 316325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': unrecognized attribute format\n"), 316425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 316525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 316625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 316725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 316825b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline size_t left (void) 316925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 317025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (const unsigned char *) data->d_buf + data->d_size - p; 317125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 317225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 317325b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (left () >= 4) 317425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 317525b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint32_t len; 317625b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&len, p, sizeof len); 317725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 317825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (len == 0) 317925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 318025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: zero length field in attribute section\n"), 318125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (p)); 318225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 318325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (MY_ELFDATA != ehdr->e_ident[EI_DATA]) 318425b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (len); 318525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 318625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (len > left ()) 318725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 318825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 318925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: invalid length in attribute section\n"), 319025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (p)); 319125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 319225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 319325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 319425b3c049e70834cf33790a28643ab058b507b35cBen Cheng const unsigned char *name = p + sizeof len; 319525b3c049e70834cf33790a28643ab058b507b35cBen Cheng p += len; 319625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 319725b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned const char *q = memchr (name, '\0', len); 319825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (q == NULL) 319925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 320025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 320125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: unterminated vendor name string\n"), 320225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (p)); 320325b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 320425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 320525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++q; 320625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 320725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (q - name == sizeof "gnu" && !memcmp (name, "gnu", sizeof "gnu")) 320825b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (q < p) 320925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 321025b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned const char *chunk = q; 321125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 321225b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int subsection_tag; 321325b3c049e70834cf33790a28643ab058b507b35cBen Cheng get_uleb128 (subsection_tag, q); 321425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 321525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (q >= p) 321625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 321725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 321825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"), 321925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (chunk)); 322025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 322125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 322225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 322325b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint32_t subsection_len; 322425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (p - q < (ptrdiff_t) sizeof subsection_len) 322525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 322625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 322725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: truncated attribute section\n"), 322825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (q)); 322925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 323025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 323125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 323225b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&subsection_len, q, sizeof subsection_len); 323325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (subsection_len == 0) 323425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 323525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 323625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: zero length field in attribute subsection\n"), 323725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (q)); 323825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 323925b3c049e70834cf33790a28643ab058b507b35cBen Cheng q += sizeof subsection_len; 324025b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 324125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 324225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 324325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (MY_ELFDATA != ehdr->e_ident[EI_DATA]) 324425b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (subsection_len); 324525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 324625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (p - chunk < (ptrdiff_t) subsection_len) 324725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 324825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 324925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: invalid length in attribute subsection\n"), 325025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (q)); 325125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 325225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 325325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 325425b3c049e70834cf33790a28643ab058b507b35cBen Cheng const unsigned char *subsection_end = chunk + subsection_len; 325525b3c049e70834cf33790a28643ab058b507b35cBen Cheng chunk = q; 325625b3c049e70834cf33790a28643ab058b507b35cBen Cheng q = subsection_end; 325725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 325825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (subsection_tag != 1) /* Tag_File */ 325925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 326025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"), 326125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (chunk), subsection_tag); 326225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 326325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 326425b3c049e70834cf33790a28643ab058b507b35cBen Cheng chunk += sizeof subsection_len; 326525b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (chunk < q) 326625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 326725b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int tag; 326825b3c049e70834cf33790a28643ab058b507b35cBen Cheng get_uleb128 (tag, chunk); 326925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 327025b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint64_t value = 0; 327125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const unsigned char *r = chunk; 327225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (tag == 32 || (tag & 1) == 0) 327325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 327425b3c049e70834cf33790a28643ab058b507b35cBen Cheng get_uleb128 (value, r); 327525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r > q) 327625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 327725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 327825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"), 327925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (chunk)); 328025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 328125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 328225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 328325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (tag == 32 || (tag & 1) != 0) 328425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 328525b3c049e70834cf33790a28643ab058b507b35cBen Cheng r = memchr (r, '\0', q - r); 328625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r == NULL) 328725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 328825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 328925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: unterminated string in attribute\n"), 329025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (chunk)); 329125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 329225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 329325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++r; 329425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 329525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 329625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *tag_name = NULL; 329725b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *value_name = NULL; 329825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!ebl_check_object_attribute (ebl, (const char *) name, 329925b3c049e70834cf33790a28643ab058b507b35cBen Cheng tag, value, 330025b3c049e70834cf33790a28643ab058b507b35cBen Cheng &tag_name, &value_name)) 330125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 330225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"), 330325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (chunk), tag); 330425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((tag & 1) == 0 && value_name == NULL) 330525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 330625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"), 330725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (chunk), 330825b3c049e70834cf33790a28643ab058b507b35cBen Cheng tag_name, value); 330925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 331025b3c049e70834cf33790a28643ab058b507b35cBen Cheng chunk = r; 331125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 331225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 331325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 331425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 331525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 331625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: vendor '%s' unknown\n"), 331725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (p), name); 331825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 331925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 332025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (left () != 0) 332125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 332225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': offset %zu: extra bytes after last attribute section\n"), 332325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), pos (p)); 332425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 332525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 332625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool has_loadable_segment; 332725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool has_interp_segment; 332825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 332925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct 333025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 333125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *name; 333225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t namelen; 333325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Word type; 333425b3c049e70834cf33790a28643ab058b507b35cBen Cheng enum { unused, exact, atleast, exact_or_gnuld } attrflag; 333525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Word attr; 333625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Word attr2; 333725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} special_sections[] = 333825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 333925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* See figure 4-14 in the gABI. */ 334025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 }, 334125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".comment", 8, SHT_PROGBITS, atleast, 0, SHF_MERGE | SHF_STRINGS }, 334225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 }, 334325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 }, 334425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".debug_str", 11, SHT_PROGBITS, exact_or_gnuld, SHF_MERGE | SHF_STRINGS, 0 }, 334525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".debug", 6, SHT_PROGBITS, exact, 0, 0 }, 334625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE }, 334725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 }, 334825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 }, 334925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 }, 335025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 }, 335125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info? 335225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 }, 335325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 }, 335425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 }, 335525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests? 335625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".line", 6, SHT_PROGBITS, exact, 0, 0 }, 335725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".note", 6, SHT_NOTE, atleast, 0, SHF_ALLOC }, 335825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests 335925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 }, 336025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC }, // XXX more tests 336125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC }, // XXX more tests 336225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS }, 336325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS }, 336425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 }, 336525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests 336625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests 336725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests 336825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 }, 336925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 }, 337025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 }, 337125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 }, 337225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 337325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The following are GNU extensions. */ 337425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".gnu.version", 13, SHT_GNU_versym, exact, SHF_ALLOC, 0 }, 337525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".gnu.version_d", 15, SHT_GNU_verdef, exact, SHF_ALLOC, 0 }, 337625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 }, 337725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { ".gnu.attributes", 16, SHT_GNU_ATTRIBUTES, exact, 0, 0 }, 337825b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 337925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define nspecial_sections \ 338025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (sizeof (special_sections) / sizeof (special_sections[0])) 338125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 338225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define IS_KNOWN_SPECIAL(idx, string, prefix) \ 338325b3c049e70834cf33790a28643ab058b507b35cBen Cheng (special_sections[idx].namelen == sizeof string - (prefix ? 1 : 0) \ 338425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !memcmp (special_sections[idx].name, string, \ 338525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof string - (prefix ? 1 : 0))) 338625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 338725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 338825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Indeces of some sections we need later. */ 338925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t eh_frame_hdr_scnndx; 339025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t eh_frame_scnndx; 339125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t gcc_except_table_scnndx; 339225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 339325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 339425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 339525b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_sections (Ebl *ebl, GElf_Ehdr *ehdr) 339625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 339725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_shoff == 0) 339825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* No section header. */ 339925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 340025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 340125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Allocate array to count references in section groups. */ 340225b3c049e70834cf33790a28643ab058b507b35cBen Cheng scnref = (int *) xcalloc (shnum, sizeof (int)); 340325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 340425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the zeroth section first. It must not have any contents 340525b3c049e70834cf33790a28643ab058b507b35cBen Cheng and the section header must contain nonzero value at most in the 340625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_size and sh_link fields. */ 340725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 340825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem); 340925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr == NULL) 341025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("cannot get section header of zeroth section\n")); 341125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 341225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 341325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_name != 0) 341425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("zeroth section has nonzero name\n")); 341525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_type != 0) 341625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("zeroth section has nonzero type\n")); 341725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_flags != 0) 341825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("zeroth section has nonzero flags\n")); 341925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_addr != 0) 342025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("zeroth section has nonzero address\n")); 342125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_offset != 0) 342225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("zeroth section has nonzero offset\n")); 342325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_addralign != 0) 342425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("zeroth section has nonzero align value\n")); 342525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_entsize != 0) 342625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("zeroth section has nonzero entry size value\n")); 342725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 342825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_size != 0 && ehdr->e_shnum != 0) 342925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 343025b3c049e70834cf33790a28643ab058b507b35cBen Chengzeroth section has nonzero size value while ELF header has nonzero shnum value\n")); 343125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 343225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX) 343325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 343425b3c049e70834cf33790a28643ab058b507b35cBen Chengzeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n")); 343525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 343625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_info != 0 && ehdr->e_phnum != PN_XNUM) 343725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 343825b3c049e70834cf33790a28643ab058b507b35cBen Chengzeroth section has nonzero link value while ELF header does not signal overflow in phnum\n")); 343925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 344025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 344125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int *segment_flags = xcalloc (phnum, sizeof segment_flags[0]); 344225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 344325b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool dot_interp_section = false; 344425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 344525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t hash_idx = 0; 344625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t gnu_hash_idx = 0; 344725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 344825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t versym_scnndx = 0; 344925b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 1; cnt < shnum; ++cnt) 345025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 345125b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &shdr_mem); 345225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr == NULL) 345325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 345425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 345525b3c049e70834cf33790a28643ab058b507b35cBen Chengcannot get section header for section [%2zu] '%s': %s\n"), 345625b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt), elf_errmsg (-1)); 345725b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 345825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 345925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 346025b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name); 346125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 346225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scnname == NULL) 346325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2zu]: invalid name\n"), cnt); 346425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 346525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 346625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check whether it is one of the special sections defined in 346725b3c049e70834cf33790a28643ab058b507b35cBen Cheng the gABI. */ 346825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t s; 346925b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (s = 0; s < nspecial_sections; ++s) 347025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strncmp (scnname, special_sections[s].name, 347125b3c049e70834cf33790a28643ab058b507b35cBen Cheng special_sections[s].namelen) == 0) 347225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 347325b3c049e70834cf33790a28643ab058b507b35cBen Cheng char stbuf1[100]; 347425b3c049e70834cf33790a28643ab058b507b35cBen Cheng char stbuf2[100]; 347525b3c049e70834cf33790a28643ab058b507b35cBen Cheng char stbuf3[100]; 347625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 347725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Word good_type = special_sections[s].type; 347825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (IS_KNOWN_SPECIAL (s, ".plt", false) 347925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ebl_bss_plt_p (ebl, ehdr)) 348025b3c049e70834cf33790a28643ab058b507b35cBen Cheng good_type = SHT_NOBITS; 348125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 348225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* In a debuginfo file, any normal section can be SHT_NOBITS. 348325b3c049e70834cf33790a28643ab058b507b35cBen Cheng This is only invalid for DWARF sections and .shstrtab. */ 348425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_type != good_type 348525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (shdr->sh_type != SHT_NOBITS 348625b3c049e70834cf33790a28643ab058b507b35cBen Cheng || !is_debuginfo 348725b3c049e70834cf33790a28643ab058b507b35cBen Cheng || IS_KNOWN_SPECIAL (s, ".debug_str", false) 348825b3c049e70834cf33790a28643ab058b507b35cBen Cheng || IS_KNOWN_SPECIAL (s, ".debug", true) 348925b3c049e70834cf33790a28643ab058b507b35cBen Cheng || IS_KNOWN_SPECIAL (s, ".shstrtab", false))) 349025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 349125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s' has wrong type: expected %s, is %s\n"), 349225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) cnt, scnname, 349325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_section_type_name (ebl, special_sections[s].type, 349425b3c049e70834cf33790a28643ab058b507b35cBen Cheng stbuf1, sizeof (stbuf1)), 349525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_section_type_name (ebl, shdr->sh_type, 349625b3c049e70834cf33790a28643ab058b507b35cBen Cheng stbuf2, sizeof (stbuf2))); 349725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 349825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (special_sections[s].attrflag == exact 349925b3c049e70834cf33790a28643ab058b507b35cBen Cheng || special_sections[s].attrflag == exact_or_gnuld) 350025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 350125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Except for the link order and group bit all the 350225b3c049e70834cf33790a28643ab058b507b35cBen Cheng other bits should match exactly. */ 350325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP)) 350425b3c049e70834cf33790a28643ab058b507b35cBen Cheng != special_sections[s].attr 350525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (special_sections[s].attrflag == exact || !gnuld)) 350625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 350725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' has wrong flags: expected %s, is %s\n"), 350825b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, scnname, 350925b3c049e70834cf33790a28643ab058b507b35cBen Cheng section_flags_string (special_sections[s].attr, 351025b3c049e70834cf33790a28643ab058b507b35cBen Cheng stbuf1, sizeof (stbuf1)), 351125b3c049e70834cf33790a28643ab058b507b35cBen Cheng section_flags_string (shdr->sh_flags 351225b3c049e70834cf33790a28643ab058b507b35cBen Cheng & ~SHF_LINK_ORDER, 351325b3c049e70834cf33790a28643ab058b507b35cBen Cheng stbuf2, sizeof (stbuf2))); 351425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 351525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (special_sections[s].attrflag == atleast) 351625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 351725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & special_sections[s].attr) 351825b3c049e70834cf33790a28643ab058b507b35cBen Cheng != special_sections[s].attr 351925b3c049e70834cf33790a28643ab058b507b35cBen Cheng || ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP 352025b3c049e70834cf33790a28643ab058b507b35cBen Cheng | special_sections[s].attr 352125b3c049e70834cf33790a28643ab058b507b35cBen Cheng | special_sections[s].attr2)) 352225b3c049e70834cf33790a28643ab058b507b35cBen Cheng != 0)) 352325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 352425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"), 352525b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, scnname, 352625b3c049e70834cf33790a28643ab058b507b35cBen Cheng section_flags_string (special_sections[s].attr, 352725b3c049e70834cf33790a28643ab058b507b35cBen Cheng stbuf1, sizeof (stbuf1)), 352825b3c049e70834cf33790a28643ab058b507b35cBen Cheng section_flags_string (special_sections[s].attr2, 352925b3c049e70834cf33790a28643ab058b507b35cBen Cheng stbuf2, sizeof (stbuf2)), 353025b3c049e70834cf33790a28643ab058b507b35cBen Cheng section_flags_string (shdr->sh_flags 353125b3c049e70834cf33790a28643ab058b507b35cBen Cheng & ~(SHF_LINK_ORDER 353225b3c049e70834cf33790a28643ab058b507b35cBen Cheng | SHF_GROUP), 353325b3c049e70834cf33790a28643ab058b507b35cBen Cheng stbuf3, sizeof (stbuf3))); 353425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 353525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 353625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strcmp (scnname, ".interp") == 0) 353725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 353825b3c049e70834cf33790a28643ab058b507b35cBen Cheng dot_interp_section = true; 353925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 354025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type == ET_REL) 354125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 354225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' present in object file\n"), 354325b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, scnname); 354425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 354525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_ALLOC) != 0 354625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !has_loadable_segment) 354725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 354825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"), 354925b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, scnname); 355025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((shdr->sh_flags & SHF_ALLOC) == 0 355125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && has_loadable_segment) 355225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 355325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"), 355425b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, scnname); 355525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 355625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 355725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 355825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strcmp (scnname, ".symtab_shndx") == 0 355925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ehdr->e_type != ET_REL) 356025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 356125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' is extension section index table in non-object file\n"), 356225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, scnname); 356325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 356425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* These sections must have the SHF_ALLOC flag set iff 356525b3c049e70834cf33790a28643ab058b507b35cBen Cheng a loadable segment is available. 356625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 356725b3c049e70834cf33790a28643ab058b507b35cBen Cheng .relxxx 356825b3c049e70834cf33790a28643ab058b507b35cBen Cheng .strtab 356925b3c049e70834cf33790a28643ab058b507b35cBen Cheng .symtab 357025b3c049e70834cf33790a28643ab058b507b35cBen Cheng .symtab_shndx 357125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 357225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Check that if there is a reference from the 357325b3c049e70834cf33790a28643ab058b507b35cBen Cheng loaded section these sections also have the 357425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ALLOC flag set. */ 357525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if 0 357625b3c049e70834cf33790a28643ab058b507b35cBen Cheng // XXX TODO 357725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_ALLOC) != 0 357825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !has_loadable_segment) 357925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 358025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"), 358125b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, scnname); 358225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((shdr->sh_flags & SHF_ALLOC) == 0 358325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && has_loadable_segment) 358425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 358525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"), 358625b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, scnname); 358725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 358825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 358925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 359025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 359125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 359225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 359325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Remember a few special sections for later. */ 359425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (strcmp (scnname, ".eh_frame_hdr") == 0) 359525b3c049e70834cf33790a28643ab058b507b35cBen Cheng eh_frame_hdr_scnndx = cnt; 359625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (strcmp (scnname, ".eh_frame") == 0) 359725b3c049e70834cf33790a28643ab058b507b35cBen Cheng eh_frame_scnndx = cnt; 359825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (strcmp (scnname, ".gcc_except_table") == 0) 359925b3c049e70834cf33790a28643ab058b507b35cBen Cheng gcc_except_table_scnndx = cnt; 360025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 360125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 360225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize) 360325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 360425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s': size not multiple of entry size\n"), 360525b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 360625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 360725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL) 360825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("cannot get section header\n")); 360925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 361025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_type >= SHT_NUM 361125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr->sh_type != SHT_GNU_ATTRIBUTES 361225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr->sh_type != SHT_GNU_LIBLIST 361325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr->sh_type != SHT_CHECKSUM 361425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr->sh_type != SHT_GNU_verdef 361525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr->sh_type != SHT_GNU_verneed 361625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr->sh_type != SHT_GNU_versym 361725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ebl_section_type_name (ebl, shdr->sh_type, NULL, 0) == NULL) 361825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2zu] '%s' has unsupported type %d\n"), 361925b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt), 362025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) shdr->sh_type); 362125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 362225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \ 362325b3c049e70834cf33790a28643ab058b507b35cBen Cheng | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \ 362425b3c049e70834cf33790a28643ab058b507b35cBen Cheng | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS) 362525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS) 362625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 362725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS; 362825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sh_flags & SHF_MASKPROC) 362925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 363025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!ebl_machine_section_flag_check (ebl, 363125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_flags & SHF_MASKPROC)) 363225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2zu] '%s'" 363325b3c049e70834cf33790a28643ab058b507b35cBen Cheng " contains invalid processor-specific flag(s)" 363425b3c049e70834cf33790a28643ab058b507b35cBen Cheng " %#" PRIx64 "\n"), 363525b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC); 363625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_flags &= ~(GElf_Xword) SHF_MASKPROC; 363725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 363825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sh_flags != 0) 363925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2zu] '%s' contains unknown flag(s)" 364025b3c049e70834cf33790a28643ab058b507b35cBen Cheng " %#" PRIx64 "\n"), 364125b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt), sh_flags); 364225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 364325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_flags & SHF_TLS) 364425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 364525b3c049e70834cf33790a28643ab058b507b35cBen Cheng // XXX Correct? 364625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_addr != 0 && !gnuld) 364725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 364825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s': thread-local data sections address not zero\n"), 364925b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 365025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 365125b3c049e70834cf33790a28643ab058b507b35cBen Cheng // XXX TODO more tests!? 365225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 365325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 365425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_link >= shnum) 365525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 365625b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s': invalid section reference in link value\n"), 365725b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 365825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 365925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum) 366025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 366125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s': invalid section reference in info value\n"), 366225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 366325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 366425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_MERGE) == 0 366525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (shdr->sh_flags & SHF_STRINGS) != 0 366625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && be_strict) 366725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 366825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s': strings flag set without merge flag\n"), 366925b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 367025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 367125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0) 367225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 367325b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s': merge flag set but entry size is zero\n"), 367425b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 367525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 367625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_flags & SHF_GROUP) 367725b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_scn_group (ebl, cnt); 367825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 367925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_flags & SHF_EXECINSTR) 368025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 368125b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (shdr->sh_type) 368225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 368325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_PROGBITS: 368425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 368525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 368625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_NOBITS: 368725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (is_debuginfo) 368825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 368925b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 369025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 369125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' has unexpected type %d for an executable section\n"), 369225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt), shdr->sh_type); 369325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 369425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 369525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 369625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_WRITE) 369725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !ebl_check_special_section (ebl, cnt, shdr, 369825b3c049e70834cf33790a28643ab058b507b35cBen Cheng section_name (ebl, cnt))) 369925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 370025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' is both executable and writable\n"), 370125b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 370225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 370325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 370425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0) 370525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 370625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure the section is contained in a loaded segment 370725b3c049e70834cf33790a28643ab058b507b35cBen Cheng and that the initialization part matches NOBITS sections. */ 370825b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int pcnt; 370925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 371025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr; 371125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 371225b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (pcnt = 0; pcnt < phnum; ++pcnt) 371325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL 371425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ((phdr->p_type == PT_LOAD 371525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (shdr->sh_flags & SHF_TLS) == 0) 371625b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (phdr->p_type == PT_TLS 371725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (shdr->sh_flags & SHF_TLS) != 0)) 371825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && phdr->p_offset <= shdr->sh_offset 371925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (phdr->p_offset + phdr->p_filesz > shdr->sh_offset 372025b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (phdr->p_offset + phdr->p_memsz > shdr->sh_offset 372125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr->sh_type == SHT_NOBITS))) 372225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 372325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Found the segment. */ 372425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_offset + phdr->p_memsz 372525b3c049e70834cf33790a28643ab058b507b35cBen Cheng < shdr->sh_offset + shdr->sh_size) 372625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 372725b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' not fully contained in segment of program header entry %d\n"), 372825b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt), pcnt); 372925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 373025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_type == SHT_NOBITS) 373125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 373225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz 373325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !is_debuginfo) 373425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 373525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"), 373625b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt), pcnt); 373725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 373825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 373925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 374025b3c049e70834cf33790a28643ab058b507b35cBen Cheng const GElf_Off end = phdr->p_offset + phdr->p_filesz; 374125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_offset > end || 374225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (shdr->sh_offset == end && shdr->sh_size != 0)) 374325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 374425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"), 374525b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt), pcnt); 374625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 374725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 374825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_type != SHT_NOBITS) 374925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 375025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_EXECINSTR) != 0) 375125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 375225b3c049e70834cf33790a28643ab058b507b35cBen Cheng segment_flags[pcnt] |= PF_X; 375325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((phdr->p_flags & PF_X) == 0) 375425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 375525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' is executable in nonexecutable segment %d\n"), 375625b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt), pcnt); 375725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 375825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 375925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((shdr->sh_flags & SHF_WRITE) != 0) 376025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 376125b3c049e70834cf33790a28643ab058b507b35cBen Cheng segment_flags[pcnt] |= PF_W; 376225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (0 /* XXX vdso images have this */ 376325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (phdr->p_flags & PF_W) == 0) 376425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 376525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' is writable in unwritable segment %d\n"), 376625b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt), pcnt); 376725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 376825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 376925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 377025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 377125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 377225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 377325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (pcnt == phnum) 377425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 377525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s': alloc flag set but section not in any loaded segment\n"), 377625b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 377725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 377825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 377925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB) 378025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 378125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"), 378225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 378325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 378425b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (shdr->sh_type) 378525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 378625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_DYNSYM: 378725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type == ET_REL) 378825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 378925b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"), 379025b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, section_name (ebl, cnt)); 379125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* FALLTHROUGH */ 379225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_SYMTAB: 379325b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_symtab (ebl, ehdr, shdr, cnt); 379425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 379525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 379625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_RELA: 379725b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_rela (ebl, ehdr, shdr, cnt); 379825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 379925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 380025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_REL: 380125b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_rel (ebl, ehdr, shdr, cnt); 380225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 380325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 380425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_DYNAMIC: 380525b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_dynamic (ebl, ehdr, shdr, cnt); 380625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 380725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 380825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_SYMTAB_SHNDX: 380925b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_symtab_shndx (ebl, ehdr, shdr, cnt); 381025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 381125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 381225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_HASH: 381325b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt); 381425b3c049e70834cf33790a28643ab058b507b35cBen Cheng hash_idx = cnt; 381525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 381625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 381725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_GNU_HASH: 381825b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt); 381925b3c049e70834cf33790a28643ab058b507b35cBen Cheng gnu_hash_idx = cnt; 382025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 382125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 382225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_NULL: 382325b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_null (ebl, shdr, cnt); 382425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 382525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 382625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_GROUP: 382725b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_group (ebl, ehdr, shdr, cnt); 382825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 382925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 383025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_NOTE: 383125b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_note_section (ebl, ehdr, shdr, cnt); 383225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 383325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 383425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_GNU_versym: 383525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We cannot process this section now since we have no guarantee 383625b3c049e70834cf33790a28643ab058b507b35cBen Cheng that the verneed and verdef sections have already been read. 383725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Just remember the section index. */ 383825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (versym_scnndx != 0) 383925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("more than one version symbol table present\n")); 384025b3c049e70834cf33790a28643ab058b507b35cBen Cheng versym_scnndx = cnt; 384125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 384225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 384325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_GNU_verneed: 384425b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_verneed (ebl, shdr, cnt); 384525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 384625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 384725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_GNU_verdef: 384825b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_verdef (ebl, shdr, cnt); 384925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 385025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 385125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_GNU_ATTRIBUTES: 385225b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_attributes (ebl, ehdr, shdr, cnt); 385325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 385425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 385525b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 385625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Nothing. */ 385725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 385825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 385925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 386025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 386125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (has_interp_segment && !dot_interp_section) 386225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("INTERP program header entry but no .interp section\n")); 386325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 386425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!is_debuginfo) 386525b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt) 386625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 386725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 386825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem); 386925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr != NULL && (phdr->p_type == PT_LOAD || phdr->p_type == PT_TLS)) 387025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 387125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((phdr->p_flags & PF_X) != 0 387225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (segment_flags[pcnt] & PF_X) == 0) 387325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 387425b3c049e70834cf33790a28643ab058b507b35cBen Chengloadable segment [%u] is executable but contains no executable sections\n"), 387525b3c049e70834cf33790a28643ab058b507b35cBen Cheng pcnt); 387625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 387725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((phdr->p_flags & PF_W) != 0 387825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (segment_flags[pcnt] & PF_W) == 0) 387925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 388025b3c049e70834cf33790a28643ab058b507b35cBen Chengloadable segment [%u] is writable but contains no writable sections\n"), 388125b3c049e70834cf33790a28643ab058b507b35cBen Cheng pcnt); 388225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 388325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 388425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 388525b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (segment_flags); 388625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 388725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (version_namelist != NULL) 388825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 388925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (versym_scnndx == 0) 389025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 389125b3c049e70834cf33790a28643ab058b507b35cBen Chengno .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section exist\n")); 389225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 389325b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_versym (ebl, versym_scnndx); 389425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 389525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check for duplicate index numbers. */ 389625b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 389725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 389825b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct version_namelist *runp = version_namelist->next; 389925b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (runp != NULL) 390025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 390125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (version_namelist->ndx == runp->ndx) 390225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 390325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("duplicate version index %d\n"), 390425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int) version_namelist->ndx); 390525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 390625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 390725b3c049e70834cf33790a28643ab058b507b35cBen Cheng runp = runp->next; 390825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 390925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 391025b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct version_namelist *old = version_namelist; 391125b3c049e70834cf33790a28643ab058b507b35cBen Cheng version_namelist = version_namelist->next; 391225b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (old); 391325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 391425b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (version_namelist != NULL); 391525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 391625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (versym_scnndx != 0) 391725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 391825b3c049e70834cf33790a28643ab058b507b35cBen Cheng.gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n")); 391925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 392025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (hash_idx != 0 && gnu_hash_idx != 0) 392125b3c049e70834cf33790a28643ab058b507b35cBen Cheng compare_hash_gnu_hash (ebl, ehdr, hash_idx, gnu_hash_idx); 392225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 392325b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (scnref); 392425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 392525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 392625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 392725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic GElf_Off 392825b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_note_data (Ebl *ebl, const GElf_Ehdr *ehdr, 392925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data, int shndx, int phndx, GElf_Off start) 393025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 393125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t offset = 0; 393225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t last_offset = 0; 393325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Nhdr nhdr; 393425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t name_offset; 393525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t desc_offset; 393625b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (offset < data->d_size 393725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (offset = gelf_getnote (data, offset, 393825b3c049e70834cf33790a28643ab058b507b35cBen Cheng &nhdr, &name_offset, &desc_offset)) > 0) 393925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 394025b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_offset = offset; 394125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 394225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure it is one of the note types we know about. */ 394325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type == ET_CORE) 394425b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (nhdr.n_type) 394525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 394625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_PRSTATUS: 394725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_FPREGSET: 394825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_PRPSINFO: 394925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_TASKSTRUCT: /* NT_PRXREG on Solaris. */ 395025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_PLATFORM: 395125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_AUXV: 395225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_GWINDOWS: 395325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_ASRS: 395425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_PSTATUS: 395525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_PSINFO: 395625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_PRCRED: 395725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_UTSNAME: 395825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_LWPSTATUS: 395925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_LWPSINFO: 396025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_PRFPXREG: 396125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Known type. */ 396225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 396325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 396425b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 396525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shndx == 0) 396625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 396725b3c049e70834cf33790a28643ab058b507b35cBen Chengphdr[%d]: unknown core file note type %" PRIu32 " at offset %" PRIu64 "\n"), 396825b3c049e70834cf33790a28643ab058b507b35cBen Cheng phndx, (uint32_t) nhdr.n_type, start + offset); 396925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 397025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 397125b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': unknown core file note type %" PRIu32 397225b3c049e70834cf33790a28643ab058b507b35cBen Cheng " at offset %Zu\n"), 397325b3c049e70834cf33790a28643ab058b507b35cBen Cheng shndx, section_name (ebl, shndx), 397425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint32_t) nhdr.n_type, offset); 397525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 397625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 397725b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (nhdr.n_type) 397825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 397925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_GNU_ABI_TAG: 398025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_GNU_HWCAP: 398125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_GNU_BUILD_ID: 398225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case NT_GNU_GOLD_VERSION: 398325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 398425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 398525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 0: 398625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Linux vDSOs use a type 0 note for the kernel version word. */ 398725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (nhdr.n_namesz == sizeof "Linux" 398825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !memcmp (data->d_buf + name_offset, "Linux", sizeof "Linux")) 398925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 399025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 399125b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 399225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shndx == 0) 399325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 399425b3c049e70834cf33790a28643ab058b507b35cBen Chengphdr[%d]: unknown object file note type %" PRIu32 " at offset %Zu\n"), 399525b3c049e70834cf33790a28643ab058b507b35cBen Cheng phndx, (uint32_t) nhdr.n_type, offset); 399625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 399725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 399825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': unknown object file note type %" PRIu32 399925b3c049e70834cf33790a28643ab058b507b35cBen Cheng " at offset %Zu\n"), 400025b3c049e70834cf33790a28643ab058b507b35cBen Cheng shndx, section_name (ebl, shndx), 400125b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint32_t) nhdr.n_type, offset); 400225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 400325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 400425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 400525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return last_offset; 400625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 400725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 400825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 400925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 401025b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt) 401125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 401225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL 401325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 401425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 401525b3c049e70834cf33790a28643ab058b507b35cBen Chengphdr[%d]: no note entries defined for the type of file\n"), 401625b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt); 401725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 401825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (is_debuginfo) 401925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The p_offset values in a separate debug file are bogus. */ 402025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 402125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 402225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_filesz == 0) 402325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 402425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 402525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off notes_size = 0; 402625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata_rawchunk (ebl->elf, 402725b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdr->p_offset, phdr->p_filesz, 402825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ELF_T_NHDR); 402925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data != NULL) 403025b3c049e70834cf33790a28643ab058b507b35cBen Cheng notes_size = check_note_data (ebl, ehdr, data, 0, cnt, phdr->p_offset); 403125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 403225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (notes_size == 0) 403325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("phdr[%d]: cannot get content of note section: %s\n"), 403425b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, elf_errmsg (-1)); 403525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (notes_size != phdr->p_filesz) 403625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("phdr[%d]: extra %" PRIu64 " bytes after last note\n"), 403725b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, phdr->p_filesz - notes_size); 403825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 403925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 404025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 404125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 404225b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_note_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 404325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 404425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_size == 0) 404525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 404625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 404725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 404825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 404925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 405025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 405125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 405225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 405325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 405425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 405525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL 405625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 405725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 405825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2d] '%s': no note entries defined for the type of file\n"), 405925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 406025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 406125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off notes_size = check_note_data (ebl, ehdr, data, idx, 0, 0); 406225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 406325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (notes_size == 0) 406425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': cannot get content of note section\n"), 406525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx)); 406625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (notes_size != shdr->sh_size) 406725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("section [%2d] '%s': extra %" PRIu64 406825b3c049e70834cf33790a28643ab058b507b35cBen Cheng " bytes after last note\n"), 406925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx, section_name (ebl, idx), shdr->sh_size - notes_size); 407025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 407125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 407225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 407325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Index of the PT_GNU_EH_FRAME program eader entry. */ 407425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int pt_gnu_eh_frame_pndx; 407525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 407625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 407725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 407825b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_program_header (Ebl *ebl, GElf_Ehdr *ehdr) 407925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 408025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_phoff == 0) 408125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 408225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 408325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN 408425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ehdr->e_type != ET_CORE) 408525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 408625b3c049e70834cf33790a28643ab058b507b35cBen Chengonly executables, shared objects, and core files can have program headers\n")); 408725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 408825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int num_pt_interp = 0; 408925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int num_pt_tls = 0; 409025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int num_pt_relro = 0; 409125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 409225b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (unsigned int cnt = 0; cnt < phnum; ++cnt) 409325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 409425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 409525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr; 409625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 409725b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem); 409825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr == NULL) 409925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 410025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("cannot get program header entry %d: %s\n"), 410125b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, elf_errmsg (-1)); 410225b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 410325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 410425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 410525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME 410625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && phdr->p_type != PT_GNU_STACK && phdr->p_type != PT_GNU_RELRO 410725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check for a known machine-specific type. */ 410825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ebl_segment_type_name (ebl, phdr->p_type, NULL, 0) == NULL) 410925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 411025b3c049e70834cf33790a28643ab058b507b35cBen Chengprogram header entry %d: unknown program header entry type %#" PRIx64 "\n"), 411125b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, (uint64_t) phdr->p_type); 411225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 411325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_type == PT_LOAD) 411425b3c049e70834cf33790a28643ab058b507b35cBen Cheng has_loadable_segment = true; 411525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (phdr->p_type == PT_INTERP) 411625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 411725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (++num_pt_interp != 1) 411825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 411925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (num_pt_interp == 2) 412025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 412125b3c049e70834cf33790a28643ab058b507b35cBen Chengmore than one INTERP entry in program header\n")); 412225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 412325b3c049e70834cf33790a28643ab058b507b35cBen Cheng has_interp_segment = true; 412425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 412525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (phdr->p_type == PT_TLS) 412625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 412725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (++num_pt_tls == 2) 412825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("more than one TLS entry in program header\n")); 412925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 413025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (phdr->p_type == PT_NOTE) 413125b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_note (ebl, ehdr, phdr, cnt); 413225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (phdr->p_type == PT_DYNAMIC) 413325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 413425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type == ET_EXEC && ! has_interp_segment) 413525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 413625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic executable cannot have dynamic sections\n")); 413725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 413825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 413925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that the .dynamic section, if it exists, has 414025b3c049e70834cf33790a28643ab058b507b35cBen Cheng the same address. */ 414125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = NULL; 414225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 414325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 414425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 414525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 414625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC) 414725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 414825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_offset != shdr->sh_offset) 414925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 415025b3c049e70834cf33790a28643ab058b507b35cBen Chengdynamic section reference in program header has wrong offset\n")); 415125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_memsz != shdr->sh_size) 415225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 415325b3c049e70834cf33790a28643ab058b507b35cBen Chengdynamic section size mismatch in program and section header\n")); 415425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 415525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 415625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 415725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 415825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 415925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (phdr->p_type == PT_GNU_RELRO) 416025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 416125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (++num_pt_relro == 2) 416225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 416325b3c049e70834cf33790a28643ab058b507b35cBen Chengmore than one GNU_RELRO entry in program header\n")); 416425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 416525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 416625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that the region is in a writable segment. */ 416725b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int inner; 416825b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (inner = 0; inner < phnum; ++inner) 416925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 417025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr2_mem; 417125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr2; 417225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 417325b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem); 417425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr2 == NULL) 417525b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 417625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 417725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr2->p_type == PT_LOAD 417825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && phdr->p_vaddr >= phdr2->p_vaddr 417925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (phdr->p_vaddr + phdr->p_memsz 418025b3c049e70834cf33790a28643ab058b507b35cBen Cheng <= phdr2->p_vaddr + phdr2->p_memsz)) 418125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 418225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((phdr2->p_flags & PF_W) == 0) 418325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 418425b3c049e70834cf33790a28643ab058b507b35cBen Chengloadable segment GNU_RELRO applies to is not writable\n")); 418525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((phdr2->p_flags & ~PF_W) != (phdr->p_flags & ~PF_W)) 418625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 418725b3c049e70834cf33790a28643ab058b507b35cBen Chengloadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"), 418825b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt, inner); 418925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 419025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 419125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 419225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 419325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (inner >= phnum) 419425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 419525b3c049e70834cf33790a28643ab058b507b35cBen Cheng%s segment not contained in a loaded segment\n"), "GNU_RELRO"); 419625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 419725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 419825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (phdr->p_type == PT_PHDR) 419925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 420025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that the region is in a writable segment. */ 420125b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int inner; 420225b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (inner = 0; inner < phnum; ++inner) 420325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 420425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr2_mem; 420525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr2; 420625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 420725b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem); 420825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr2 != NULL 420925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && phdr2->p_type == PT_LOAD 421025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && phdr->p_vaddr >= phdr2->p_vaddr 421125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (phdr->p_vaddr + phdr->p_memsz 421225b3c049e70834cf33790a28643ab058b507b35cBen Cheng <= phdr2->p_vaddr + phdr2->p_memsz)) 421325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 421425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 421525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 421625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (inner >= phnum) 421725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 421825b3c049e70834cf33790a28643ab058b507b35cBen Cheng%s segment not contained in a loaded segment\n"), "PHDR"); 421925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 422025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that offset in segment corresponds to offset in ELF 422125b3c049e70834cf33790a28643ab058b507b35cBen Cheng header. */ 422225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_offset != ehdr->e_phoff) 422325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 422425b3c049e70834cf33790a28643ab058b507b35cBen Chengprogram header offset in ELF header and PHDR entry do not match")); 422525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 422625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (phdr->p_type == PT_GNU_EH_FRAME) 422725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 422825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If there is an .eh_frame_hdr section it must be 422925b3c049e70834cf33790a28643ab058b507b35cBen Cheng referenced by this program header entry. */ 423025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = NULL; 423125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 423225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = NULL; 423325b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool any = false; 423425b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 423525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 423625b3c049e70834cf33790a28643ab058b507b35cBen Cheng any = true; 423725b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr = gelf_getshdr (scn, &shdr_mem); 423825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr != NULL 423925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr->sh_type == (is_debuginfo 424025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? SHT_NOBITS : SHT_PROGBITS) 424125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ! strcmp (".eh_frame_hdr", 424225b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_strptr (ebl->elf, shstrndx, shdr->sh_name))) 424325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 424425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (! is_debuginfo) 424525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 424625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_offset != shdr->sh_offset) 424725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 424825b3c049e70834cf33790a28643ab058b507b35cBen Chengcall frame search table reference in program header has wrong offset\n")); 424925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_memsz != shdr->sh_size) 425025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 425125b3c049e70834cf33790a28643ab058b507b35cBen Chengcall frame search table size mismatch in program and section header\n")); 425225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 425325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 425425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 425525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 425625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 425725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scn == NULL) 425825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 425925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If there is no section header table we don't 426025b3c049e70834cf33790a28643ab058b507b35cBen Cheng complain. But if there is one there should be an 426125b3c049e70834cf33790a28643ab058b507b35cBen Cheng entry for .eh_frame_hdr. */ 426225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (any) 426325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 426425b3c049e70834cf33790a28643ab058b507b35cBen ChengPT_GNU_EH_FRAME present but no .eh_frame_hdr section\n")); 426525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 426625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 426725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 426825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The section must be allocated and not be writable and 426925b3c049e70834cf33790a28643ab058b507b35cBen Cheng executable. */ 427025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((phdr->p_flags & PF_R) == 0) 427125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 427225b3c049e70834cf33790a28643ab058b507b35cBen Chengcall frame search table must be allocated\n")); 427325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (shdr != NULL && (shdr->sh_flags & SHF_ALLOC) == 0) 427425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 427525b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' must be allocated\n"), elf_ndxscn (scn), ".eh_frame_hdr"); 427625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 427725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((phdr->p_flags & PF_W) != 0) 427825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 427925b3c049e70834cf33790a28643ab058b507b35cBen Chengcall frame search table must not be writable\n")); 428025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (shdr != NULL && (shdr->sh_flags & SHF_WRITE) != 0) 428125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 428225b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' must not be writable\n"), 428325b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_ndxscn (scn), ".eh_frame_hdr"); 428425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 428525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((phdr->p_flags & PF_X) != 0) 428625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 428725b3c049e70834cf33790a28643ab058b507b35cBen Chengcall frame search table must not be executable\n")); 428825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (shdr != NULL && (shdr->sh_flags & SHF_EXECINSTR) != 0) 428925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 429025b3c049e70834cf33790a28643ab058b507b35cBen Chengsection [%2zu] '%s' must not be executable\n"), 429125b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_ndxscn (scn), ".eh_frame_hdr"); 429225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 429325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 429425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Remember which entry this is. */ 429525b3c049e70834cf33790a28643ab058b507b35cBen Cheng pt_gnu_eh_frame_pndx = cnt; 429625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 429725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 429825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_filesz > phdr->p_memsz 429925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (phdr->p_memsz != 0 || phdr->p_type != PT_NOTE)) 430025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 430125b3c049e70834cf33790a28643ab058b507b35cBen Chengprogram header entry %d: file size greater than memory size\n"), 430225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cnt); 430325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 430425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_align > 1) 430525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 430625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!powerof2 (phdr->p_align)) 430725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 430825b3c049e70834cf33790a28643ab058b507b35cBen Chengprogram header entry %d: alignment not a power of 2\n"), cnt); 430925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0) 431025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("\ 431125b3c049e70834cf33790a28643ab058b507b35cBen Chengprogram header entry %d: file offset and virtual address not module of alignment\n"), cnt); 431225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 431325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 431425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 431525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 431625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 431725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 431825b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_exception_data (Ebl *ebl __attribute__ ((unused)), 431925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Ehdr *ehdr __attribute__ ((unused))) 432025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 432125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN) 432225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && pt_gnu_eh_frame_pndx == 0 && eh_frame_hdr_scnndx != 0) 432325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("executable/DSO with .eh_frame_hdr section does not have " 432425b3c049e70834cf33790a28643ab058b507b35cBen Cheng "a PT_GNU_EH_FRAME program header entry")); 432525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 432625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 432725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 432825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Process one file. */ 432925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 433025b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_elf_file (Elf *elf, const char *prefix, const char *suffix, 433125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *fname, size_t size, bool only_one) 433225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 433325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Reset variables. */ 433425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ndynamic = 0; 433525b3c049e70834cf33790a28643ab058b507b35cBen Cheng nverneed = 0; 433625b3c049e70834cf33790a28643ab058b507b35cBen Cheng nverdef = 0; 433725b3c049e70834cf33790a28643ab058b507b35cBen Cheng textrel = false; 433825b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed_textrel = false; 433925b3c049e70834cf33790a28643ab058b507b35cBen Cheng has_loadable_segment = false; 434025b3c049e70834cf33790a28643ab058b507b35cBen Cheng has_interp_segment = false; 434125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 434225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Ehdr ehdr_mem; 434325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 434425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Ebl *ebl; 434525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 434625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Print the file name. */ 434725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!only_one) 434825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 434925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefix != NULL) 435025b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf ("\n%s(%s)%s:\n", prefix, fname, suffix); 435125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 435225b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf ("\n%s:\n", fname); 435325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 435425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 435525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr == NULL) 435625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 435725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("cannot read ELF header: %s\n"), elf_errmsg (-1)); 435825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 435925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 436025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 436125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl = ebl_openbackend (elf); 436225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If there is no appropriate backend library we cannot test 436325b3c049e70834cf33790a28643ab058b507b35cBen Cheng architecture and OS specific features. Any encountered extension 436425b3c049e70834cf33790a28643ab058b507b35cBen Cheng is an error. */ 436525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 436625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Go straight by the gABI, check all the parts in turn. */ 436725b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_elf_header (ebl, ehdr, size); 436825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 436925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the program header. */ 437025b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_program_header (ebl, ehdr); 437125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 437225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Next the section headers. It is OK if there are no section 437325b3c049e70834cf33790a28643ab058b507b35cBen Cheng headers at all. */ 437425b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_sections (ebl, ehdr); 437525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 437625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check the exception handling data, if it exists. */ 437725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (pt_gnu_eh_frame_pndx != 0 || eh_frame_hdr_scnndx != 0 437825b3c049e70834cf33790a28643ab058b507b35cBen Cheng || eh_frame_scnndx != 0 || gcc_except_table_scnndx != 0) 437925b3c049e70834cf33790a28643ab058b507b35cBen Cheng check_exception_data (ebl, ehdr); 438025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 438125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Report if no relocation section needed the text relocation flag. */ 438225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (textrel && !needed_textrel) 438325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ERROR (gettext ("text relocation flag set but not needed\n")); 438425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 438525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Free the resources. */ 438625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ebl_closebackend (ebl); 438725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 438825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 438925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 439025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "debugpred.h" 4391